From 7ce8661619559d2d9145af15cc6b7647068c7f60 Mon Sep 17 00:00:00 2001
From: Dameng <313880747@qq.com>
Date: Thu, 28 Mar 2024 15:03:39 +0800
Subject: [PATCH 1/6] throw `DockerLoadException` when GetDockerConfig while
docker daemon is not running.
---
.../LocalDaemons/DockerCli.cs | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs b/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
index b7b0733ad52a..802477bd5af0 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
@@ -185,7 +185,6 @@ internal static JsonDocument GetDockerConfig()
dockerCommand.CaptureStdErr();
CommandResult dockerCommandResult = dockerCommand.Execute();
-
if (dockerCommandResult.ExitCode != 0)
{
throw new DockerLoadException(Resource.FormatString(
@@ -195,9 +194,17 @@ internal static JsonDocument GetDockerConfig()
dockerCommandResult.StdErr));
}
- return JsonDocument.Parse(dockerCommandResult.StdOut);
+ var result = JsonDocument.Parse(dockerCommandResult.StdOut);
+ if(result.RootElement.TryGetProperty("ID", out var id) ==false || string.IsNullOrWhiteSpace(id.GetString()))
+ {
+ var serverErrors = result.RootElement.TryGetProperty("ServerErrors",out var error)
+ ? string.Join(Environment.NewLine, error.EnumerateArray().Select(o=>o.GetString()))
+ : string.Empty;
+ throw new DockerLoadException(Resource.FormatString(nameof(Strings.DockerInfoFailed_Ex), serverErrors));
+ }
+ return result;
}
catch (Exception e) when (e is not DockerLoadException)
{
From e621b0ad7384700512e1cdf645a3cd5909564b81 Mon Sep 17 00:00:00 2001
From: Dameng <313880747@qq.com>
Date: Thu, 28 Mar 2024 15:07:24 +0800
Subject: [PATCH 2/6] add `http` prefix when docker config detect a insecure
registry
---
.../ContainerHelpers.cs | 29 ++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
index 3aac2935fe27..a8971ff103a5 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
@@ -9,6 +9,7 @@
using System.Diagnostics.CodeAnalysis;
#endif
using System.Text;
+using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
using Microsoft.NET.Build.Containers.Resources;
@@ -143,13 +144,39 @@ internal static bool IsValidImageTag(string imageTag)
return ReferenceParser.anchoredTagRegexp.IsMatch(imageTag);
}
+
///
/// Given an already-validated registry domain, this is our hueristic to determine what HTTP protocol should be used to interact with it.
+ /// If the domain is localhost, we default to HTTP. Otherwise, we check the Docker config to see if the registry is marked as insecure.
/// This is primarily for testing - in the real world almost all usage should be through HTTPS!
///
internal static Uri TryExpandRegistryToUri(string alreadyValidatedDomain)
{
- var prefix = alreadyValidatedDomain.StartsWith("localhost", StringComparison.Ordinal) ? "http" : "https";
+ string prefix = "https";
+ if (alreadyValidatedDomain.StartsWith("localhost", StringComparison.Ordinal))
+ {
+ prefix = "http";
+ }
+#if !NET472
+ //check the docker config to see if the registry is marked as insecure
+ if (DockerCli.GetDockerConfig().RootElement.TryGetProperty("RegistryConfig", out var registryConfig) && registryConfig.ValueKind == System.Text.Json.JsonValueKind.Object)
+ {
+ if(registryConfig.TryGetProperty("IndexConfigs",out var indexConfigs) && indexConfigs.ValueKind == System.Text.Json.JsonValueKind.Object){
+ foreach (var property in indexConfigs.EnumerateObject())
+ {
+ if(property.Value.ValueKind == System.Text.Json.JsonValueKind.Object && property.Value.TryGetProperty("Secure",out var secure) && !secure.GetBoolean())
+ {
+ if (property.Name.Equals(alreadyValidatedDomain,StringComparison.Ordinal))
+ {
+ prefix = "http";
+ break;
+ }
+ }
+ }
+ }
+ }
+#endif
+
return new Uri($"{prefix}://{alreadyValidatedDomain}");
}
From 3856a7741ffb55bdb10d30312dde4d1dfb2e6453 Mon Sep 17 00:00:00 2001
From: Dameng <313880747@qq.com>
Date: Fri, 29 Mar 2024 13:24:38 +0800
Subject: [PATCH 3/6] add IsInsecureRegistry; add podman support
---
.../ContainerHelpers.cs | 16 +-----
.../LocalDaemons/DockerCli.cs | 57 +++++++++++++++----
2 files changed, 47 insertions(+), 26 deletions(-)
diff --git a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
index a8971ff103a5..4d6764107891 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
@@ -159,21 +159,9 @@ internal static Uri TryExpandRegistryToUri(string alreadyValidatedDomain)
}
#if !NET472
//check the docker config to see if the registry is marked as insecure
- if (DockerCli.GetDockerConfig().RootElement.TryGetProperty("RegistryConfig", out var registryConfig) && registryConfig.ValueKind == System.Text.Json.JsonValueKind.Object)
+ else if (DockerCli.IsInsecureRegistry(alreadyValidatedDomain))
{
- if(registryConfig.TryGetProperty("IndexConfigs",out var indexConfigs) && indexConfigs.ValueKind == System.Text.Json.JsonValueKind.Object){
- foreach (var property in indexConfigs.EnumerateObject())
- {
- if(property.Value.ValueKind == System.Text.Json.JsonValueKind.Object && property.Value.TryGetProperty("Secure",out var secure) && !secure.GetBoolean())
- {
- if (property.Name.Equals(alreadyValidatedDomain,StringComparison.Ordinal))
- {
- prefix = "http";
- break;
- }
- }
- }
- }
+ prefix = "http";
}
#endif
diff --git a/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs b/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
index 802477bd5af0..930c9c386b5a 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
@@ -193,24 +193,57 @@ internal static JsonDocument GetDockerConfig()
dockerCommandResult.StdOut,
dockerCommandResult.StdErr));
}
-
-
- var result = JsonDocument.Parse(dockerCommandResult.StdOut);
- if(result.RootElement.TryGetProperty("ID", out var id) ==false || string.IsNullOrWhiteSpace(id.GetString()))
- {
- var serverErrors = result.RootElement.TryGetProperty("ServerErrors",out var error)
- ? string.Join(Environment.NewLine, error.EnumerateArray().Select(o=>o.GetString()))
- : string.Empty;
- throw new DockerLoadException(Resource.FormatString(nameof(Strings.DockerInfoFailed_Ex), serverErrors));
- }
-
- return result;
+
+ return JsonDocument.Parse(dockerCommandResult.StdOut);
}
catch (Exception e) when (e is not DockerLoadException)
{
throw new DockerLoadException(Resource.FormatString(nameof(Strings.DockerInfoFailed_Ex), e.Message));
}
}
+ ///
+ /// Checks if the registry is marked as insecure in the docker/podman config.
+ ///
+ ///
+ ///
+ public static bool IsInsecureRegistry(string registryDomain)
+ {
+ //check the docker config to see if the registry is marked as insecure
+ var rootElement = GetDockerConfig().RootElement;
+ //for docker
+ if (rootElement.TryGetProperty("RegistryConfig", out var registryConfig) && registryConfig.ValueKind == JsonValueKind.Object)
+ {
+ if(registryConfig.TryGetProperty("IndexConfigs",out var indexConfigs) && indexConfigs.ValueKind == JsonValueKind.Object)
+ {
+ foreach (var property in indexConfigs.EnumerateObject())
+ {
+ if(property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Secure",out var secure) && !secure.GetBoolean())
+ {
+ if (property.Name.Equals(registryDomain, StringComparison.Ordinal))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ //for podman
+ if(rootElement.TryGetProperty("registries",out var registries) && registries.ValueKind == JsonValueKind.Object)
+ {
+ foreach (var property in registries.EnumerateObject())
+ {
+ if(property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Insecure",out var insecure) && insecure.GetBoolean())
+ {
+ if (property.Name.Equals(registryDomain, StringComparison.Ordinal))
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
private static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e) => throw new NotImplementedException();
From 1cc85d7495accbf0c14f25c249b92e6bee1d3fea Mon Sep 17 00:00:00 2001
From: Dameng <313880747@qq.com>
Date: Fri, 29 Mar 2024 20:12:39 +0800
Subject: [PATCH 4/6] add available check before check is insecure.
---
.../Microsoft.NET.Build.Containers/ContainerHelpers.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
index 4d6764107891..97dfe78b1499 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
@@ -159,7 +159,7 @@ internal static Uri TryExpandRegistryToUri(string alreadyValidatedDomain)
}
#if !NET472
//check the docker config to see if the registry is marked as insecure
- else if (DockerCli.IsInsecureRegistry(alreadyValidatedDomain))
+ else if (DockerCli.IsAvailable() && DockerCli.IsInsecureRegistry(alreadyValidatedDomain))
{
prefix = "http";
}
From 03816b089f17fbf80151f5c96a24c7022af29783 Mon Sep 17 00:00:00 2001
From: Dameng <313880747@qq.com>
Date: Fri, 29 Mar 2024 20:20:46 +0800
Subject: [PATCH 5/6] fix stupid mistake.
---
.../ContainerHelpers.cs | 2 +-
.../LocalDaemons/DockerCli.cs | 47 +++++++++++--------
2 files changed, 29 insertions(+), 20 deletions(-)
diff --git a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
index 97dfe78b1499..4d6764107891 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
@@ -159,7 +159,7 @@ internal static Uri TryExpandRegistryToUri(string alreadyValidatedDomain)
}
#if !NET472
//check the docker config to see if the registry is marked as insecure
- else if (DockerCli.IsAvailable() && DockerCli.IsInsecureRegistry(alreadyValidatedDomain))
+ else if (DockerCli.IsInsecureRegistry(alreadyValidatedDomain))
{
prefix = "http";
}
diff --git a/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs b/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
index 930c9c386b5a..f67a3856df8d 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
@@ -208,41 +208,50 @@ internal static JsonDocument GetDockerConfig()
///
public static bool IsInsecureRegistry(string registryDomain)
{
- //check the docker config to see if the registry is marked as insecure
- var rootElement = GetDockerConfig().RootElement;
- //for docker
- if (rootElement.TryGetProperty("RegistryConfig", out var registryConfig) && registryConfig.ValueKind == JsonValueKind.Object)
+ try
{
- if(registryConfig.TryGetProperty("IndexConfigs",out var indexConfigs) && indexConfigs.ValueKind == JsonValueKind.Object)
+ //check the docker config to see if the registry is marked as insecure
+ var rootElement = GetDockerConfig().RootElement;
+
+ //for docker
+ if (rootElement.TryGetProperty("RegistryConfig", out var registryConfig) && registryConfig.ValueKind == JsonValueKind.Object)
{
- foreach (var property in indexConfigs.EnumerateObject())
+ if(registryConfig.TryGetProperty("IndexConfigs",out var indexConfigs) && indexConfigs.ValueKind == JsonValueKind.Object)
{
- if(property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Secure",out var secure) && !secure.GetBoolean())
+ foreach (var property in indexConfigs.EnumerateObject())
{
- if (property.Name.Equals(registryDomain, StringComparison.Ordinal))
+ if(property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Secure",out var secure) && !secure.GetBoolean())
{
- return true;
+ if (property.Name.Equals(registryDomain, StringComparison.Ordinal))
+ {
+ return true;
+ }
}
}
}
}
- }
- //for podman
- if(rootElement.TryGetProperty("registries",out var registries) && registries.ValueKind == JsonValueKind.Object)
- {
- foreach (var property in registries.EnumerateObject())
+
+ //for podman
+ if(rootElement.TryGetProperty("registries",out var registries) && registries.ValueKind == JsonValueKind.Object)
{
- if(property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Insecure",out var insecure) && insecure.GetBoolean())
+ foreach (var property in registries.EnumerateObject())
{
- if (property.Name.Equals(registryDomain, StringComparison.Ordinal))
+ if(property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Insecure",out var insecure) && insecure.GetBoolean())
{
- return true;
+ if (property.Name.Equals(registryDomain, StringComparison.Ordinal))
+ {
+ return true;
+ }
}
}
}
+ return false;
+ }
+ catch (DockerLoadException)
+ {
+ //if docker load fails, we can't check the config so we assume the registry is secure
+ return false;
}
-
- return false;
}
private static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e) => throw new NotImplementedException();
From 94dedc62fc3b22e8dca6db6221234f7dde6c7668 Mon Sep 17 00:00:00 2001
From: Chet Husk
Date: Fri, 12 Apr 2024 22:04:38 -0500
Subject: [PATCH 6/6] Add enough of DockerCli to be able to use it to check
insecure registries.
---
.../ContainerHelpers.cs | 4 +--
.../LocalDaemons/DockerCli.cs | 30 ++++++++++++++-----
.../Microsoft.NET.Build.Containers.csproj | 2 ++
3 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
index 4d6764107891..3324adff837a 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs
@@ -157,13 +157,13 @@ internal static Uri TryExpandRegistryToUri(string alreadyValidatedDomain)
{
prefix = "http";
}
-#if !NET472
+
//check the docker config to see if the registry is marked as insecure
else if (DockerCli.IsInsecureRegistry(alreadyValidatedDomain))
{
prefix = "http";
}
-#endif
+
return new Uri($"{prefix}://{alreadyValidatedDomain}");
}
diff --git a/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs b/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
index f67a3856df8d..fb0e09b87d5a 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs
@@ -2,7 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+#if NET
using System.Formats.Tar;
+#endif
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.DotNet.Cli.Utils;
@@ -12,7 +14,10 @@
namespace Microsoft.NET.Build.Containers;
// Wraps the 'docker'/'podman' cli.
-internal sealed class DockerCli : ILocalRegistry
+internal sealed class DockerCli
+#if NET
+: ILocalRegistry
+#endif
{
public const string DockerCommand = "docker";
public const string PodmanCommand = "podman";
@@ -21,7 +26,10 @@ internal sealed class DockerCli : ILocalRegistry
private readonly ILogger _logger;
private string? _command;
+
+#if NET
private string? _fullCommandPath;
+#endif
public DockerCli(string? command, ILoggerFactory loggerFactory)
{
@@ -53,6 +61,7 @@ private static string FindFullPathFromPath(string command)
return command;
}
+#if NET
private async ValueTask FindFullCommandPath(CancellationToken cancellationToken)
{
if (_fullCommandPath != null)
@@ -164,6 +173,7 @@ public bool IsAvailable()
public string? GetCommand()
=> GetCommandAsync(default).GetAwaiter().GetResult();
+#endif
///
/// Gets docker configuration.
@@ -193,7 +203,7 @@ internal static JsonDocument GetDockerConfig()
dockerCommandResult.StdOut,
dockerCommandResult.StdErr));
}
-
+
return JsonDocument.Parse(dockerCommandResult.StdOut);
}
catch (Exception e) when (e is not DockerLoadException)
@@ -208,7 +218,7 @@ internal static JsonDocument GetDockerConfig()
///
public static bool IsInsecureRegistry(string registryDomain)
{
- try
+ try
{
//check the docker config to see if the registry is marked as insecure
var rootElement = GetDockerConfig().RootElement;
@@ -216,11 +226,11 @@ public static bool IsInsecureRegistry(string registryDomain)
//for docker
if (rootElement.TryGetProperty("RegistryConfig", out var registryConfig) && registryConfig.ValueKind == JsonValueKind.Object)
{
- if(registryConfig.TryGetProperty("IndexConfigs",out var indexConfigs) && indexConfigs.ValueKind == JsonValueKind.Object)
+ if (registryConfig.TryGetProperty("IndexConfigs", out var indexConfigs) && indexConfigs.ValueKind == JsonValueKind.Object)
{
foreach (var property in indexConfigs.EnumerateObject())
{
- if(property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Secure",out var secure) && !secure.GetBoolean())
+ if (property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Secure", out var secure) && !secure.GetBoolean())
{
if (property.Name.Equals(registryDomain, StringComparison.Ordinal))
{
@@ -230,13 +240,13 @@ public static bool IsInsecureRegistry(string registryDomain)
}
}
}
-
+
//for podman
- if(rootElement.TryGetProperty("registries",out var registries) && registries.ValueKind == JsonValueKind.Object)
+ if (rootElement.TryGetProperty("registries", out var registries) && registries.ValueKind == JsonValueKind.Object)
{
foreach (var property in registries.EnumerateObject())
{
- if(property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Insecure",out var insecure) && insecure.GetBoolean())
+ if (property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Insecure", out var insecure) && insecure.GetBoolean())
{
if (property.Name.Equals(registryDomain, StringComparison.Ordinal))
{
@@ -256,6 +266,7 @@ public static bool IsInsecureRegistry(string registryDomain)
private static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e) => throw new NotImplementedException();
+#if NET
public static async Task WriteImageToStreamAsync(BuiltImage image, SourceImageReference sourceReference, DestinationImageReference destinationReference, Stream imageStream, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -361,6 +372,7 @@ await Task.WhenAll(
return _command;
}
+#endif
private static bool IsPodmanAlias()
{
@@ -382,6 +394,7 @@ private static bool IsPodmanAlias()
}
}
+#if NET
private async Task TryRunVersionCommandAsync(string command, CancellationToken cancellationToken)
{
try
@@ -404,6 +417,7 @@ private async Task TryRunVersionCommandAsync(string command, CancellationT
return false;
}
}
+#endif
public override string ToString()
{
diff --git a/src/Containers/Microsoft.NET.Build.Containers/Microsoft.NET.Build.Containers.csproj b/src/Containers/Microsoft.NET.Build.Containers/Microsoft.NET.Build.Containers.csproj
index 040677b24bf5..2c6b5818c1af 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/Microsoft.NET.Build.Containers.csproj
+++ b/src/Containers/Microsoft.NET.Build.Containers/Microsoft.NET.Build.Containers.csproj
@@ -43,6 +43,8 @@
+
+