using System; using System.Diagnostics; using System.IO; using System.Security.Cryptography.X509Certificates; using Semmle.Util; using Semmle.Util.Logging; namespace Semmle.Extraction.CSharp.DependencyFetching { public class DependabotProxy : IDisposable { private readonly string host; private readonly string port; /// /// The full address of the Dependabot proxy, if available. /// internal string Address { get; } /// /// The path to the temporary file where the certificate is stored. /// internal string? CertificatePath { get; private set; } /// /// The certificate used for the Dependabot proxy. /// internal X509Certificate2? Certificate { get; private set; } internal static DependabotProxy? GetDependabotProxy(ILogger logger, TemporaryDirectory tempWorkingDirectory) { // Setting HTTP(S)_PROXY and SSL_CERT_FILE have no effect on Windows or macOS, // but we would still end up using the Dependabot proxy to check for feed reachability. // This would result in us discovering that the feeds are reachable, but `dotnet` would // fail to connect to them. To prevent this from happening, we do not initialise an // instance of `DependabotProxy` on those platforms. if (SystemBuildActions.Instance.IsWindows() || SystemBuildActions.Instance.IsMacOs()) return null; // Obtain and store the address of the Dependabot proxy, if available. var host = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyHost); var port = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyPort); if (string.IsNullOrWhiteSpace(host) || string.IsNullOrWhiteSpace(port)) { logger.LogInfo("No Dependabot proxy credentials are configured."); return null; } var result = new DependabotProxy(host, port); logger.LogInfo($"Dependabot proxy configured at {result.Address}"); // Obtain and store the proxy's certificate, if available. var cert = Environment.GetEnvironmentVariable(EnvironmentVariableNames.ProxyCertificate); if (!string.IsNullOrWhiteSpace(cert)) { logger.LogInfo("No certificate configured for Dependabot proxy."); var certDirPath = new DirectoryInfo(Path.Join(tempWorkingDirectory.DirInfo.FullName, ".dependabot-proxy")); Directory.CreateDirectory(certDirPath.FullName); result.CertificatePath = Path.Join(certDirPath.FullName, "proxy.crt"); var certFile = new FileInfo(result.CertificatePath); using var writer = certFile.CreateText(); writer.Write(cert); writer.Close(); logger.LogInfo($"Stored Dependabot proxy certificate at {result.CertificatePath}"); result.Certificate = X509Certificate2.CreateFromPem(cert); } return result; } private DependabotProxy(string host, string port) { this.host = host; this.port = port; this.Address = $"http://{this.host}:{this.port}"; } public void Dispose() { this.Certificate?.Dispose(); } } }