53 lines
1.9 KiB
C#
53 lines
1.9 KiB
C#
using System.Text.RegularExpressions;
|
|
|
|
namespace StellaOps.Zastava.Webhook.Admission;
|
|
|
|
internal interface IImageDigestResolver
|
|
{
|
|
Task<ImageResolutionResult> ResolveAsync(string imageReference, CancellationToken cancellationToken);
|
|
}
|
|
|
|
internal sealed class ImageDigestResolver : IImageDigestResolver
|
|
{
|
|
private static readonly Regex DigestPattern = new(@"(?<algorithm>[a-z0-9_+.-]+):(?<digest>[a-f0-9]{32,})", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
|
|
|
public Task<ImageResolutionResult> ResolveAsync(string imageReference, CancellationToken cancellationToken)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(imageReference))
|
|
{
|
|
return Task.FromResult(ImageResolutionResult.CreateFailure(imageReference, "image.reference.empty"));
|
|
}
|
|
|
|
if (imageReference.Contains('@', StringComparison.Ordinal))
|
|
{
|
|
var digest = imageReference[(imageReference.IndexOf('@') + 1)..];
|
|
if (DigestPattern.IsMatch(digest))
|
|
{
|
|
return Task.FromResult(ImageResolutionResult.CreateSuccess(imageReference, digest));
|
|
}
|
|
|
|
return Task.FromResult(ImageResolutionResult.CreateFailure(imageReference, "image.reference.invalid_digest"));
|
|
}
|
|
|
|
if (DigestPattern.IsMatch(imageReference))
|
|
{
|
|
return Task.FromResult(ImageResolutionResult.CreateSuccess(imageReference, imageReference));
|
|
}
|
|
|
|
return Task.FromResult(ImageResolutionResult.CreateFailure(imageReference, "image.reference.tag_unresolved"));
|
|
}
|
|
}
|
|
|
|
internal sealed record ImageResolutionResult(
|
|
string Original,
|
|
string? ResolvedDigest,
|
|
bool Success,
|
|
string? FailureReason)
|
|
{
|
|
public static ImageResolutionResult CreateSuccess(string original, string digest)
|
|
=> new(original, digest, true, null);
|
|
|
|
public static ImageResolutionResult CreateFailure(string original, string reason)
|
|
=> new(original, null, false, reason);
|
|
}
|