* Start of richer results from verification * Pull out VSA code from signing * Expose attestation signing fns * Add VSA test * Notes for policy result * Require separate policy for VSA creation * Load test signing key from tests * Return rich object from policy * Add result object schema and fix tests * Ensure example test runs * Remove data.yaml files from mock policies * Don't run example - TUF policy isn't compatible * Add attestation to manifests for all subjects * Ensure adding attestation doesn't touch statements * Don't export sign function * Remove attestations from VerificationResult * Change bool to Outcome enum in result * Use outputLayout directly * Make clearer that Outcome strings are for VSA * Return multiple SLSA levels from policy * Fix unmarshalling of policy-id (#39) * Rename function * Rename policy.VerificationResult -> policy.Result * Re-add test for canonical input --------- Co-authored-by: James Carnegie <james.carnegie@docker.com> Co-authored-by: James Carnegie <kipz@users.noreply.github.com>
69 lines
1.9 KiB
Go
69 lines
1.9 KiB
Go
package oci
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/google/go-containerregistry/pkg/authn"
|
|
"github.com/google/go-containerregistry/pkg/name"
|
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
|
"github.com/google/go-containerregistry/pkg/v1/layout"
|
|
"github.com/google/go-containerregistry/pkg/v1/remote"
|
|
)
|
|
|
|
const (
|
|
DockerReferenceDigest = "vnd.docker.reference.digest"
|
|
AttestationManifestType = "attestation-manifest"
|
|
InTotoPredicateType = "in-toto.io/predicate-type"
|
|
OciReferenceTarget = "org.opencontainers.image.ref.name"
|
|
)
|
|
|
|
type AttestationIndex struct {
|
|
Index v1.ImageIndex
|
|
Name string
|
|
}
|
|
|
|
func AttestationIndexFromPath(path string) (*AttestationIndex, error) {
|
|
wrapperIdx, err := layout.ImageIndexFromPath(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load image index: %w", err)
|
|
}
|
|
|
|
idxm, err := wrapperIdx.IndexManifest()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get digest: %w", err)
|
|
}
|
|
imageName := idxm.Manifests[0].Annotations[OciReferenceTarget]
|
|
idxDigest := idxm.Manifests[0].Digest
|
|
|
|
idx, err := wrapperIdx.ImageIndex(idxDigest)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to extract ImageIndex for digest %s: %w", idxDigest.String(), err)
|
|
}
|
|
return &AttestationIndex{
|
|
Index: idx,
|
|
Name: imageName,
|
|
}, nil
|
|
}
|
|
|
|
func AttestationIndexFromRemote(image string) (*AttestationIndex, error) {
|
|
ref, err := name.ParseReference(image)
|
|
if err != nil {
|
|
log.Fatalf("Failed to parse image name: %v", err)
|
|
}
|
|
// Get the authenticator from the default Docker keychain
|
|
auth, err := authn.DefaultKeychain.Resolve(ref.Context())
|
|
if err != nil {
|
|
log.Fatalf("Failed to get authenticator: %v", err)
|
|
}
|
|
// Pull the image from the registry
|
|
idx, err := remote.Index(ref, remote.WithAuth(auth))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to pull image %s: %w", image, err)
|
|
}
|
|
return &AttestationIndex{
|
|
Index: idx,
|
|
Name: image,
|
|
}, nil
|
|
}
|