Files
attest/README.md
2024-04-30 15:45:36 -05:00

4.1 KiB

attest

library to create, verify, and evaluate policy for attestations on container images

usage

signing attestations

  1. generate an image with intoto Statements (optional)

    docker buildx build <PATH TO DOCKERFILE> --sbom true --provenance true --output type=oci,tar=false,name=<REPO>:<TAG>,dest=<OUTPUT DIR>
    
  2. confgiure a dsse.SignerVerifier

    var signer dsse.SignerVerifier 
    signer, err = signerverifier.GetAWSSigner(cmd.Context(), aws_arn, aws_region)
    
  3. configure signing options

    opts := &attest.SigningOptions{
     	Replace: true, // replace unsigned intoto statements with signed intoto attestations, otherwise leave in place
         }
    
    • add Verification Summary Attestation (VSA) for all intoto attestations (optional)
      opts.VSAOptions = &attestation.VSAOptions{
      	BuildLevel: "SLSA_BUILD_LEVEL_" + slsaBuildLevel,
      	PolicyURI:  slsaPolicyUri,
      	VerifierID: slsaVerifierId,
          }
      
  4. load attestations

    • oci registry
      ref := "docker/attest:latest"
      att, err := oci.AttestationIndexFromRemote(ref)
      
    • local filepath
      path := "/test-image"
      att, err := oci.AttestationIndexFromPath(path)
      
  5. sign attestations

    signedImageIndex, err := attest.SignIndexAttestations(ctx, att, signer, opts)
    

    attest.SignedIndexAttestations() iterates over all attestation manifests in the image index and signs all intoto statements (optionally generates a VSA), returning a mutated ImageIndex with all intoto statements signed as attestations.

  6. save output (optional)

    • push to oci registry
      err = mirror.PushToRegistry(signedImageIndex, ref)
      
    • save to local filesystem
      idx := v1.ImageIndex(empty.Index)
      idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
      	Add: signedImageIndex,
      	Descriptor: v1.Descriptor{
      		Annotations: map[string]string{
      			oci.OciReferenceTarget: att.Name,
      		},
      	},
      })
      err = mirror.SaveAsOCILayout(idx, path)
      

verifying attestations

  1. create a TUF client

    • using OCI registry for TUF
      tufClient, err := tuf.NewTufClient(embed.DefaultRoot, "/.docker/tuf", "docker/tuf-metadata:latest", "docker/tuf-targets")
      
    • using HTTPS for TUF
      tufClient, err := tuf.NewTufClient(embed.DefaultRoot, "/.docker/tuf", "https://docker.github.io/tuf/metadata", "https://docker.github.io/tuf/targets")
      
  2. configure an attestation resolver

    • using OCI registry
      var resolver oci.AttestationResolver
      resolver = &oci.RegistryResolver{
      	Image:    image,    // path to image index in OCI registry containing image attestations (e.g. docker/nginx:latest)
      	Platform: platform, // platform of subject image (image that attestations are being verified against)
      }
      
    • using local OCI layout
      var resolver oci.AttestationResolver
      resolver = &oci.OCILayoutResolver{
      	Path:     path,     // file path to OCI layout containing image attestations (e.g. /myimage)
      	Platform: platform, // platform of subject image (image that attestations are being verified against)
      }
      
  3. configure policy options

    opts := &policy.PolicyOptions{
    	TufClient:       tufClient,
    	LocalTargetsDir: "/.docker/policy", // location to store policy files downloaded from TUF
    	LocalPolicyDir:  "", // overrides TUF policy for local policy files
    }
    
  4. verify attestations

    policy, err := attest.Verify(ctx, opts, resolver)
    if err != nil {
        return false // failed policy or attestation signature verification
    }
    if policy {
        return true // passed policy
    }
    return true // no policy for image
    

mirroring TUF repositories

TODO: write content for this outline

mirroring TUF metadata to OCI

delegated metadata

mirroring TUF targets to OCI

delegated targets

using go-tuf OCI registry client