Skip to content

Commit 407ab0d

Browse files
github-actions[bot]dameng324baronfel
authored
[release/8.0.4xx] Add http prefix when docker config detect a insecure registry (#40905)
Co-authored-by: Dameng <[email protected]> Co-authored-by: Chet Husk <[email protected]>
1 parent 742f819 commit 407ab0d

File tree

3 files changed

+85
-5
lines changed

3 files changed

+85
-5
lines changed

src/Containers/Microsoft.NET.Build.Containers/ContainerHelpers.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Diagnostics.CodeAnalysis;
1010
#endif
1111
using System.Text;
12+
using System.Text.Json.Nodes;
1213
using System.Text.RegularExpressions;
1314
using Microsoft.NET.Build.Containers.Resources;
1415

@@ -143,13 +144,27 @@ internal static bool IsValidImageTag(string imageTag)
143144
return ReferenceParser.anchoredTagRegexp.IsMatch(imageTag);
144145
}
145146

147+
146148
/// <summary>
147149
/// Given an already-validated registry domain, this is our hueristic to determine what HTTP protocol should be used to interact with it.
150+
/// If the domain is localhost, we default to HTTP. Otherwise, we check the Docker config to see if the registry is marked as insecure.
148151
/// This is primarily for testing - in the real world almost all usage should be through HTTPS!
149152
/// </summary>
150153
internal static Uri TryExpandRegistryToUri(string alreadyValidatedDomain)
151154
{
152-
var prefix = alreadyValidatedDomain.StartsWith("localhost", StringComparison.Ordinal) ? "http" : "https";
155+
string prefix = "https";
156+
if (alreadyValidatedDomain.StartsWith("localhost", StringComparison.Ordinal))
157+
{
158+
prefix = "http";
159+
}
160+
161+
//check the docker config to see if the registry is marked as insecure
162+
else if (DockerCli.IsInsecureRegistry(alreadyValidatedDomain))
163+
{
164+
prefix = "http";
165+
}
166+
167+
153168
return new Uri($"{prefix}://{alreadyValidatedDomain}");
154169
}
155170

src/Containers/Microsoft.NET.Build.Containers/LocalDaemons/DockerCli.cs

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Diagnostics;
5+
#if NET
56
using System.Formats.Tar;
7+
#endif
68
using System.Text.Json;
79
using System.Text.Json.Nodes;
810
using Microsoft.DotNet.Cli.Utils;
@@ -12,7 +14,10 @@
1214
namespace Microsoft.NET.Build.Containers;
1315

