From 2bf7dec72e55f5667d9004245442f0c4cc94e166 Mon Sep 17 00:00:00 2001 From: mrjoelkamp Date: Wed, 14 Aug 2024 12:32:51 -0500 Subject: [PATCH] feat: add policy.downloadLocation --- README.md | 1 + pkg/attest/verify.go | 6 +----- pkg/attest/verify_test.go | 6 ++++-- pkg/attestation/vsa.go | 7 ++++--- pkg/tuf/registry.go | 4 ++-- pkg/tuf/registry_test.go | 2 +- pkg/tuf/tuf.go | 6 +----- 7 files changed, 14 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index b588997..8b320a1 100644 --- a/README.md +++ b/README.md @@ -346,6 +346,7 @@ The VSA can be signed and published to the registry using the signing functions "resourceUri": "pkg:docker/example.org/example-image@1.0?platform=linux%2Famd64&digest=sha256%3A49f717386e5462e945232569a97a05831cb83bef8c3369be3bb7ea1793686960", "policy": { "uri": "https://example.org/internal-policy/v1", + "downloadLocation": "https://docker.github.io/tuf-staging/targets/docker/d71d6b8f49fcba1295b16f5394dd5863a14e4277eb663d66d8c48e392509afe0.policy.rego", "digest": {"sha256": "d71d6b8f49fcba1295b16f5394dd5863a14e4277eb663d66d8c48e392509afe0"} }, "verificationResult": "PASSED", diff --git a/pkg/attest/verify.go b/pkg/attest/verify.go index 1b29bcd..d30082e 100644 --- a/pkg/attest/verify.go +++ b/pkg/attest/verify.go @@ -86,11 +86,7 @@ func toVerificationResult(p *policy.Policy, input *policy.Input, result *policy. return nil, err } - vsaPolicy := attestation.VSAPolicy{URI: result.Summary.PolicyURI, Digest: p.Digest} - // if the policy URI is not set by the result summary then use the policy's target URI - if vsaPolicy.URI == "" { - vsaPolicy = attestation.VSAPolicy{URI: p.URI, Digest: p.Digest} - } + vsaPolicy := attestation.VSAPolicy{URI: result.Summary.PolicyURI, DownloadLocation: p.URI, Digest: p.Digest} return &VerificationResult{ Policy: p, diff --git a/pkg/attest/verify_test.go b/pkg/attest/verify_test.go index 2a493f8..b386619 100644 --- a/pkg/attest/verify_test.go +++ b/pkg/attest/verify_test.go @@ -112,7 +112,8 @@ func TestVSA(t *testing.T) { assert.Equal(t, "PASSED", attestationPredicate.VerificationResult) assert.Equal(t, "docker-official-images", attestationPredicate.Verifier.ID) assert.Equal(t, []string{"SLSA_BUILD_LEVEL_3"}, attestationPredicate.VerifiedLevels) - assert.Equal(t, PassPolicyDir+"/policy.rego", attestationPredicate.Policy.URI) + assert.Equal(t, PassPolicyDir+"/policy.rego", attestationPredicate.Policy.DownloadLocation) + assert.Equal(t, "https://docker.com/official/policy/v0.1", attestationPredicate.Policy.URI) assert.Equal(t, map[string]string{"sha256": "d71d6b8f49fcba1295b16f5394dd5863a14e4277eb663d66d8c48e392509afe0"}, attestationPredicate.Policy.Digest) } @@ -163,7 +164,8 @@ func TestVerificationFailure(t *testing.T) { assert.Equal(t, "FAILED", attestationPredicate.VerificationResult) assert.Equal(t, "docker-official-images", attestationPredicate.Verifier.ID) assert.Equal(t, []string{"SLSA_BUILD_LEVEL_3"}, attestationPredicate.VerifiedLevels) - assert.Equal(t, FailPolicyDir+"/policy.rego", attestationPredicate.Policy.URI) + assert.Equal(t, FailPolicyDir+"/policy.rego", attestationPredicate.Policy.DownloadLocation) + assert.Equal(t, "https://docker.com/official/policy/v0.1", attestationPredicate.Policy.URI) assert.Equal(t, map[string]string{"sha256": "ad045e1bd7cd602d90196acf68f2c57d7b51565d59e6e30e30d94ae86aa16201"}, attestationPredicate.Policy.Digest) } diff --git a/pkg/attestation/vsa.go b/pkg/attestation/vsa.go index 82f7022..e580601 100644 --- a/pkg/attestation/vsa.go +++ b/pkg/attestation/vsa.go @@ -16,7 +16,7 @@ type VSAPredicate struct { TimeVerified string `json:"timeVerified"` ResourceURI string `json:"resourceUri"` Policy VSAPolicy `json:"policy"` - InputAttestations []VSAInputAttestation `json:"inputAttestations"` + InputAttestations []VSAInputAttestation `json:"inputAttestations,omitempty"` VerificationResult string `json:"verificationResult"` VerifiedLevels []string `json:"verifiedLevels"` } @@ -26,8 +26,9 @@ type VSAVerifier struct { } type VSAPolicy struct { - URI string `json:"uri"` - Digest map[string]string `json:"digest"` + URI string `json:"uri,omitempty"` + Digest map[string]string `json:"digest"` + DownloadLocation string `json:"downloadLocation,omitempty"` } type VSAInputAttestation struct { diff --git a/pkg/tuf/registry.go b/pkg/tuf/registry.go index 09af4d8..fa47cc3 100644 --- a/pkg/tuf/registry.go +++ b/pkg/tuf/registry.go @@ -81,7 +81,7 @@ func NewRegistryFetcher(metadataRepo, metadataTag, targetsRepo string) *Registry func (d *RegistryFetcher) DownloadFile(urlPath string, maxLength int64, timeout time.Duration) ([]byte, error) { d.timeout = timeout - imgRef, fileName, err := d.ParseImgRef(urlPath) + imgRef, fileName, err := d.parseImgRef(urlPath) if err != nil { return nil, err } @@ -186,7 +186,7 @@ func getDataFromLayer(fileLayer v1.Layer, maxLength int64) ([]byte, error) { } // 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) { +func (d *RegistryFetcher) parseImgRef(urlPath string) (imgRef, fileName string, err error) { // Check if repo is target or metadata if strings.Contains(urlPath, d.targetsRepo) { // determine if the target path contains subdirectories and set image name accordingly diff --git a/pkg/tuf/registry_test.go b/pkg/tuf/registry_test.go index 6e3123b..45ead27 100644 --- a/pkg/tuf/registry_test.go +++ b/pkg/tuf/registry_test.go @@ -206,7 +206,7 @@ func TestParseImgRef(t *testing.T) { metadataTag: LatestTag, targetsRepo: targetsRepo, } - imgRef, file, err := d.ParseImgRef(tc.ref) + imgRef, file, err := d.parseImgRef(tc.ref) assert.NoError(t, err) assert.Equal(t, tc.expectedRef, imgRef) assert.Equal(t, tc.expectedFile, file) diff --git a/pkg/tuf/tuf.go b/pkg/tuf/tuf.go index 06c24af..c54eec0 100644 --- a/pkg/tuf/tuf.go +++ b/pkg/tuf/tuf.go @@ -144,11 +144,7 @@ func (t *Client) generateTargetURI(target *metadata.TargetFiles, digest string) switch fetcher := t.cfg.Fetcher.(type) { case *RegistryFetcher: - ref, _, err := fetcher.ParseImgRef(fullURL) - if err != nil { - return "", fmt.Errorf("failed to parse image reference: %w", err) - } - return ref, nil + return fmt.Sprintf("%s@sha256:%s", t.cfg.RemoteTargetsURL, digest), nil case *fetcher.DefaultFetcher: return fullURL, nil default: