diff --git a/NuGet.config b/NuGet.config index 36e0a24c0c43..13d42f0a00e7 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,11 +4,7 @@ - - - - - + @@ -23,11 +19,7 @@ - - - - - + @@ -44,16 +36,13 @@ + - - - - - + @@ -80,17 +69,14 @@ - - - - - + + @@ -103,11 +89,7 @@ - - - - - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index bfaa6069e072..62543c4a6cef 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -14,46 +14,46 @@ 60fbe5b3d89acb26ded4dbb02f456a52a8faa4b1 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 08338fcaa5c9b9a8190abb99222fed12aaba956c - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 08338fcaa5c9b9a8190abb99222fed12aaba956c - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 08338fcaa5c9b9a8190abb99222fed12aaba956c - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 08338fcaa5c9b9a8190abb99222fed12aaba956c - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 08338fcaa5c9b9a8190abb99222fed12aaba956c - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 08338fcaa5c9b9a8190abb99222fed12aaba956c - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 08338fcaa5c9b9a8190abb99222fed12aaba956c https://dev.azure.com/dnceng/internal/_git/dotnet-runtime 2aade6beb02ea367fd97c4070a4198802fe61c03 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 08338fcaa5c9b9a8190abb99222fed12aaba956c - + https://github.com/dotnet/emsdk - a64772f521c578bc9925578b1384d3a08a02d31d + e92f92efe5854b6fe013787830b59166cb9b4ed9 https://github.com/dotnet/msbuild @@ -111,13 +111,13 @@ https://github.com/dotnet/roslyn 1c559959e2b25fea517c6f89d0c363698421865d - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 https://github.com/nuget/nuget.client @@ -200,9 +200,9 @@ https://github.com/microsoft/vstest c4d80397805bec06b354d20aeb1773e243c6add0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 08338fcaa5c9b9a8190abb99222fed12aaba956c https://dev.azure.com/dnceng/internal/_git/dotnet-runtime @@ -224,70 +224,70 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime 5535e31a712343a63f5d7d796cd874e563e5ac14 - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 28ae95bc8703be1ebc194391b03b6477cf59bed2 + 1526afd4eae1d862d586402ef8e005151a919d52 - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 28ae95bc8703be1ebc194391b03b6477cf59bed2 + 1526afd4eae1d862d586402ef8e005151a919d52 - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 28ae95bc8703be1ebc194391b03b6477cf59bed2 + 1526afd4eae1d862d586402ef8e005151a919d52 - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 28ae95bc8703be1ebc194391b03b6477cf59bed2 + 1526afd4eae1d862d586402ef8e005151a919d52 - + https://dev.azure.com/dnceng/internal/_git/dotnet-wpf - 43bb8cc831c2658e1117415019264bfe6f644f94 + 883fc207bb50622d4458ff09ae6a62548783826a - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 https://github.com/dotnet/razor @@ -302,21 +302,21 @@ https://github.com/dotnet/razor b5c4983ae50d899cac4847531295feafa5e442b2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 https://github.com/dotnet/xdt @@ -433,9 +433,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime 5535e31a712343a63f5d7d796cd874e563e5ac14 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 2f1db20456007c9515068a35a65afdf99af70bc6 + 954f61dd38b33caa2b736c73530bd5a294174437 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime diff --git a/eng/Versions.props b/eng/Versions.props index 08593f4c1fa5..68eb4e694e50 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -51,22 +51,22 @@ - 8.0.7 - 8.0.7-servicing.24313.11 - 8.0.7 + 8.0.8 + 8.0.8-servicing.24366.12 + 8.0.8 $(MicrosoftNETCoreAppRuntimewinx64PackageVersion) 8.0.1 - 8.0.7 - 8.0.7-servicing.24313.11 + 8.0.8 + 8.0.8-servicing.24366.12 8.0.0 $(MicrosoftExtensionsDependencyModelPackageVersion) 8.0.0 8.0.1 8.0.0 - 8.0.7 + 8.0.8 8.0.0 8.0.0 - 8.0.7 + 8.0.8 8.0.0 8.0.0 8.0.0 @@ -168,13 +168,13 @@ - 8.0.7 - 8.0.7-servicing.24314.2 - 8.0.7-servicing.24314.2 - 8.0.7-servicing.24314.2 - 8.0.7-servicing.24314.2 - 8.0.7-servicing.24314.2 - 8.0.7 + 8.0.8 + 8.0.8-servicing.24369.8 + 8.0.8-servicing.24369.8 + 8.0.8-servicing.24369.8 + 8.0.8-servicing.24369.8 + 8.0.8-servicing.24369.8 + 8.0.8 @@ -184,7 +184,7 @@ - 8.0.7-servicing.24313.7 + 8.0.8-servicing.24366.7 @@ -228,7 +228,7 @@ - 8.0.7 + 8.0.8 $(MicrosoftNETWorkloadEmscriptenCurrentManifest80100PackageVersion) 8.0.100$([System.Text.RegularExpressions.Regex]::Match($(EmscriptenWorkloadManifestVersion), `-rtm|-[A-z]*\.*\d*`)) diff --git a/src/Containers/Microsoft.NET.Build.Containers/AuthHandshakeMessageHandler.cs b/src/Containers/Microsoft.NET.Build.Containers/AuthHandshakeMessageHandler.cs index 10ff6c46a554..4751d450a9bc 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/AuthHandshakeMessageHandler.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/AuthHandshakeMessageHandler.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Concurrent; +using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Net; @@ -38,12 +39,14 @@ private sealed record AuthInfo(string Realm, string? Service, string? Scope); private readonly string _registryName; private readonly ILogger _logger; + private readonly RegistryMode _registryMode; private static ConcurrentDictionary _authenticationHeaders = new(); - public AuthHandshakeMessageHandler(string registryName, HttpMessageHandler innerHandler, ILogger logger) : base(innerHandler) + public AuthHandshakeMessageHandler(string registryName, HttpMessageHandler innerHandler, ILogger logger, RegistryMode mode) : base(innerHandler) { _registryName = registryName; _logger = logger; + _registryMode = mode; } /// @@ -157,8 +160,7 @@ public DateTimeOffset ResolvedExpiration private async Task<(AuthenticationHeaderValue, DateTimeOffset)?> GetAuthenticationAsync(string registry, string scheme, AuthInfo? bearerAuthInfo, CancellationToken cancellationToken) { // Allow overrides for auth via environment variables - string? credU = Environment.GetEnvironmentVariable(ContainerHelpers.HostObjectUser); - string? credP = Environment.GetEnvironmentVariable(ContainerHelpers.HostObjectPass); + (string? credU, string? credP) = GetDockerCredentialsFromEnvironment(_registryMode); // fetch creds for the host DockerCredentials? privateRepoCreds; @@ -196,6 +198,50 @@ public DateTimeOffset ResolvedExpiration } } + /// + /// Gets docker credentials from the environment variables based on registry mode. + /// + internal static (string? credU, string? credP) GetDockerCredentialsFromEnvironment(RegistryMode mode) + { + if (mode == RegistryMode.Push) + { + string? credU = Environment.GetEnvironmentVariable(ContainerHelpers.PushHostObjectUser); + string? credP = Environment.GetEnvironmentVariable(ContainerHelpers.PushHostObjectPass); + + if (string.IsNullOrEmpty(credU) || string.IsNullOrEmpty(credP)) + { + // Fallback to the old environment variables + return (Environment.GetEnvironmentVariable(ContainerHelpers.HostObjectUser), + Environment.GetEnvironmentVariable(ContainerHelpers.HostObjectPass)); + } + + return (credU, credP); + } + else if (mode == RegistryMode.Pull) + { + return (Environment.GetEnvironmentVariable(ContainerHelpers.PullHostObjectUser), + Environment.GetEnvironmentVariable(ContainerHelpers.PullHostObjectPass)); + } + else if (mode == RegistryMode.PullFromOutput) + { + string? credU = Environment.GetEnvironmentVariable(ContainerHelpers.PullHostObjectUser); + string? credP = Environment.GetEnvironmentVariable(ContainerHelpers.PullHostObjectPass); + + if (string.IsNullOrEmpty(credU) || string.IsNullOrEmpty(credP)) + { + // Fallback to the old environment variables + return (Environment.GetEnvironmentVariable(ContainerHelpers.HostObjectUser), + Environment.GetEnvironmentVariable(ContainerHelpers.HostObjectPass)); + } + + return (credU, credP); + } + else + { + throw new InvalidEnumArgumentException(nameof(mode), (int)mode, typeof(RegistryMode)); + } + } + /// /// Implements the Docker OAuth2 Authentication flow as documented at . /// ContainerizeAsync( logger.LogTrace("Trace logging: enabled."); bool isLocalPull = string.IsNullOrEmpty(baseRegistry); - Registry? sourceRegistry = isLocalPull ? null : new Registry(baseRegistry, logger); + RegistryMode sourceRegistryMode = baseRegistry.Equals(outputRegistry, StringComparison.InvariantCultureIgnoreCase) ? RegistryMode.PullFromOutput : RegistryMode.Pull; + Registry? sourceRegistry = isLocalPull ? null : new Registry(baseRegistry, logger, sourceRegistryMode); SourceImageReference sourceImageReference = new(sourceRegistry, baseImageName, baseImageTag); DestinationImageReference destinationImageReference = DestinationImageReference.CreateFromSettings( diff --git a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs index 5706c6171b5c..244ebd6cc9e4 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs @@ -16,9 +16,14 @@ namespace Microsoft.NET.Build.Containers; public static class ContainerHelpers { internal const string HostObjectUser = "SDK_CONTAINER_REGISTRY_UNAME"; - internal const string HostObjectPass = "SDK_CONTAINER_REGISTRY_PWORD"; + internal const string PushHostObjectUser = "SDK_CONTAINER_PUSH_REGISTRY_UNAME"; + internal const string PushHostObjectPass = "SDK_CONTAINER_PUSH_REGISTRY_PWORD"; + + internal const string PullHostObjectUser = "SDK_CONTAINER_PULL_REGISTRY_UNAME"; + internal const string PullHostObjectPass = "SDK_CONTAINER_PULL_REGISTRY_PWORD"; + internal const string DockerRegistryAlias = "docker.io"; /// diff --git a/src/Containers/Microsoft.NET.Build.Containers/DestinationImageReference.cs b/src/Containers/Microsoft.NET.Build.Containers/DestinationImageReference.cs index 46eb30ebc338..b885d791166b 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/DestinationImageReference.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/DestinationImageReference.cs @@ -75,7 +75,10 @@ public static DestinationImageReference CreateFromSettings( } else if (!string.IsNullOrEmpty(outputRegistry)) { - destinationImageReference = new DestinationImageReference(new Registry(outputRegistry, loggerFactory.CreateLogger()), repository, imageTags); + destinationImageReference = new DestinationImageReference( + new Registry(outputRegistry, loggerFactory.CreateLogger(), RegistryMode.Push), + repository, + imageTags); } else { diff --git a/src/Containers/Microsoft.NET.Build.Containers/Registry/DefaultRegistryAPI.cs b/src/Containers/Microsoft.NET.Build.Containers/Registry/DefaultRegistryAPI.cs index 885879b29b07..015ea7d535de 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Registry/DefaultRegistryAPI.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/Registry/DefaultRegistryAPI.cs @@ -22,12 +22,12 @@ internal class DefaultRegistryAPI : IRegistryAPI // Making this a round 30 for convenience. private static TimeSpan LongRequestTimeout = TimeSpan.FromMinutes(30); - internal DefaultRegistryAPI(string registryName, Uri baseUri, ILogger logger) + internal DefaultRegistryAPI(string registryName, Uri baseUri, ILogger logger, RegistryMode mode) { bool isAmazonECRRegistry = baseUri.IsAmazonECRRegistry(); _baseUri = baseUri; _logger = logger; - _client = CreateClient(registryName, baseUri, logger, isAmazonECRRegistry); + _client = CreateClient(registryName, baseUri, logger, isAmazonECRRegistry, mode); Manifest = new DefaultManifestOperations(_baseUri, registryName, _client, _logger); Blob = new DefaultBlobOperations(_baseUri, registryName, _client, _logger); } @@ -36,7 +36,7 @@ internal DefaultRegistryAPI(string registryName, Uri baseUri, ILogger logger) public IManifestOperations Manifest { get; } - private static HttpClient CreateClient(string registryName, Uri baseUri, ILogger logger, bool isAmazonECRRegistry = false) + private static HttpClient CreateClient(string registryName, Uri baseUri, ILogger logger, bool isAmazonECRRegistry, RegistryMode mode) { var innerHandler = new SocketsHttpHandler() { @@ -55,7 +55,7 @@ private static HttpClient CreateClient(string registryName, Uri baseUri, ILogger }; } - HttpMessageHandler clientHandler = new AuthHandshakeMessageHandler(registryName, innerHandler, logger); + HttpMessageHandler clientHandler = new AuthHandshakeMessageHandler(registryName, innerHandler, logger, mode); if (isAmazonECRRegistry) { diff --git a/src/Containers/Microsoft.NET.Build.Containers/Registry/Registry.cs b/src/Containers/Microsoft.NET.Build.Containers/Registry/Registry.cs index 21ba5d8c9271..87f1069de75d 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Registry/Registry.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/Registry/Registry.cs @@ -53,6 +53,13 @@ public RidGraphManifestPicker(string runtimeIdentifierGraphPath) } +internal enum RegistryMode +{ + Push, + Pull, + PullFromOutput +} + internal sealed class Registry { private const string DockerHubRegistry1 = "registry-1.docker.io"; @@ -70,11 +77,23 @@ internal sealed class Registry /// public string RegistryName { get; } - internal Registry(string registryName, ILogger logger, IRegistryAPI? registryAPI = null, RegistrySettings? settings = null) : - this(ContainerHelpers.TryExpandRegistryToUri(registryName), logger, registryAPI, settings) + internal Registry(string registryName, ILogger logger, RegistryMode mode, RegistrySettings? settings = null) : this( + ContainerHelpers.TryExpandRegistryToUri(registryName), logger, new RegistryApiFactory(mode), settings) { } - internal Registry(Uri baseUri, ILogger logger, IRegistryAPI? registryAPI = null, RegistrySettings? settings = null) + internal Registry(string registryName, ILogger logger, IRegistryAPI registryAPI, RegistrySettings? settings = null) : this( + ContainerHelpers.TryExpandRegistryToUri(registryName), logger, new RegistryApiFactory(registryAPI), settings) + { } + + internal Registry(Uri baseUri, ILogger logger, IRegistryAPI registryAPI, RegistrySettings? settings = null) : + this(baseUri, logger, new RegistryApiFactory(registryAPI), settings) + { } + + internal Registry(Uri baseUri, ILogger logger, RegistryMode mode, RegistrySettings? settings = null) : + this(baseUri, logger, new RegistryApiFactory(mode), settings) + { } + + private Registry(Uri baseUri, ILogger logger, RegistryApiFactory factory, RegistrySettings? settings = null) { RegistryName = DeriveRegistryName(baseUri); @@ -87,7 +106,7 @@ internal Registry(Uri baseUri, ILogger logger, IRegistryAPI? registryAPI = null, _logger = logger; _settings = settings ?? new RegistrySettings(); - _registryAPI = registryAPI ?? new DefaultRegistryAPI(RegistryName, BaseUri, logger); + _registryAPI = factory.Create(RegistryName, BaseUri, logger); } private static string DeriveRegistryName(Uri baseUri) @@ -500,4 +519,25 @@ private async Task PushAsync(BuiltImage builtImage, SourceImageReference source, _logger.LogInformation(Strings.Registry_ManifestUploaded, RegistryName); } } + + private readonly ref struct RegistryApiFactory + { + private readonly IRegistryAPI? _registryApi; + private readonly RegistryMode? _mode; + + public RegistryApiFactory(IRegistryAPI registryApi) + { + _registryApi = registryApi; + } + + public RegistryApiFactory(RegistryMode mode) + { + _mode = mode; + } + + public IRegistryAPI Create(string registryName, Uri baseUri, ILogger logger) + { + return _registryApi ?? new DefaultRegistryAPI(registryName, baseUri, logger, _mode!.Value); + } + } } diff --git a/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.cs b/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.cs index ced4b0646988..96eaa4e81df5 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.cs @@ -60,7 +60,8 @@ internal async Task ExecuteAsync(CancellationToken cancellationToken) return !Log.HasLoggedErrors; } - Registry? sourceRegistry = IsLocalPull ? null : new Registry(BaseRegistry, logger); + RegistryMode sourceRegistryMode = BaseRegistry.Equals(OutputRegistry, StringComparison.InvariantCultureIgnoreCase) ? RegistryMode.PullFromOutput : RegistryMode.Pull; + Registry? sourceRegistry = IsLocalPull ? null : new Registry(BaseRegistry, logger, sourceRegistryMode); SourceImageReference sourceImageReference = new(sourceRegistry, BaseImageName, BaseImageTag); DestinationImageReference destinationImageReference = DestinationImageReference.CreateFromSettings( diff --git a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/CreateNewImageTests.cs b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/CreateNewImageTests.cs index e9fe7898dff5..cf25db4b0309 100644 --- a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/CreateNewImageTests.cs +++ b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/CreateNewImageTests.cs @@ -225,7 +225,7 @@ public async System.Threading.Tasks.Task CreateNewImage_RootlessBaseImage() var logger = loggerFactory.CreateLogger(nameof(CreateNewImage_RootlessBaseImage)); // Build a rootless base runtime image. - Registry registry = new Registry(DockerRegistryManager.LocalRegistry, logger); + Registry registry = new(DockerRegistryManager.LocalRegistry, logger, RegistryMode.Push); ImageBuilder imageBuilder = await registry.GetImageManifestAsync( DockerRegistryManager.RuntimeBaseImage, diff --git a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryManager.cs b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryManager.cs index 534a4a78056d..f6648123e6d9 100644 --- a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryManager.cs +++ b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryManager.cs @@ -43,8 +43,8 @@ public static async Task StartAndPopulateDockerRegistry(ITestOutputHelper testOu int spawnRegistryDelay = 1000; //ms StringBuilder failureReasons = new(); - var pullRegistry = new Registry(BaseImageSource, logger); - var pushRegistry = new Registry(LocalRegistry, logger); + var pullRegistry = new Registry(BaseImageSource, logger, RegistryMode.Pull); + var pushRegistry = new Registry(LocalRegistry, logger, RegistryMode.Push); for (int spawnRegistryAttempt = 1; spawnRegistryAttempt <= spawnRegistryMaxRetry; spawnRegistryAttempt++) { diff --git a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryTests.cs b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryTests.cs index 18638ee17b84..2066e986a2b5 100644 --- a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryTests.cs +++ b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryTests.cs @@ -22,7 +22,7 @@ public async Task GetFromRegistry() { var loggerFactory = new TestLoggerFactory(_testOutput); var logger = loggerFactory.CreateLogger(nameof(GetFromRegistry)); - Registry registry = new Registry(DockerRegistryManager.LocalRegistry, logger); + Registry registry = new(DockerRegistryManager.LocalRegistry, logger, RegistryMode.Push); var ridgraphfile = ToolsetUtils.GetRuntimeGraphFilePath(); // Don't need rid graph for local registry image pulls - since we're only pushing single image manifests (not manifest lists) @@ -73,9 +73,9 @@ public async Task WriteToPrivateBasicRegistry() // login to that registry ContainerCli.LoginCommand(_testOutput, "--username", "testuser", "--password", "testpassword", registryName).Execute().Should().Pass(); // push an image to that registry using username/password - Registry localAuthed = new Registry(new Uri($"https://{registryName}"), logger, settings: new() { ParallelUploadEnabled = false, ForceChunkedUpload = true }); + Registry localAuthed = new(new Uri($"https://{registryName}"), logger, RegistryMode.Push, settings: new() { ParallelUploadEnabled = false, ForceChunkedUpload = true }); var ridgraphfile = ToolsetUtils.GetRuntimeGraphFilePath(); - Registry mcr = new Registry(DockerRegistryManager.BaseImageSource, logger); + Registry mcr = new(DockerRegistryManager.BaseImageSource, logger, RegistryMode.Pull); var sourceImage = new SourceImageReference(mcr, DockerRegistryManager.RuntimeBaseImage, DockerRegistryManager.Net6ImageTag); var destinationImage = new DestinationImageReference(localAuthed, DockerRegistryManager.RuntimeBaseImage,new[] { DockerRegistryManager.Net6ImageTag }); diff --git a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs index 9dc7db0b6586..d78b88cc211b 100644 --- a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs +++ b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs @@ -46,7 +46,7 @@ public async Task ApiEndToEndWithRegistryPushAndPull() // Build the image - Registry registry = new Registry(DockerRegistryManager.LocalRegistry, logger); + Registry registry = new(DockerRegistryManager.LocalRegistry, logger, RegistryMode.Push); ImageBuilder imageBuilder = await registry.GetImageManifestAsync( DockerRegistryManager.RuntimeBaseImage, @@ -93,7 +93,7 @@ public async Task ApiEndToEndWithLocalLoad() // Build the image - Registry registry = new Registry(DockerRegistryManager.LocalRegistry, logger); + Registry registry = new(DockerRegistryManager.LocalRegistry, logger, RegistryMode.Push); ImageBuilder imageBuilder = await registry.GetImageManifestAsync( DockerRegistryManager.RuntimeBaseImage, @@ -134,7 +134,7 @@ public async Task ApiEndToEndWithArchiveWritingAndLoad() // Build the image - Registry registry = new Registry(DockerRegistryManager.LocalRegistry, logger); + Registry registry = new(DockerRegistryManager.LocalRegistry, logger, RegistryMode.Push); ImageBuilder imageBuilder = await registry.GetImageManifestAsync( DockerRegistryManager.RuntimeBaseImage, @@ -555,7 +555,7 @@ public async Task CanPackageForAllSupportedContainerRIDs(string dockerPlatform, string publishDirectory = BuildLocalApp(tfm: ToolsetInfo.CurrentTargetFramework, rid: rid); // Build the image - Registry registry = new(DockerRegistryManager.BaseImageSource, logger); + Registry registry = new(DockerRegistryManager.BaseImageSource, logger, RegistryMode.Push); var isWin = rid.StartsWith("win"); ImageBuilder? imageBuilder = await registry.GetImageManifestAsync( DockerRegistryManager.RuntimeBaseImage, diff --git a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/RegistryTests.cs b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/RegistryTests.cs index 0f58b21e98ec..814892354356 100644 --- a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/RegistryTests.cs +++ b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/RegistryTests.cs @@ -39,7 +39,7 @@ public async Task CanReadManifestFromRegistry(string fullyQualifiedContainerName containerTag ??= "latest"; ILogger logger = _loggerFactory.CreateLogger(nameof(CanReadManifestFromRegistry)); - Registry registry = new Registry(containerRegistry, logger); + Registry registry = new(containerRegistry, logger, RegistryMode.Pull); var ridgraphfile = ToolsetUtils.GetRuntimeGraphFilePath(); diff --git a/src/Tests/Microsoft.NET.Build.Containers.UnitTests/AuthHandshakeMessageHandlerTests.cs b/src/Tests/Microsoft.NET.Build.Containers.UnitTests/AuthHandshakeMessageHandlerTests.cs new file mode 100644 index 000000000000..a50b816bdb91 --- /dev/null +++ b/src/Tests/Microsoft.NET.Build.Containers.UnitTests/AuthHandshakeMessageHandlerTests.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.NET.Build.Containers.UnitTests +{ + public class AuthHandshakeMessageHandlerTests + { + [Theory] + [InlineData("SDK_CONTAINER_REGISTRY_UNAME", "SDK_CONTAINER_REGISTRY_PWORD", (int)RegistryMode.Push)] + [InlineData("SDK_CONTAINER_PUSH_REGISTRY_UNAME", "SDK_CONTAINER_PUSH_REGISTRY_PWORD", (int)RegistryMode.Push)] + [InlineData("SDK_CONTAINER_PULL_REGISTRY_UNAME", "SDK_CONTAINER_PULL_REGISTRY_PWORD", (int)RegistryMode.Pull)] + [InlineData("SDK_CONTAINER_PULL_REGISTRY_UNAME", "SDK_CONTAINER_PULL_REGISTRY_PWORD", (int)RegistryMode.PullFromOutput)] + [InlineData("SDK_CONTAINER_REGISTRY_UNAME", "SDK_CONTAINER_REGISTRY_PWORD", (int)RegistryMode.PullFromOutput)] + public void GetDockerCredentialsFromEnvironment_ReturnsCorrectValues(string unameVarName, string pwordVarName, int mode) + { + string? originalUnameValue = Environment.GetEnvironmentVariable(unameVarName); + string? originalPwordValue = Environment.GetEnvironmentVariable(pwordVarName); + + Environment.SetEnvironmentVariable(unameVarName, "uname"); + Environment.SetEnvironmentVariable(pwordVarName, "pword"); + + (string? credU, string? credP) = AuthHandshakeMessageHandler.GetDockerCredentialsFromEnvironment((RegistryMode)mode); + + Assert.Equal("uname", credU); + Assert.Equal("pword", credP); + + // restore env variable values + Environment.SetEnvironmentVariable(unameVarName, originalUnameValue); + Environment.SetEnvironmentVariable(pwordVarName, originalPwordValue); + } + } +} diff --git a/src/Tests/Microsoft.NET.Build.Containers.UnitTests/RegistryTests.cs b/src/Tests/Microsoft.NET.Build.Containers.UnitTests/RegistryTests.cs index 3c3fba3d2cd6..87f81f3b85e5 100644 --- a/src/Tests/Microsoft.NET.Build.Containers.UnitTests/RegistryTests.cs +++ b/src/Tests/Microsoft.NET.Build.Containers.UnitTests/RegistryTests.cs @@ -30,7 +30,7 @@ public void Dispose() public void CheckIfGoogleArtifactRegistry(string registryName, bool isECR) { ILogger logger = _loggerFactory.CreateLogger(nameof(CheckIfGoogleArtifactRegistry)); - Registry registry = new Registry(registryName, logger); + Registry registry = new(registryName, logger, RegistryMode.Push); Assert.Equal(isECR, registry.IsGoogleArtifactRegistry); } @@ -38,7 +38,7 @@ public void CheckIfGoogleArtifactRegistry(string registryName, bool isECR) public void DockerIoAlias() { ILogger logger = _loggerFactory.CreateLogger(nameof(DockerIoAlias)); - Registry registry = new Registry("docker.io", logger); + Registry registry = new("docker.io", logger, RegistryMode.Push); Assert.True(registry.IsDockerHub); Assert.Equal("docker.io", registry.RegistryName); Assert.Equal("registry-1.docker.io", registry.BaseUri.Host);