Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .dependabot/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: 1
update_configs:
- package_manager: "dotnet:nuget"
directory: "/honeypot"
update_schedule: "daily"
default_labels:
- "vendors"
26 changes: 26 additions & 0 deletions honeypot/Datadog.Dependabot.Honeypot.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<RootNamespace>Datadog.Dependabot.Honeypot</RootNamespace>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why Honeypot?

Copy link
Member Author

@colin-higgins colin-higgins Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed like an apt name.
https://en.wikipedia.org/wiki/Honeypot_(computing)
It's not an attacker, but it isn't a REAL project: It's a fake project designed to attract the dependabot.

🍯 🐝 🐝 🐝

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

designed to attract the dependabot.

Ah, I didn't think of it that way. Thanks.

</PropertyGroup>

<ItemGroup>
<!-- https://www.nuget.org/packages/Serilog/2.8.0 -->
<PackageReference Include="Serilog" Version="2.8.0" />

<!-- https://www.nuget.org/packages/Serilog.Sinks.File/4.0.0 -->
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" />

<!-- https://www.nuget.org/packages/StatsdClient/6.0.0 -->
<PackageReference Include="StatsdClient" Version="6.0.0" />

<!-- https://www.nuget.org/packages/MessagePack/1.9.3 -->
<PackageReference Include="MessagePack" Version="1.9.3" />

<!-- https://www.nuget.org/packages/Newtonsoft.Json/12.0.1 -->
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />

</ItemGroup>

</Project>
11 changes: 11 additions & 0 deletions tools/UpdateVendors/Datadog.Dependabot.Honeypot.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<RootNamespace>Datadog.Dependabot.Honeypot</RootNamespace>
</PropertyGroup>

<ItemGroup>##PACKAGE_REFS##
</ItemGroup>

</Project>
158 changes: 52 additions & 106 deletions tools/UpdateVendors/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,12 @@
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using Datadog.Trace.TestHelpers;

