diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs
new file mode 100644
index 000000000000..96ba3452cefe
--- /dev/null
+++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependabotProxy.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using Semmle.Util;
+using Semmle.Util.Logging;
+
+namespace Semmle.Extraction.CSharp.DependencyFetching
+{
+ internal class DependabotProxy
+ {
+ private readonly string? host;
+ private readonly string? port;
+ private readonly FileInfo? certFile;
+
+ ///
+ /// The full address of the Dependabot proxy, if available.
+ ///
+ internal readonly string? Address;
+
+ ///
+ /// Gets a value indicating whether a Dependabot proxy is configured.
+ ///
+ internal bool IsConfigured => !string.IsNullOrEmpty(this.Address);
+
+ internal DependabotProxy(TemporaryDirectory tempWorkingDirectory)
+ {
+ // Obtain and store the address of the Dependabot proxy, if available.
+ this.host = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyHost);
+ this.port = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyPort);
+
+ if (string.IsNullOrWhiteSpace(host) || string.IsNullOrWhiteSpace(port))
+ {
+ return;
+ }
+
+ this.Address = $"http://{this.host}:{this.port}";
+
+ // Obtain and store the proxy's certificate, if available.
+ var cert = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyCertificate);
+
+ if (string.IsNullOrWhiteSpace(cert))
+ {
+ return;
+ }
+
+ var certDirPath = new DirectoryInfo(Path.Join(tempWorkingDirectory.DirInfo.FullName, ".dependabot-proxy"));
+ Directory.CreateDirectory(certDirPath.FullName);
+
+ this.certFile = new FileInfo(Path.Join(certDirPath.FullName, "proxy.crt"));
+
+ using var writer = this.certFile.CreateText();
+ writer.Write(cert);
+ }
+
+ internal void ApplyProxy(ILogger logger, ProcessStartInfo startInfo)
+ {
+ // If the proxy isn't configured, we have nothing to do.
+ if (!this.IsConfigured) return;
+
+ logger.LogInfo($"Setting up Dependabot proxy at {this.Address}");
+
+ startInfo.EnvironmentVariables["HTTP_PROXY"] = this.Address;
+ startInfo.EnvironmentVariables["HTTPS_PROXY"] = this.Address;
+ startInfo.EnvironmentVariables["SSL_CERT_FILE"] = this.certFile?.FullName;
+ }
+ }
+}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNet.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNet.cs
index d0646ea921cf..860f60cd5390 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNet.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNet.cs
@@ -27,7 +27,7 @@ private DotNet(IDotNetCliInvoker dotnetCliInvoker, ILogger logger, TemporaryDire
Info();
}
- private DotNet(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory) : this(new DotNetCliInvoker(logger, Path.Combine(dotNetPath ?? string.Empty, "dotnet")), logger, tempWorkingDirectory) { }
+ private DotNet(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory) : this(new DotNetCliInvoker(logger, Path.Combine(dotNetPath ?? string.Empty, "dotnet"), tempWorkingDirectory), logger, tempWorkingDirectory) { }
internal static IDotNet Make(IDotNetCliInvoker dotnetCliInvoker, ILogger logger) => new DotNet(dotnetCliInvoker, logger);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNetCliInvoker.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNetCliInvoker.cs
index 4295cce67167..522d3e9ffd45 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNetCliInvoker.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNetCliInvoker.cs
@@ -12,12 +12,14 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
internal sealed class DotNetCliInvoker : IDotNetCliInvoker
{
private readonly ILogger logger;
+ private readonly DependabotProxy proxy;
public string Exec { get; }
- public DotNetCliInvoker(ILogger logger, string exec)
+ public DotNetCliInvoker(ILogger logger, string exec, TemporaryDirectory tempWorkingDirectory)
{
this.logger = logger;
+ this.proxy = new DependabotProxy(tempWorkingDirectory);
this.Exec = exec;
logger.LogInfo($"Using .NET CLI executable: '{Exec}'");
}
@@ -38,6 +40,10 @@ private ProcessStartInfo MakeDotnetStartInfo(string args, string? workingDirecto
startInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"] = "en";
startInfo.EnvironmentVariables["MSBUILDDISABLENODEREUSE"] = "1";
startInfo.EnvironmentVariables["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "true";
+
+ // Configure the proxy settings, if applicable.
+ this.proxy.ApplyProxy(this.logger, startInfo);
+
return startInfo;
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/EnvironmentVariableNames.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/EnvironmentVariableNames.cs
index 345cb43453fc..d825e5daeb03 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/EnvironmentVariableNames.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/EnvironmentVariableNames.cs
@@ -74,5 +74,20 @@ internal static class EnvironmentVariableNames
/// Specifies the location of the diagnostic directory.
///
public const string DiagnosticDir = "CODEQL_EXTRACTOR_CSHARP_DIAGNOSTIC_DIR";
+
+ ///
+ /// Specifies the hostname of the Dependabot proxy.
+ ///
+ public const string ProxyHost = "CODEQL_PROXY_HOST";
+
+ ///
+ /// Specifies the hostname of the Dependabot proxy.
+ ///
+ public const string ProxyPort = "CODEQL_PROXY_PORT";
+
+ ///
+ /// Contains the certificate used by the Dependabot proxy.
+ ///
+ public const string ProxyCertificate = "CODEQL_PROXY_CA_CERTIFICATE";
}
}