Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -143,13 +144,27 @@ internal static bool IsValidImageTag(string imageTag)
return ReferenceParser.anchoredTagRegexp.IsMatch(imageTag);
}


/// <summary>
/// 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!
/// </summary>
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";
}

//check the docker config to see if the registry is marked as insecure
else if (DockerCli.IsInsecureRegistry(alreadyValidatedDomain))
{
prefix = "http";
}


return new Uri($"{prefix}://{alreadyValidatedDomain}");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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";
Expand All @@ -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)
{
Expand Down Expand Up @@ -53,6 +61,7 @@ private static string FindFullPathFromPath(string command)
return command;
}

#if NET
private async ValueTask<string> FindFullCommandPath(CancellationToken cancellationToken)
{
if (_fullCommandPath != null)
Expand Down Expand Up @@ -164,6 +173,7 @@ public bool IsAvailable()

public string? GetCommand()
=> GetCommandAsync(default).GetAwaiter().GetResult();
#endif

/// <summary>
/// Gets docker configuration.
Expand All @@ -185,7 +195,6 @@ internal static JsonDocument GetDockerConfig()
dockerCommand.CaptureStdErr();
CommandResult dockerCommandResult = dockerCommand.Execute();


if (dockerCommandResult.ExitCode != 0)
{
throw new DockerLoadException(Resource.FormatString(
Expand All @@ -196,17 +205,68 @@ internal static JsonDocument GetDockerConfig()
}

return JsonDocument.Parse(dockerCommandResult.StdOut);


}
catch (Exception e) when (e is not DockerLoadException)
{
throw new DockerLoadException(Resource.FormatString(nameof(Strings.DockerInfoFailed_Ex), e.Message));
}
}
/// <summary>
/// Checks if the registry is marked as insecure in the docker/podman config.
/// </summary>
/// <param name="registryDomain"></param>
/// <returns></returns>
public static bool IsInsecureRegistry(string registryDomain)
{
try
{
//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;
}
catch (DockerLoadException)
{
//if docker load fails, we can't check the config so we assume the registry is secure
return false;
}
}

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();
Expand Down Expand Up @@ -312,6 +372,7 @@ await Task.WhenAll(

return _command;
}
#endif

private static bool IsPodmanAlias()
{
Expand All @@ -333,6 +394,7 @@ private static bool IsPodmanAlias()
}
}

#if NET
private async Task<bool> TryRunVersionCommandAsync(string command, CancellationToken cancellationToken)
{
try
Expand All @@ -355,6 +417,7 @@ private async Task<bool> TryRunVersionCommandAsync(string command, CancellationT
return false;
}
}
#endif

public override string ToString()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
<Compile Remove="**/*.*" />
<Compile Include="ReferenceParser.cs" />
<Compile Include="KnownStrings.cs" />
<Compile Include="DockerLoadException.cs" />
<Compile Include="LocalDaemons/DockerCli.cs" />
<Compile Include="Tasks/ParseContainerProperties.cs" />
<Compile Include="Tasks/CreateNewImage.Interface.cs" />
<Compile Include="Tasks/CreateNewImageToolTask.cs" />
Expand Down