namespace UpdateVendors
{
public class Program
{
private const string AutoGeneratedMessage = @"//------------------------------------------------------------------------------
// <auto-generated />
// This file was automatically generated by the UpdateVendors tool.
//------------------------------------------------------------------------------
";

private static readonly string DownloadDirectory = Path.Combine(Environment.CurrentDirectory, "downloads");
private static string _vendorProjectDirectory;

Expand All @@ -26,83 +19,51 @@ public static void Main()
var solutionDirectory = GetSolutionDirectory();
_vendorProjectDirectory = Path.Combine(solutionDirectory, "src", "Datadog.Trace", "Vendors");

UpdateVendor(
libraryName: "Serilog",
downloadUrl: "https://github.com/serilog/serilog/archive/v2.8.0.zip",
pathToSrc: new[] { "serilog-2.8.0", "src", "Serilog" },
transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Serilog"));

UpdateVendor(
libraryName: "Serilog.Sinks.File",
downloadUrl: "https://github.com/serilog/serilog-sinks-file/archive/v4.0.0.zip",
pathToSrc: new[] { "serilog-sinks-file-4.0.0", "src", "Serilog.Sinks.File" },
transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Serilog"));

UpdateVendor(
libraryName: "StatsdClient",
downloadUrl: "https://github.com/DataDog/dogstatsd-csharp-client/archive/6.0.0.zip",
pathToSrc: new[] { "dogstatsd-csharp-client-6.0.0", "src", "StatsdClient" },
transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "StatsdClient"));

UpdateVendor(
libraryName: "MessagePack",
downloadUrl: "https://github.com/neuecc/MessagePack-CSharp/archive/v1.9.3.zip",
pathToSrc: new[] { "MessagePack-CSharp-1.9.3", "src", "MessagePack" },
transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "MessagePack"));

UpdateVendor(
libraryName: "Newtonsoft.Json",
downloadUrl: "https://github.com/JamesNK/Newtonsoft.Json/archive/12.0.1.zip",
pathToSrc: new[] { "Newtonsoft.Json-12.0.1", "src", "Newtonsoft.Json" },
transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Newtonsoft.Json"));
var fakeRefs = string.Empty;

foreach (var dependency in VendoredDependency.All)
{
fakeRefs += $@"{Environment.NewLine} <!-- https://www.nuget.org/packages/{dependency.LibraryName}/{dependency.Version} -->";
fakeRefs += $@"{Environment.NewLine} <PackageReference Include=""{dependency.LibraryName}"" Version=""{dependency.Version}"" />{Environment.NewLine}";
UpdateVendor(dependency);
}

var honeypotProjTemplate = GetHoneyPotProjTemplate();
honeypotProjTemplate = honeypotProjTemplate.Replace("##PACKAGE_REFS##", fakeRefs);
var projLocation = Path.Combine(EnvironmentHelper.GetSolutionDirectory(), "honeypot", "Datadog.Dependabot.Honeypot.csproj");
File.WriteAllText(projLocation, honeypotProjTemplate);
}

private static void RewriteCsFileWithStandardTransform(string filePath, string originalNamespace, Func<string, string, string> extraTransform = null)
private static string GetHoneyPotProjTemplate()
{
if (string.Equals(Path.GetExtension(filePath), ".cs", StringComparison.OrdinalIgnoreCase))
var templateName = "Datadog.Dependabot.Honeypot.template";
var directory = Directory.GetCurrentDirectory();
string template = null;
var levelLimit = 4;

while (template == null && --levelLimit >= 0)
{
RewriteFileWithTransform(
filePath,
content =>
foreach (var filePath in Directory.EnumerateFiles(directory))
{
if (filePath.Contains(templateName))
{
// Disable analyzer
var builder = new StringBuilder(AutoGeneratedMessage, content.Length * 2);

builder.Append(content);

// Special Newtonsoft.Json processing
if (originalNamespace.Equals("Newtonsoft.Json"))
{
builder.Replace($"using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs", "using ErrorEventArgs = Datadog.Trace.Vendors.Newtonsoft.Json.Serialization.ErrorEventArgs");

if (content.Contains("using Newtonsoft.Json.Serialization;"))
{
builder.Replace($"Func<", $"System.Func<");
builder.Replace($"Action<", $"System.Action<");
}
}

// Prevent namespace conflicts
builder.Replace($"using {originalNamespace}", $"using Datadog.Trace.Vendors.{originalNamespace}");
builder.Replace($"namespace {originalNamespace}", $"namespace Datadog.Trace.Vendors.{originalNamespace}");
builder.Replace($"[CLSCompliant(false)]", $"// [CLSCompliant(false)]");

// Don't expose anything we don't intend to
// by replacing all "public" access modifiers with "internal"
return Regex.Replace(
builder.ToString(),
@"public(\s+((abstract|sealed|static)\s+)?(partial\s+)?(class|readonly\s+struct|struct|interface|enum|delegate))",
match => $"internal{match.Groups[1]}");
});
template = File.ReadAllText(filePath);
break;
}
}

directory = Directory.GetParent(directory).FullName;
}

return template;
}

private static void UpdateVendor(
string libraryName,
string downloadUrl,
string[] pathToSrc,
Action<string> transform = null)
private static void UpdateVendor(VendoredDependency dependency)
{
var libraryName = dependency.LibraryName;
var downloadUrl = dependency.DownloadUrl;
var pathToSrc = dependency.PathToSrc;

Console.WriteLine($"Starting {libraryName} upgrade.");

var zipLocation = Path.Combine(DownloadDirectory, $"{libraryName}.zip");
Expand Down Expand Up @@ -142,30 +103,27 @@ private static void UpdateVendor(
SafeDeleteDirectory(assemblyPropertiesFolder);
Console.WriteLine($"Deleted {libraryName} assembly properties file.");

if (transform != null)
{
Console.WriteLine($"Running transforms on files for {libraryName}.");
Console.WriteLine($"Running transforms on files for {libraryName}.");

var files = Directory.GetFiles(
sourceLocation,
"*.*",
SearchOption.AllDirectories);
var files = Directory.GetFiles(
sourceLocation,
"*.*",
SearchOption.AllDirectories);

foreach (var file in files)
foreach (var file in files)
{
if (ShouldDropFile(file))
{
if (ShouldDropFile(file))
{
File.Delete(file);
}
else
{
transform(file);
}
File.Delete(file);
}
else
{
dependency.Transform(file);
}

Console.WriteLine($"Finished transforms on files for {libraryName}.");
}

Console.WriteLine($"Finished transforms on files for {libraryName}.");

// Move it all to the vendors directory
Console.WriteLine($"Copying source of {libraryName} to vendor project.");
SafeDeleteDirectory(vendorFinalPath);
Expand All @@ -192,18 +150,6 @@ private static bool ShouldDropFile(string filePath)
return false;
}

private static void RewriteFileWithTransform(string filePath, Func<string, string> transform)
{
var fileContent = File.ReadAllText(filePath);
fileContent = transform(fileContent);
// Normalize text to use CRLF line endings so we have deterministic results
fileContent = fileContent.Replace("\r\n", "\n").Replace("\n", "\r\n");
File.WriteAllText(
filePath,
fileContent,
new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}

private static void InitializeCleanDirectory(string directoryPath)
{
SafeDeleteDirectory(directoryPath);
Expand Down
4 changes: 4 additions & 0 deletions tools/UpdateVendors/UpdateVendors.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\test\Datadog.Trace.TestHelpers\Datadog.Trace.TestHelpers.csproj" />
</ItemGroup>

</Project>
136 changes: 136 additions & 0 deletions tools/UpdateVendors/VendoredDependency.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace UpdateVendors
{
public class VendoredDependency
{
private const string AutoGeneratedMessage = @"//------------------------------------------------------------------------------
// <auto-generated />
// This file was automatically generated by the UpdateVendors tool.
//------------------------------------------------------------------------------
";

static VendoredDependency()
{
Add(
libraryName: "Serilog",
version: "2.8.0",
downloadUrl: "https://github.com/serilog/serilog/archive/v2.8.0.zip",
pathToSrc: new[] { "serilog-2.8.0", "src", "Serilog" },
transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Serilog"));

Add(
libraryName: "Serilog.Sinks.File",
version: "4.0.0",
downloadUrl: "https://github.com/serilog/serilog-sinks-file/archive/v4.0.0.zip",
pathToSrc: new[] { "serilog-sinks-file-4.0.0", "src", "Serilog.Sinks.File" },
transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Serilog"));

Add(
libraryName: "StatsdClient",
version: "6.0.0",
downloadUrl: "https://github.com/DataDog/dogstatsd-csharp-client/archive/6.0.0.zip",
pathToSrc: new[] { "dogstatsd-csharp-client-6.0.0", "src", "StatsdClient" },
transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "StatsdClient"));

Add(
libraryName: "MessagePack",
version: "1.9.3",
downloadUrl: "https://github.com/neuecc/MessagePack-CSharp/archive/v1.9.3.zip",
pathToSrc: new[] { "MessagePack-CSharp-1.9.3", "src", "MessagePack" },
transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "MessagePack"));

Add(
libraryName: "Newtonsoft.Json",
version: "12.0.1",
downloadUrl: "https://github.com/JamesNK/Newtonsoft.Json/archive/12.0.1.zip",
pathToSrc: new[] { "Newtonsoft.Json-12.0.1", "src", "Newtonsoft.Json" },
transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Newtonsoft.Json"));
}

public static List<VendoredDependency> All { get; set; } = new List<VendoredDependency>();

public string LibraryName { get; set; }

public string Version { get; set; }

public string DownloadUrl { get; set; }

public string[] PathToSrc { get; set; }

public Action<string> Transform { get; set; }

private static void Add(
string libraryName,
string version,
string downloadUrl,
string[] pathToSrc,
Action<string> transform)
{
All.Add(new VendoredDependency()
{
LibraryName = libraryName,
Version = version,
DownloadUrl = downloadUrl,
PathToSrc = pathToSrc,
Transform = transform,
});
}

private static void RewriteCsFileWithStandardTransform(string filePath, string originalNamespace, Func<string, string, string> extraTransform = null)
{
if (string.Equals(Path.GetExtension(filePath), ".cs", StringComparison.OrdinalIgnoreCase))
{
RewriteFileWithTransform(
filePath,
content =>
{
// Disable analyzer
var builder = new StringBuilder(AutoGeneratedMessage, content.Length * 2);

builder.Append(content);

// Special Newtonsoft.Json processing
if (originalNamespace.Equals("Newtonsoft.Json"))
{
builder.Replace($"using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs", "using ErrorEventArgs = Datadog.Trace.Vendors.Newtonsoft.Json.Serialization.ErrorEventArgs");

if (content.Contains("using Newtonsoft.Json.Serialization;"))
{
builder.Replace($"Func<", $"System.Func<");
builder.Replace($"Action<", $"System.Action<");
}
}

// Prevent namespace conflicts
builder.Replace($"using {originalNamespace}", $"using Datadog.Trace.Vendors.{originalNamespace}");
builder.Replace($"namespace {originalNamespace}", $"namespace Datadog.Trace.Vendors.{originalNamespace}");
builder.Replace($"[CLSCompliant(false)]", $"// [CLSCompliant(false)]");

// Don't expose anything we don't intend to
// by replacing all "public" access modifiers with "internal"
return Regex.Replace(
builder.ToString(),
@"public(\s+((abstract|sealed|static)\s+)?(partial\s+)?(class|readonly\s+struct|struct|interface|enum|delegate))",
match => $"internal{match.Groups[1]}");
});
}
}

private static void RewriteFileWithTransform(string filePath, Func<string, string> transform)
{
var fileContent = File.ReadAllText(filePath);
fileContent = transform(fileContent);
// Normalize text to use CRLF line endings so we have deterministic results
fileContent = fileContent.Replace("\r\n", "\n").Replace("\n", "\r\n");
File.WriteAllText(
filePath,
fileContent,
new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
}
}