1416
// Wraps the 'docker'/'podman' cli.
15-
internal sealed class DockerCli : ILocalRegistry
17+
internal sealed class DockerCli
18+
#if NET
19+
: ILocalRegistry
20+
#endif
1621
{
1722
public const string DockerCommand = "docker";
1823
public const string PodmanCommand = "podman";
@@ -21,7 +26,10 @@ internal sealed class DockerCli : ILocalRegistry
2126

2227
private readonly ILogger _logger;
2328
private string? _command;
29+
30+
#if NET
2431
private string? _fullCommandPath;
32+
#endif
2533

2634
public DockerCli(string? command, ILoggerFactory loggerFactory)
2735
{
@@ -53,6 +61,7 @@ private static string FindFullPathFromPath(string command)
5361
return command;
5462
}
5563

64+
#if NET
5665
private async ValueTask<string> FindFullCommandPath(CancellationToken cancellationToken)
5766
{
5867
if (_fullCommandPath != null)
@@ -162,6 +171,7 @@ public bool IsAvailable()
162171

163172
public string? GetCommand()
164173
=> GetCommandAsync(default).GetAwaiter().GetResult();
174+
#endif
165175

166176
/// <summary>
167177
/// Gets docker configuration.
@@ -183,7 +193,6 @@ internal static JsonDocument GetDockerConfig()
183193
dockerCommand.CaptureStdErr();
184194
CommandResult dockerCommandResult = dockerCommand.Execute();
185195

186-
187196
if (dockerCommandResult.ExitCode != 0)
188197
{
189198
throw new DockerLoadException(Resource.FormatString(
@@ -194,17 +203,68 @@ internal static JsonDocument GetDockerConfig()
194203
}
195204

196205
return JsonDocument.Parse(dockerCommandResult.StdOut);
197-
198-
199206
}
200207
catch (Exception e) when (e is not DockerLoadException)
201208
{
202209
throw new DockerLoadException(Resource.FormatString(nameof(Strings.DockerInfoFailed_Ex), e.Message));
203210
}
204211
}
212+
/// <summary>
213+
/// Checks if the registry is marked as insecure in the docker/podman config.
214+
/// </summary>
215+
/// <param name="registryDomain"></param>
216+
/// <returns></returns>
217+
public static bool IsInsecureRegistry(string registryDomain)
218+
{
219+
try
220+
{
221+
//check the docker config to see if the registry is marked as insecure
222+
var rootElement = GetDockerConfig().RootElement;
223+
224+
//for docker
225+
if (rootElement.TryGetProperty("RegistryConfig", out var registryConfig) && registryConfig.ValueKind == JsonValueKind.Object)
226+
{
227+
if (registryConfig.TryGetProperty("IndexConfigs", out var indexConfigs) && indexConfigs.ValueKind == JsonValueKind.Object)
228+
{
229+
foreach (var property in indexConfigs.EnumerateObject())
230+
{
231+
if (property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Secure", out var secure) && !secure.GetBoolean())
232+
{
233+
if (property.Name.Equals(registryDomain, StringComparison.Ordinal))
234+
{
235+
return true;
236+
}
237+
}
238+
}
239+
}
240+
}
241+
242+
//for podman
243+
if (rootElement.TryGetProperty("registries", out var registries) && registries.ValueKind == JsonValueKind.Object)
244+
{
245+
foreach (var property in registries.EnumerateObject())
246+
{
247+
if (property.Value.ValueKind == JsonValueKind.Object && property.Value.TryGetProperty("Insecure", out var insecure) && insecure.GetBoolean())
248+
{
249+
if (property.Name.Equals(registryDomain, StringComparison.Ordinal))
250+
{
251+
return true;
252+
}
253+
}
254+
}
255+
}
256+
return false;
257+
}
258+
catch (DockerLoadException)
259+
{
260+
//if docker load fails, we can't check the config so we assume the registry is secure
261+
return false;
262+
}
263+
}
205264

206265
private static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e) => throw new NotImplementedException();
207266

267+
#if NET
208268
public static async Task WriteImageToStreamAsync(BuiltImage image, SourceImageReference sourceReference, DestinationImageReference destinationReference, Stream imageStream, CancellationToken cancellationToken)
209269
{
210270
cancellationToken.ThrowIfCancellationRequested();
@@ -310,6 +370,7 @@ await Task.WhenAll(
310370

311371
return _command;
312372
}
373+
#endif
313374

314375
private static bool IsPodmanAlias()
315376
{
@@ -331,6 +392,7 @@ private static bool IsPodmanAlias()
331392
}
332393
}
333394

395+
#if NET
334396
private async Task<bool> TryRunVersionCommandAsync(string command, CancellationToken cancellationToken)
335397
{
336398
try
@@ -353,6 +415,7 @@ private async Task<bool> TryRunVersionCommandAsync(string command, CancellationT
353415
return false;
354416
}
355417
}
418+
#endif
356419

357420
public override string ToString()
358421
{

src/Containers/Microsoft.NET.Build.Containers/Microsoft.NET.Build.Containers.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
<Compile Remove="**/*.*" />
4545
<Compile Include="ReferenceParser.cs" />
4646
<Compile Include="KnownStrings.cs" />
47+
<Compile Include="DockerLoadException.cs" />
48+
<Compile Include="LocalDaemons/DockerCli.cs" />
4749
<Compile Include="Tasks/ParseContainerProperties.cs" />
4850
<Compile Include="Tasks/CreateNewImage.Interface.cs" />
4951
<Compile Include="Tasks/CreateNewImageToolTask.cs" />

0 commit comments

Comments
 (0)