fix: standardize casing of initialisms (#112)
* fix: standardize casing of initialisms * fix: rename intoto -> inToto and Intoto to InToto * fix: fix all linting errors
This commit is contained in:
@@ -17,19 +17,21 @@ import (
|
||||
"github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
)
|
||||
|
||||
// GetAttestationManifestsFromIndex extracts all attestation manifests from an index
|
||||
func GetAttestationManifestsFromIndex(index v1.ImageIndex) ([]*AttestationManifest, error) {
|
||||
// GetAttestationManifestsFromIndex extracts all attestation manifests from an index.
|
||||
func GetAttestationManifestsFromIndex(index v1.ImageIndex) ([]*Manifest, error) {
|
||||
idx, err := index.IndexManifest()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to extract IndexManifest from ImageIndex: %w", err)
|
||||
}
|
||||
subjects := make(map[string]*v1.Descriptor)
|
||||
for _, subject := range idx.Manifests {
|
||||
subjects[subject.Digest.String()] = &subject
|
||||
for i := range idx.Manifests {
|
||||
subject := &idx.Manifests[i]
|
||||
subjects[subject.Digest.String()] = subject
|
||||
}
|
||||
|
||||
var attestationManifests []*AttestationManifest
|
||||
for _, desc := range idx.Manifests {
|
||||
var attestationManifests []*Manifest
|
||||
for i := range idx.Manifests {
|
||||
desc := idx.Manifests[i]
|
||||
if desc.Annotations[DockerReferenceType] == AttestationManifestType {
|
||||
subject := subjects[desc.Annotations[DockerReferenceDigest]]
|
||||
if subject == nil {
|
||||
@@ -44,7 +46,7 @@ func GetAttestationManifestsFromIndex(index v1.ImageIndex) ([]*AttestationManife
|
||||
return nil, fmt.Errorf("failed to get attestations from image: %w", err)
|
||||
}
|
||||
attestationManifests = append(attestationManifests,
|
||||
&AttestationManifest{
|
||||
&Manifest{
|
||||
OriginalDescriptor: &desc,
|
||||
SubjectDescriptor: subject,
|
||||
OriginalLayers: attestationLayers,
|
||||
@@ -54,13 +56,13 @@ func GetAttestationManifestsFromIndex(index v1.ImageIndex) ([]*AttestationManife
|
||||
return attestationManifests, nil
|
||||
}
|
||||
|
||||
// GetAttestationsFromImage extracts all attestation layers from an image
|
||||
func GetAttestationsFromImage(image v1.Image) ([]*AttestationLayer, error) {
|
||||
// GetAttestationsFromImage extracts all attestation layers from an image.
|
||||
func GetAttestationsFromImage(image v1.Image) ([]*Layer, error) {
|
||||
layers, err := image.Layers()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to extract layers from image: %w", err)
|
||||
}
|
||||
var attestationLayers []*AttestationLayer
|
||||
var attestationLayers []*Layer
|
||||
for _, layer := range layers {
|
||||
// parse layer blob as json
|
||||
r, err := layer.Uncompressed()
|
||||
@@ -86,12 +88,12 @@ 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, Statement: stmt, Annotations: ann})
|
||||
attestationLayers = append(attestationLayers, &Layer{Layer: layer, Statement: stmt, Annotations: ann})
|
||||
}
|
||||
return attestationLayers, nil
|
||||
}
|
||||
|
||||
func (manifest *AttestationManifest) AddAttestation(ctx context.Context, signer dsse.SignerVerifier, statement *intoto.Statement, opts *SigningOptions) error {
|
||||
func (manifest *Manifest) AddAttestation(ctx context.Context, signer dsse.SignerVerifier, statement *intoto.Statement, opts *SigningOptions) error {
|
||||
layer, err := createSignedImageLayer(ctx, statement, signer, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create signed layer: %w", err)
|
||||
@@ -100,7 +102,7 @@ func (manifest *AttestationManifest) AddAttestation(ctx context.Context, signer
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSignedImageLayer(ctx context.Context, statement *intoto.Statement, signer dsse.SignerVerifier, opts *SigningOptions) (*AttestationLayer, error) {
|
||||
func createSignedImageLayer(ctx context.Context, statement *intoto.Statement, signer dsse.SignerVerifier, opts *SigningOptions) (*Layer, error) {
|
||||
// sign the statement
|
||||
env, err := SignInTotoStatement(ctx, statement, signer, opts)
|
||||
if err != nil {
|
||||
@@ -115,7 +117,7 @@ func createSignedImageLayer(ctx context.Context, statement *intoto.Statement, si
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal envelope: %w", err)
|
||||
}
|
||||
return &AttestationLayer{
|
||||
return &Layer{
|
||||
Statement: statement,
|
||||
Annotations: map[string]string{
|
||||
InTotoPredicateType: statement.PredicateType,
|
||||
@@ -139,8 +141,8 @@ func SignInTotoStatement(ctx context.Context, statement *intoto.Statement, signe
|
||||
|
||||
func UpdateIndexImage(
|
||||
idx v1.ImageIndex,
|
||||
manifest *AttestationManifest,
|
||||
options ...func(*AttestationManifestImageOptions) error,
|
||||
manifest *Manifest,
|
||||
options ...func(*ManifestImageOptions) error,
|
||||
) (v1.ImageIndex, error) {
|
||||
image, err := manifest.BuildAttestationImage(options...)
|
||||
if err != nil {
|
||||
@@ -164,7 +166,7 @@ func UpdateIndexImage(
|
||||
return idx, nil
|
||||
}
|
||||
|
||||
func UpdateIndexImages(idx v1.ImageIndex, manifest []*AttestationManifest, options ...func(*AttestationManifestImageOptions) error) (v1.ImageIndex, error) {
|
||||
func UpdateIndexImages(idx v1.ImageIndex, manifest []*Manifest, options ...func(*ManifestImageOptions) error) (v1.ImageIndex, error) {
|
||||
var err error
|
||||
for _, m := range manifest {
|
||||
idx, err = UpdateIndexImage(idx, m, options...)
|
||||
@@ -175,8 +177,8 @@ func UpdateIndexImages(idx v1.ImageIndex, manifest []*AttestationManifest, optio
|
||||
return idx, nil
|
||||
}
|
||||
|
||||
func newOptions(options ...func(*AttestationManifestImageOptions) error) (*AttestationManifestImageOptions, error) {
|
||||
opts := &AttestationManifestImageOptions{}
|
||||
func newOptions(options ...func(*ManifestImageOptions) error) (*ManifestImageOptions, error) {
|
||||
opts := &ManifestImageOptions{}
|
||||
for _, opt := range options {
|
||||
err := opt(opts)
|
||||
if err != nil {
|
||||
@@ -186,22 +188,22 @@ func newOptions(options ...func(*AttestationManifestImageOptions) error) (*Attes
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func WithoutSubject(skipSubject bool) func(*AttestationManifestImageOptions) error {
|
||||
return func(r *AttestationManifestImageOptions) error {
|
||||
func WithoutSubject(skipSubject bool) func(*ManifestImageOptions) error {
|
||||
return func(r *ManifestImageOptions) error {
|
||||
r.skipSubject = skipSubject
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithReplacedLayers(replaceLayers bool) func(*AttestationManifestImageOptions) error {
|
||||
return func(r *AttestationManifestImageOptions) error {
|
||||
func WithReplacedLayers(replaceLayers bool) func(*ManifestImageOptions) error {
|
||||
return func(r *ManifestImageOptions) error {
|
||||
r.replaceLayers = replaceLayers
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// build an image with signed attestations, optionally replacing existing layers with signed layers
|
||||
func (manifest *AttestationManifest) BuildAttestationImage(options ...func(*AttestationManifestImageOptions) error) (v1.Image, error) {
|
||||
// build an image with signed attestations, optionally replacing existing layers with signed layers.
|
||||
func (manifest *Manifest) BuildAttestationImage(options ...func(*ManifestImageOptions) error) (v1.Image, error) {
|
||||
opts, err := newOptions(options...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create options: %w", err)
|
||||
@@ -224,7 +226,7 @@ func (manifest *AttestationManifest) BuildAttestationImage(options ...func(*Atte
|
||||
resultLayers = append(resultLayers, existingLayer)
|
||||
}
|
||||
}
|
||||
// so taht we attach all attestations to a single attestations image - as per current buildkit
|
||||
// so that we attach all attestations to a single attestations image - as per current buildkit
|
||||
opts.laxReferrers = true
|
||||
newImg, err := buildImage(resultLayers, manifest.OriginalDescriptor, manifest.SubjectDescriptor, opts)
|
||||
if err != nil {
|
||||
@@ -233,12 +235,12 @@ func (manifest *AttestationManifest) BuildAttestationImage(options ...func(*Atte
|
||||
return newImg, nil
|
||||
}
|
||||
|
||||
// build an image per attestation (layer) suitable for use as Referrers
|
||||
func (manifest *AttestationManifest) BuildReferringArtifacts() ([]v1.Image, error) {
|
||||
// build an image per attestation (layer) suitable for use as Referrers.
|
||||
func (manifest *Manifest) BuildReferringArtifacts() ([]v1.Image, error) {
|
||||
var images []v1.Image
|
||||
for _, layer := range manifest.SignedLayers {
|
||||
opts := &AttestationManifestImageOptions{}
|
||||
newImg, err := buildImage([]*AttestationLayer{layer}, manifest.OriginalDescriptor, manifest.SubjectDescriptor, opts)
|
||||
opts := &ManifestImageOptions{}
|
||||
newImg, err := buildImage([]*Layer{layer}, manifest.OriginalDescriptor, manifest.SubjectDescriptor, opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build image: %w", err)
|
||||
}
|
||||
@@ -247,14 +249,14 @@ func (manifest *AttestationManifest) BuildReferringArtifacts() ([]v1.Image, erro
|
||||
return images, nil
|
||||
}
|
||||
|
||||
// build and image containing only layers
|
||||
func buildImage(layers []*AttestationLayer, manifest *v1.Descriptor, subject *v1.Descriptor, opts *AttestationManifestImageOptions) (v1.Image, error) {
|
||||
// build and image containing only layers.
|
||||
func buildImage(layers []*Layer, manifest *v1.Descriptor, subject *v1.Descriptor, opts *ManifestImageOptions) (v1.Image, error) {
|
||||
newImg := empty.Image
|
||||
var err error
|
||||
if len(layers) == 0 {
|
||||
return nil, fmt.Errorf("no layers supplied to build image")
|
||||
}
|
||||
// NB: if we add the subject before the layers, it does not end up being computed/serialised in the output for some reason
|
||||
// NB: if we add the subject before the layers, it does not end up being computed/serialized in the output for some reason
|
||||
// TODO - recreate this bug and push upstream
|
||||
for _, layer := range layers {
|
||||
add := mutate.Addendum{
|
||||
@@ -285,7 +287,11 @@ func buildImage(layers []*AttestationLayer, manifest *v1.Descriptor, subject *v1
|
||||
// see note above - must be added after the layers!
|
||||
if !opts.skipSubject {
|
||||
subject.Platform = nil
|
||||
newImg = mutate.Subject(newImg, *subject).(v1.Image)
|
||||
ok := false
|
||||
newImg, ok = mutate.Subject(newImg, *subject).(v1.Image)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to set subject: %w", err)
|
||||
}
|
||||
}
|
||||
if !opts.laxReferrers {
|
||||
// as per https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidance-for-an-empty-descriptor
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
|
||||
)
|
||||
|
||||
func ExampleAttestationManifest() {
|
||||
func ExampleManifest() {
|
||||
// configure signerverifier
|
||||
// local signer (unsafe for production)
|
||||
signer, err := signerverifier.GenKeyPair()
|
||||
@@ -55,7 +55,7 @@ func ExampleAttestationManifest() {
|
||||
ID: "test-verifier",
|
||||
},
|
||||
TimeVerified: time.Now().UTC().Format(time.RFC3339),
|
||||
ResourceUri: "some-uri",
|
||||
ResourceURI: "some-uri",
|
||||
Policy: attestation.VSAPolicy{URI: "some-uri"},
|
||||
VerificationResult: "PASSED",
|
||||
VerifiedLevels: []string{"SLSA_BUILD_LEVEL_1"},
|
||||
|
||||
@@ -137,7 +137,7 @@ func TestAttestationReferenceTypes(t *testing.T) {
|
||||
ref = fmt.Sprintf("%s/repo@%s", u.Host, idxDigest.String())
|
||||
}
|
||||
|
||||
policyOpts := &policy.PolicyOptions{
|
||||
policyOpts := &policy.Options{
|
||||
LocalPolicyDir: LocalPolicy,
|
||||
}
|
||||
|
||||
@@ -201,12 +201,12 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
||||
} {
|
||||
server := tc.server
|
||||
defer server.Close()
|
||||
serverUrl, err := url.Parse(server.URL)
|
||||
serverURL, err := url.Parse(server.URL)
|
||||
require.NoError(t, err)
|
||||
|
||||
refServer := tc.refServer
|
||||
defer refServer.Close()
|
||||
refServerUrl, err := url.Parse(refServer.URL)
|
||||
refServerURL, err := url.Parse(refServer.URL)
|
||||
require.NoError(t, err)
|
||||
|
||||
opts := &attestation.SigningOptions{
|
||||
@@ -215,7 +215,7 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
||||
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
|
||||
require.NoError(t, err)
|
||||
|
||||
indexName := fmt.Sprintf("%s/%s:latest", serverUrl.Host, repoName)
|
||||
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
||||
err = mirror.PushIndexToRegistry(attIdx.Index, indexName)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -227,12 +227,12 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
||||
// push references using subject-digest.att convention
|
||||
image, err := signedManifest.BuildAttestationImage()
|
||||
require.NoError(t, err)
|
||||
err = mirror.PushImageToRegistry(image, fmt.Sprintf("%s/%s:tag-does-not-matter", refServerUrl.Host, repoName))
|
||||
err = mirror.PushImageToRegistry(image, fmt.Sprintf("%s/%s:tag-does-not-matter", refServerURL.Host, repoName))
|
||||
require.NoError(t, err)
|
||||
|
||||
refServer := tc.refServer
|
||||
defer refServer.Close()
|
||||
refServerUrl, err := url.Parse(refServer.URL)
|
||||
refServerURL, err := url.Parse(refServer.URL)
|
||||
require.NoError(t, err)
|
||||
|
||||
opts := &attestation.SigningOptions{
|
||||
@@ -241,7 +241,7 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
||||
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
|
||||
require.NoError(t, err)
|
||||
|
||||
indexName := fmt.Sprintf("%s/%s:latest", serverUrl.Host, repoName)
|
||||
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
||||
err = mirror.PushIndexToRegistry(attIdx.Index, indexName)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -254,7 +254,7 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
||||
imgs, err := mf.BuildReferringArtifacts()
|
||||
require.NoError(t, err)
|
||||
for _, img := range imgs {
|
||||
err = mirror.PushImageToRegistry(img, fmt.Sprintf("%s/%s:tag-does-not-matter", refServerUrl.Host, repoName))
|
||||
err = mirror.PushImageToRegistry(img, fmt.Sprintf("%s/%s:tag-does-not-matter", refServerURL.Host, repoName))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
@@ -267,7 +267,7 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
||||
}
|
||||
// can evaluate policy using referrers in a different repo
|
||||
referencedImage := fmt.Sprintf("%s@%s", indexName, mf.Digest.String())
|
||||
policyOpts := &policy.PolicyOptions{
|
||||
policyOpts := &policy.Options{
|
||||
LocalPolicyDir: PassPolicyDir,
|
||||
}
|
||||
src, err := oci.ParseImageSpec(referencedImage)
|
||||
@@ -285,7 +285,7 @@ func TestCorrectArtifactTypeInTagFallback(t *testing.T) {
|
||||
server := httptest.NewServer(registry.New())
|
||||
|
||||
defer server.Close()
|
||||
serverUrl, err := url.Parse(server.URL)
|
||||
serverURL, err := url.Parse(server.URL)
|
||||
require.NoError(t, err)
|
||||
|
||||
repoName := "repo"
|
||||
@@ -296,7 +296,7 @@ func TestCorrectArtifactTypeInTagFallback(t *testing.T) {
|
||||
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
|
||||
require.NoError(t, err)
|
||||
|
||||
indexName := fmt.Sprintf("%s/%s:latest", serverUrl.Host, repoName)
|
||||
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
||||
err = mirror.PushIndexToRegistry(attIdx.Index, indexName)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -308,12 +308,12 @@ func TestCorrectArtifactTypeInTagFallback(t *testing.T) {
|
||||
imgs, err := mf.BuildReferringArtifacts()
|
||||
require.NoError(t, err)
|
||||
for _, img := range imgs {
|
||||
err = mirror.PushImageToRegistry(img, fmt.Sprintf("%s/%s:tag-does-not-matter", serverUrl.Host, repoName))
|
||||
err = mirror.PushImageToRegistry(img, fmt.Sprintf("%s/%s:tag-does-not-matter", serverURL.Host, repoName))
|
||||
require.NoError(t, err)
|
||||
mf, err := img.Manifest()
|
||||
require.NoError(t, err)
|
||||
subject := mf.Subject
|
||||
subjectRef, err := name.ParseReference(fmt.Sprintf("%s/%s:sha256-%s", serverUrl.Host, repoName, subject.Digest.Hex))
|
||||
subjectRef, err := name.ParseReference(fmt.Sprintf("%s/%s:sha256-%s", serverURL.Host, repoName, subject.Digest.Hex))
|
||||
require.NoError(t, err)
|
||||
idx, err := remote.Index(subjectRef)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
)
|
||||
|
||||
// SignDSSE signs a payload with a given signer and uploads the signature to the transparency log
|
||||
// SignDSSE signs a payload with a given signer and uploads the signature to the transparency log.
|
||||
func SignDSSE(ctx context.Context, payload []byte, signer dsse.SignerVerifier, opts *SigningOptions) (*Envelope, error) {
|
||||
payloadType := intoto.PayloadType
|
||||
env := new(Envelope)
|
||||
@@ -28,13 +28,13 @@ func SignDSSE(ctx context.Context, payload []byte, signer dsse.SignerVerifier, o
|
||||
}
|
||||
|
||||
// get Key ID from signer
|
||||
keyId, err := signer.KeyID()
|
||||
keyID, err := signer.KeyID()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting public key ID: %w", err)
|
||||
}
|
||||
|
||||
dsseSig := Signature{
|
||||
KeyID: keyId,
|
||||
dsseSig := &Signature{
|
||||
KeyID: keyID,
|
||||
Sig: base64Encoding.EncodeToString(sig),
|
||||
}
|
||||
if !opts.SkipTL {
|
||||
@@ -42,22 +42,22 @@ func SignDSSE(ctx context.Context, payload []byte, signer dsse.SignerVerifier, o
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to log to rekor: %w", err)
|
||||
}
|
||||
dsseSig.Extension = *ext
|
||||
dsseSig.Extension = ext
|
||||
}
|
||||
// add signature to dsse envelope
|
||||
env.Signatures = []Signature{dsseSig}
|
||||
env.Signatures = []*Signature{dsseSig}
|
||||
|
||||
return env, nil
|
||||
}
|
||||
|
||||
// returns a new envelope with the transparency log entry added to the signature extension
|
||||
// returns a new envelope with the transparency log entry added to the signature extension.
|
||||
func logSignature(ctx context.Context, t tlog.TL, sig *[]byte, encPayload *[]byte, signer dsse.SignerVerifier) (*Extension, error) {
|
||||
// get Key ID from signer
|
||||
keyId, err := signer.KeyID()
|
||||
keyID, err := signer.KeyID()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting public key ID: %w", err)
|
||||
}
|
||||
entry, err := t.UploadLogEntry(ctx, keyId, *encPayload, *sig, signer)
|
||||
entry, err := t.UploadLogEntry(ctx, keyID, *encPayload, *sig, signer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error uploading TL entry: %w", err)
|
||||
}
|
||||
@@ -66,10 +66,10 @@ func logSignature(ctx context.Context, t tlog.TL, sig *[]byte, encPayload *[]byt
|
||||
return nil, fmt.Errorf("error unmarshaling tl entry: %w", err)
|
||||
}
|
||||
return &Extension{
|
||||
Kind: DockerDsseExtKind,
|
||||
Ext: DockerDsseExtension{
|
||||
Tl: DockerTlExtension{
|
||||
Kind: RekorTlExtKind,
|
||||
Kind: DockerDSSEExtKind,
|
||||
Ext: &DockerDSSEExtension{
|
||||
TL: &DockerTLExtension{
|
||||
Kind: RekorTLExtKind,
|
||||
Data: entryObj, // transparency log entry metadata
|
||||
},
|
||||
},
|
||||
|
||||
@@ -44,20 +44,20 @@ func TestSignVerifyAttestation(t *testing.T) {
|
||||
// signer.Public() used here for test purposes
|
||||
ecPub, ok := signer.Public().(*ecdsa.PublicKey)
|
||||
assert.True(t, ok)
|
||||
pem, err := signerverifier.ToPEM(ecPub)
|
||||
pem, err := signerverifier.ConvertToPEM(ecPub)
|
||||
assert.NoError(t, err)
|
||||
keyId, err := signerverifier.KeyID(ecPub)
|
||||
keyID, err := signerverifier.KeyID(ecPub)
|
||||
assert.NoError(t, err)
|
||||
|
||||
badKeyPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
badKey := &badKeyPriv.PublicKey
|
||||
badPEM, err := signerverifier.ToPEM(badKey)
|
||||
badPEM, err := signerverifier.ConvertToPEM(badKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
keyId string
|
||||
keyID string
|
||||
pem []byte
|
||||
distrust bool
|
||||
from time.Time
|
||||
@@ -67,7 +67,7 @@ func TestSignVerifyAttestation(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "all OK",
|
||||
keyId: keyId,
|
||||
keyID: keyID,
|
||||
pem: pem,
|
||||
distrust: false,
|
||||
from: time.Time{},
|
||||
@@ -77,17 +77,17 @@ func TestSignVerifyAttestation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "key not found",
|
||||
keyId: "someotherkey",
|
||||
keyID: "someotherkey",
|
||||
pem: pem,
|
||||
distrust: false,
|
||||
from: time.Time{},
|
||||
to: nil,
|
||||
status: "active",
|
||||
expectedError: fmt.Sprintf("key not found: %s", keyId),
|
||||
expectedError: fmt.Sprintf("key not found: %s", keyID),
|
||||
},
|
||||
{
|
||||
name: "key distrusted",
|
||||
keyId: keyId,
|
||||
keyID: keyID,
|
||||
pem: pem,
|
||||
distrust: true,
|
||||
from: time.Time{},
|
||||
@@ -97,7 +97,7 @@ func TestSignVerifyAttestation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "key not yet valid",
|
||||
keyId: keyId,
|
||||
keyID: keyID,
|
||||
pem: pem,
|
||||
distrust: false,
|
||||
from: time.Now().Add(time.Hour),
|
||||
@@ -107,7 +107,7 @@ func TestSignVerifyAttestation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "key already revoked",
|
||||
keyId: keyId,
|
||||
keyID: keyID,
|
||||
pem: pem,
|
||||
distrust: false,
|
||||
from: time.Time{},
|
||||
@@ -117,7 +117,7 @@ func TestSignVerifyAttestation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "bad key",
|
||||
keyId: keyId,
|
||||
keyID: keyID,
|
||||
pem: badPEM,
|
||||
distrust: false,
|
||||
from: time.Time{},
|
||||
@@ -129,8 +129,8 @@ func TestSignVerifyAttestation(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
keyMeta := attestation.KeyMetadata{
|
||||
ID: tc.keyId,
|
||||
keyMeta := &attestation.KeyMetadata{
|
||||
ID: tc.keyID,
|
||||
PEM: string(tc.pem),
|
||||
Distrust: tc.distrust,
|
||||
From: tc.from,
|
||||
|
||||
@@ -15,8 +15,8 @@ const (
|
||||
AttestationManifestType = "attestation-manifest"
|
||||
InTotoPredicateType = "in-toto.io/predicate-type"
|
||||
DockerReferenceDigest = "vnd.docker.reference.digest"
|
||||
DockerDsseExtKind = "application/vnd.docker.attestation-verification.v1+json"
|
||||
RekorTlExtKind = "Rekor"
|
||||
DockerDSSEExtKind = "application/vnd.docker.attestation-verification.v1+json"
|
||||
RekorTLExtKind = "Rekor"
|
||||
OCIDescriptorDSSEMediaType = ociv1.MediaTypeDescriptor + "+dsse"
|
||||
InTotoReferenceLifecycleStage = "vnd.docker.lifecycle-stage"
|
||||
LifecycleStageExperimental = "experimental"
|
||||
@@ -24,58 +24,58 @@ const (
|
||||
|
||||
var base64Encoding = base64.StdEncoding.Strict()
|
||||
|
||||
type AttestationLayer struct {
|
||||
type Layer struct {
|
||||
Statement *intoto.Statement
|
||||
Layer v1.Layer
|
||||
Annotations map[string]string
|
||||
}
|
||||
|
||||
type AttestationManifest struct {
|
||||
type Manifest struct {
|
||||
OriginalDescriptor *v1.Descriptor
|
||||
OriginalLayers []*AttestationLayer
|
||||
OriginalLayers []*Layer
|
||||
|
||||
// accumulated during signing
|
||||
SignedLayers []*AttestationLayer
|
||||
SignedLayers []*Layer
|
||||
// details of subect image
|
||||
SubjectName string
|
||||
SubjectDescriptor *v1.Descriptor
|
||||
}
|
||||
|
||||
type AttestationManifestImageOptions struct {
|
||||
type ManifestImageOptions struct {
|
||||
// how to output the image
|
||||
skipSubject bool
|
||||
replaceLayers bool
|
||||
laxReferrers bool
|
||||
}
|
||||
|
||||
// the following types are needed until https://github.com/secure-systems-lab/dsse/pull/61 is merged
|
||||
// the following types are needed until https://github.com/secure-systems-lab/dsse/pull/61 is merged.
|
||||
type Envelope struct {
|
||||
PayloadType string `json:"payloadType"`
|
||||
Payload string `json:"payload"`
|
||||
Signatures []Signature `json:"signatures"`
|
||||
PayloadType string `json:"payloadType"`
|
||||
Payload string `json:"payload"`
|
||||
Signatures []*Signature `json:"signatures"`
|
||||
}
|
||||
type Signature struct {
|
||||
KeyID string `json:"keyid"`
|
||||
Sig string `json:"sig"`
|
||||
Extension Extension `json:"extension,omitempty"`
|
||||
KeyID string `json:"keyid"`
|
||||
Sig string `json:"sig"`
|
||||
Extension *Extension `json:"extension,omitempty"`
|
||||
}
|
||||
type Extension struct {
|
||||
Kind string `json:"kind"`
|
||||
Ext DockerDsseExtension `json:"ext"`
|
||||
Kind string `json:"kind"`
|
||||
Ext *DockerDSSEExtension `json:"ext"`
|
||||
}
|
||||
|
||||
type DockerDsseExtension struct {
|
||||
Tl DockerTlExtension `json:"tl"`
|
||||
type DockerDSSEExtension struct {
|
||||
TL *DockerTLExtension `json:"tl"`
|
||||
}
|
||||
|
||||
type DockerTlExtension struct {
|
||||
type DockerTLExtension struct {
|
||||
Kind string `json:"kind"`
|
||||
Data any `json:"data"`
|
||||
}
|
||||
|
||||
type VerifyOptions struct {
|
||||
Keys []KeyMetadata `json:"keys"`
|
||||
SkipTL bool `json:"skip_tl"`
|
||||
Keys []*KeyMetadata `json:"keys"`
|
||||
SkipTL bool `json:"skip_tl"`
|
||||
}
|
||||
|
||||
type SigningOptions struct {
|
||||
|
||||
@@ -28,8 +28,8 @@ type KeyMetadata struct {
|
||||
}
|
||||
|
||||
type (
|
||||
Keys []KeyMetadata
|
||||
KeysMap map[string]KeyMetadata
|
||||
Keys []*KeyMetadata
|
||||
KeysMap map[string]*KeyMetadata
|
||||
)
|
||||
|
||||
func VerifyDSSE(ctx context.Context, env *Envelope, opts *VerifyOptions) ([]byte, error) {
|
||||
@@ -60,8 +60,8 @@ func VerifyDSSE(ctx context.Context, env *Envelope, opts *VerifyOptions) ([]byte
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
func verifySignature(ctx context.Context, sig Signature, payload []byte, opts *VerifyOptions) error {
|
||||
keys := make(map[string]KeyMetadata, len(opts.Keys))
|
||||
func verifySignature(ctx context.Context, sig *Signature, payload []byte, opts *VerifyOptions) error {
|
||||
keys := make(map[string]*KeyMetadata, len(opts.Keys))
|
||||
for _, key := range opts.Keys {
|
||||
keys[key.ID] = key
|
||||
}
|
||||
@@ -74,26 +74,25 @@ func verifySignature(ctx context.Context, sig Signature, payload []byte, opts *V
|
||||
return fmt.Errorf("key %s is distrusted", keyMeta.ID)
|
||||
}
|
||||
// TODO: this is unmarshalling with MarshalPKIXPublicKey only for us to marshal it again
|
||||
publicKey, err := signerverifier.Parse([]byte(keyMeta.PEM))
|
||||
publicKey, err := signerverifier.ParsePublicKey([]byte(keyMeta.PEM))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse public key: %w", err)
|
||||
}
|
||||
|
||||
if !opts.SkipTL {
|
||||
t := tlog.GetTL(ctx)
|
||||
|
||||
if sig.Extension.Kind == "" {
|
||||
return fmt.Errorf("error missing signature extension kind")
|
||||
if sig.Extension == nil || sig.Extension.Kind == "" {
|
||||
return fmt.Errorf("error missing signature extension")
|
||||
}
|
||||
if sig.Extension.Kind != DockerDsseExtKind {
|
||||
if sig.Extension.Kind != DockerDSSEExtKind {
|
||||
return fmt.Errorf("error unsupported signature extension kind: %s", sig.Extension.Kind)
|
||||
}
|
||||
|
||||
// verify TL entry
|
||||
if sig.Extension.Ext.Tl.Kind != RekorTlExtKind {
|
||||
return fmt.Errorf("error unsupported TL extension kind: %s", sig.Extension.Ext.Tl.Kind)
|
||||
if sig.Extension.Ext.TL.Kind != RekorTLExtKind {
|
||||
return fmt.Errorf("error unsupported TL extension kind: %s", sig.Extension.Ext.TL.Kind)
|
||||
}
|
||||
entry := sig.Extension.Ext.Tl.Data
|
||||
entry := sig.Extension.Ext.TL.Data
|
||||
entryBytes, err := json.Marshal(entry)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal TL entry: %w", err)
|
||||
|
||||
@@ -35,7 +35,7 @@ func TestVerifyUnsignedAttestation(t *testing.T) {
|
||||
payload := []byte("payload")
|
||||
env := &attestation.Envelope{
|
||||
// no signatures
|
||||
Signatures: []attestation.Signature{},
|
||||
Signatures: []*attestation.Signature{},
|
||||
Payload: base64.StdEncoding.EncodeToString(payload),
|
||||
PayloadType: intoto.PayloadType,
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ const (
|
||||
type VSAPredicate struct {
|
||||
Verifier VSAVerifier `json:"verifier"`
|
||||
TimeVerified string `json:"timeVerified"`
|
||||
ResourceUri string `json:"resourceUri"`
|
||||
ResourceURI string `json:"resourceUri"`
|
||||
Policy VSAPolicy `json:"policy"`
|
||||
InputAttestations []VSAInputAttestation `json:"inputAttestations"`
|
||||
VerificationResult string `json:"verificationResult"`
|
||||
|
||||
Reference in New Issue
Block a user