diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 040c817..88bdbf8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: id-token: write strategy: matrix: - go-version: [1.21.x] + go-version: [1.22.x] # temp disable windows tests see https://github.com/docker/image-signer-verifier/pull/154 # os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest] diff --git a/internal/test/mocks.go b/internal/test/mocks.go index 5ec7d6f..096ddf2 100644 --- a/internal/test/mocks.go +++ b/internal/test/mocks.go @@ -16,15 +16,15 @@ type MockResolver struct { Envs []*attestation.Envelope } -func (r MockResolver) Attestations(ctx context.Context, mediaType string) ([]*attestation.Envelope, error) { +func (r MockResolver) Attestations(_ context.Context, _ string) ([]*attestation.Envelope, error) { return r.Envs, nil } -func (r MockResolver) ImageName(ctx context.Context) (string, error) { +func (r MockResolver) ImageName(_ context.Context) (string, error) { return "library/alpine:latest", nil } -func (r MockResolver) ImageDescriptor(ctx context.Context) (*v1.Descriptor, error) { +func (r MockResolver) ImageDescriptor(_ context.Context) (*v1.Descriptor, error) { digest, err := v1.NewHash("sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620") if err != nil { return nil, err @@ -36,7 +36,7 @@ func (r MockResolver) ImageDescriptor(ctx context.Context) (*v1.Descriptor, erro }, nil } -func (r MockResolver) ImagePlatform(ctx context.Context) (*v1.Platform, error) { +func (r MockResolver) ImagePlatform(_ context.Context) (*v1.Platform, error) { return oci.ParsePlatform("linux/amd64") } @@ -46,15 +46,15 @@ type MockRegistryResolver struct { *MockResolver } -func (r *MockRegistryResolver) ImageDescriptor(ctx context.Context) (*v1.Descriptor, error) { +func (r *MockRegistryResolver) ImageDescriptor(_ context.Context) (*v1.Descriptor, error) { return r.Subject, nil } -func (r *MockRegistryResolver) ImageName(ctx context.Context) (string, error) { +func (r *MockRegistryResolver) ImageName(_ context.Context) (string, error) { return r.ImageNameStr, nil } -func GetMockSigner(ctx context.Context) (dsse.SignerVerifier, error) { +func GetMockSigner(_ context.Context) (dsse.SignerVerifier, error) { priv, err := os.ReadFile(filepath.Join("..", "..", "test", "testdata", "test-signing-key.pem")) if err != nil { return nil, err diff --git a/internal/test/test.go b/internal/test/test.go index 793f9ef..4f63668 100644 --- a/internal/test/test.go +++ b/internal/test/test.go @@ -21,12 +21,12 @@ import ( ) const ( - USE_MOCK_TL = true - USE_MOCK_KMS = true - USE_MOCK_POLICY = true + UseMockTL = true + UseMockKMS = true + UseMockPolicy = true - AwsRegion = "us-east-1" - AwsKmsKeyArn = "arn:aws:kms:us-east-1:175142243308:alias/doi-signing" // sandbox + AWSRegion = "us-east-1" + AWSKMSKeyARN = "arn:aws:kms:us-east-1:175142243308:alias/doi-signing" // sandbox ) func CreateTempDir(t *testing.T, dir, pattern string) string { @@ -47,7 +47,7 @@ func CreateTempDir(t *testing.T, dir, pattern string) string { func Setup(t *testing.T) (context.Context, dsse.SignerVerifier) { var tl tlog.TL - if USE_MOCK_TL { + if UseMockTL { tl = tlog.GetMockTL() } else { tl = &tlog.RekorTL{} @@ -55,8 +55,8 @@ func Setup(t *testing.T) (context.Context, dsse.SignerVerifier) { ctx := tlog.WithTL(context.Background(), tl) - var policyEvaluator policy.PolicyEvaluator - if USE_MOCK_POLICY { + var policyEvaluator policy.Evaluator + if UseMockPolicy { policyEvaluator = policy.GetMockPolicy() } else { policyEvaluator = policy.NewRegoEvaluator(true) @@ -66,13 +66,13 @@ func Setup(t *testing.T) (context.Context, dsse.SignerVerifier) { var signer dsse.SignerVerifier var err error - if USE_MOCK_KMS { + if UseMockKMS { signer, err = GetMockSigner(ctx) if err != nil { t.Fatal(err) } } else { - signer, err = signerverifier.GetAWSSigner(ctx, AwsKmsKeyArn, AwsRegion) + signer, err = signerverifier.GetAWSSigner(ctx, AWSKMSKeyARN, AWSRegion) if err != nil { t.Fatal(err) } @@ -95,7 +95,8 @@ func ExtractStatementsFromIndex(idx v1.ImageIndex, mediaType string) ([]*Annotat var statements []*AnnotatedStatement - for _, mf := range mfs2.Manifests { + for i := range mfs2.Manifests { + mf := &mfs2.Manifests[i] if mf.Annotations[attestation.DockerReferenceType] != "attestation-manifest" { continue } @@ -124,7 +125,7 @@ func ExtractStatementsFromIndex(idx v1.ImageIndex, mediaType string) ([]*Annotat return nil, fmt.Errorf("failed to get layer contents: %w", err) } defer r.Close() - intotoStatement := new(intoto.Statement) + inTotoStatement := new(intoto.Statement) var desc *v1.Descriptor if strings.HasSuffix(string(mt), "+dsse") { env := new(attestation.Envelope) @@ -136,7 +137,7 @@ func ExtractStatementsFromIndex(idx v1.ImageIndex, mediaType string) ([]*Annotat if err != nil { return nil, fmt.Errorf("failed to decode payload: %w", err) } - err = json.Unmarshal([]byte(payload), intotoStatement) + err = json.Unmarshal([]byte(payload), inTotoStatement) if err != nil { return nil, fmt.Errorf("failed to decode %s statement: %w", mediaType, err) } @@ -158,7 +159,7 @@ func ExtractStatementsFromIndex(idx v1.ImageIndex, mediaType string) ([]*Annotat } statements = append(statements, &AnnotatedStatement{ OCIDescriptor: desc, - InTotoStatement: intotoStatement, + InTotoStatement: inTotoStatement, Annotations: annotations, }) } diff --git a/pkg/attest/example_sign_test.go b/pkg/attest/example_sign_test.go index ef2d256..a867562 100644 --- a/pkg/attest/example_sign_test.go +++ b/pkg/attest/example_sign_test.go @@ -66,7 +66,7 @@ func ExampleSignStatements_remote() { Add: signedIndex, Descriptor: v1.Descriptor{ Annotations: map[string]string{ - oci.OciReferenceTarget: attIdx.Name, + oci.OCIReferenceTarget: attIdx.Name, }, }, }) diff --git a/pkg/attest/example_verify_test.go b/pkg/attest/example_verify_test.go index 3517ab6..25e30fd 100644 --- a/pkg/attest/example_verify_test.go +++ b/pkg/attest/example_verify_test.go @@ -13,7 +13,7 @@ import ( "github.com/docker/attest/pkg/tuf" ) -func createTufClient(outputPath string) (*tuf.TufClient, error) { +func createTufClient(outputPath string) (*tuf.Client, error) { // using oci tuf metadata and targets metadataURI := "registry-1.docker.io/docker/tuf-metadata:latest" targetsURI := "registry-1.docker.io/docker/tuf-targets" @@ -21,7 +21,7 @@ func createTufClient(outputPath string) (*tuf.TufClient, error) { // metadataURI := "https://docker.github.io/tuf-staging/metadata" // targetsURI := "https://docker.github.io/tuf-staging/targets" - return tuf.NewTufClient(embed.RootStaging.Data, outputPath, metadataURI, targetsURI, tuf.NewMockVersionChecker()) + return tuf.NewClient(embed.RootStaging.Data, outputPath, metadataURI, targetsURI, tuf.NewMockVersionChecker()) } func ExampleVerify_remote() { @@ -41,11 +41,11 @@ func ExampleVerify_remote() { platform := "linux/amd64" // configure policy options - opts := &policy.PolicyOptions{ - TufClient: tufClient, + opts := &policy.Options{ + TUFClient: tufClient, LocalTargetsDir: filepath.Join(home, ".docker", "policy"), // location to store policy files downloaded from TUF LocalPolicyDir: "", // overrides TUF policy for local policy files if set - PolicyId: "", // set to ignore policy mapping and select a policy by id + PolicyID: "", // set to ignore policy mapping and select a policy by id } src, err := oci.ParseImageSpec(image, oci.WithPlatform(platform)) diff --git a/pkg/attest/sign.go b/pkg/attest/sign.go index 15d0b98..5e9971d 100644 --- a/pkg/attest/sign.go +++ b/pkg/attest/sign.go @@ -9,8 +9,8 @@ import ( "github.com/secure-systems-lab/go-securesystemslib/dsse" ) -// this is only relevant if there are (unsigned) in-toto statements -func SignStatements(ctx context.Context, idx v1.ImageIndex, signer dsse.SignerVerifier, opts *attestation.SigningOptions) ([]*attestation.AttestationManifest, error) { +// this is only relevant if there are (unsigned) in-toto statements. +func SignStatements(ctx context.Context, idx v1.ImageIndex, signer dsse.SignerVerifier, opts *attestation.SigningOptions) ([]*attestation.Manifest, error) { // extract attestation manifests from index attestationManifests, err := attestation.GetAttestationManifestsFromIndex(idx) if err != nil { diff --git a/pkg/attest/sign_test.go b/pkg/attest/sign_test.go index 7332d56..06c4b49 100644 --- a/pkg/attest/sign_test.go +++ b/pkg/attest/sign_test.go @@ -52,7 +52,7 @@ func TestSignVerifyOCILayout(t *testing.T) { {"no provenance (replace)", NoProvenanceImage, 0, 2, true}, {"no provenance (no replace)", NoProvenanceImage, 2, 2, false}, } - policyOpts := &policy.PolicyOptions{ + policyOpts := &policy.Options{ LocalPolicyDir: PassPolicyDir, } for _, tc := range testCases { @@ -72,7 +72,7 @@ func TestSignVerifyOCILayout(t *testing.T) { Add: signedIndex, Descriptor: v1.Descriptor{ Annotations: map[string]string{ - oci.OciReferenceTarget: attIdx.Name, + oci.OCIReferenceTarget: attIdx.Name, }, }, }) @@ -120,7 +120,7 @@ func TestAddSignedLayerAnnotations(t *testing.T) { testLayer := static.NewLayer(data, types.MediaType(intoto.PayloadType)) mediaType := types.OCIManifestSchema1 opts := &attestation.SigningOptions{} - originalLayer := &attestation.AttestationLayer{ + originalLayer := &attestation.Layer{ Layer: testLayer, Statement: &intoto.Statement{ StatementHeader: intoto.StatementHeader{ @@ -130,11 +130,11 @@ func TestAddSignedLayerAnnotations(t *testing.T) { Annotations: map[string]string{"test": "test"}, } - manifest := &attestation.AttestationManifest{ + manifest := &attestation.Manifest{ OriginalDescriptor: &v1.Descriptor{ MediaType: mediaType, }, - OriginalLayers: []*attestation.AttestationLayer{ + OriginalLayers: []*attestation.Layer{ originalLayer, }, SubjectDescriptor: &v1.Descriptor{}, diff --git a/pkg/attest/types.go b/pkg/attest/types.go index ee8b620..d3bbf4d 100644 --- a/pkg/attest/types.go +++ b/pkg/attest/types.go @@ -30,7 +30,7 @@ func (o Outcome) StringForVSA() (string, error) { type VerificationResult struct { Outcome Outcome Policy *policy.Policy - Input *policy.PolicyInput + Input *policy.Input VSA *intoto.Statement Violations []policy.Violation SubjectDescriptor *v1.Descriptor diff --git a/pkg/attest/verify.go b/pkg/attest/verify.go index db33043..b6f5ec7 100644 --- a/pkg/attest/verify.go +++ b/pkg/attest/verify.go @@ -15,7 +15,7 @@ import ( intoto "github.com/in-toto/in-toto-golang/in_toto" ) -func Verify(ctx context.Context, src *oci.ImageSpec, opts *policy.PolicyOptions) (result *VerificationResult, err error) { +func Verify(ctx context.Context, src *oci.ImageSpec, opts *policy.Options) (result *VerificationResult, err error) { // so that we can resolve mapping from the image name earlier detailsResolver, err := policy.CreateImageDetailsResolver(src) if err != nil { @@ -61,16 +61,16 @@ func Verify(ctx context.Context, src *oci.ImageSpec, opts *policy.PolicyOptions) return result, nil } -func toVerificationResult(p *policy.Policy, input *policy.PolicyInput, result *policy.Result) (*VerificationResult, error) { +func toVerificationResult(p *policy.Policy, input *policy.Input, result *policy.Result) (*VerificationResult, error) { dgst, err := oci.SplitDigest(input.Digest) if err != nil { return nil, fmt.Errorf("failed to split digest: %w", err) } subject := intoto.Subject{ - Name: input.Purl, + Name: input.PURL, Digest: dgst, } - resourceUri, err := attestation.ToVSAResourceURI(subject) + resourceURI, err := attestation.ToVSAResourceURI(subject) if err != nil { return nil, fmt.Errorf("failed to create resource uri: %w", err) } @@ -103,7 +103,7 @@ func toVerificationResult(p *policy.Policy, input *policy.PolicyInput, result *p ID: result.Summary.Verifier, }, TimeVerified: time.Now().UTC().Format(time.RFC3339), - ResourceUri: resourceUri, + ResourceURI: resourceURI, Policy: attestation.VSAPolicy{URI: result.Summary.PolicyURI}, VerificationResult: outcomeStr, VerifiedLevels: result.Summary.SLSALevels, @@ -143,9 +143,9 @@ func VerifyAttestations(ctx context.Context, resolver oci.AttestationResolver, p if err != nil { return nil, fmt.Errorf("failed to convert ref to purl: %w", err) } - input := &policy.PolicyInput{ + input := &policy.Input{ Digest: digest, - Purl: purl, + PURL: purl, IsCanonical: canonical, } @@ -165,12 +165,12 @@ func VerifyAttestations(ctx context.Context, resolver oci.AttestationResolver, p return verificationResult, nil } -func NewAttestationManifest(subject *v1.Descriptor) (*attestation.AttestationManifest, error) { - return &attestation.AttestationManifest{ +func NewAttestationManifest(subject *v1.Descriptor) (*attestation.Manifest, error) { + return &attestation.Manifest{ OriginalDescriptor: &v1.Descriptor{ MediaType: "application/vnd.oci.image.manifest.v1+json", }, - OriginalLayers: []*attestation.AttestationLayer{}, + OriginalLayers: []*attestation.Layer{}, SubjectDescriptor: subject, }, nil } diff --git a/pkg/attest/verify_test.go b/pkg/attest/verify_test.go index a04ffd2..04c4805 100644 --- a/pkg/attest/verify_test.go +++ b/pkg/attest/verify_test.go @@ -50,7 +50,7 @@ func TestVerifyAttestations(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { mockPE := policy.MockPolicyEvaluator{ - EvaluateFunc: func(ctx context.Context, resolver oci.AttestationResolver, pctx *policy.Policy, input *policy.PolicyInput) (*policy.Result, error) { + EvaluateFunc: func(_ context.Context, _ oci.AttestationResolver, _ *policy.Policy, _ *policy.Input) (*policy.Result, error) { return policy.AllowedResult(), tc.policyEvaluationError }, } @@ -89,7 +89,7 @@ func TestVSA(t *testing.T) { Add: signedIndex, Descriptor: v1.Descriptor{ Annotations: map[string]string{ - oci.OciReferenceTarget: attIdx.Name, + oci.OCIReferenceTarget: attIdx.Name, }, }, }) @@ -97,7 +97,7 @@ func TestVSA(t *testing.T) { assert.NoError(t, err) // mocked vsa query should pass - policyOpts := &policy.PolicyOptions{ + policyOpts := &policy.Options{ LocalPolicyDir: PassPolicyDir, } src, err := oci.ParseImageSpec("oci://"+outputLayout, oci.WithPlatform(LinuxAMD64)) @@ -117,7 +117,8 @@ func TestVSA(t *testing.T) { assert.Len(t, results.VSA.Subject, 1) require.IsType(t, attestation.VSAPredicate{}, results.VSA.Predicate) - attestationPredicate := results.VSA.Predicate.(attestation.VSAPredicate) + attestationPredicate, ok := results.VSA.Predicate.(attestation.VSAPredicate) + require.True(t, ok) assert.Equal(t, "PASSED", attestationPredicate.VerificationResult) assert.Equal(t, "docker-official-images", attestationPredicate.Verifier.ID) @@ -146,7 +147,7 @@ func TestVerificationFailure(t *testing.T) { Add: signedIndex, Descriptor: v1.Descriptor{ Annotations: map[string]string{ - oci.OciReferenceTarget: attIdx.Name, + oci.OCIReferenceTarget: attIdx.Name, }, }, }) @@ -154,7 +155,7 @@ func TestVerificationFailure(t *testing.T) { assert.NoError(t, err) // mocked vsa query should fail - policyOpts := &policy.PolicyOptions{ + policyOpts := &policy.Options{ LocalPolicyDir: FailPolicyDir, } src, err := oci.ParseImageSpec("oci://"+outputLayout, oci.WithPlatform(LinuxAMD64)) @@ -174,7 +175,8 @@ func TestVerificationFailure(t *testing.T) { assert.Len(t, results.VSA.Subject, 1) require.IsType(t, attestation.VSAPredicate{}, results.VSA.Predicate) - attestationPredicate := results.VSA.Predicate.(attestation.VSAPredicate) + attestationPredicate, ok := results.VSA.Predicate.(attestation.VSAPredicate) + require.True(t, ok) assert.Equal(t, "FAILED", attestationPredicate.VerificationResult) assert.Equal(t, "docker-official-images", attestationPredicate.Verifier.ID) @@ -227,14 +229,14 @@ func TestSignVerify(t *testing.T) { Add: signedIndex, Descriptor: v1.Descriptor{ Annotations: map[string]string{ - oci.OciReferenceTarget: imageName, + oci.OCIReferenceTarget: imageName, }, }, }) _, err = layout.Write(outputLayout, idx) assert.NoError(t, err) - policyOpts := &policy.PolicyOptions{ + policyOpts := &policy.Options{ LocalPolicyDir: tc.policyDir, } src, err := oci.ParseImageSpec("oci://"+outputLayout, oci.WithPlatform(LinuxAMD64)) @@ -250,7 +252,7 @@ func TestSignVerify(t *testing.T) { require.NoError(t, err) expectedPURL, _, err := oci.RefToPURL(attIdx.Name, platform) require.NoError(t, err) - assert.Equal(t, expectedPURL, results.Input.Purl) + assert.Equal(t, expectedPURL, results.Input.PURL) }) } } diff --git a/pkg/attestation/attestation.go b/pkg/attestation/attestation.go index 8ddbd4d..c1a522c 100644 --- a/pkg/attestation/attestation.go +++ b/pkg/attestation/attestation.go @@ -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 diff --git a/pkg/attestation/example_attestation_manifest_test.go b/pkg/attestation/example_attestation_manifest_test.go index 45a6d4d..8abe117 100644 --- a/pkg/attestation/example_attestation_manifest_test.go +++ b/pkg/attestation/example_attestation_manifest_test.go @@ -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"}, diff --git a/pkg/attestation/referrers_test.go b/pkg/attestation/referrers_test.go index da820f6..6588769 100644 --- a/pkg/attestation/referrers_test.go +++ b/pkg/attestation/referrers_test.go @@ -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) diff --git a/pkg/attestation/sign.go b/pkg/attestation/sign.go index 7fd77c6..6633bcc 100644 --- a/pkg/attestation/sign.go +++ b/pkg/attestation/sign.go @@ -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 }, }, diff --git a/pkg/attestation/sign_test.go b/pkg/attestation/sign_test.go index 81fbb9c..d586c3e 100644 --- a/pkg/attestation/sign_test.go +++ b/pkg/attestation/sign_test.go @@ -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, diff --git a/pkg/attestation/types.go b/pkg/attestation/types.go index 3aa6cea..fd28c83 100644 --- a/pkg/attestation/types.go +++ b/pkg/attestation/types.go @@ -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 { diff --git a/pkg/attestation/verify.go b/pkg/attestation/verify.go index 78ab79f..ea2c935 100644 --- a/pkg/attestation/verify.go +++ b/pkg/attestation/verify.go @@ -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) diff --git a/pkg/attestation/verify_test.go b/pkg/attestation/verify_test.go index 7ba351a..e8c001b 100644 --- a/pkg/attestation/verify_test.go +++ b/pkg/attestation/verify_test.go @@ -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, } diff --git a/pkg/attestation/vsa.go b/pkg/attestation/vsa.go index 5451b67..0e5804e 100644 --- a/pkg/attestation/vsa.go +++ b/pkg/attestation/vsa.go @@ -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"` diff --git a/pkg/config/config.go b/pkg/config/config.go index 164c4f6..e724c2d 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -31,7 +31,7 @@ func LoadLocalMappings(configDir string) (*PolicyMappings, error) { return expandMappingFile(mappings) } -func LoadTufMappings(tufClient tuf.TUFClient, localTargetsDir string) (*PolicyMappings, error) { +func LoadTUFMappings(tufClient tuf.Downloader, localTargetsDir string) (*PolicyMappings, error) { if tufClient == nil { return nil, fmt.Errorf("tuf client not set") } @@ -52,7 +52,7 @@ func LoadTufMappings(tufClient tuf.TUFClient, localTargetsDir string) (*PolicyMa func expandMappingFile(mappingFile *policyMappingsFile) (*PolicyMappings, error) { policies := make(map[string]*PolicyMapping) for _, policy := range mappingFile.Policies { - policies[policy.Id] = policy + policies[policy.ID] = policy } var rules []*PolicyRule @@ -63,7 +63,7 @@ func expandMappingFile(mappingFile *policyMappingsFile) (*PolicyMappings, error) } rules = append(rules, &PolicyRule{ Pattern: r, - PolicyId: rule.PolicyId, + PolicyID: rule.PolicyID, Replacement: rule.Replacement, }) } diff --git a/pkg/config/types.go b/pkg/config/types.go index 1521803..e3ebc83 100644 --- a/pkg/config/types.go +++ b/pkg/config/types.go @@ -13,7 +13,7 @@ type policyMappingsFile struct { type policyRuleFile struct { Pattern string `json:"pattern"` - PolicyId string `json:"policy-id"` + PolicyID string `json:"policy-id"` Replacement string `json:"rewrite"` } @@ -32,7 +32,7 @@ const ( ) type PolicyMapping struct { - Id string `json:"id"` + ID string `json:"id"` Description string `json:"description"` Files []PolicyMappingFile `json:"files"` Attestations *AttestationConfig `json:"attestations"` @@ -49,6 +49,6 @@ type PolicyMappingFile struct { type PolicyRule struct { Pattern *regexp.Regexp - PolicyId string + PolicyID string Replacement string } diff --git a/pkg/mirror/example_mirror_test.go b/pkg/mirror/example_mirror_test.go index c2924b0..534b9fd 100644 --- a/pkg/mirror/example_mirror_test.go +++ b/pkg/mirror/example_mirror_test.go @@ -14,12 +14,12 @@ import ( type TufMirrorOutput struct { metadata v1.Image - delegatedMetadata []*mirror.MirrorImage - targets []*mirror.MirrorImage - delegatedTargets []*mirror.MirrorIndex + delegatedMetadata []*mirror.Image + targets []*mirror.Image + delegatedTargets []*mirror.Index } -func ExampleNewTufMirror() { +func ExampleNewTUFMirror() { home, err := os.UserHomeDir() if err != nil { panic(err) @@ -29,7 +29,7 @@ func ExampleNewTufMirror() { // configure TUF mirror metadataURI := "https://docker.github.io/tuf-staging/metadata" targetsURI := "https://docker.github.io/tuf-staging/targets" - m, err := mirror.NewTufMirror(embed.RootStaging.Data, tufOutputPath, metadataURI, targetsURI, tuf.NewMockVersionChecker()) + m, err := mirror.NewTUFMirror(embed.RootStaging.Data, tufOutputPath, metadataURI, targetsURI, tuf.NewMockVersionChecker()) if err != nil { panic(err) } @@ -46,7 +46,7 @@ func ExampleNewTufMirror() { } // create targets manifest - targets, err := m.GetTufTargetMirrors() + targets, err := m.GetTUFTargetMirrors() if err != nil { panic(err) } diff --git a/pkg/mirror/metadata.go b/pkg/mirror/metadata.go index 81f1c9f..7f84b89 100644 --- a/pkg/mirror/metadata.go +++ b/pkg/mirror/metadata.go @@ -16,9 +16,9 @@ import ( // TUF root metadata // ----------------- -// GetMetadataManifest returns an image with TUF root metadata as layers -func (m *TufMirror) GetMetadataManifest(metadataURL string) (v1.Image, error) { - metadata, err := m.getTufMetadataMirror(metadataURL) +// GetMetadataManifest returns an image with TUF root metadata as layers. +func (m *TUFMirror) GetMetadataManifest(metadataURL string) (v1.Image, error) { + metadata, err := m.getMetadataMirror(metadataURL) if err != nil { return nil, fmt.Errorf("failed to get metadata: %w", err) } @@ -29,16 +29,16 @@ func (m *TufMirror) GetMetadataManifest(metadataURL string) (v1.Image, error) { return manifest, nil } -// getTufMetadataMirror returns a TufMetadata struct with TUF metadata as map of file names to bytes -func (m *TufMirror) getTufMetadataMirror(metadataURL string) (*TufMetadata, error) { - trustedMetadata := m.TufClient.GetMetadata() +// getMetadataMirror returns a TufMetadata struct with TUF metadata as map of file names to bytes. +func (m *TUFMirror) getMetadataMirror(metadataURL string) (*TUFMetadata, error) { + trustedMetadata := m.TUFClient.GetMetadata() rootMetadata := map[string][]byte{} rootVersion := trustedMetadata.Root.Signed.Version // get the previous versions of root metadata if any if rootVersion != 1 { var err error - rootMetadata, err = m.TufClient.GetPriorRoots(metadataURL) + rootMetadata, err = m.TUFClient.GetPriorRoots(metadataURL) if err != nil { return nil, fmt.Errorf("failed to get prior root metadata: %w", err) } @@ -69,7 +69,7 @@ func (m *TufMirror) getTufMetadataMirror(metadataURL string) (*TufMetadata, erro snapshotVersion = strconv.FormatInt(trustedMetadata.Snapshot.Signed.Version, 10) targetsVersion = strconv.FormatInt(trustedMetadata.Targets[metadata.TARGETS].Signed.Version, 10) } - return &TufMetadata{ + return &TUFMetadata{ Root: rootMetadata, Snapshot: map[string][]byte{nameFromRole(metadata.SNAPSHOT, snapshotVersion): snapshotBytes}, Targets: map[string][]byte{nameFromRole(metadata.TARGETS, targetsVersion): targetsBytes}, @@ -77,12 +77,12 @@ func (m *TufMirror) getTufMetadataMirror(metadataURL string) (*TufMetadata, erro }, nil } -// buildMetadataManifest returns an OCI image with TUF metadata as layers with annotations -func (m *TufMirror) buildMetadataManifest(metadata *TufMetadata) (v1.Image, error) { +// buildMetadataManifest returns an OCI image with TUF metadata as layers with annotations. +func (m *TUFMirror) buildMetadataManifest(metadata *TUFMetadata) (v1.Image, error) { img := empty.Image img = mutate.MediaType(img, types.OCIManifestSchema1) img = mutate.ConfigMediaType(img, types.OCIConfigJSON) - for _, role := range TufRoles { + for _, role := range TUFRoles { layers, err := m.makeRoleLayers(role, metadata) if err != nil { return nil, fmt.Errorf("failed to make role layer: %w", err) @@ -95,8 +95,8 @@ func (m *TufMirror) buildMetadataManifest(metadata *TufMetadata) (v1.Image, erro return img, nil } -// makeRoleLayers returns a list of layers for a given TUF role -func (m *TufMirror) makeRoleLayers(role TufRole, tufMetadata *TufMetadata) ([]mutate.Addendum, error) { +// makeRoleLayers returns a list of layers for a given TUF role. +func (m *TUFMirror) makeRoleLayers(role TUFRole, tufMetadata *TUFMetadata) ([]mutate.Addendum, error) { var layers []mutate.Addendum ann := map[string]string{tufFileAnnotation: ""} switch role { @@ -115,8 +115,8 @@ func (m *TufMirror) makeRoleLayers(role TufRole, tufMetadata *TufMetadata) ([]mu return layers, nil } -// annotatedMetaLayers returns a list of layers with annotations for each TUF metadata file -func (m *TufMirror) annotatedMetaLayers(meta map[string][]byte) []mutate.Addendum { +// annotatedMetaLayers returns a list of layers with annotations for each TUF metadata file. +func (m *TUFMirror) annotatedMetaLayers(meta map[string][]byte) []mutate.Addendum { var layers []mutate.Addendum for name, data := range meta { ann := map[string]string{tufFileAnnotation: name} @@ -129,8 +129,8 @@ func (m *TufMirror) annotatedMetaLayers(meta map[string][]byte) []mutate.Addendu // TUF delegated targets metadata // ------------------------------ -// GetDelegatedMetadataMirrors returns a list of mirrors (image/tag pairs) for each delegated targets role metadata -func (m *TufMirror) GetDelegatedMetadataMirrors() ([]*MirrorImage, error) { +// GetDelegatedMetadataMirrors returns a list of mirrors (image/tag pairs) for each delegated targets role metadata. +func (m *TUFMirror) GetDelegatedMetadataMirrors() ([]*Image, error) { // get current delegated targets metadata delegatedTargets, err := m.getDelegatedTargetsMetadata() if err != nil { @@ -143,12 +143,12 @@ func (m *TufMirror) GetDelegatedMetadataMirrors() ([]*MirrorImage, error) { return mirror, nil } -// getDelegatedTargetsMetadata returns delegated targets metadata as a list of DelegatedTargetMetadata (role name and data) -func (m *TufMirror) getDelegatedTargetsMetadata() ([]DelegatedTargetMetadata, error) { +// getDelegatedTargetsMetadata returns delegated targets metadata as a list of DelegatedTargetMetadata (role name and data). +func (m *TUFMirror) getDelegatedTargetsMetadata() ([]DelegatedTargetMetadata, error) { var delegatedTargets []DelegatedTargetMetadata - md := m.TufClient.GetMetadata() + md := m.TUFClient.GetMetadata() for _, role := range md.Targets[metadata.TARGETS].Signed.Delegations.Roles { - roleMetadata, err := m.TufClient.LoadDelegatedTargets(role.Name, metadata.TARGETS) + roleMetadata, err := m.TUFClient.LoadDelegatedTargets(role.Name, metadata.TARGETS) if err != nil { return nil, fmt.Errorf("failed to get delegated role metadata: %w", err) } @@ -170,9 +170,9 @@ func (m *TufMirror) getDelegatedTargetsMetadata() ([]DelegatedTargetMetadata, er return delegatedTargets, nil } -// buildDelegatedMetadataManifests returns a list of mirrors (image/tag pairs) for each delegated target role metadata -func (m *TufMirror) buildDelegatedMetadataManifests(delegated []DelegatedTargetMetadata) ([]*MirrorImage, error) { - manifests := []*MirrorImage{} +// buildDelegatedMetadataManifests returns a list of mirrors (image/tag pairs) for each delegated target role metadata. +func (m *TUFMirror) buildDelegatedMetadataManifests(delegated []DelegatedTargetMetadata) ([]*Image, error) { + manifests := []*Image{} for _, role := range delegated { img := empty.Image img = mutate.MediaType(img, types.OCIManifestSchema1) @@ -183,7 +183,7 @@ func (m *TufMirror) buildDelegatedMetadataManifests(delegated []DelegatedTargetM if err != nil { return nil, fmt.Errorf("failed to append delegated targets layer to image: %w", err) } - manifests = append(manifests, &MirrorImage{Image: img, Tag: role.Name}) + manifests = append(manifests, &Image{Image: img, Tag: role.Name}) } return manifests, nil } diff --git a/pkg/mirror/metadata_test.go b/pkg/mirror/metadata_test.go index ee85b2d..98f5983 100644 --- a/pkg/mirror/metadata_test.go +++ b/pkg/mirror/metadata_test.go @@ -21,10 +21,10 @@ func TestGetTufMetadataMirror(t *testing.T) { defer server.Close() path := test.CreateTempDir(t, "", "tuf_temp") - m, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) + m, err := NewTUFMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) assert.NoError(t, err) - tufMetadata, err := m.getTufMetadataMirror(server.URL + "/metadata") + tufMetadata, err := m.getMetadataMirror(server.URL + "/metadata") assert.NoError(t, err) // check that all roles are not empty @@ -39,7 +39,7 @@ func TestGetMetadataManifest(t *testing.T) { defer server.Close() path := test.CreateTempDir(t, "", "tuf_temp") - m, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) + m, err := NewTUFMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) assert.NoError(t, err) img, err := m.GetMetadataManifest(server.URL + "/metadata") @@ -78,7 +78,7 @@ func TestGetDelegatedMetadataMirrors(t *testing.T) { defer server.Close() path := test.CreateTempDir(t, "", "tuf_temp") - m, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) + m, err := NewTUFMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) assert.NoError(t, err) delegations, err := m.GetDelegatedMetadataMirrors() diff --git a/pkg/mirror/mirror.go b/pkg/mirror/mirror.go index fdf4b42..eb927ac 100644 --- a/pkg/mirror/mirror.go +++ b/pkg/mirror/mirror.go @@ -16,15 +16,15 @@ import ( "github.com/google/go-containerregistry/pkg/v1/remote" ) -func NewTufMirror(root []byte, tufPath, metadataURL, targetsURL string, versionChecker tuf.VersionChecker) (*TufMirror, error) { +func NewTUFMirror(root []byte, tufPath, metadataURL, targetsURL string, versionChecker tuf.VersionChecker) (*TUFMirror, error) { if root == nil { root = embed.RootDefault.Data } - tufClient, err := tuf.NewTufClient(root, tufPath, metadataURL, targetsURL, versionChecker) + tufClient, err := tuf.NewClient(root, tufPath, metadataURL, targetsURL, versionChecker) if err != nil { return nil, fmt.Errorf("failed to create TUF client: %w", err) } - return &TufMirror{TufClient: tufClient, tufPath: tufPath, metadataURL: metadataURL, targetsURL: targetsURL}, nil + return &TUFMirror{TUFClient: tufClient, tufPath: tufPath, metadataURL: metadataURL, targetsURL: targetsURL}, nil } func PushImageToRegistry(image v1.Image, imageName string) error { @@ -85,7 +85,7 @@ func SaveIndex(outputs []*oci.ImageSpec, index v1.ImageIndex, indexName string) Add: index, Descriptor: v1.Descriptor{ Annotations: map[string]string{ - oci.OciReferenceTarget: indexName, + oci.OCIReferenceTarget: indexName, }, }, }) @@ -110,7 +110,7 @@ func SaveImage(output *oci.ImageSpec, image v1.Image, imageName string) error { Add: image, Descriptor: v1.Descriptor{ Annotations: map[string]string{ - oci.OciReferenceTarget: imageName, + oci.OCIReferenceTarget: imageName, }, }, }) @@ -127,7 +127,7 @@ func SaveImage(output *oci.ImageSpec, image v1.Image, imageName string) error { return nil } -func SaveReferrers(manifest *attestation.AttestationManifest, outputs []*oci.ImageSpec) error { +func SaveReferrers(manifest *attestation.Manifest, outputs []*oci.ImageSpec) error { for _, output := range outputs { if output.Type == oci.OCI { continue diff --git a/pkg/mirror/targets.go b/pkg/mirror/targets.go index 89a4fd2..3a73411 100644 --- a/pkg/mirror/targets.go +++ b/pkg/mirror/targets.go @@ -13,16 +13,16 @@ import ( "github.com/theupdateframework/go-tuf/v2/metadata" ) -// GetTufTargetMirrors returns a list of top-level target files as MirrorImages (image with tag) -func (m *TufMirror) GetTufTargetMirrors() ([]*MirrorImage, error) { - targetMirrors := []*MirrorImage{} - md := m.TufClient.GetMetadata() +// GetTUFTargetMirrors returns a list of top-level target files as MirrorImages (image with tag). +func (m *TUFMirror) GetTUFTargetMirrors() ([]*Image, error) { + targetMirrors := []*Image{} + md := m.TUFClient.GetMetadata() // for each top-level target file, create an image with the target file as a layer targets := md.Targets[metadata.TARGETS].Signed.Targets for _, t := range targets { // download target file - _, data, err := m.TufClient.DownloadTarget(t.Path, filepath.Join(m.tufPath, "download")) + _, data, err := m.TUFClient.DownloadTarget(t.Path, filepath.Join(m.tufPath, "download")) if err != nil { return nil, fmt.Errorf("failed to download target %s: %w", t.Path, err) } @@ -42,16 +42,16 @@ func (m *TufMirror) GetTufTargetMirrors() ([]*MirrorImage, error) { if err != nil { return nil, fmt.Errorf("failed to append role layer to image: %w", err) } - targetMirrors = append(targetMirrors, &MirrorImage{Image: img, Tag: name}) + targetMirrors = append(targetMirrors, &Image{Image: img, Tag: name}) } return targetMirrors, nil } // GetDelegatedTargetMirrors returns a list of delegated target files as MirrorIndexes (image index with tag) -// each image in the index contains a delegated target file -func (m *TufMirror) GetDelegatedTargetMirrors() ([]*MirrorIndex, error) { - mirror := []*MirrorIndex{} - md := m.TufClient.GetMetadata() +// each image in the index contains a delegated target file. +func (m *TUFMirror) GetDelegatedTargetMirrors() ([]*Index, error) { + mirror := []*Index{} + md := m.TUFClient.GetMetadata() // for each delegated role, create an image index with target files as images roles := md.Targets[metadata.TARGETS].Signed.Delegations.Roles @@ -60,7 +60,7 @@ func (m *TufMirror) GetDelegatedTargetMirrors() ([]*MirrorIndex, error) { index := v1.ImageIndex(empty.Index) // get delegated targets metadata for role - roleMeta, err := m.TufClient.LoadDelegatedTargets(role.Name, metadata.TARGETS) + roleMeta, err := m.TUFClient.LoadDelegatedTargets(role.Name, metadata.TARGETS) if err != nil { return nil, fmt.Errorf("failed to load delegated targets metadata: %w", err) } @@ -68,7 +68,7 @@ func (m *TufMirror) GetDelegatedTargetMirrors() ([]*MirrorIndex, error) { // for each target file, create an image with the target file as a layer for _, target := range roleMeta.Signed.Targets { // download target file - _, data, err := m.TufClient.DownloadTarget(target.Path, filepath.Join(m.tufPath, "download")) + _, data, err := m.TUFClient.DownloadTarget(target.Path, filepath.Join(m.tufPath, "download")) if err != nil { return nil, fmt.Errorf("failed to download target %s: %w", target.Path, err) } @@ -103,7 +103,7 @@ func (m *TufMirror) GetDelegatedTargetMirrors() ([]*MirrorIndex, error) { }, }) } - mirror = append(mirror, &MirrorIndex{Index: index, Tag: role.Name}) + mirror = append(mirror, &Index{Index: index, Tag: role.Name}) } return mirror, nil } diff --git a/pkg/mirror/targets_test.go b/pkg/mirror/targets_test.go index 39f21cf..aa785ef 100644 --- a/pkg/mirror/targets_test.go +++ b/pkg/mirror/targets_test.go @@ -27,10 +27,10 @@ func TestGetTufTargetsMirror(t *testing.T) { defer server.Close() path := test.CreateTempDir(t, "", "tuf_temp") - m, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) + m, err := NewTUFMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) assert.NoError(t, err) - targets, err := m.GetTufTargetMirrors() + targets, err := m.GetTUFTargetMirrors() assert.NoError(t, err) assert.Greater(t, len(targets), 0) @@ -61,10 +61,10 @@ func TestTargetDelegationMetadata(t *testing.T) { defer server.Close() path := test.CreateTempDir(t, "", "tuf_temp") - tm, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) + tm, err := NewTUFMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) assert.NoError(t, err) - targets, err := tm.TufClient.LoadDelegatedTargets("test-role", "targets") + targets, err := tm.TUFClient.LoadDelegatedTargets("test-role", "targets") assert.NoError(t, err) assert.Greater(t, len(targets.Signed.Targets), 0) } @@ -74,7 +74,7 @@ func TestGetDelegatedTargetMirrors(t *testing.T) { defer server.Close() path := test.CreateTempDir(t, "", "tuf_temp") - m, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) + m, err := NewTUFMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker()) assert.NoError(t, err) mirrors, err := m.GetDelegatedTargetMirrors() diff --git a/pkg/mirror/types.go b/pkg/mirror/types.go index 555cfbb..b064c6c 100644 --- a/pkg/mirror/types.go +++ b/pkg/mirror/types.go @@ -14,11 +14,11 @@ const ( tufFileAnnotation = "tuf.io/filename" ) -type TufRole string +type TUFRole string -var TufRoles = []TufRole{metadata.ROOT, metadata.SNAPSHOT, metadata.TARGETS, metadata.TIMESTAMP} +var TUFRoles = []TUFRole{metadata.ROOT, metadata.SNAPSHOT, metadata.TARGETS, metadata.TIMESTAMP} -type TufMetadata struct { +type TUFMetadata struct { Root map[string][]byte Snapshot map[string][]byte Targets map[string][]byte @@ -31,18 +31,18 @@ type DelegatedTargetMetadata struct { Data []byte } -type MirrorImage struct { +type Image struct { Image v1.Image Tag string } -type MirrorIndex struct { +type Index struct { Index v1.ImageIndex Tag string } -type TufMirror struct { - TufClient *tuf.TufClient +type TUFMirror struct { + TUFClient *tuf.Client tufPath string metadataURL string targetsURL string diff --git a/pkg/oci/http.go b/pkg/oci/http.go index 0c1b302..5578a0b 100644 --- a/pkg/oci/http.go +++ b/pkg/oci/http.go @@ -7,21 +7,21 @@ import ( ) type userAgentTransporter struct { - ua string - rt http.RoundTripper + userAgent string + roundTripper http.RoundTripper } type Option = func(*http.Client) func (u *userAgentTransporter) RoundTrip(req *http.Request) (*http.Response, error) { - req.Header.Set("User-Agent", u.ua) + req.Header.Set("User-Agent", u.userAgent) - return u.rt.RoundTrip(req) + return u.roundTripper.RoundTrip(req) } -func HttpTransport() http.RoundTripper { +func HTTPTransport() http.RoundTripper { return &userAgentTransporter{ - ua: "Docker-Client", - rt: cleanhttp.DefaultTransport(), + userAgent: "Docker-Client", + roundTripper: cleanhttp.DefaultTransport(), } } diff --git a/pkg/oci/layout.go b/pkg/oci/layout.go index 9368c0c..5c54ebd 100644 --- a/pkg/oci/layout.go +++ b/pkg/oci/layout.go @@ -11,14 +11,14 @@ import ( "github.com/google/go-containerregistry/pkg/v1/layout" ) -// implementation of AttestationResolver that closes over attestations from an oci layout -type OCILayoutResolver struct { - *attestation.AttestationManifest +// implementation of AttestationResolver that closes over attestations from an oci layout. +type LayoutResolver struct { + *attestation.Manifest *ImageSpec } -func NewOCILayoutAttestationResolver(src *ImageSpec) (*OCILayoutResolver, error) { - r := &OCILayoutResolver{ +func NewOCILayoutAttestationResolver(src *ImageSpec) (*LayoutResolver, error) { + r := &LayoutResolver{ ImageSpec: src, } _, err := r.fetchAttestationManifest() @@ -28,25 +28,25 @@ func NewOCILayoutAttestationResolver(src *ImageSpec) (*OCILayoutResolver, error) return r, nil } -func (r *OCILayoutResolver) fetchAttestationManifest() (*attestation.AttestationManifest, error) { - if r.AttestationManifest == nil { +func (r *LayoutResolver) fetchAttestationManifest() (*attestation.Manifest, error) { + if r.Manifest == nil { m, err := attestationManifestFromOCILayout(r.Identifier, r.ImageSpec.Platform) if err != nil { return nil, err } - r.AttestationManifest = m + r.Manifest = m } - return r.AttestationManifest, nil + return r.Manifest, nil } -func (r *OCILayoutResolver) Attestations(ctx context.Context, predicateType string) ([]*att.Envelope, error) { +func (r *LayoutResolver) Attestations(_ context.Context, predicateType string) ([]*att.Envelope, error) { var envs []*att.Envelope dsseMediaType, err := attestation.DSSEMediaType(predicateType) if err != nil { return nil, fmt.Errorf("failed to get DSSE media type for predicate '%s': %w", predicateType, err) } - for _, attestationLayer := range r.AttestationManifest.OriginalLayers { + for _, attestationLayer := range r.Manifest.OriginalLayers { mt, err := attestationLayer.Layer.MediaType() if err != nil { return nil, fmt.Errorf("failed to get layer media type: %w", err) @@ -71,19 +71,19 @@ func (r *OCILayoutResolver) Attestations(ctx context.Context, predicateType stri return envs, nil } -func (r *OCILayoutResolver) ImageName(ctx context.Context) (string, error) { +func (r *LayoutResolver) ImageName(_ context.Context) (string, error) { return r.SubjectName, nil } -func (r *OCILayoutResolver) ImageDescriptor(ctx context.Context) (*v1.Descriptor, error) { +func (r *LayoutResolver) ImageDescriptor(_ context.Context) (*v1.Descriptor, error) { return r.SubjectDescriptor, nil } -func (r *OCILayoutResolver) ImagePlatform(ctx context.Context) (*v1.Platform, error) { +func (r *LayoutResolver) ImagePlatform(_ context.Context) (*v1.Platform, error) { return r.ImageSpec.Platform, nil } -func attestationManifestFromOCILayout(path string, platform *v1.Platform) (*attestation.AttestationManifest, error) { +func attestationManifestFromOCILayout(path string, platform *v1.Platform) (*attestation.Manifest, error) { idx, err := layout.ImageIndexFromPath(path) if err != nil { return nil, err @@ -107,13 +107,15 @@ func attestationManifestFromOCILayout(path string, platform *v1.Platform) (*atte return nil, fmt.Errorf("failed to extract IndexManifest from ImageIndex: %w", err) } var subjectDescriptor *v1.Descriptor - for _, mf := range mfs2.Manifests { - if mf.Platform.Equals(*platform) { - subjectDescriptor = &mf + for i := range mfs2.Manifests { + manifest := &mfs2.Manifests[i] + if manifest.Platform.Equals(*platform) { + subjectDescriptor = manifest break } } - for _, mf := range mfs2.Manifests { + for i := range mfs2.Manifests { + mf := &mfs2.Manifests[i] if mf.Annotations[att.DockerReferenceType] != attestation.AttestationManifestType { continue } @@ -130,9 +132,9 @@ func attestationManifestFromOCILayout(path string, platform *v1.Platform) (*atte if err != nil { return nil, fmt.Errorf("failed to get attestations from image: %w", err) } - attest := &attestation.AttestationManifest{ + attest := &attestation.Manifest{ OriginalLayers: layers, - OriginalDescriptor: &mf, + OriginalDescriptor: mf, SubjectName: name, SubjectDescriptor: subjectDescriptor, } diff --git a/pkg/oci/oci.go b/pkg/oci/oci.go index c5a7638..f362224 100644 --- a/pkg/oci/oci.go +++ b/pkg/oci/oci.go @@ -18,7 +18,7 @@ import ( ) // ParsePlatform parses the provided platform string or attempts to obtain -// the platform of the current host system +// the platform of the current host system. func ParsePlatform(platformStr string) (*v1.Platform, error) { if platformStr == "" { cdp := platforms.Normalize(platforms.DefaultSpec()) @@ -30,14 +30,13 @@ func ParsePlatform(platformStr string) (*v1.Platform, error) { Architecture: cdp.Architecture, Variant: cdp.Variant, }, nil - } else { - return v1.ParsePlatform(platformStr) } + return v1.ParsePlatform(platformStr) } func WithOptions(ctx context.Context, platform *v1.Platform) []remote.Option { // prepare options - options := []remote.Option{MultiKeychainOption(), remote.WithTransport(HttpTransport()), remote.WithContext(ctx)} + options := []remote.Option{MultiKeychainOption(), remote.WithTransport(HTTPTransport()), remote.WithContext(ctx)} // add in platform into remote Get operation; this might conflict with an explicit digest, but we are trying anyway if platform != nil { @@ -46,7 +45,7 @@ func WithOptions(ctx context.Context, platform *v1.Platform) []remote.Option { return options } -func ExtractEnvelopes(manifest *attestation.AttestationManifest, predicateType string) ([]*att.Envelope, error) { +func ExtractEnvelopes(manifest *attestation.Manifest, predicateType string) ([]*att.Envelope, error) { var envs []*att.Envelope dsseMediaType, err := attestation.DSSEMediaType(predicateType) if err != nil { @@ -76,16 +75,18 @@ func ExtractEnvelopes(manifest *attestation.AttestationManifest, predicateType s } func imageDescriptor(ix *v1.IndexManifest, platform *v1.Platform) (*v1.Descriptor, error) { - for _, m := range ix.Manifests { + for i := range ix.Manifests { + m := &ix.Manifests[i] if (m.MediaType == ocispec.MediaTypeImageManifest || m.MediaType == "application/vnd.docker.distribution.manifest.v2+json") && m.Platform.Equals(*platform) { - return &m, nil + return m, nil } } return nil, fmt.Errorf("no image found for platform %v", platform) } func attestationDigestForDigest(ix *v1.IndexManifest, imageDigest string, attestType string) (string, error) { - for _, m := range ix.Manifests { + for i := range ix.Manifests { + m := &ix.Manifests[i] if v, ok := m.Annotations[att.DockerReferenceType]; ok && v == attestType { if d, ok := m.Annotations[att.DockerReferenceDigest]; ok && d == imageDigest { return m.Digest.String(), nil @@ -160,7 +161,7 @@ func ReplaceTagInSpec(src *ImageSpec, digest v1.Hash) (*ImageSpec, error) { }, nil } -// so that the index tag is replaced with a tag unique to the image digest and doesn't overwrite it +// so that the index tag is replaced with a tag unique to the image digest and doesn't overwrite it. func replaceTag(image string, digest v1.Hash) (string, error) { if strings.HasPrefix(image, LocalPrefix) { return image, nil diff --git a/pkg/oci/referrers.go b/pkg/oci/referrers.go index 3ef3e31..f5401c3 100644 --- a/pkg/oci/referrers.go +++ b/pkg/oci/referrers.go @@ -35,7 +35,7 @@ func WithReferrersRepo(repo string) func(*ReferrersResolver) error { } } -func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateType string) ([]*attestation.AttestationManifest, error) { +func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateType string) ([]*attestation.Manifest, error) { dsseMediaType, err := attestation.DSSEMediaType(predicateType) if err != nil { return nil, fmt.Errorf("failed to get DSSE media type for predicate '%s': %w", predicateType, err) @@ -75,8 +75,9 @@ func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateTy if err != nil { return nil, fmt.Errorf("failed to get index manifest: %w", err) } - aManifests := make([]*attestation.AttestationManifest, 0) - for _, m := range referrersIndexManifest.Manifests { + aManifests := make([]*attestation.Manifest, 0) + for i := range referrersIndexManifest.Manifests { + m := referrersIndexManifest.Manifests[i] remoteRef := referrersSubjectRef.Context().Digest(m.Digest.String()) options = WithOptions(ctx, nil) attestationImage, err := remote.Image(remoteRef, options...) @@ -97,7 +98,7 @@ func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateTy if string(mt) != dsseMediaType { return nil, fmt.Errorf("expected layer media type %s, got %s", dsseMediaType, mt) } - attest := &attestation.AttestationManifest{ + attest := &attestation.Manifest{ SubjectName: imageName, OriginalLayers: layers, OriginalDescriptor: &m, diff --git a/pkg/oci/registry.go b/pkg/oci/registry.go index 4e766c7..a36f4fd 100644 --- a/pkg/oci/registry.go +++ b/pkg/oci/registry.go @@ -13,7 +13,7 @@ import ( type RegistryResolver struct { *RegistryImageDetailsResolver - *attestation.AttestationManifest + *attestation.Manifest } type RegistryImageDetailsResolver struct { @@ -33,11 +33,11 @@ func NewRegistryAttestationResolver(src *RegistryImageDetailsResolver) (*Registr }, nil } -func (r *RegistryImageDetailsResolver) ImageName(ctx context.Context) (string, error) { +func (r *RegistryImageDetailsResolver) ImageName(_ context.Context) (string, error) { return r.Identifier, nil } -func (r *RegistryImageDetailsResolver) ImagePlatform(ctx context.Context) (*v1.Platform, error) { +func (r *RegistryImageDetailsResolver) ImagePlatform(_ context.Context) (*v1.Platform, error) { return r.Platform, nil } @@ -74,17 +74,17 @@ func (r *RegistryImageDetailsResolver) ImageDescriptor(ctx context.Context) (*v1 } func (r *RegistryResolver) Attestations(ctx context.Context, predicateType string) ([]*att.Envelope, error) { - if r.AttestationManifest == nil { + if r.Manifest == nil { attest, err := FetchAttestationManifest(ctx, r.Identifier, r.ImageSpec.Platform) if err != nil { return nil, err } - r.AttestationManifest = attest + r.Manifest = attest } - return ExtractEnvelopes(r.AttestationManifest, predicateType) + return ExtractEnvelopes(r.Manifest, predicateType) } -func FetchAttestationManifest(ctx context.Context, image string, platform *v1.Platform) (*attestation.AttestationManifest, error) { +func FetchAttestationManifest(ctx context.Context, image string, platform *v1.Platform) (*attestation.Manifest, error) { // we want to get to the image index, so ignoring platform for now options := WithOptions(ctx, nil) ref, err := name.ParseReference(image) @@ -131,7 +131,7 @@ func FetchAttestationManifest(ctx context.Context, image string, platform *v1.Pl if err != nil { return nil, fmt.Errorf("failed to get attestations from image: %w", err) } - attest := &attestation.AttestationManifest{ + attest := &attestation.Manifest{ OriginalLayers: layers, OriginalDescriptor: &remoteDescriptor.Descriptor, SubjectName: image, diff --git a/pkg/oci/types.go b/pkg/oci/types.go index 507f9da..689bf35 100644 --- a/pkg/oci/types.go +++ b/pkg/oci/types.go @@ -11,7 +11,7 @@ import ( ) const ( - OciReferenceTarget = "org.opencontainers.image.ref.name" + OCIReferenceTarget = "org.opencontainers.image.ref.name" LocalPrefix = "oci://" RegistryPrefix = "docker://" OCI SourceType = "OCI" @@ -52,7 +52,7 @@ func IndexFromPath(path string) (*NamedIndex, error) { if err != nil { return nil, fmt.Errorf("failed to get digest: %w", err) } - imageName := idxm.Manifests[0].Annotations[OciReferenceTarget] + imageName := idxm.Manifests[0].Annotations[OCIReferenceTarget] idxDigest := idxm.Manifests[0].Digest idx, err := wrapperIdx.ImageIndex(idxDigest) @@ -85,9 +85,8 @@ func IndexFromRemote(image string) (*NamedIndex, error) { func LoadIndex(input *ImageSpec) (*NamedIndex, error) { if input.Type == OCI { return IndexFromPath(input.Identifier) - } else { - return IndexFromRemote(input.Identifier) } + return IndexFromRemote(input.Identifier) } func (i *ImageSpec) ForPlatforms(platform string) ([]*ImageSpec, error) { diff --git a/pkg/policy/evaluator.go b/pkg/policy/evaluator.go index 2df6390..87492da 100644 --- a/pkg/policy/evaluator.go +++ b/pkg/policy/evaluator.go @@ -11,20 +11,20 @@ type policyEvaluatorCtxKeyType struct{} var PolicyEvaluatorCtxKey policyEvaluatorCtxKeyType -// sets PolicyEvaluator in context -func WithPolicyEvaluator(ctx context.Context, pe PolicyEvaluator) context.Context { +// sets PolicyEvaluator in context. +func WithPolicyEvaluator(ctx context.Context, pe Evaluator) context.Context { return context.WithValue(ctx, PolicyEvaluatorCtxKey, pe) } -// gets PolicyEvaluator from context, defaults to Rego PolicyEvaluator if not set -func GetPolicyEvaluator(ctx context.Context) (PolicyEvaluator, error) { - t, ok := ctx.Value(PolicyEvaluatorCtxKey).(PolicyEvaluator) +// gets PolicyEvaluator from context, defaults to Rego PolicyEvaluator if not set. +func GetPolicyEvaluator(ctx context.Context) (Evaluator, error) { + t, ok := ctx.Value(PolicyEvaluatorCtxKey).(Evaluator) if !ok { return nil, fmt.Errorf("no policy evaluator client set on context (set one with policy.WithPolicyEvaluator)") } return t, nil } -type PolicyEvaluator interface { - Evaluate(ctx context.Context, resolver oci.AttestationResolver, pctx *Policy, input *PolicyInput) (*Result, error) +type Evaluator interface { + Evaluate(ctx context.Context, resolver oci.AttestationResolver, pctx *Policy, input *Input) (*Result, error) } diff --git a/pkg/policy/mock.go b/pkg/policy/mock.go index 9904815..e6e724b 100644 --- a/pkg/policy/mock.go +++ b/pkg/policy/mock.go @@ -7,19 +7,19 @@ import ( ) type MockPolicyEvaluator struct { - EvaluateFunc func(ctx context.Context, resolver oci.AttestationResolver, pctx *Policy, input *PolicyInput) (*Result, error) + EvaluateFunc func(ctx context.Context, resolver oci.AttestationResolver, pctx *Policy, input *Input) (*Result, error) } -func (pe *MockPolicyEvaluator) Evaluate(ctx context.Context, resolver oci.AttestationResolver, pctx *Policy, input *PolicyInput) (*Result, error) { +func (pe *MockPolicyEvaluator) Evaluate(ctx context.Context, resolver oci.AttestationResolver, pctx *Policy, input *Input) (*Result, error) { if pe.EvaluateFunc != nil { return pe.EvaluateFunc(ctx, resolver, pctx, input) } return AllowedResult(), nil } -func GetMockPolicy() PolicyEvaluator { +func GetMockPolicy() Evaluator { return &MockPolicyEvaluator{ - EvaluateFunc: func(ctx context.Context, resolver oci.AttestationResolver, pctx *Policy, input *PolicyInput) (*Result, error) { + EvaluateFunc: func(_ context.Context, _ oci.AttestationResolver, _ *Policy, _ *Input) (*Result, error) { return AllowedResult(), nil }, } diff --git a/pkg/policy/policy.go b/pkg/policy/policy.go index 2f3650e..27bab5b 100644 --- a/pkg/policy/policy.go +++ b/pkg/policy/policy.go @@ -12,11 +12,11 @@ import ( "github.com/docker/attest/pkg/oci" ) -func resolveLocalPolicy(opts *PolicyOptions, mapping *config.PolicyMapping, imageName string, matchedName string) (*Policy, error) { +func resolveLocalPolicy(opts *Options, mapping *config.PolicyMapping, imageName string, matchedName string) (*Policy, error) { if opts.LocalPolicyDir == "" { return nil, fmt.Errorf("local policy dir not set") } - files := make([]*PolicyFile, 0, len(mapping.Files)) + files := make([]*File, 0, len(mapping.Files)) for _, f := range mapping.Files { filename := f.Path filePath := path.Join(opts.LocalPolicyDir, filename) @@ -24,7 +24,7 @@ func resolveLocalPolicy(opts *PolicyOptions, mapping *config.PolicyMapping, imag if err != nil { return nil, fmt.Errorf("failed to read policy file %s: %w", filename, err) } - files = append(files, &PolicyFile{ + files = append(files, &File{ Path: filename, Content: fileContents, }) @@ -39,15 +39,15 @@ func resolveLocalPolicy(opts *PolicyOptions, mapping *config.PolicyMapping, imag return policy, nil } -func resolveTufPolicy(opts *PolicyOptions, mapping *config.PolicyMapping, imageName string, matchedName string) (*Policy, error) { - files := make([]*PolicyFile, 0, len(mapping.Files)) +func resolveTUFPolicy(opts *Options, mapping *config.PolicyMapping, imageName string, matchedName string) (*Policy, error) { + files := make([]*File, 0, len(mapping.Files)) for _, f := range mapping.Files { filename := f.Path - _, fileContents, err := opts.TufClient.DownloadTarget(filename, filepath.Join(opts.LocalTargetsDir, filename)) + _, fileContents, err := opts.TUFClient.DownloadTarget(filename, filepath.Join(opts.LocalTargetsDir, filename)) if err != nil { return nil, fmt.Errorf("failed to download policy file %s: %w", filename, err) } - files = append(files, &PolicyFile{ + files = append(files, &File{ Path: filename, Content: fileContents, }) @@ -88,12 +88,12 @@ func findPolicyMatchImpl(imageName string, mappings *config.PolicyMappings, matc for _, rule := range mappings.Rules { if rule.Pattern.MatchString(imageName) { switch { - case rule.PolicyId == "" && rule.Replacement == "": + case rule.PolicyID == "" && rule.Replacement == "": return nil, fmt.Errorf("rule %s has neither policy-id nor rewrite", rule.Pattern) - case rule.PolicyId != "" && rule.Replacement != "": + case rule.PolicyID != "" && rule.Replacement != "": return nil, fmt.Errorf("rule %s has both policy-id and rewrite", rule.Pattern) - case rule.PolicyId != "": - policy := mappings.Policies[rule.PolicyId] + case rule.PolicyID != "": + policy := mappings.Policies[rule.PolicyID] if policy != nil { return &policyMatch{ matchType: matchTypePolicy, @@ -120,35 +120,35 @@ func findPolicyMatchImpl(imageName string, mappings *config.PolicyMappings, matc return &policyMatch{matchType: matchTypeNoMatch, matchedName: imageName}, nil } -func resolvePolicyById(opts *PolicyOptions) (*Policy, error) { - if opts.PolicyId != "" { +func resolvePolicyByID(opts *Options) (*Policy, error) { + if opts.PolicyID != "" { localMappings, err := config.LoadLocalMappings(opts.LocalPolicyDir) if err != nil { return nil, fmt.Errorf("failed to load local policy mappings: %w", err) } if localMappings != nil { - policy := localMappings.Policies[opts.PolicyId] + policy := localMappings.Policies[opts.PolicyID] if policy != nil { return resolveLocalPolicy(opts, policy, "", "") } } // must check tuf - tufMappings, err := config.LoadTufMappings(opts.TufClient, opts.LocalTargetsDir) + tufMappings, err := config.LoadTUFMappings(opts.TUFClient, opts.LocalTargetsDir) if err != nil { return nil, fmt.Errorf("failed to load tuf policy mappings by id: %w", err) } - policy := tufMappings.Policies[opts.PolicyId] + policy := tufMappings.Policies[opts.PolicyID] if policy != nil { - return resolveTufPolicy(opts, policy, "", "") + return resolveTUFPolicy(opts, policy, "", "") } - return nil, fmt.Errorf("policy with id %s not found", opts.PolicyId) + return nil, fmt.Errorf("policy with id %s not found", opts.PolicyID) } return nil, nil } -func ResolvePolicy(ctx context.Context, detailsResolver oci.ImageDetailsResolver, opts *PolicyOptions) (*Policy, error) { - p, err := resolvePolicyById(opts) +func ResolvePolicy(ctx context.Context, detailsResolver oci.ImageDetailsResolver, opts *Options) (*Policy, error) { + p, err := resolvePolicyByID(opts) if err != nil { return nil, fmt.Errorf("failed to resolve policy by id: %w", err) } @@ -175,7 +175,7 @@ func ResolvePolicy(ctx context.Context, detailsResolver oci.ImageDetailsResolver return resolveLocalPolicy(opts, match.policy, imageName, match.matchedName) } // must check tuf - tufMappings, err := config.LoadTufMappings(opts.TufClient, opts.LocalTargetsDir) + tufMappings, err := config.LoadTUFMappings(opts.TUFClient, opts.LocalTargetsDir) if err != nil { return nil, fmt.Errorf("failed to load tuf policy mappings as fallback: %w", err) } @@ -183,8 +183,8 @@ func ResolvePolicy(ctx context.Context, detailsResolver oci.ImageDetailsResolver // it's a mirror of a tuf policy if match.matchType == matchTypeMatchNoPolicy { for _, mapping := range tufMappings.Policies { - if mapping.Id == match.rule.PolicyId { - return resolveTufPolicy(opts, mapping, imageName, match.matchedName) + if mapping.ID == match.rule.PolicyID { + return resolveTUFPolicy(opts, mapping, imageName, match.matchedName) } } } @@ -195,7 +195,7 @@ func ResolvePolicy(ctx context.Context, detailsResolver oci.ImageDetailsResolver return nil, err } if match.matchType == matchTypePolicy { - return resolveTufPolicy(opts, match.policy, imageName, match.matchedName) + return resolveTUFPolicy(opts, match.policy, imageName, match.matchedName) } return nil, nil } @@ -229,7 +229,7 @@ func CreateAttestationResolver(resolver oci.ImageDetailsResolver, mapping *confi } return oci.NewReferrersAttestationResolver(resolver) } - case *oci.OCILayoutResolver: + case *oci.LayoutResolver: if mapping.Attestations != nil && mapping.Attestations.Style == config.AttestationStyleAttached { return resolver, nil } else { diff --git a/pkg/policy/policy_match_test.go b/pkg/policy/policy_match_test.go index 62d71bc..6682406 100644 --- a/pkg/policy/policy_match_test.go +++ b/pkg/policy/policy_match_test.go @@ -112,7 +112,7 @@ func TestFindPolicyMatch(t *testing.T) { assert.Equal(t, tc.expectedMatchType, match.matchType) if match.matchType == matchTypePolicy { if assert.NotNil(t, match.policy) { - assert.Equal(t, tc.expectedPolicyID, match.policy.Id) + assert.Equal(t, tc.expectedPolicyID, match.policy.ID) } } assert.Equal(t, tc.expectedImageName, match.matchedName) diff --git a/pkg/policy/policy_test.go b/pkg/policy/policy_test.go index b7f2fc6..c9917c1 100644 --- a/pkg/policy/policy_test.go +++ b/pkg/policy/policy_test.go @@ -47,13 +47,13 @@ func TestRegoEvaluator_Evaluate(t *testing.T) { expectSuccess bool isCanonical bool resolver oci.AttestationResolver - policy *policy.PolicyOptions - policyId string + policy *policy.Options + policyID string errorStr string }{ {repo: "testdata/mock-tuf-allow", expectSuccess: true, isCanonical: false, resolver: defaultResolver}, - {repo: "testdata/mock-tuf-allow", expectSuccess: true, isCanonical: false, resolver: defaultResolver, policyId: "docker-official-images"}, - {repo: "testdata/mock-tuf-allow", expectSuccess: false, isCanonical: false, resolver: defaultResolver, policyId: "non-existent-policy-id", errorStr: errorStr}, + {repo: "testdata/mock-tuf-allow", expectSuccess: true, isCanonical: false, resolver: defaultResolver, policyID: "docker-official-images"}, + {repo: "testdata/mock-tuf-allow", expectSuccess: false, isCanonical: false, resolver: defaultResolver, policyID: "non-existent-policy-id", errorStr: errorStr}, {repo: "testdata/mock-tuf-deny", expectSuccess: false, isCanonical: false, resolver: defaultResolver}, {repo: "testdata/mock-tuf-verify-sig", expectSuccess: true, isCanonical: false, resolver: defaultResolver}, {repo: "testdata/mock-tuf-wrong-key", expectSuccess: false, isCanonical: false, resolver: defaultResolver}, @@ -63,18 +63,18 @@ func TestRegoEvaluator_Evaluate(t *testing.T) { for _, tc := range testCases { t.Run(tc.repo, func(t *testing.T) { - input := &policy.PolicyInput{ + input := &policy.Input{ Digest: "sha256:test-digest", - Purl: "test-purl", + PURL: "test-purl", IsCanonical: tc.isCanonical, } tufClient := tuf.NewMockTufClient(tc.repo, test.CreateTempDir(t, "", "tuf-dest")) if tc.policy == nil { - tc.policy = &policy.PolicyOptions{ - TufClient: tufClient, + tc.policy = &policy.Options{ + TUFClient: tufClient, LocalTargetsDir: test.CreateTempDir(t, "", "tuf-targets"), - PolicyId: tc.policyId, + PolicyID: tc.policyID, } } imageName, err := tc.resolver.ImageName(ctx) @@ -110,8 +110,8 @@ func TestLoadingMappings(t *testing.T) { require.NoError(t, err) assert.Equal(t, len(policyMappings.Rules), 3) for _, mirror := range policyMappings.Rules { - if mirror.PolicyId != "" { - assert.Equal(t, "docker-official-images", mirror.PolicyId) + if mirror.PolicyID != "" { + assert.Equal(t, "docker-official-images", mirror.PolicyID) } } } diff --git a/pkg/policy/rego.go b/pkg/policy/rego.go index a3e8ec0..5dec1c3 100644 --- a/pkg/policy/rego.go +++ b/pkg/policy/rego.go @@ -30,13 +30,13 @@ const ( resultBinding = "result" ) -func NewRegoEvaluator(debug bool) PolicyEvaluator { +func NewRegoEvaluator(debug bool) Evaluator { return ®oEvaluator{ debug: debug, } } -func (re *regoEvaluator) Evaluate(ctx context.Context, resolver oci.AttestationResolver, pctx *Policy, input *PolicyInput) (*Result, error) { +func (re *regoEvaluator) Evaluate(ctx context.Context, resolver oci.AttestationResolver, pctx *Policy, input *Input) (*Result, error) { var regoOpts []func(*rego.Rego) // Create a new in-memory store @@ -113,7 +113,7 @@ func (re *regoEvaluator) Evaluate(ctx context.Context, resolver oci.AttestationR } func jsonGenerator[T any]() func(t *ast.Term, ec *rego.EvalContext) (any, error) { - return func(t *ast.Term, ec *rego.EvalContext) (any, error) { + return func(t *ast.Term, _ *rego.EvalContext) (any, error) { // TODO: this is horrible - we're converting the AST to JSON and then back to AST, then using ast.As to convert it to a struct // We can't use ast.As directly because it fails if the AST contains a set json, err := ast.JSON(t.Value) @@ -164,9 +164,9 @@ func handleErrors1(f func(rCtx rego.BuiltinContext, a *ast.Term) (*ast.Term, err } } -func handleErrors2(f func(rCtx rego.BuiltinContext, a, b *ast.Term) (*ast.Term, error)) rego.Builtin2 { +func handleErrors2(f func(rCtx *rego.BuiltinContext, a, b *ast.Term) (*ast.Term, error)) rego.Builtin2 { return func(rCtx rego.BuiltinContext, a, b *ast.Term) (*ast.Term, error) { - return wrapFunctionResult(f(rCtx, a, b)) + return wrapFunctionResult(f(&rCtx, a, b)) } } @@ -181,7 +181,7 @@ func RegoFunctions(resolver oci.AttestationResolver) []*tester.Builtin { Memoize: true, Nondeterministic: verifyDecl.Nondeterministic, }, - handleErrors2(verifyIntotoEnvelope)), + handleErrors2(verifyInTotoEnvelope)), }, { Decl: attestDecl, @@ -192,12 +192,12 @@ func RegoFunctions(resolver oci.AttestationResolver) []*tester.Builtin { Memoize: true, Nondeterministic: attestDecl.Nondeterministic, }, - handleErrors1(fetchIntotoAttestations(resolver))), + handleErrors1(fetchInTotoAttestations(resolver))), }, } } -func fetchIntotoAttestations(resolver oci.AttestationResolver) rego.Builtin1 { +func fetchInTotoAttestations(resolver oci.AttestationResolver) rego.Builtin1 { return func(rCtx rego.BuiltinContext, predicateTypeTerm *ast.Term) (*ast.Term, error) { predicateTypeStr, ok := predicateTypeTerm.Value.(ast.String) if !ok { @@ -227,7 +227,7 @@ func fetchIntotoAttestations(resolver oci.AttestationResolver) rego.Builtin1 { } } -func verifyIntotoEnvelope(rCtx rego.BuiltinContext, envTerm, optsTerm *ast.Term) (*ast.Term, error) { +func verifyInTotoEnvelope(rCtx *rego.BuiltinContext, envTerm, optsTerm *ast.Term) (*ast.Term, error) { env := new(att.Envelope) opts := new(att.VerifyOptions) err := ast.As(envTerm.Value, env) diff --git a/pkg/policy/types.go b/pkg/policy/types.go index 6f534a4..54cc993 100644 --- a/pkg/policy/types.go +++ b/pkg/policy/types.go @@ -26,29 +26,29 @@ type Result struct { Summary Summary `json:"summary"` } -type PolicyOptions struct { - TufClient tuf.TUFClient +type Options struct { + TUFClient tuf.Downloader LocalTargetsDir string LocalPolicyDir string - PolicyId string + PolicyID string ReferrersRepo string AttestationStyle config.AttestationStyle } type Policy struct { - InputFiles []*PolicyFile + InputFiles []*File Query string Mapping *config.PolicyMapping ResolvedName string } -type PolicyInput struct { +type Input struct { Digest string `json:"digest"` - Purl string `json:"purl"` + PURL string `json:"purl"` IsCanonical bool `json:"isCanonical"` } -type PolicyFile struct { +type File struct { Path string Content []byte } diff --git a/pkg/signerverifier/aws.go b/pkg/signerverifier/aws.go index 45f968a..8f817bb 100644 --- a/pkg/signerverifier/aws.go +++ b/pkg/signerverifier/aws.go @@ -9,18 +9,18 @@ import ( awssigner "github.com/sigstore/sigstore/pkg/signature/kms/aws" ) -// using AWS KMS -func GetAWSSigner(ctx context.Context, keyArn string, region string) (dsse.SignerVerifier, error) { - keypath := fmt.Sprintf("awskms:///%s", keyArn) - sv, err := awssigner.LoadSignerVerifier(ctx, keypath, config.WithRegion(region)) +// using AWS KMS. +func GetAWSSigner(ctx context.Context, keyARN string, region string) (dsse.SignerVerifier, error) { + keyPath := fmt.Sprintf("awskms:///%s", keyARN) + sv, err := awssigner.LoadSignerVerifier(ctx, keyPath, config.WithRegion(region)) if err != nil { return nil, fmt.Errorf("error loading aws signer verifier: %w", err) } - cs, _, err := sv.CryptoSigner(context.Background(), func(err error) {}) + cs, _, err := sv.CryptoSigner(context.Background(), func(_ error) {}) if err != nil { return nil, fmt.Errorf("error getting aws crypto signer: %w", err) } - signer := &ECDSA256_SignerVerifier{ + signer := &ECDSA256SignerVerifier{ Signer: cs, } return signer, nil diff --git a/pkg/signerverifier/common.go b/pkg/signerverifier/common.go index f15034c..87124fd 100644 --- a/pkg/signerverifier/common.go +++ b/pkg/signerverifier/common.go @@ -14,12 +14,12 @@ import ( "github.com/secure-systems-lab/go-securesystemslib/dsse" ) -type ECDSA256_SignerVerifier struct { +type ECDSA256SignerVerifier struct { crypto.Signer } -// implement keyid function -func (s *ECDSA256_SignerVerifier) KeyID() (string, error) { +// implement keyid function. +func (s *ECDSA256SignerVerifier) KeyID() (string, error) { keyid, err := KeyID(s.Signer.Public()) if err != nil { return "", fmt.Errorf("error getting keyid: %w", err) @@ -27,15 +27,15 @@ func (s *ECDSA256_SignerVerifier) KeyID() (string, error) { return keyid, nil } -func (s *ECDSA256_SignerVerifier) Public() crypto.PublicKey { +func (s *ECDSA256SignerVerifier) Public() crypto.PublicKey { return s.Signer.Public() } -func (s *ECDSA256_SignerVerifier) Sign(ctx context.Context, data []byte) ([]byte, error) { +func (s *ECDSA256SignerVerifier) Sign(_ context.Context, data []byte) ([]byte, error) { return s.Signer.Sign(rand.Reader, data, crypto.SHA256) } -func (s *ECDSA256_SignerVerifier) Verify(ctx context.Context, data []byte, sig []byte) error { +func (s *ECDSA256SignerVerifier) Verify(_ context.Context, data []byte, sig []byte) error { pub, ok := s.Signer.Public().(*ecdsa.PublicKey) if !ok { return fmt.Errorf("public key is not ecdsa") @@ -52,7 +52,7 @@ func LoadKeyPair(priv []byte) (dsse.SignerVerifier, error) { if err != nil { return nil, err } - return &ECDSA256_SignerVerifier{ + return &ECDSA256SignerVerifier{ Signer: privateKey, }, nil } @@ -78,7 +78,7 @@ func GenKeyPair() (dsse.SignerVerifier, error) { if err != nil { return nil, err } - return &ECDSA256_SignerVerifier{ + return &ECDSA256SignerVerifier{ Signer: signer, }, nil } diff --git a/pkg/signerverifier/gcp.go b/pkg/signerverifier/gcp.go index e0221cd..e8b81a4 100644 --- a/pkg/signerverifier/gcp.go +++ b/pkg/signerverifier/gcp.go @@ -10,18 +10,18 @@ import ( ) // using GCP KMS -// reference should be in the format projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEY_RING]/cryptoKeys/[KEY]/cryptoKeyVersions/[VERSION] +// reference should be in the format projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEY_RING]/cryptoKeys/[KEY]/cryptoKeyVersions/[VERSION]. func GetGCPSigner(ctx context.Context, reference string, opts ...option.ClientOption) (dsse.SignerVerifier, error) { reference = fmt.Sprintf("gcpkms://%s", reference) sv, err := gcpsigner.LoadSignerVerifier(ctx, reference, opts...) if err != nil { return nil, fmt.Errorf("error loading gcp signer verifier: %w", err) } - cs, _, err := sv.CryptoSigner(ctx, func(err error) {}) + cs, _, err := sv.CryptoSigner(ctx, func(_ error) {}) if err != nil { return nil, fmt.Errorf("error getting gcp crypto signer: %w", err) } - signer := &ECDSA256_SignerVerifier{ + signer := &ECDSA256SignerVerifier{ Signer: cs, } return signer, nil diff --git a/pkg/signerverifier/gcp_test.go b/pkg/signerverifier/gcp_test.go index 78ca8c4..90f4ac5 100644 --- a/pkg/signerverifier/gcp_test.go +++ b/pkg/signerverifier/gcp_test.go @@ -37,7 +37,7 @@ func TestGCPKMS_Signer(t *testing.T) { keyId, err := signer.KeyID() require.NoError(t, err) assert.NotEmpty(t, keyId) - publicKey, err := Parse([]byte(publicKeyPEM)) + publicKey, err := ParsePublicKey([]byte(publicKeyPEM)) require.NoError(t, err) // verify payload ecdsa signature ok := ecdsa.VerifyASN1(publicKey, hash, sig) diff --git a/pkg/signerverifier/keyid.go b/pkg/signerverifier/keyid.go index 4bd0c4a..f709f7d 100644 --- a/pkg/signerverifier/keyid.go +++ b/pkg/signerverifier/keyid.go @@ -11,7 +11,7 @@ import ( func KeyID(pubKey crypto.PublicKey) (string, error) { pub, err := x509.MarshalPKIXPublicKey(pubKey) if err != nil { - return "", fmt.Errorf("error marshalling public key: %w", err) + return "", fmt.Errorf("error marshaling public key: %w", err) } return util.SHA256Hex(pub), nil } diff --git a/pkg/signerverifier/parse.go b/pkg/signerverifier/parse.go index ca00038..c4be243 100644 --- a/pkg/signerverifier/parse.go +++ b/pkg/signerverifier/parse.go @@ -9,7 +9,7 @@ import ( const pemType = "PUBLIC KEY" -func Parse(pubkeyBytes []byte) (*ecdsa.PublicKey, error) { +func ParsePublicKey(pubkeyBytes []byte) (*ecdsa.PublicKey, error) { p, _ := pem.Decode(pubkeyBytes) if p == nil { return nil, fmt.Errorf("pubkey file does not contain any PEM data") @@ -29,7 +29,7 @@ func Parse(pubkeyBytes []byte) (*ecdsa.PublicKey, error) { return ecdsaPubKey, nil } -func ToPEM(ecdsaPubKey *ecdsa.PublicKey) ([]byte, error) { +func ConvertToPEM(ecdsaPubKey *ecdsa.PublicKey) ([]byte, error) { pubKeyBytes, err := x509.MarshalPKIXPublicKey(ecdsaPubKey) if err != nil { return nil, fmt.Errorf("error failed to marshal public key: %w", err) diff --git a/pkg/tlog/mock.go b/pkg/tlog/mock.go index 6f7fac1..33bf80b 100644 --- a/pkg/tlog/mock.go +++ b/pkg/tlog/mock.go @@ -10,7 +10,7 @@ import ( ) const ( - USE_MOCK_TL = true + UseMockTL = true TestEntry = `{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI5Zjg2ZDA4MTg4NGM3ZDY1OWEyZmVhYTBjNTVhZDAxNWEzYmY0ZjFiMmIwYjgyMmNkMTVkNmMxNWIwZjAwYTA4In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJQUlyVUZGUzBIYmNzZjc5L08yajVXdHl2R2Vvd1NVSXpZcDlBM2IwWnREVUFpQVQxZU42ZjFyVmVWa011REFlN3dxWkJ2bE5LY2VsajNVVDNmaWhyQjZSY2c9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVSlZla05DSzJGQlJFRm5SVU5CWjBWQ1RVRnZSME5EY1VkVFRUUTVRa0ZOUTAxQk9IaEVWRUZNUW1kT1ZrSkJUVlJDU0ZKc1l6TlJkMGhvWTA0S1RXcE5lRTFxU1ROTlZHdDVUWHBWTlZkb1kwNU5hbEY0VFdwSk1rMVVhM2xOZWxVMVYycEJVRTFSTUhkRGQxbEVWbEZSUkVWM1VqQmFXRTR3VFVacmR3cEZkMWxJUzI5YVNYcHFNRU5CVVZsSlMyOWFTWHBxTUVSQlVXTkVVV2RCUlVRMFZpdFNSV2g0SzJGeFYwZzNlV3hOVFVSSVlXaE9UVzVOVEZOUFNsQXZDamxyUVcwNWJIQXJNMjF4V1ZSQmFGVlNjbUUyVDBRMVVYZzRXbUprSzJWMVVIbFFhemw1SzNjdloxZEhSRUk1ZW00dlNXd3hTMDVIVFVWUmQwUm5XVVFLVmxJd1VFRlJTQzlDUVZGRVFXZGxRVTFDVFVkQk1WVmtTbEZSVFUxQmIwZERRM05IUVZGVlJrSjNUVVJOUVhkSFFURlZaRVYzUlVJdmQxRkRUVUZCZHdwRWQxbEVWbEl3VWtKQlozZENiMGxGWkVkV2VtUkVRVXRDWjJkeGFHdHFUMUJSVVVSQlowNUtRVVJDUjBGcFJVRTNOMjFFTDFSbVJtRlJVemxrWlhRMENqbFhaRk41YURKT1VTOUZiMVJtYVVGdFFtaHVWblpEVTNSUVowTkpVVU1yZDNSdllpOU9iMUp4T0c5cU4wZDNibTVKYUZKVGRDOVJNbmtyVXpoUkwzSUthRkpVYW5GaE9HZExRVDA5Q2kwdExTMHRSVTVFSUVORlVsUkpSa2xEUVZSRkxTMHRMUzBLIn19fX0=","integratedTime":1703705039,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d","logIndex":59674396,"verification":{"inclusionProof":{"checkpoint":"rekor.sigstore.dev - 2605736670972794746\n55510966\nJCi1O53Xmdi9lXnui4Q5SQ+MJSMnWr1Bxn+Q2Qf22tU=\nTimestamp: 1703705040158839214\n\n— rekor.sigstore.dev wNI9ajBFAiAXgtjFDVqCSgiSP04TQzELrz4+EyBwyYVL2EEULTCy0AIhAI9peLU76ZUD1tvU8qvzBJBo77IYD1rc+A1MPc35AeVK\n","hashes":["fb77ee213b48f4b18dc81c6e634c570abf99b257713561f174f2e0f4c039af67","6cb113bbefadecbbb8b89b1c08232438a6125071790b6a062cff8c1ccfdcb91e","6fbe1424e264e4590ca502d671b7a036c87f7a90d1f57534b98eb781144160bf","077b606720a6478200f6c3ed08a68e9b01b1cae192cb120888ddcc95521601bd","b6f8e8bc21ae0cde82b92422a4b4f37b28a43185821e468a4e65b6c79ed8f5b7","89332533fac54e9bc68c7353c42f6ebb9fe38039f67910332ff95082072068d4","0814d6f707a75fb3334bab14ab5466bd8b9a64ae7be7cd4d53a428c64932bc66","e883e826f10329c63a4a2ed21156037a050df43b9d74079296beac6968ed4150","d79230703257b7e4a8a61b032b6980d1a0bdbc7ae96ca838b525b3751785fe48","2f4a77e5288462cd3b75084d37f1502dcbe0943d18dd95cb247fc1ebbabc0aad","38562c253d3536d0d00e3547c880b6b0251a25ac69605b50c9eaa1a27186cc7a","9dea192350ff8b3c0f5ccda38261cb38ebd61869281c3928912332d1144e0a04","2c4d25ba59aa573ab2c79c2d3cd9e1d74789b10632432724d63112ce50b44874","98c486feb5d87092a78a46c4b5be04868654900affc2e86ffb20074dc73a883a","6969c49bd73f19bf28a5eaeabd331ddd60502defb2cd3d96e17b741c80adec6c"],"logIndex":55510965,"rootHash":"2428b53b9dd799d8bd9579ee8b8439490f8c2523275abd41c67f90d907f6dad5","treeSize":55510966},"signedEntryTimestamp":"MEUCIQCG9PRI8PcvtJyE9pbcculZipze6NEWR1Nk8EYocto3BwIgYu5gqgjW80HMjSjUxUNJLp0wlVTesnJCeByUBySc59w="}}` ) @@ -26,10 +26,10 @@ func GetMockTL() TL { } return &MockTL{ - UploadLogEntryFunc: func(ctx context.Context, subject string, payload []byte, signature []byte, signer dsse.SignerVerifier) ([]byte, error) { + UploadLogEntryFunc: func(_ context.Context, _ string, _ []byte, _ []byte, _ dsse.SignerVerifier) ([]byte, error) { return []byte(TestEntry), nil }, - VerifyLogEntryFunc: func(ctx context.Context, entryBytes []byte) (time.Time, error) { + VerifyLogEntryFunc: func(_ context.Context, entryBytes []byte) (time.Time, error) { // return the integrated time in the log entry without any checking le, err := unmarshalEntry(entryBytes) if err != nil { @@ -40,7 +40,7 @@ func GetMockTL() TL { } return time.Unix(*le.IntegratedTime, 0), nil }, - VerifyEntryPayloadFunc: func(entryBytes, payload, pkToken []byte) error { + VerifyEntryPayloadFunc: func(_, _, _ []byte) error { return nil }, UnmarshalEntryFunc: func(entry []byte) (any, error) { diff --git a/pkg/tlog/tl.go b/pkg/tlog/tl.go index 8bddeab..906fa8f 100644 --- a/pkg/tlog/tl.go +++ b/pkg/tlog/tl.go @@ -1,6 +1,7 @@ package tlog import ( + "bytes" "context" "crypto/rand" "crypto/sha256" @@ -31,23 +32,23 @@ const ( type tlCtxKeyType struct{} -var TlCtxKey tlCtxKeyType +var TLCtxKey tlCtxKeyType -// sets TL in context +// sets TL in context. func WithTL(ctx context.Context, tl TL) context.Context { - return context.WithValue(ctx, TlCtxKey, tl) + return context.WithValue(ctx, TLCtxKey, tl) } -// gets TL from context, defaults to Rekor TL if not set +// gets TL from context, defaults to Rekor TL if not set. func GetTL(ctx context.Context) TL { - t, ok := ctx.Value(TlCtxKey).(TL) + t, ok := ctx.Value(TLCtxKey).(TL) if !ok { t = &RekorTL{} } return t } -type TlPayload struct { +type TLPayload struct { Algorithm string Hash string Signature string @@ -98,7 +99,7 @@ func (tl *MockTL) UnmarshalEntry(entryBytes []byte) (any, error) { type RekorTL struct{} -// UploadLogEntry submits a PK token signature to the transparency log +// UploadLogEntry submits a PK token signature to the transparency log. func (tl *RekorTL) UploadLogEntry(ctx context.Context, subject string, payload, signature []byte, signer dsse.SignerVerifier) ([]byte, error) { // generate self-signed x509 cert pubCert, err := CreateX509Cert(subject, signer) @@ -121,12 +122,12 @@ func (tl *RekorTL) UploadLogEntry(ctx context.Context, subject string, payload, } entryBytes, err := entry.MarshalBinary() if err != nil { - return nil, fmt.Errorf("error marshalling TL entry: %w", err) + return nil, fmt.Errorf("error marshaling TL entry: %w", err) } return entryBytes, nil } -// VerifyLogEntry verifies a transparency log entry +// VerifyLogEntry verifies a transparency log entry. func (tl *RekorTL) VerifyLogEntry(ctx context.Context, entryBytes []byte) (time.Time, error) { zeroTime := time.Time{} entry, err := tl.UnmarshalEntry(entryBytes) @@ -157,12 +158,12 @@ func (tl *RekorTL) VerifyLogEntry(ctx context.Context, entryBytes []byte) (time. return integratedTime, nil } -// CreateX509Cert generates a self-signed x509 cert for TL submission +// CreateX509Cert generates a self-signed x509 cert for TL submission. func CreateX509Cert(subject string, signer dsse.SignerVerifier) ([]byte, error) { // encode ephemeral public key ecPub, err := x509.MarshalPKIXPublicKey(signer.Public()) if err != nil { - return nil, fmt.Errorf("error marshalling public key: %w", err) + return nil, fmt.Errorf("error marshaling public key: %w", err) } template := x509.Certificate{ @@ -180,7 +181,7 @@ func CreateX509Cert(subject string, signer dsse.SignerVerifier) ([]byte, error) // dsse.SignerVerifier doesn't implement cypto.Signer exactly - csigner, ok := signer.(*signerverifier.ECDSA256_SignerVerifier) + csigner, ok := signer.(*signerverifier.ECDSA256SignerVerifier) if !ok { return nil, fmt.Errorf("expected signer to be of type *signerverifier.ECDSA_SignerVerifier, got %T", signer) } @@ -193,7 +194,7 @@ func CreateX509Cert(subject string, signer dsse.SignerVerifier) ([]byte, error) return pem.EncodeToMemory(certBlock), nil } -// VerifyEntryPayload checks that the TL entry payload matches envelope payload +// VerifyEntryPayload checks that the TL entry payload matches envelope payload. func (tl *RekorTL) VerifyEntryPayload(entryBytes, payload, publicKey []byte) error { entry, err := tl.UnmarshalEntry(entryBytes) if err != nil { @@ -228,7 +229,7 @@ func (tl *RekorTL) VerifyEntryPayload(entryBytes, payload, publicKey []byte) err if err != nil { return fmt.Errorf("failed to parse certificate: %w", err) } - if string(result.RawSubjectPublicKeyInfo) != string(publicKey) { + if !bytes.Equal(result.RawSubjectPublicKeyInfo, publicKey) { return fmt.Errorf("error payload and tl entry public key mismatch") } return nil @@ -243,9 +244,9 @@ func (tl *RekorTL) UnmarshalEntry(entry []byte) (any, error) { return le, nil } -func extractHashedRekord(Body string) (*TlPayload, error) { - sig := new(TlPayload) - pe, err := models.UnmarshalProposedEntry(base64.NewDecoder(base64.StdEncoding, strings.NewReader(Body)), runtime.JSONConsumer()) +func extractHashedRekord(body string) (*TLPayload, error) { + sig := new(TLPayload) + pe, err := models.UnmarshalProposedEntry(base64.NewDecoder(base64.StdEncoding, strings.NewReader(body)), runtime.JSONConsumer()) if err != nil { return nil, err } diff --git a/pkg/tlog/tl_test.go b/pkg/tlog/tl_test.go index a51c3c9..4df4aca 100644 --- a/pkg/tlog/tl_test.go +++ b/pkg/tlog/tl_test.go @@ -14,7 +14,7 @@ import ( ) const ( - // test artifacts + // test artifacts. TestPayload = "test" TestPublicKey = "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAED4V+REhx+aqWH7ylMMDHahNMnMLS\nOJP/9kAm9lp+3mqYTAhURra6OD5Qx8Zbd+euPyPk9y+w/gWGDB9zn/Il1A==\n-----END PUBLIC KEY-----" ) @@ -53,15 +53,15 @@ func TestUploadAndVerifyLogEntry(t *testing.T) { assert.NoError(t, err) var tl TL - if USE_MOCK_TL { + if UseMockTL { tl = &MockTL{ - UploadLogEntryFunc: func(ctx context.Context, subject string, payload []byte, signature []byte, signer dsse.SignerVerifier) ([]byte, error) { + UploadLogEntryFunc: func(_ context.Context, _ string, _ []byte, _ []byte, _ dsse.SignerVerifier) ([]byte, error) { return []byte(TestEntry), nil }, - VerifyLogEntryFunc: func(ctx context.Context, entryBytes []byte) (time.Time, error) { + VerifyLogEntryFunc: func(_ context.Context, _ []byte) (time.Time, error) { return time.Time{}, nil }, - VerifyEntryPayloadFunc: func(entryBytes, payload, publicKey []byte) error { + VerifyEntryPayloadFunc: func(_, _, _ []byte) error { return nil }, } diff --git a/pkg/tuf/example_registry_test.go b/pkg/tuf/example_registry_test.go index a1b4821..bf9ddbc 100644 --- a/pkg/tuf/example_registry_test.go +++ b/pkg/tuf/example_registry_test.go @@ -9,7 +9,7 @@ import ( "github.com/theupdateframework/go-tuf/v2/metadata" ) -func ExampleNewTufClient_registry() { +func ExampleNewClient_registry() { // create a tuf client home, err := os.UserHomeDir() if err != nil { @@ -21,7 +21,7 @@ func ExampleNewTufClient_registry() { metadataURI := "registry-1.docker.io/docker/tuf-metadata:latest" targetsURI := "registry-1.docker.io/docker/tuf-targets" - registryClient, err := tuf.NewTufClient(embed.RootStaging.Data, tufOutputPath, metadataURI, targetsURI, tuf.NewMockVersionChecker()) + registryClient, err := tuf.NewClient(embed.RootStaging.Data, tufOutputPath, metadataURI, targetsURI, tuf.NewMockVersionChecker()) if err != nil { panic(err) } diff --git a/pkg/tuf/mock.go b/pkg/tuf/mock.go index bdd065f..ae79545 100644 --- a/pkg/tuf/mock.go +++ b/pkg/tuf/mock.go @@ -6,25 +6,25 @@ import ( "path/filepath" ) -type mockTufClient struct { +type MockTufClient struct { srcPath string dstPath string } -func NewMockTufClient(srcPath string, dstPath string) *mockTufClient { +func NewMockTufClient(srcPath string, dstPath string) *MockTufClient { if srcPath == "" { panic("srcPath must be set") } if dstPath == "" { panic("dstPath must be set") } - return &mockTufClient{ + return &MockTufClient{ srcPath: srcPath, dstPath: dstPath, } } -func (dc *mockTufClient) DownloadTarget(target string, filePath string) (actualFilePath string, data []byte, err error) { +func (dc *MockTufClient) DownloadTarget(target string, filePath string) (actualFilePath string, data []byte, err error) { src, err := os.Open(filepath.Join(dc.srcPath, target)) if err != nil { return "", nil, err @@ -59,14 +59,14 @@ func (dc *mockTufClient) DownloadTarget(target string, filePath string) (actualF return dstFilePath, b, nil } -type mockVersionChecker struct { +type MockVersionChecker struct { err error } -func NewMockVersionChecker() *mockVersionChecker { - return &mockVersionChecker{} +func NewMockVersionChecker() *MockVersionChecker { + return &MockVersionChecker{} } -func (vc *mockVersionChecker) CheckVersion(client TUFClient) error { +func (vc *MockVersionChecker) CheckVersion(_ Downloader) error { return vc.err } diff --git a/pkg/tuf/registry.go b/pkg/tuf/registry.go index 3aad2bd..fa47cc3 100644 --- a/pkg/tuf/registry.go +++ b/pkg/tuf/registry.go @@ -19,14 +19,14 @@ import ( ) const ( - TufFileNameAnnotation = "tuf.io/filename" + TUFFileNameAnnotation = "tuf.io/filename" ) -type TufRole string +type Role string -var TufRoles = []TufRole{metadata.ROOT, metadata.SNAPSHOT, metadata.TARGETS, metadata.TIMESTAMP} +var Roles = []Role{metadata.ROOT, metadata.SNAPSHOT, metadata.TARGETS, metadata.TIMESTAMP} -// RegistryFetcher implements Fetcher +// RegistryFetcher implements Fetcher. type RegistryFetcher struct { httpUserAgent string metadataRepo string @@ -46,13 +46,13 @@ func NewImageCache() *ImageCache { } } -// Get image from cache +// Get image from cache. func (c *ImageCache) Get(imgRef string) ([]byte, bool) { img, found := c.cache[imgRef] return img, found } -// Add image to cache +// Add image to cache. func (c *ImageCache) Put(imgRef string, img []byte) { c.cache[imgRef] = img } @@ -113,7 +113,7 @@ func (d *RegistryFetcher) DownloadFile(urlPath string, maxLength int64, timeout } } -// getManifest returns the manifest for an image or index +// getManifest returns the manifest for an image or index. func (d *RegistryFetcher) getManifest(ref string) ([]byte, error) { // Pull image manifest var err error @@ -135,7 +135,7 @@ func (d *RegistryFetcher) getManifest(ref string) ([]byte, error) { return mf, nil } -// pullFileLayer pulls a layer for an image or index and returns its data +// pullFileLayer pulls a layer for an image or index and returns its data. func (d *RegistryFetcher) pullFileLayer(ref string, maxLength int64) ([]byte, error) { var data []byte var found bool @@ -159,7 +159,7 @@ func (d *RegistryFetcher) pullFileLayer(ref string, maxLength int64) ([]byte, er return data, nil } -// getDataFromLayer returns the data from a layer in an image +// getDataFromLayer returns the data from a layer in an image. func getDataFromLayer(fileLayer v1.Layer, maxLength int64) ([]byte, error) { length, err := fileLayer.Size() if err != nil { @@ -185,7 +185,7 @@ func getDataFromLayer(fileLayer v1.Layer, maxLength int64) ([]byte, error) { return data, nil } -// parseImgRef maintains the Fetcher interface by parsing a URL path to an image reference and file name +// parseImgRef maintains the Fetcher interface by parsing a URL path to an image reference and file name. func (d *RegistryFetcher) parseImgRef(urlPath string) (imgRef, fileName string, err error) { // Check if repo is target or metadata if strings.Contains(urlPath, d.targetsRepo) { @@ -208,12 +208,11 @@ func (d *RegistryFetcher) parseImgRef(urlPath string) (imgRef, fileName string, return fmt.Sprintf("%s:%s", d.metadataRepo, role), fileName, nil } return fmt.Sprintf("%s:%s", d.metadataRepo, d.metadataTag), fileName, nil - } else { - return "", "", fmt.Errorf("urlPath: %s must be in metadata or targets repo", urlPath) } + return "", "", fmt.Errorf("urlPath: %s must be in metadata or targets repo", urlPath) } -// findFileInManifest searches the image or index manifest for a file with the given name and returns its digest +// findFileInManifest searches the image or index manifest for a file with the given name and returns its digest. func (d *RegistryFetcher) findFileInManifest(mf []byte, name string) (*v1.Hash, error) { var index bool @@ -226,20 +225,21 @@ func (d *RegistryFetcher) findFileInManifest(mf []byte, name string) (*v1.Hash, // determine image or index manifest var layers []Layer - if l.MediaType == string(types.OCIImageIndex) { + switch l.MediaType { + case string(types.OCIImageIndex): layers = l.Manifests index = true - } else if l.MediaType == string(types.OCIManifestSchema1) { + case string(types.OCIManifestSchema1): layers = l.Layers index = false - } else { + default: return nil, fmt.Errorf("invalid manifest media type: %s", l.MediaType) } // find annotation with file name var digest string for _, layer := range layers { - if layer.Annotations[TufFileNameAnnotation] == name { + if layer.Annotations[TUFFileNameAnnotation] == name { digest = layer.Digest break } @@ -267,7 +267,7 @@ func (d *RegistryFetcher) findFileInManifest(mf []byte, name string) (*v1.Hash, return hash, nil } -// transportWithTimeout returns a http.RoundTripper with a specified timeout +// transportWithTimeout returns a http.RoundTripper with a specified timeout. func transportWithTimeout(timeout time.Duration) http.RoundTripper { // transport is based on go-containerregistry remote.DefaultTransport // with modifications to include a specified timeout @@ -286,9 +286,9 @@ func transportWithTimeout(timeout time.Duration) http.RoundTripper { } } -// isDelegatedRole returns true if the role is a delegated role +// isDelegatedRole returns true if the role is a delegated role. func isDelegatedRole(role string) bool { - for _, r := range TufRoles { + for _, r := range Roles { if role == string(r) { return false // role is not a delegated role } @@ -296,7 +296,7 @@ func isDelegatedRole(role string) bool { return true // role is a delegated role } -// roleFromConsistentName returns the role name from a consistent snapshot file name +// roleFromConsistentName returns the role name from a consistent snapshot file name. func roleFromConsistentName(filename string) string { name := strings.TrimSuffix(filename, ".json") role := strings.Split(name, ".") diff --git a/pkg/tuf/registry_test.go b/pkg/tuf/registry_test.go index 713404b..16418c6 100644 --- a/pkg/tuf/registry_test.go +++ b/pkg/tuf/registry_test.go @@ -30,6 +30,8 @@ import ( const ( tufTargetMediaType = "application/vnd.tuf.target" + testRole = "test-role" + tufMetadataRepo = "tuf-metadata" ) func TestRegistryFetcher(t *testing.T) { @@ -40,13 +42,13 @@ func TestRegistryFetcher(t *testing.T) { t.Fatalf("failed to terminate container: %s", err) // nolint:gocritic } }() - LoadRegistryTestData(t, regAddr, OciTufTestDataPath) + LoadRegistryTestData(t, regAddr, OCITUFTestDataPath) metadataRepo := regAddr.Host + "/tuf-metadata" - metadataImgTag := "latest" + metadataImgTag := LatestTag targetsRepo := regAddr.Host + "/tuf-targets" targetFile := "test.txt" - delegatedRole := "test-role" + delegatedRole := testRole dir := CreateTempDir(t, "", "tuf_temp") delegatedDir := CreateTempDir(t, dir, delegatedRole) delegatedTargetFile := fmt.Sprintf("%s/%s", delegatedRole, targetFile) @@ -126,11 +128,11 @@ func TestFindFileInManifest(t *testing.T) { img = mutate.ConfigMediaType(img, types.OCIConfigJSON) // add test layer name := strings.Join([]string{hash.Hex, file}, ".") - ann := map[string]string{TufFileNameAnnotation: name} + ann := map[string]string{TUFFileNameAnnotation: name} layer := mutate.Addendum{Layer: static.NewLayer(data, tufTargetMediaType), Annotations: ann} img, err := mutate.Append(img, layer) assert.NoError(t, err) - image_manifest, err := img.RawManifest() + imageManifest, err := img.RawManifest() assert.NoError(t, err) // make test index manifest @@ -141,11 +143,11 @@ func TestFindFileInManifest(t *testing.T) { Add: img, Descriptor: v1.Descriptor{ Annotations: map[string]string{ - TufFileNameAnnotation: name, + TUFFileNameAnnotation: name, }, }, }) - index_manifest, err := idx.RawManifest() + indexManifest, err := idx.RawManifest() assert.NoError(t, err) // cache image layer targetsRepo := "test/tuf-targets" @@ -155,7 +157,7 @@ func TestFindFileInManifest(t *testing.T) { } imgHash, err := img.Digest() assert.NoError(t, err) - d.cache.Put(fmt.Sprintf("%s@%s", targetsRepo, imgHash.String()), image_manifest) + d.cache.Put(fmt.Sprintf("%s@%s", targetsRepo, imgHash.String()), imageManifest) testCases := []struct { name string @@ -163,9 +165,9 @@ func TestFindFileInManifest(t *testing.T) { file string expected string }{ - {"consistent filename image", image_manifest, fmt.Sprintf("%s.%s", hash.Hex, file), hash.Hex}, - {"filename image", image_manifest, file, ""}, - {"consistent filename index", index_manifest, fmt.Sprintf("%s.%s", hash.Hex, file), hash.Hex}, + {"consistent filename image", imageManifest, fmt.Sprintf("%s.%s", hash.Hex, file), hash.Hex}, + {"filename image", imageManifest, file, ""}, + {"consistent filename index", indexManifest, fmt.Sprintf("%s.%s", hash.Hex, file), hash.Hex}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { @@ -182,9 +184,9 @@ func TestFindFileInManifest(t *testing.T) { func TestParseImgRef(t *testing.T) { metadataRepo := "test/tuf-metadata" - metadataTag := "latest" + metadataTag := LatestTag targetsRepo := "test/tuf-targets" - delegatedRole := "test-role" + delegatedRole := testRole testCases := []struct { name string ref string @@ -200,7 +202,7 @@ func TestParseImgRef(t *testing.T) { t.Run(tc.name, func(t *testing.T) { d := &RegistryFetcher{ metadataRepo: metadataRepo, - metadataTag: "latest", + metadataTag: LatestTag, targetsRepo: targetsRepo, } imgRef, file, err := d.parseImgRef(tc.ref) @@ -246,7 +248,7 @@ func TestPullFileLayer(t *testing.T) { }() // make test layer - repo := "tuf-metadata" + repo := tufMetadataRepo data := []byte("test") testLayer := static.NewLayer(data, tufTargetMediaType) hash, err := testLayer.Digest() @@ -303,7 +305,7 @@ func TestGetManifest(t *testing.T) { }() // make test manifest - repo := "tuf-metadata" + repo := tufMetadataRepo img := empty.Image img = mutate.MediaType(img, types.OCIManifestSchema1) img = mutate.ConfigMediaType(img, types.OCIConfigJSON) @@ -339,7 +341,7 @@ func TestGetManifest(t *testing.T) { } } -// RunTestRegistry starts a registry testcontainer for TUF on OCI testdata +// RunTestRegistry starts a registry testcontainer for TUF on OCI testdata. func RunTestRegistry(t *testing.T) (*registry.RegistryContainer, *url.URL) { registryContainer, err := registry.Run(context.Background(), "registry:2.8.3") if err != nil { @@ -359,22 +361,21 @@ func RunTestRegistry(t *testing.T) (*registry.RegistryContainer, *url.URL) { return registryContainer, addr } -// LoadRegistryTestData pushes TUF metadata and targets to an OCI registry +// LoadRegistryTestData pushes TUF metadata and targets to an OCI registry. func LoadRegistryTestData(t *testing.T, registry *url.URL, path string) { // push tuf metadata and targets to local registry - METADATA_REPO := "tuf-metadata" - METADATA_TAG := "latest" - TARGETS_REPO := "tuf-targets" - DELEGATED_ROLE := "test-role" + MetadataRepo := tufMetadataRepo + TargetsRepo := "tuf-targets" + DelegatedRole := testRole // push top-level metadata -> metadata:latest - err := LoadMetadata(filepath.Join(path, "metadata"), registry.Host, METADATA_REPO, METADATA_TAG) + err := LoadMetadata(filepath.Join(path, "metadata"), registry.Host, MetadataRepo, LatestTag) if err != nil { t.Fatal(err) } // push delegated metadata -> metadata: - err = LoadMetadata(filepath.Join(path, "metadata", DELEGATED_ROLE), registry.Host, METADATA_REPO, DELEGATED_ROLE) + err = LoadMetadata(filepath.Join(path, "metadata", DelegatedRole), registry.Host, MetadataRepo, DelegatedRole) if err != nil { t.Fatal(err) } @@ -392,7 +393,7 @@ func LoadRegistryTestData(t *testing.T, registry *url.URL, path string) { if err != nil { t.Fatal(err) } - ref, err := name.ParseReference(fmt.Sprintf("%s/%s:%s", registry.Host, TARGETS_REPO, dir.Name())) + ref, err := name.ParseReference(fmt.Sprintf("%s/%s:%s", registry.Host, TargetsRepo, dir.Name())) if err != nil { t.Fatal(err) } @@ -400,7 +401,8 @@ func LoadRegistryTestData(t *testing.T, registry *url.URL, path string) { if err != nil { t.Fatal(err) } - if len(mf.Manifests) == 1 { + switch len(mf.Manifests) { + case 1: // top-level target img, err := tIdx.Image(mf.Manifests[0].Digest) if err != nil { @@ -410,19 +412,19 @@ func LoadRegistryTestData(t *testing.T, registry *url.URL, path string) { if err != nil { t.Fatal(err) } - } else if len(mf.Manifests) > 1 { + case 2: // delegated target err = remote.WriteIndex(ref, tIdx, oci.MultiKeychainOption()) if err != nil { t.Fatal(err) } - } else { + default: t.Fatal("no manifests found") } } } -// LoadMetadata loads TUF metadata from a local path and pushes to a registry +// LoadMetadata loads TUF metadata from a local path and pushes to a registry. func LoadMetadata(path, host, repo, tag string) error { mIdx, err := layout.ImageIndexFromPath(path) if err != nil { diff --git a/pkg/tuf/tuf.go b/pkg/tuf/tuf.go index 4bb61a2..14fee91 100644 --- a/pkg/tuf/tuf.go +++ b/pkg/tuf/tuf.go @@ -20,36 +20,37 @@ import ( "github.com/theupdateframework/go-tuf/v2/metadata/updater" ) -type TufSource string +type Source string const ( - HttpSource TufSource = "http" - OciSource TufSource = "oci" + HTTPSource Source = "http" + OCISource Source = "oci" + LatestTag string = "latest" ) var ( - DockerTufRootProd = embed.RootProd - DockerTufRootStaging = embed.RootStaging - DockerTufRootDev = embed.RootDev - DockerTufRootDefault = embed.RootDefault + DockerTUFRootProd = embed.RootProd + DockerTUFRootStaging = embed.RootStaging + DockerTUFRootDev = embed.RootDev + DockerTUFRootDefault = embed.RootDefault ) -type TUFClient interface { +type Downloader interface { DownloadTarget(target, filePath string) (actualFilePath string, data []byte, err error) } -type TufClient struct { +type Client struct { updater *updater.Updater cfg *config.UpdaterConfig } -// NewTufClient creates a new TUF client -func NewTufClient(initialRoot []byte, tufPath, metadataSource, targetsSource string, versionChecker VersionChecker) (*TufClient, error) { - var tufSource TufSource +// NewClient creates a new TUF client. +func NewClient(initialRoot []byte, tufPath, metadataSource, targetsSource string, versionChecker VersionChecker) (*Client, error) { + var tufSource Source if strings.HasPrefix(metadataSource, "https://") || strings.HasPrefix(metadataSource, "http://") { - tufSource = HttpSource + tufSource = HTTPSource } else { - tufSource = OciSource + tufSource = OCISource } tufRootDigest := util.SHA256Hex(initialRoot) @@ -84,11 +85,11 @@ func NewTufClient(initialRoot []byte, tufPath, metadataSource, targetsSource str cfg.LocalTargetsDir = filepath.Join(metadataPath, "download") cfg.RemoteTargetsURL = targetsSource - if tufSource == OciSource { + if tufSource == OCISource { metadataRepo, metadataTag, found := strings.Cut(metadataSource, ":") if !found { fmt.Printf("metadata tag not found in URL, using latest\n") - metadataTag = "latest" + metadataTag = LatestTag } cfg.Fetcher = NewRegistryFetcher(metadataRepo, metadataTag, targetsSource) } @@ -105,7 +106,7 @@ func NewTufClient(initialRoot []byte, tufPath, metadataSource, targetsSource str return nil, fmt.Errorf("failed to refresh trusted metadata: %w", err) } - client := &TufClient{ + client := &Client{ updater: up, cfg: cfg, } @@ -121,7 +122,7 @@ func NewTufClient(initialRoot []byte, tufPath, metadataSource, targetsSource str // DownloadTarget downloads the target file using Updater. The Updater gets the target // information, verifies if the target is already cached, and if it is not cached, // downloads the target file. -func (t *TufClient) DownloadTarget(target string, filePath string) (actualFilePath string, data []byte, err error) { +func (t *Client) DownloadTarget(target string, filePath string) (actualFilePath string, data []byte, err error) { // search if the desired target is available targetInfo, err := t.updater.GetTargetInfo(target) if err != nil { @@ -154,15 +155,15 @@ func (t *TufClient) DownloadTarget(target string, filePath string) (actualFilePa return actualFilePath, data, err } -func (t *TufClient) GetMetadata() trustedmetadata.TrustedMetadata { +func (t *Client) GetMetadata() trustedmetadata.TrustedMetadata { return t.updater.GetTrustedMetadataSet() } -func (t *TufClient) MaxRootLength() int64 { +func (t *Client) MaxRootLength() int64 { return t.cfg.RootMaxLength } -func (t *TufClient) GetPriorRoots(metadataURL string) (map[string][]byte, error) { +func (t *Client) GetPriorRoots(metadataURL string) (map[string][]byte, error) { rootMetadata := map[string][]byte{} trustedMetadata := t.GetMetadata() client := fetcher.DefaultFetcher{} @@ -176,12 +177,12 @@ func (t *TufClient) GetPriorRoots(metadataURL string) (map[string][]byte, error) return rootMetadata, nil } -func (t *TufClient) SetRemoteTargetsURL(url string) { +func (t *Client) SetRemoteTargetsURL(url string) { t.cfg.RemoteTargetsURL = url } -// Derived from updater.loadTargets() in theupdateframework/go-tuf -func (t *TufClient) LoadDelegatedTargets(roleName, parentName string) (*metadata.Metadata[metadata.TargetsType], error) { +// Derived from updater.loadTargets() in theupdateframework/go-tuf. +func (t *Client) LoadDelegatedTargets(roleName, parentName string) (*metadata.Metadata[metadata.TargetsType], error) { // extract the targets meta from the trusted snapshot metadata meta := t.updater.GetTrustedMetadataSet() metaInfo := meta.Snapshot.Signed.Meta[fmt.Sprintf("%s.json", roleName)] @@ -208,8 +209,8 @@ func (t *TufClient) LoadDelegatedTargets(roleName, parentName string) (*metadata return delegatedTargets, nil } -// downloadMetadata download a metadata file and return it as bytes -func (t *TufClient) downloadMetadata(roleName string, length int64, version string) ([]byte, error) { +// downloadMetadata download a metadata file and return it as bytes. +func (t *Client) downloadMetadata(roleName string, length int64, version string) ([]byte, error) { urlPath := ensureTrailingSlash(t.cfg.RemoteMetadataURL) // build urlPath if version == "" { @@ -220,7 +221,7 @@ func (t *TufClient) downloadMetadata(roleName string, length int64, version stri return t.cfg.Fetcher.DownloadFile(urlPath, length, time.Second*15) } -// ensureTrailingSlash ensures url ends with a slash +// ensureTrailingSlash ensures url ends with a slash. func ensureTrailingSlash(url string) string { if updater.IsWindowsPath(url) { slash := string(filepath.Separator) @@ -235,7 +236,7 @@ func ensureTrailingSlash(url string) string { return url + "/" } -// GetEmbeddedTufRoot returns the embedded TUF root based on the given root name -func GetEmbeddedTufRoot(root string) (*embed.EmbeddedRoot, error) { +// GetEmbeddedRoot returns the embedded TUF root based on the given root name. +func GetEmbeddedRoot(root string) (*embed.EmbeddedRoot, error) { return embed.GetRootFromName(root) } diff --git a/pkg/tuf/tuf_test.go b/pkg/tuf/tuf_test.go index dc3a569..ddd935b 100644 --- a/pkg/tuf/tuf_test.go +++ b/pkg/tuf/tuf_test.go @@ -15,8 +15,8 @@ import ( ) var ( - HttpTufTestDataPath = filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo") - OciTufTestDataPath = filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo-oci") + HTTPTUFTestDataPath = filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo") + OCITUFTestDataPath = filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo-oci") ) func CreateTempDir(t *testing.T, dir, pattern string) string { @@ -35,12 +35,12 @@ func CreateTempDir(t *testing.T, dir, pattern string) string { return tempDir } -// NewTufClient creates a new TUF client +// NewTufClient creates a new TUF client. func TestRootInit(t *testing.T) { tufPath := CreateTempDir(t, "", "tuf_temp") // Start a test HTTP server to serve data from /test/testdata/tuf/test-repo/ paths - server := httptest.NewServer(http.FileServer(http.Dir(HttpTufTestDataPath))) + server := httptest.NewServer(http.FileServer(http.Dir(HTTPTUFTestDataPath))) defer server.Close() // run local registry @@ -50,10 +50,10 @@ func TestRootInit(t *testing.T) { t.Fatalf("failed to terminate container: %s", err) // nolint:gocritic } }() - LoadRegistryTestData(t, regAddr, OciTufTestDataPath) + LoadRegistryTestData(t, regAddr, OCITUFTestDataPath) - alwaysGoodVersionChecker := &mockVersionChecker{err: nil} - alwaysBadVersionChecker := &mockVersionChecker{err: assert.AnError} + alwaysGoodVersionChecker := &MockVersionChecker{err: nil} + alwaysBadVersionChecker := &MockVersionChecker{err: assert.AnError} testCases := []struct { name string @@ -65,17 +65,17 @@ func TestRootInit(t *testing.T) { } for _, tc := range testCases { - _, err := NewTufClient(embed.RootDev.Data, tufPath, tc.metadataSource, tc.targetsSource, alwaysGoodVersionChecker) + _, err := NewClient(embed.RootDev.Data, tufPath, tc.metadataSource, tc.targetsSource, alwaysGoodVersionChecker) assert.NoErrorf(t, err, "Failed to create TUF client: %v", err) // recreation should work with same root - _, err = NewTufClient(embed.RootDev.Data, tufPath, tc.metadataSource, tc.targetsSource, alwaysGoodVersionChecker) + _, err = NewClient(embed.RootDev.Data, tufPath, tc.metadataSource, tc.targetsSource, alwaysGoodVersionChecker) assert.NoErrorf(t, err, "Failed to recreate TUF client: %v", err) - _, err = NewTufClient([]byte("broken"), tufPath, tc.metadataSource, tc.targetsSource, alwaysGoodVersionChecker) + _, err = NewClient([]byte("broken"), tufPath, tc.metadataSource, tc.targetsSource, alwaysGoodVersionChecker) assert.Errorf(t, err, "Expected error recreating TUF client with broken root: %v", err) - _, err = NewTufClient(embed.RootDev.Data, tufPath, tc.metadataSource, tc.targetsSource, alwaysBadVersionChecker) + _, err = NewClient(embed.RootDev.Data, tufPath, tc.metadataSource, tc.targetsSource, alwaysBadVersionChecker) assert.Errorf(t, err, "Expected error creating TUF client with bad attest version: %v", err) } } @@ -83,11 +83,11 @@ func TestRootInit(t *testing.T) { func TestDownloadTarget(t *testing.T) { tufPath := CreateTempDir(t, "", "tuf_temp") targetFile := "test.txt" - delegatedRole := "test-role" + delegatedRole := testRole delegatedTargetFile := fmt.Sprintf("%s/%s", delegatedRole, targetFile) // Start a test HTTP server to serve data from /test/testdata/tuf/test-repo/ paths - server := httptest.NewServer(http.FileServer(http.Dir(HttpTufTestDataPath))) + server := httptest.NewServer(http.FileServer(http.Dir(HTTPTUFTestDataPath))) defer server.Close() // run local registry @@ -97,9 +97,9 @@ func TestDownloadTarget(t *testing.T) { t.Fatalf("failed to terminate container: %s", err) // nolint:gocritic } }() - LoadRegistryTestData(t, regAddr, OciTufTestDataPath) + LoadRegistryTestData(t, regAddr, OCITUFTestDataPath) - alwaysGoodVersionChecker := &mockVersionChecker{err: nil} + alwaysGoodVersionChecker := &MockVersionChecker{err: nil} testCases := []struct { name string @@ -111,7 +111,7 @@ func TestDownloadTarget(t *testing.T) { } for _, tc := range testCases { - tufClient, err := NewTufClient(embed.RootDev.Data, tufPath, tc.metadataSource, tc.targetsSource, alwaysGoodVersionChecker) + tufClient, err := NewClient(embed.RootDev.Data, tufPath, tc.metadataSource, tc.targetsSource, alwaysGoodVersionChecker) assert.NoErrorf(t, err, "Failed to create TUF client: %v", err) // get trusted tuf metadata @@ -135,22 +135,22 @@ func TestDownloadTarget(t *testing.T) { } func TestGetEmbeddedTufRootBytes(t *testing.T) { - dev, err := GetEmbeddedTufRoot("dev") + dev, err := GetEmbeddedRoot("dev") assert.NoError(t, err) - staging, err := GetEmbeddedTufRoot("staging") + staging, err := GetEmbeddedRoot("staging") assert.NoError(t, err) assert.NotEqual(t, dev.Data, staging.Data) - prod, err := GetEmbeddedTufRoot("prod") + prod, err := GetEmbeddedRoot("prod") assert.NoError(t, err) assert.NotEqual(t, dev.Data, prod.Data) assert.NotEqual(t, staging.Data, prod.Data) - def, err := GetEmbeddedTufRoot("") + def, err := GetEmbeddedRoot("") assert.NoError(t, err) assert.Equal(t, def.Data, prod.Data) - _, err = GetEmbeddedTufRoot("invalid") + _, err = GetEmbeddedRoot("invalid") assert.Error(t, err) } diff --git a/pkg/tuf/version.go b/pkg/tuf/version.go index a9eef52..f751d1e 100644 --- a/pkg/tuf/version.go +++ b/pkg/tuf/version.go @@ -12,7 +12,7 @@ const ThisModulePath = "github.com/docker/attest" type VersionChecker interface { // CheckVersion checks if the current version of this library meets the constraints from the TUF repo - CheckVersion(tufClient TUFClient) error + CheckVersion(tufClient Downloader) error } type InvalidVersionError struct { @@ -32,13 +32,13 @@ func (e *InvalidVersionError) Error() string { return fmt.Sprintf("%s version %s does not satisfy constraints %s: %s", ThisModulePath, e.AttestVersion, e.VersionConstraint, errsStr.String()) } -func NewVersionChecker() *versionChecker { - return &versionChecker{} +func NewDefaultVersionChecker() *DefaultVersionChecker { + return &DefaultVersionChecker{} } -type versionChecker struct{} +type DefaultVersionChecker struct{} -func (vc *versionChecker) CheckVersion(client TUFClient) error { +func (vc *DefaultVersionChecker) CheckVersion(client Downloader) error { var attestMod *debug.Module bi, ok := debug.ReadBuildInfo() if !ok {