feat: add policy.downloadLocation
This commit is contained in:
@@ -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",
|
"resourceUri": "pkg:docker/example.org/example-image@1.0?platform=linux%2Famd64&digest=sha256%3A49f717386e5462e945232569a97a05831cb83bef8c3369be3bb7ea1793686960",
|
||||||
"policy": {
|
"policy": {
|
||||||
"uri": "https://example.org/internal-policy/v1",
|
"uri": "https://example.org/internal-policy/v1",
|
||||||
|
"downloadLocation": "https://docker.github.io/tuf-staging/targets/docker/d71d6b8f49fcba1295b16f5394dd5863a14e4277eb663d66d8c48e392509afe0.policy.rego",
|
||||||
"digest": {"sha256": "d71d6b8f49fcba1295b16f5394dd5863a14e4277eb663d66d8c48e392509afe0"}
|
"digest": {"sha256": "d71d6b8f49fcba1295b16f5394dd5863a14e4277eb663d66d8c48e392509afe0"}
|
||||||
},
|
},
|
||||||
"verificationResult": "PASSED",
|
"verificationResult": "PASSED",
|
||||||
|
|||||||
@@ -86,11 +86,7 @@ func toVerificationResult(p *policy.Policy, input *policy.Input, result *policy.
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
vsaPolicy := attestation.VSAPolicy{URI: result.Summary.PolicyURI, Digest: p.Digest}
|
vsaPolicy := attestation.VSAPolicy{URI: result.Summary.PolicyURI, DownloadLocation: p.URI, 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}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &VerificationResult{
|
return &VerificationResult{
|
||||||
Policy: p,
|
Policy: p,
|
||||||
|
|||||||
@@ -112,7 +112,8 @@ func TestVSA(t *testing.T) {
|
|||||||
assert.Equal(t, "PASSED", attestationPredicate.VerificationResult)
|
assert.Equal(t, "PASSED", attestationPredicate.VerificationResult)
|
||||||
assert.Equal(t, "docker-official-images", attestationPredicate.Verifier.ID)
|
assert.Equal(t, "docker-official-images", attestationPredicate.Verifier.ID)
|
||||||
assert.Equal(t, []string{"SLSA_BUILD_LEVEL_3"}, attestationPredicate.VerifiedLevels)
|
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)
|
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, "FAILED", attestationPredicate.VerificationResult)
|
||||||
assert.Equal(t, "docker-official-images", attestationPredicate.Verifier.ID)
|
assert.Equal(t, "docker-official-images", attestationPredicate.Verifier.ID)
|
||||||
assert.Equal(t, []string{"SLSA_BUILD_LEVEL_3"}, attestationPredicate.VerifiedLevels)
|
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)
|
assert.Equal(t, map[string]string{"sha256": "ad045e1bd7cd602d90196acf68f2c57d7b51565d59e6e30e30d94ae86aa16201"}, attestationPredicate.Policy.Digest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type VSAPredicate struct {
|
|||||||
TimeVerified string `json:"timeVerified"`
|
TimeVerified string `json:"timeVerified"`
|
||||||
ResourceURI string `json:"resourceUri"`
|
ResourceURI string `json:"resourceUri"`
|
||||||
Policy VSAPolicy `json:"policy"`
|
Policy VSAPolicy `json:"policy"`
|
||||||
InputAttestations []VSAInputAttestation `json:"inputAttestations"`
|
InputAttestations []VSAInputAttestation `json:"inputAttestations,omitempty"`
|
||||||
VerificationResult string `json:"verificationResult"`
|
VerificationResult string `json:"verificationResult"`
|
||||||
VerifiedLevels []string `json:"verifiedLevels"`
|
VerifiedLevels []string `json:"verifiedLevels"`
|
||||||
}
|
}
|
||||||
@@ -26,8 +26,9 @@ type VSAVerifier struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type VSAPolicy struct {
|
type VSAPolicy struct {
|
||||||
URI string `json:"uri"`
|
URI string `json:"uri,omitempty"`
|
||||||
Digest map[string]string `json:"digest"`
|
Digest map[string]string `json:"digest"`
|
||||||
|
DownloadLocation string `json:"downloadLocation,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VSAInputAttestation struct {
|
type VSAInputAttestation struct {
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ func NewRegistryFetcher(metadataRepo, metadataTag, targetsRepo string) *Registry
|
|||||||
func (d *RegistryFetcher) DownloadFile(urlPath string, maxLength int64, timeout time.Duration) ([]byte, error) {
|
func (d *RegistryFetcher) DownloadFile(urlPath string, maxLength int64, timeout time.Duration) ([]byte, error) {
|
||||||
d.timeout = timeout
|
d.timeout = timeout
|
||||||
|
|
||||||
imgRef, fileName, err := d.ParseImgRef(urlPath)
|
imgRef, fileName, err := d.parseImgRef(urlPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// 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
|
// Check if repo is target or metadata
|
||||||
if strings.Contains(urlPath, d.targetsRepo) {
|
if strings.Contains(urlPath, d.targetsRepo) {
|
||||||
// determine if the target path contains subdirectories and set image name accordingly
|
// determine if the target path contains subdirectories and set image name accordingly
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ func TestParseImgRef(t *testing.T) {
|
|||||||
metadataTag: LatestTag,
|
metadataTag: LatestTag,
|
||||||
targetsRepo: targetsRepo,
|
targetsRepo: targetsRepo,
|
||||||
}
|
}
|
||||||
imgRef, file, err := d.ParseImgRef(tc.ref)
|
imgRef, file, err := d.parseImgRef(tc.ref)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, tc.expectedRef, imgRef)
|
assert.Equal(t, tc.expectedRef, imgRef)
|
||||||
assert.Equal(t, tc.expectedFile, file)
|
assert.Equal(t, tc.expectedFile, file)
|
||||||
|
|||||||
@@ -144,11 +144,7 @@ func (t *Client) generateTargetURI(target *metadata.TargetFiles, digest string)
|
|||||||
|
|
||||||
switch fetcher := t.cfg.Fetcher.(type) {
|
switch fetcher := t.cfg.Fetcher.(type) {
|
||||||
case *RegistryFetcher:
|
case *RegistryFetcher:
|
||||||
ref, _, err := fetcher.ParseImgRef(fullURL)
|
return fmt.Sprintf("%s@sha256:%s", t.cfg.RemoteTargetsURL, digest), nil
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to parse image reference: %w", err)
|
|
||||||
}
|
|
||||||
return ref, nil
|
|
||||||
case *fetcher.DefaultFetcher:
|
case *fetcher.DefaultFetcher:
|
||||||
return fullURL, nil
|
return fullURL, nil
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user