Single attestation when creating VSA

This commit is contained in:
James Carnegie
2024-07-07 22:34:34 +01:00
parent a4c3bd07fe
commit c3ece3f02d
17 changed files with 433 additions and 188 deletions

View File

@@ -29,15 +29,15 @@ func GetAttestationManifestsFromIndex(index v1.ImageIndex) ([]*AttestationManife
}
var attestationManifests []*AttestationManifest
for _, manifest := range idx.Manifests {
if manifest.Annotations[DockerReferenceType] == AttestationManifestType {
subject := subjects[manifest.Annotations[DockerReferenceDigest]]
for _, desc := range idx.Manifests {
if desc.Annotations[DockerReferenceType] == AttestationManifestType {
subject := subjects[desc.Annotations[DockerReferenceDigest]]
if subject == nil {
return nil, fmt.Errorf("failed to find subject for attestation manifest: %w", err)
}
attestationImage, err := index.Image(manifest.Digest)
attestationImage, err := index.Image(desc.Digest)
if err != nil {
return nil, fmt.Errorf("failed to extract attestation image with digest %s: %w", manifest.Digest.String(), err)
return nil, fmt.Errorf("failed to extract attestation image with digest %s: %w", desc.Digest.String(), err)
}
attestationLayers, err := GetAttestationsFromImage(attestationImage)
if err != nil {
@@ -45,14 +45,11 @@ func GetAttestationManifestsFromIndex(index v1.ImageIndex) ([]*AttestationManife
}
attestationManifests = append(attestationManifests,
&AttestationManifest{
Descriptor: &manifest,
SubjectDescriptor: subject,
Attestation: &AttestationImage{
Layers: attestationLayers,
Image: attestationImage},
MediaType: manifest.MediaType,
Annotations: manifest.Annotations,
Digest: manifest.Digest})
OriginalDescriptor: &desc,
SubjectDescriptor: subject,
AttestationImage: &AttestationImage{
Layers: attestationLayers,
Descriptor: &desc}})
}
}
return attestationManifests, nil
@@ -90,7 +87,7 @@ func GetAttestationsFromImage(image v1.Image) ([]*AttestationLayer, error) {
return nil, fmt.Errorf("failed to decode statement layer contents: %w", err)
}
}
attestationLayers = append(attestationLayers, &AttestationLayer{Layer: layer, MediaType: mt, Statement: stmt, Annotations: ann})
attestationLayers = append(attestationLayers, &AttestationLayer{Layer: layer, Statement: stmt, Annotations: ann})
}
return attestationLayers, nil
}
@@ -100,13 +97,7 @@ func (manifest *AttestationManifest) AddAttestation(ctx context.Context, signer
if err != nil {
return fmt.Errorf("failed to create signed layer: %w", err)
}
newImg, newDesc, err := addLayerToImage(manifest, layer, opts)
if err != nil {
return fmt.Errorf("failed to add signed layers to image: %w", err)
}
manifest.Attestation.Image = newImg
manifest.Descriptor = newDesc
return nil
return addLayerToImage(manifest, layer, opts)
}
func createSignedImageLayer(ctx context.Context, statement *intoto.Statement, signer dsse.SignerVerifier, opts *SigningOptions) (*AttestationLayer, error) {
@@ -127,7 +118,6 @@ func createSignedImageLayer(ctx context.Context, statement *intoto.Statement, si
}
return &AttestationLayer{
Statement: statement,
MediaType: types.MediaType(intoto.PayloadType),
Annotations: map[string]string{
InTotoPredicateType: statement.PredicateType,
InTotoReferenceLifecycleStage: LifecycleStageExperimental,
@@ -151,35 +141,27 @@ func SignInTotoStatement(ctx context.Context, statement *intoto.Statement, signe
func addLayerToImage(
manifest *AttestationManifest,
layer *AttestationLayer,
opts *SigningOptions) (v1.Image, *v1.Descriptor, error) {
opts *SigningOptions) error {
err := manifest.AddOrReplaceLayer(layer, opts)
if err != nil {
return nil, nil, fmt.Errorf("failed to add signed layers: %w", err)
return fmt.Errorf("failed to add signed layers: %w", err)
}
newImg := manifest.Attestation.Image
if !opts.SkipSubject {
newImg = mutate.Subject(newImg, *manifest.SubjectDescriptor).(v1.Image)
manifest.AttestationImage.Image = mutate.Subject(manifest.AttestationImage.Image, *manifest.SubjectDescriptor).(v1.Image)
}
newDesc, err := partial.Descriptor(newImg)
newDesc, err := partial.Descriptor(manifest.AttestationImage.Image)
if err != nil {
return nil, nil, fmt.Errorf("failed to get descriptor: %w", err)
return fmt.Errorf("failed to get descriptor: %w", err)
}
cf, err := manifest.Attestation.Image.ConfigFile()
if err != nil {
return nil, nil, fmt.Errorf("failed to get config file: %w", err)
newDesc.Platform = &v1.Platform{
Architecture: "unknown",
OS: "unknown",
}
newDesc.Platform = cf.Platform()
if newDesc.Platform == nil {
newDesc.Platform = &v1.Platform{
Architecture: "unknown",
OS: "unknown",
}
}
newDesc.MediaType = manifest.MediaType
newDesc.Annotations = manifest.Annotations
return newImg, newDesc, nil
newDesc.MediaType = manifest.OriginalDescriptor.MediaType
newDesc.Annotations = manifest.OriginalDescriptor.Annotations
manifest.AttestationImage.Descriptor = newDesc
return nil
}
// AddOrReplaceLayer adds signed layers to a new or existing attestation image
@@ -189,12 +171,13 @@ func (manifest *AttestationManifest) AddOrReplaceLayer(signedLayer *AttestationL
var err error
// always create a new image from all the layers
newImg := empty.Image
//TODO: maybe we don't need these anymore
newImg = mutate.Annotations(newImg, map[string]string{
DockerReferenceType: AttestationManifestType,
DockerReferenceDigest: manifest.SubjectDescriptor.Digest.String(),
}).(v1.Image)
newImg = mutate.MediaType(newImg, manifest.MediaType)
newImg = mutate.MediaType(newImg, manifest.OriginalDescriptor.MediaType)
newImg = mutate.ConfigMediaType(newImg, "application/vnd.oci.image.config.v1+json")
add := mutate.Addendum{
Layer: signedLayer.Layer,
@@ -204,23 +187,25 @@ func (manifest *AttestationManifest) AddOrReplaceLayer(signedLayer *AttestationL
if err != nil {
return fmt.Errorf("failed to add signed layer to image: %w", err)
}
layers := make([]*AttestationLayer, 0)
for _, layer := range manifest.Attestation.Layers {
if layer.Statement == signedLayer.Statement && opts.Replace {
newLayers := make([]*AttestationLayer, 0)
for _, existingLayer := range manifest.AttestationImage.Layers {
// if we're replacing, then we don't add it back in
if existingLayer.Statement == signedLayer.Statement && opts.Replace {
continue
}
// add original layer back in
add := mutate.Addendum{
Layer: layer.Layer,
Annotations: layer.Annotations,
Layer: existingLayer.Layer,
Annotations: existingLayer.Annotations,
}
newImg, err = mutate.Append(newImg, add)
layers = append(layers, layer)
newLayers = append(newLayers, existingLayer)
if err != nil {
return fmt.Errorf("failed to add layer to image: %w", err)
}
}
manifest.Attestation.Layers = append(layers, signedLayer)
manifest.Attestation.Image = newImg
manifest.AttestationImage.Layers = append(newLayers, signedLayer)
manifest.AttestationImage.Image = newImg
return nil
}
@@ -228,10 +213,10 @@ func AddImageToIndex(
idx v1.ImageIndex,
manifest *AttestationManifest,
) (v1.ImageIndex, error) {
idx = mutate.RemoveManifests(idx, match.Digests(manifest.Digest))
idx = mutate.RemoveManifests(idx, match.Digests(manifest.OriginalDescriptor.Digest))
idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
Add: manifest.Attestation.Image,
Descriptor: *manifest.Descriptor,
Add: manifest.AttestationImage.Image,
Descriptor: *manifest.AttestationImage.Descriptor,
})
return idx, nil
}