diff --git a/src/Bicep.Core/Registry/AzureContainerRegistryManager.cs b/src/Bicep.Core/Registry/AzureContainerRegistryManager.cs index 69cd24143d7..12d2c2001cc 100644 --- a/src/Bicep.Core/Registry/AzureContainerRegistryManager.cs +++ b/src/Bicep.Core/Registry/AzureContainerRegistryManager.cs @@ -155,7 +155,9 @@ private static async Task DownloadManifestAndLayersAsync(IOci .Select(async layer => new OciArtifactLayer(layer.Digest, layer.MediaType, await PullLayerAsync(client, layer))); var layers = await Task.WhenAll(layerTasks); - var config = new OciArtifactLayer(deserializedManifest.Config.Digest, deserializedManifest.Config.MediaType, await PullLayerAsync(client, deserializedManifest.Config)); + var config = !deserializedManifest.Config.IsEmpty() ? + new OciArtifactLayer(deserializedManifest.Config.Digest, deserializedManifest.Config.MediaType, await PullLayerAsync(client, deserializedManifest.Config)) : + null; return deserializedManifest.ArtifactType switch { diff --git a/src/Bicep.Core/Registry/Oci/OciDescriptor.cs b/src/Bicep.Core/Registry/Oci/OciDescriptor.cs index b4cc65dcda5..dac49cab55f 100644 --- a/src/Bicep.Core/Registry/Oci/OciDescriptor.cs +++ b/src/Bicep.Core/Registry/Oci/OciDescriptor.cs @@ -56,5 +56,23 @@ public static string ComputeDigest(string algorithmIdentifier, BinaryData data, AlgorithmIdentifierSha512 => SHA512.Create(), _ => throw new NotImplementedException($"Unknown hash algorithm '{algorithm}'.") }; + + public bool IsEmpty() + { + if (Size == 0) + { + return true; + } + + if (Size == 2 && + OciArtifactReferenceFacts.DigestComparer.Equals(Digest, "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a")) + { + // This SHA is a special case - it refers to "{}" (empty object). + // See https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidance-for-an-empty-descriptor for more information. + return true; + } + + return false; + } } } diff --git a/src/Bicep.Core/Registry/Oci/OciProviderArtifactResult.cs b/src/Bicep.Core/Registry/Oci/OciProviderArtifactResult.cs index 6b9a0440c5d..febee76cee5 100644 --- a/src/Bicep.Core/Registry/Oci/OciProviderArtifactResult.cs +++ b/src/Bicep.Core/Registry/Oci/OciProviderArtifactResult.cs @@ -7,7 +7,7 @@ public class OciProviderArtifactResult : OciArtifactResult { private readonly OciArtifactLayer mainLayer; - public OciProviderArtifactResult(BinaryData manifestBits, string manifestDigest, IEnumerable layers, OciArtifactLayer config) : + public OciProviderArtifactResult(BinaryData manifestBits, string manifestDigest, IEnumerable layers, OciArtifactLayer? config) : base(manifestBits, manifestDigest, layers) { var manifest = this.Manifest; @@ -27,6 +27,6 @@ public OciProviderArtifactResult(BinaryData manifestBits, string manifestDigest, public override OciArtifactLayer GetMainLayer() => this.mainLayer; - public OciArtifactLayer Config { get; } + public OciArtifactLayer? Config { get; } } } diff --git a/src/Bicep.Core/Registry/OciArtifactRegistry.cs b/src/Bicep.Core/Registry/OciArtifactRegistry.cs index f2fb224ccb2..7e7f6664edd 100644 --- a/src/Bicep.Core/Registry/OciArtifactRegistry.cs +++ b/src/Bicep.Core/Registry/OciArtifactRegistry.cs @@ -402,7 +402,9 @@ protected override void WriteArtifactContentToCache(OciArtifactReference referen if (result is OciProviderArtifactResult providerArtifact) { - var config = JsonSerializer.Deserialize(providerArtifact.Config.Data, OciProvidersV1ConfigSerializationContext.Default.OciProvidersV1Config); + var config = providerArtifact.Config is {} ? + JsonSerializer.Deserialize(providerArtifact.Config.Data, OciProvidersV1ConfigSerializationContext.Default.OciProvidersV1Config) : + null; // if the artifact supports local deployment, fetch the provider binary if (config?.LocalDeployEnabled == true)