Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a363be7f3a | ||
|
|
99846a3483 | ||
|
|
f760b12bb2 | ||
|
|
bab474669f | ||
|
|
0705a71115 | ||
|
|
b00e02af01 | ||
|
|
ff53657cc9 | ||
|
|
c8383f3f5a | ||
|
|
dc247bd348 | ||
|
|
ce7d173150 | ||
|
|
fb69d9a09b | ||
|
|
48e58a9115 | ||
|
|
bfacaf1de0 | ||
|
|
67ad27ac22 | ||
|
|
41847ef238 | ||
|
|
1f806f33a8 | ||
|
|
8982778507 | ||
|
|
16834292de |
11
.github/release-drafter-config.yml
vendored
11
.github/release-drafter-config.yml
vendored
@@ -14,6 +14,9 @@ categories:
|
||||
- title: "🧰 Maintenance"
|
||||
labels:
|
||||
- "chore"
|
||||
- title: "💥 Breaking Changes"
|
||||
labels:
|
||||
- "breaking"
|
||||
|
||||
change-template: "- $TITLE @$AUTHOR (#$NUMBER)"
|
||||
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
|
||||
@@ -21,6 +24,7 @@ version-resolver:
|
||||
major:
|
||||
labels:
|
||||
- "major"
|
||||
- "breaking"
|
||||
minor:
|
||||
labels:
|
||||
- "minor"
|
||||
@@ -40,11 +44,13 @@ autolabeler:
|
||||
branch:
|
||||
- '/docs{0,1}\/.+/'
|
||||
- '/tests{0,1}\/.+/'
|
||||
- '/chore{0,1}\/.+/'
|
||||
- '/chore\/.+/'
|
||||
- '/refactor\/.+/'
|
||||
title:
|
||||
- "/docs/i"
|
||||
- "/test/i"
|
||||
- "/chore/i"
|
||||
- "/refactor/i"
|
||||
- label: "bug"
|
||||
branch:
|
||||
- '/fix\/.+/'
|
||||
@@ -60,3 +66,6 @@ autolabeler:
|
||||
title:
|
||||
- "/feat/i"
|
||||
- "/add/i"
|
||||
- label: "breaking"
|
||||
title:
|
||||
- "/^[a-zA-Z]+!:/i"
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
steps:
|
||||
- name: Generate GitHub App Token
|
||||
id: app-token
|
||||
uses: actions/create-github-app-token@31c86eb3b33c9b601a1f60f98dcbfd1d70f379b4 # v1.10.3
|
||||
uses: actions/create-github-app-token@3378cda945da322a8db4b193e19d46352ebe2de5 # v1.10.4
|
||||
with:
|
||||
app-id: ${{ vars.ATTEST_RELEASE_APP_ID }}
|
||||
private-key: ${{ secrets.ATTEST_RELEASE_APP_PRIVATE_KEY }}
|
||||
|
||||
@@ -66,7 +66,7 @@ See [Policy Mapping](#policy-mapping) for more details.
|
||||
|
||||
The `attest.Verify` function returns a `VerificationSummary` object, which contains the results of the policy evaluation.
|
||||
|
||||
See [example_verify_test.go](./pkg/attest/example_verify_test.go) for an example of how to verify an image against a policy.
|
||||
See [example_verify_test.go](./example_verify_test.go) for an example of how to verify an image against a policy.
|
||||
|
||||
## Signing Attestations
|
||||
|
||||
@@ -76,7 +76,7 @@ This function takes a statement and DSSE signer, and returns a signed DSSE envel
|
||||
For the common use case of signing a statement and adding it to a manifest, e.g. for pushing to a registry as a referrer to the image being attested, the `attestation.AttestationManifest` type can be used.
|
||||
See [example_attestation_manifest_test.go](./pkg/attestation/example_attestation_manifest_test.go)
|
||||
|
||||
See also [example_sign_test.go](./pkg/attest/example_sign_test.go) for an example of how to sign all attached in-toto statements on an image, e.g. those produced by buildkit.
|
||||
See also [example_sign_test.go](./example_sign_test.go) for an example of how to sign all attached in-toto statements on an image, e.g. those produced by buildkit.
|
||||
|
||||
# Rego Policy
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"maps"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/empty"
|
||||
"github.com/google/go-containerregistry/pkg/v1/layout"
|
||||
@@ -3,8 +3,8 @@ package attestation_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
const ExpectedStatements = 4
|
||||
|
||||
func TestExtractAnnotatedStatements(t *testing.T) {
|
||||
statements, err := attestation.ExtractAnnotatedStatements(test.UnsignedTestImage, intoto.PayloadType)
|
||||
statements, err := attestation.ExtractAnnotatedStatements(test.UnsignedTestImage(".."), intoto.PayloadType)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, len(statements), ExpectedStatements, "expected %d statement, got %d", ExpectedStatements, len(statements))
|
||||
}
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/signerverifier"
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/signerverifier"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/layout"
|
||||
)
|
||||
@@ -4,11 +4,11 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest"
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/attest"
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/policy"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/policy"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -24,7 +24,7 @@ func TestAttestationFromOCILayout(t *testing.T) {
|
||||
}
|
||||
|
||||
opts := &attestation.SigningOptions{}
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage)
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
||||
require.NoError(t, err)
|
||||
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
|
||||
require.NoError(t, err)
|
||||
@@ -3,12 +3,19 @@ package attestation
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
)
|
||||
|
||||
// ensure MockResolver implements Resolver.
|
||||
var _ oci.ImageDetailsResolver = MockResolver{}
|
||||
|
||||
type MockResolver struct {
|
||||
Envs []*Envelope
|
||||
Envs []*Envelope
|
||||
Image string
|
||||
PlatformFn func() (*v1.Platform, error)
|
||||
DescriptorFn func() (*v1.Descriptor, error)
|
||||
ImangeNameFn func() (string, error)
|
||||
}
|
||||
|
||||
func (r MockResolver) Attestations(_ context.Context, _ string) ([]*Envelope, error) {
|
||||
@@ -16,10 +23,19 @@ func (r MockResolver) Attestations(_ context.Context, _ string) ([]*Envelope, er
|
||||
}
|
||||
|
||||
func (r MockResolver) ImageName(_ context.Context) (string, error) {
|
||||
if r.Image != "" {
|
||||
return r.Image, nil
|
||||
}
|
||||
if r.ImangeNameFn != nil {
|
||||
return r.ImangeNameFn()
|
||||
}
|
||||
return "library/alpine:latest", nil
|
||||
}
|
||||
|
||||
func (r MockResolver) ImageDescriptor(_ context.Context) (*v1.Descriptor, error) {
|
||||
if r.DescriptorFn != nil {
|
||||
return r.DescriptorFn()
|
||||
}
|
||||
digest, err := v1.NewHash("sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -32,6 +48,9 @@ func (r MockResolver) ImageDescriptor(_ context.Context) (*v1.Descriptor, error)
|
||||
}
|
||||
|
||||
func (r MockResolver) ImagePlatform(_ context.Context) (*v1.Platform, error) {
|
||||
if r.PlatformFn != nil {
|
||||
return r.PlatformFn()
|
||||
}
|
||||
return oci.ParsePlatform("linux/amd64")
|
||||
}
|
||||
|
||||
@@ -5,11 +5,14 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||
)
|
||||
|
||||
// ensure ReferrersResolver implements Resolver.
|
||||
var _ Resolver = &ReferrersResolver{}
|
||||
|
||||
type ReferrersResolver struct {
|
||||
referrersRepo string
|
||||
oci.ImageDetailsResolver
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest"
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/config"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/attest"
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/config"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/policy"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/policy"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/google/go-containerregistry/pkg/registry"
|
||||
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||
@@ -21,12 +21,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
NoProvenanceImage = filepath.Join("..", "..", "test", "testdata", "no-provenance-image")
|
||||
PassPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-pass")
|
||||
LocalPolicy = filepath.Join("..", "..", "test", "testdata", "local-policy")
|
||||
LocalPolicyAttached = filepath.Join("..", "..", "test", "testdata", "local-policy-attached")
|
||||
PassNoTLPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-no-tl")
|
||||
FailPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-fail")
|
||||
NoProvenanceImage = filepath.Join("..", "test", "testdata", "no-provenance-image")
|
||||
PassPolicyDir = filepath.Join("..", "test", "testdata", "local-policy-pass")
|
||||
LocalPolicy = filepath.Join("..", "test", "testdata", "local-policy")
|
||||
LocalPolicyAttached = filepath.Join("..", "test", "testdata", "local-policy-attached")
|
||||
PassNoTLPolicyDir = filepath.Join("..", "test", "testdata", "local-policy-no-tl")
|
||||
FailPolicyDir = filepath.Join("..", "test", "testdata", "local-policy-fail")
|
||||
TestTempDir = "attest-sign-test"
|
||||
)
|
||||
|
||||
@@ -90,7 +90,7 @@ func TestAttestationReferenceTypes(t *testing.T) {
|
||||
opts := &attestation.SigningOptions{
|
||||
SkipTL: true,
|
||||
}
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage)
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
||||
require.NoError(t, err)
|
||||
|
||||
indexName := fmt.Sprintf("%s/repo:root", u.Host)
|
||||
@@ -212,7 +212,7 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
||||
opts := &attestation.SigningOptions{
|
||||
SkipTL: true,
|
||||
}
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage)
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
||||
require.NoError(t, err)
|
||||
|
||||
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
||||
@@ -238,7 +238,7 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
||||
opts := &attestation.SigningOptions{
|
||||
SkipTL: true,
|
||||
}
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage)
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
||||
require.NoError(t, err)
|
||||
|
||||
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
||||
@@ -294,7 +294,7 @@ func TestCorrectArtifactTypeInTagFallback(t *testing.T) {
|
||||
opts := &attestation.SigningOptions{
|
||||
SkipTL: true,
|
||||
}
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage)
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
||||
require.NoError(t, err)
|
||||
|
||||
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
||||
@@ -4,12 +4,15 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||
)
|
||||
|
||||
// ensure RegistryResolver implements Resolver.
|
||||
var _ Resolver = &RegistryResolver{}
|
||||
|
||||
type RegistryResolver struct {
|
||||
*oci.RegistryImageDetailsResolver
|
||||
*Manifest
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest"
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/attest"
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/policy"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/policy"
|
||||
"github.com/google/go-containerregistry/pkg/registry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -25,7 +25,7 @@ func TestRegistry(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
opts := &attestation.SigningOptions{}
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage)
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
||||
require.NoError(t, err)
|
||||
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
|
||||
require.NoError(t, err)
|
||||
@@ -3,7 +3,7 @@ package attestation
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
)
|
||||
|
||||
type Resolver interface {
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/attest/internal/util"
|
||||
"github.com/docker/attest/pkg/tlog"
|
||||
"github.com/docker/attest/tlog"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
"github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
)
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/signerverifier"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/signerverifier"
|
||||
"github.com/google/go-containerregistry/pkg/registry"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/static"
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
v02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
|
||||
slsav1 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@@ -98,6 +99,8 @@ type Options struct {
|
||||
func DSSEMediaType(predicateType string) (string, error) {
|
||||
var predicateName string
|
||||
switch predicateType {
|
||||
case slsav1.PredicateSLSAProvenance:
|
||||
predicateName = "provenance"
|
||||
case v02.PredicateSLSAProvenance:
|
||||
predicateName = "provenance"
|
||||
case intoto.PredicateSPDX:
|
||||
44
attestation/types_test.go
Normal file
44
attestation/types_test.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package attestation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
v02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
|
||||
slsav1 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDSSEMediaType(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: slsav1.PredicateSLSAProvenance,
|
||||
expected: "provenance",
|
||||
},
|
||||
{
|
||||
name: v02.PredicateSLSAProvenance,
|
||||
expected: "provenance",
|
||||
},
|
||||
{
|
||||
name: intoto.PredicateSPDX,
|
||||
expected: "spdx",
|
||||
},
|
||||
{
|
||||
name: VSAPredicateType,
|
||||
expected: "verification_summary",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
mt, err := DSSEMediaType(tc.name)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, fmt.Sprintf("application/vnd.in-toto.%s+dsse", tc.expected), mt)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/attest/internal/util"
|
||||
"github.com/docker/attest/pkg/signerverifier"
|
||||
"github.com/docker/attest/pkg/tlog"
|
||||
"github.com/docker/attest/signerverifier"
|
||||
"github.com/docker/attest/tlog"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
120
config/config.go
Normal file
120
config/config.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/docker/attest/tuf"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const (
|
||||
MappingFilename = "mapping.yaml"
|
||||
)
|
||||
|
||||
func validateMappingsFile(mappings *policyMappingsFile) error {
|
||||
var validationErrors []error
|
||||
if mappings.Kind != "policy-mapping" {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("file is not of kind policy-mapping: %s", mappings.Kind))
|
||||
}
|
||||
if mappings.Version != "v1" {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("unsupported policy mapping file version: %s", mappings.Version))
|
||||
}
|
||||
for _, rule := range mappings.Rules {
|
||||
if rule.Pattern == "" {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("rule missing pattern: %s", rule))
|
||||
}
|
||||
if rule.PolicyID == "" && rule.Replacement == "" {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("rule must have policy-id or replacement: %s", rule))
|
||||
}
|
||||
if rule.PolicyID != "" && rule.Replacement != "" {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("rule cannot have both policy-id and replacement: %s", rule))
|
||||
}
|
||||
}
|
||||
for _, policy := range mappings.Policies {
|
||||
if policy.ID == "" {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("policy missing id: %s", policy.ID))
|
||||
}
|
||||
if len(policy.Files) == 0 {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("policy missing files: %v", policy))
|
||||
}
|
||||
for _, file := range policy.Files {
|
||||
if file.Path == "" {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("file missing path: %s", file))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(validationErrors) > 0 {
|
||||
return errors.Join(validationErrors...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parsePolicyMappingsFile(data []byte) (*PolicyMappings, error) {
|
||||
mappings := &policyMappingsFile{}
|
||||
err := yaml.Unmarshal(data, mappings)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal policy mapping file: %w", err)
|
||||
}
|
||||
err = validateMappingsFile(mappings)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid policy mapping file: %w", err)
|
||||
}
|
||||
return expandMappingFile(mappings)
|
||||
}
|
||||
|
||||
func LoadLocalMappings(configDir string) (*PolicyMappings, error) {
|
||||
if configDir == "" {
|
||||
return nil, nil
|
||||
}
|
||||
path := filepath.Join(configDir, MappingFilename)
|
||||
mappingFile, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read local policy mapping file %s: %w", path, err)
|
||||
}
|
||||
return parsePolicyMappingsFile(mappingFile)
|
||||
}
|
||||
|
||||
func LoadTUFMappings(tufClient tuf.Downloader, localTargetsDir string) (*PolicyMappings, error) {
|
||||
if tufClient == nil {
|
||||
return nil, fmt.Errorf("tuf client not set")
|
||||
}
|
||||
filename := MappingFilename
|
||||
file, err := tufClient.DownloadTarget(filename, filepath.Join(localTargetsDir, filename))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to download policy mapping file %s: %w", filename, err)
|
||||
}
|
||||
return parsePolicyMappingsFile(file.Data)
|
||||
}
|
||||
|
||||
func expandMappingFile(mappingFile *policyMappingsFile) (*PolicyMappings, error) {
|
||||
policies := make(map[string]*PolicyMapping)
|
||||
for _, policy := range mappingFile.Policies {
|
||||
policies[policy.ID] = policy
|
||||
}
|
||||
|
||||
var rules []*PolicyRule
|
||||
for _, rule := range mappingFile.Rules {
|
||||
r, err := regexp.Compile(rule.Pattern)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rules = append(rules, &PolicyRule{
|
||||
Pattern: r,
|
||||
PolicyID: rule.PolicyID,
|
||||
Replacement: rule.Replacement,
|
||||
})
|
||||
}
|
||||
|
||||
return &PolicyMappings{
|
||||
Version: mappingFile.Version,
|
||||
Kind: mappingFile.Kind,
|
||||
Policies: policies,
|
||||
Rules: rules,
|
||||
}, nil
|
||||
}
|
||||
82
config/config_test.go
Normal file
82
config/config_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newMapping() *policyMappingsFile {
|
||||
return &policyMappingsFile{
|
||||
Version: "v1",
|
||||
Kind: "policy-mapping",
|
||||
Policies: []*PolicyMapping{
|
||||
{
|
||||
ID: "docker-official-images",
|
||||
Files: []PolicyMappingFile{
|
||||
{
|
||||
Path: "docker.io/library/alpine",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: []*policyRuleFile{
|
||||
{
|
||||
Pattern: "docker.io/library/alpine",
|
||||
PolicyID: "docker-official-images",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestMappingsFileValidation(t *testing.T) {
|
||||
mappings := newMapping()
|
||||
err := validateMappingsFile(mappings)
|
||||
require.NoError(t, err)
|
||||
|
||||
mappings = newMapping()
|
||||
mappings.Kind = "not-policy-mapping"
|
||||
err = validateMappingsFile(mappings)
|
||||
require.ErrorContains(t, err, "file is not of kind policy-mapping: not-policy-mapping")
|
||||
|
||||
mappings = newMapping()
|
||||
mappings.Version = "v2"
|
||||
err = validateMappingsFile(mappings)
|
||||
require.ErrorContains(t, err, "unsupported policy mapping file version: v2")
|
||||
|
||||
mappings = newMapping()
|
||||
mappings.Rules[0].Pattern = ""
|
||||
err = validateMappingsFile(mappings)
|
||||
require.ErrorContains(t, err, "rule missing pattern")
|
||||
|
||||
mappings = newMapping()
|
||||
mappings.Rules[0].PolicyID = ""
|
||||
err = validateMappingsFile(mappings)
|
||||
require.ErrorContains(t, err, "rule must have policy-id or replacement")
|
||||
|
||||
mappings = newMapping()
|
||||
mappings.Rules[0].PolicyID = "docker-official-images"
|
||||
mappings.Rules[0].Replacement = "docker.io/library/alpine"
|
||||
err = validateMappingsFile(mappings)
|
||||
require.ErrorContains(t, err, "rule cannot have both policy-id and replacement")
|
||||
|
||||
mappings = newMapping()
|
||||
mappings.Policies[0].ID = ""
|
||||
err = validateMappingsFile(mappings)
|
||||
require.ErrorContains(t, err, "policy missing id")
|
||||
|
||||
mappings = newMapping()
|
||||
mappings.Policies[0].Files = nil
|
||||
err = validateMappingsFile(mappings)
|
||||
require.ErrorContains(t, err, "policy missing files")
|
||||
|
||||
mappings = newMapping()
|
||||
mappings.Policies[0].Files[0].Path = ""
|
||||
err = validateMappingsFile(mappings)
|
||||
require.ErrorContains(t, err, "file missing path")
|
||||
|
||||
// multiple errors
|
||||
mappings.Policies[0].ID = ""
|
||||
err = validateMappingsFile(mappings)
|
||||
require.ErrorContains(t, err, "policy missing id: \nfile missing path: {}")
|
||||
}
|
||||
@@ -3,10 +3,10 @@ package attest_test
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/attest/pkg/attest"
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/signerverifier"
|
||||
"github.com/docker/attest"
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/signerverifier"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/empty"
|
||||
"github.com/google/go-containerregistry/pkg/v1/mutate"
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/attest/pkg/attest"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/policy"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/docker/attest"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/policy"
|
||||
"github.com/docker/attest/tuf"
|
||||
)
|
||||
|
||||
func ExampleVerify_remote() {
|
||||
71
go.mod
71
go.mod
@@ -4,27 +4,27 @@ go 1.22.5
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver/v3 v3.3.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.31
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.33
|
||||
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8
|
||||
github.com/containerd/platforms v0.2.1
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/go-openapi/runtime v0.28.0
|
||||
github.com/go-openapi/strfmt v0.23.0
|
||||
github.com/google/go-containerregistry v0.20.1
|
||||
github.com/google/go-containerregistry v0.20.2
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2
|
||||
github.com/in-toto/in-toto-golang v0.9.0
|
||||
github.com/open-policy-agent/opa v0.67.1
|
||||
github.com/open-policy-agent/opa v0.68.0
|
||||
github.com/opencontainers/image-spec v1.1.0
|
||||
github.com/package-url/packageurl-go v0.1.3
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.8.0
|
||||
github.com/sigstore/cosign/v2 v2.4.0
|
||||
github.com/sigstore/rekor v1.3.6
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.8
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.8
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.9
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.9
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/testcontainers/testcontainers-go/modules/registry v0.33.0
|
||||
github.com/theupdateframework/go-tuf/v2 v2.0.0
|
||||
google.golang.org/api v0.195.0
|
||||
google.golang.org/api v0.196.0
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
@@ -33,12 +33,12 @@ replace github.com/google/go-containerregistry => github.com/docker/go-container
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.115.1 // indirect
|
||||
cloud.google.com/go/auth v0.9.1 // indirect
|
||||
cloud.google.com/go/auth v0.9.3 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.13 // indirect
|
||||
cloud.google.com/go/kms v1.18.5 // indirect
|
||||
cloud.google.com/go/longrunning v0.5.12 // indirect
|
||||
cloud.google.com/go/iam v1.2.0 // indirect
|
||||
cloud.google.com/go/kms v1.19.0 // indirect
|
||||
cloud.google.com/go/longrunning v0.6.0 // indirect
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
@@ -46,27 +46,27 @@ require (
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/agnivade/levenshtein v1.1.1 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.32 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.29.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.24.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 // indirect
|
||||
github.com/aws/smithy-go v1.20.4 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.8 // indirect
|
||||
github.com/containerd/containerd v1.7.20 // indirect
|
||||
github.com/containerd/containerd v1.7.21 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
|
||||
github.com/cpuguy83/dockercfg v0.3.1 // indirect
|
||||
@@ -104,17 +104,17 @@ require (
|
||||
github.com/google/certificate-transparency-go v1.2.1 // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.3 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect
|
||||
github.com/jellydator/ttlcache/v3 v3.2.0 // indirect
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
@@ -124,7 +124,8 @@ require (
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/user v0.1.0 // indirect
|
||||
github.com/moby/sys/user v0.3.0 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
@@ -136,7 +137,7 @@ require (
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/prometheus/client_golang v1.19.1 // indirect
|
||||
github.com/prometheus/client_golang v1.20.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
@@ -173,12 +174,12 @@ require (
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
go.mongodb.org/mongo-driver v1.15.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
||||
go.opentelemetry.io/otel v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.28.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
|
||||
go.opentelemetry.io/otel v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.29.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.26.0 // indirect
|
||||
@@ -191,10 +192,10 @@ require (
|
||||
golang.org/x/term v0.23.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240823204242-4ba0660f739c // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240823204242-4ba0660f739c // indirect
|
||||
google.golang.org/grpc v1.65.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/grpc v1.66.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
||||
138
go.sum
138
go.sum
@@ -1,18 +1,18 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ=
|
||||
cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc=
|
||||
cloud.google.com/go/auth v0.9.1 h1:+pMtLEV2k0AXKvs/tGZojuj6QaioxfUjOpMsG5Gtx+w=
|
||||
cloud.google.com/go/auth v0.9.1/go.mod h1:Sw8ocT5mhhXxFklyhT12Eiy0ed6tTrPMCJjSI8KhYLk=
|
||||
cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U=
|
||||
cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc=
|
||||
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
|
||||
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
|
||||
cloud.google.com/go/iam v1.1.13 h1:7zWBXG9ERbMLrzQBRhFliAV+kjcRToDTgQT3CTwYyv4=
|
||||
cloud.google.com/go/iam v1.1.13/go.mod h1:K8mY0uSXwEXS30KrnVb+j54LB/ntfZu1dr+4zFMNbus=
|
||||
cloud.google.com/go/kms v1.18.5 h1:75LSlVs60hyHK3ubs2OHd4sE63OAMcM2BdSJc2bkuM4=
|
||||
cloud.google.com/go/kms v1.18.5/go.mod h1:yXunGUGzabH8rjUPImp2ndHiGolHeWJJ0LODLedicIY=
|
||||
cloud.google.com/go/longrunning v0.5.12 h1:5LqSIdERr71CqfUsFlJdBpOkBH8FBCFD7P1nTWy3TYE=
|
||||
cloud.google.com/go/longrunning v0.5.12/go.mod h1:S5hMV8CDJ6r50t2ubVJSKQVv5u0rmik5//KgLO3k4lU=
|
||||
cloud.google.com/go/iam v1.2.0 h1:kZKMKVNk/IsSSc/udOb83K0hL/Yh/Gcqpz+oAkoIFN8=
|
||||
cloud.google.com/go/iam v1.2.0/go.mod h1:zITGuWgsLZxd8OwAlX+eMFgZDXzBm7icj1PVTYG766Q=
|
||||
cloud.google.com/go/kms v1.19.0 h1:x0OVJDl6UH1BSX4THKlMfdcFWoE4ruh90ZHuilZekrU=
|
||||
cloud.google.com/go/kms v1.19.0/go.mod h1:e4imokuPJUc17Trz2s6lEXFDt8bgDmvpVynH39bdrHM=
|
||||
cloud.google.com/go/longrunning v0.6.0 h1:mM1ZmaNsQsnb+5n1DNPeL0KwQd9jQRqSqSDEkBZr+aI=
|
||||
cloud.google.com/go/longrunning v0.6.0/go.mod h1:uHzSZqW89h7/pasCWNYdUpwGz3PcVWhrWupreVPYLts=
|
||||
cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2 h1:BnG6pr9TTr6CYlrJznYUDj6V7xldD1W+1iXPum0wT/w=
|
||||
cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2/go.mod h1:pK23AUVXuNzzTpfMCA06sxZGeVQ/75FdVtW249de9Uo=
|
||||
cuelang.org/go v0.9.2 h1:pfNiry2PdRBr02G/aKm5k2vhzmqbAOoaB4WurmEbWvs=
|
||||
@@ -102,18 +102,18 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
|
||||
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.31 h1:kxBoRsjhT3pq0cKthgj6RU6bXTm/2SgdoUMyrVw0rAI=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.31/go.mod h1:z04nZdSWFPaDwK3DdJOG2r+scLQzMYuJeW0CujEm9FM=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30 h1:aau/oYFtibVovr2rDt8FHlU17BTicFEMAi29V1U+L5Q=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30/go.mod h1:BPJ/yXV92ZVq6G8uYvbU0gSl8q94UB63nMT5ctNO38g=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.5 h1:mWSRTwQAb0aLE17dSzztCVJWI9+cRMgqebndjwDyK0g=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.5/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.33 h1:Nof9o/MsmH4oa0s2q9a0k7tMz5x/Yj5k06lDODWz3BU=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.33/go.mod h1:kEqdYzRb8dd8Sy2pOdEbExTTF5v7ozEXX0McgPE7xks=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.32 h1:7Cxhp/BnT2RcGy4VisJ9miUPecY+lyE9I8JvcZofn9I=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.32/go.mod h1:P5/QMF3/DCHbXGEGkdbilXHsyTBX5D3HSwcrSc9p20I=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 h1:pfQ2sqNpMVK6xz2RbqLEL0GH87JOwSxPV2rzm8Zsb74=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13/go.mod h1:NG7RXPUlqfsCLLFfi0+IpKN4sCB9D9fw/qTaSB+xRoU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 h1:pI7Bzt0BJtYA0N/JEC6B8fJ4RBrEMi1LBrkMdFYNSnQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17/go.mod h1:Dh5zzJYMtxfIjYW+/evjQ8uj2OyR/ve2KROHGHlSFqE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF42Zh5iMiQNcOYthFYwCyrnuWlc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17/go.mod h1:aLJpZlCmjE+V+KtN1q1uyZkfnUWpQGpbsn89XPKyzfU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.29.1 h1:ywNLJrn/Qn4enDsz/XnKlvpnLqvJxFGQV2BltWltbis=
|
||||
@@ -122,16 +122,16 @@ github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.24.1 h1:Eq9i/mvOlGghiKe9NtsmeD
|
||||
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.24.1/go.mod h1:VtOgEoLEPV1YADuq+Z2XOK6/wKkGW2YK6DjChZ/GvDs=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.3 h1:UPTdlTOwWUX49fVi7cymEN6hDqCwe3LNv1vi7TXUutk=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.3/go.mod h1:gjDP16zn+WWalyaUqwCCioQ8gU8lzttCCc9jYsiQI/8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.5 h1:OMsEmCyz2i89XwRwPouAJvhj81wINh+4UK+k/0Yo/q8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.5/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 h1:rfprUlsdzgl7ZL2KlXiUAoJnI/VxfHCvDFr2QDFj6u4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19/go.mod h1:SCWkEdRq8/7EK60NcvvQ6NXKuTcchAD4ROAsC37VEZE=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.5 h1:XUomV7SiclZl1QuXORdGcfFqHxEHET7rmNGtxTfNB+M=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.5/go.mod h1:A5CS0VRmxxj2YKYLCY08l/Zzbd01m6JZn0WzxgT1OCA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 h1:pIaGg+08llrP7Q5aiz9ICWbY8cqhTkyy+0SHvfzQpTc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.7/go.mod h1:eEygMHnTKH/3kNp9Jr1n3PdejuSNcgwLe1dWgQtO0VQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 h1:/Cfdu0XV3mONYKaOt1Gr0k1KvQzkzPyiKUdlWJqy+J4=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7/go.mod h1:bCbAxKDqNvkHxRaIMnyVPXPo+OaPRwvmgzMxbz1VKSA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 h1:NKTa1eqZYw8tiHSRGpP0VtTdub/8KNk8sDkNPFaOKDE=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.7/go.mod h1:NXi1dIAGteSaRLqYgarlhP/Ij0cFT+qmCwiJqWh/U5o=
|
||||
github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4=
|
||||
github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8 h1:SoFYaT9UyGkR0+nogNyD/Lj+bsixB+SNuAS4ABlEs6M=
|
||||
@@ -178,8 +178,8 @@ github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUo
|
||||
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
|
||||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ=
|
||||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w=
|
||||
github.com/containerd/containerd v1.7.20 h1:Sl6jQYk3TRavaU83h66QMbI2Nqg9Jm6qzwX57Vsn1SQ=
|
||||
github.com/containerd/containerd v1.7.20/go.mod h1:52GsS5CwquuqPuLncsXwG0t2CiUce+KsNHJZQJvAgR0=
|
||||
github.com/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA=
|
||||
github.com/containerd/containerd v1.7.21/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
||||
@@ -362,8 +362,8 @@ github.com/google/trillian v1.6.0/go.mod h1:Yu3nIMITzNhhMJEHjAtp6xKiu+H/iHu2Oq5F
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.3 h1:QRje2j5GZimBzlbhGA2V2QlGNgL8G6e+wGo/+/2bWI0=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.3/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s=
|
||||
github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
@@ -405,8 +405,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY=
|
||||
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E=
|
||||
github.com/jellydator/ttlcache/v3 v3.2.0 h1:6lqVJ8X3ZaUwvzENqPAobDsXNExfUJd61u++uW8a3LE=
|
||||
github.com/jellydator/ttlcache/v3 v3.2.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4=
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc=
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
@@ -419,8 +419,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
||||
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
@@ -456,8 +456,10 @@ github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkV
|
||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||
github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
|
||||
github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
|
||||
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
||||
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
@@ -491,8 +493,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/open-policy-agent/opa v0.67.1 h1:rzy26J6g1X+CKknAcx0Vfbt41KqjuSzx4E0A8DAZf3E=
|
||||
github.com/open-policy-agent/opa v0.67.1/go.mod h1:aqKlHc8E2VAAylYE9x09zJYr/fYzGX+JKne89UGqFzk=
|
||||
github.com/open-policy-agent/opa v0.68.0 h1:Jl3U2vXRjwk7JrHmS19U3HZO5qxQRinQbJ2eCJYSqJQ=
|
||||
github.com/open-policy-agent/opa v0.68.0/go.mod h1:5E5SvaPwTpwt2WM177I9Z3eT7qUpmOGjk1ZdHs+TZ4w=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
@@ -515,8 +517,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
||||
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||
github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
|
||||
github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
@@ -565,12 +567,12 @@ github.com/sigstore/sigstore v1.8.8 h1:B6ZQPBKK7Z7tO3bjLNnlCMG+H66tO4E/+qAphX8T/
|
||||
github.com/sigstore/sigstore v1.8.8/go.mod h1:GW0GgJSCTBJY3fUOuGDHeFWcD++c4G8Y9K015pwcpDI=
|
||||
github.com/sigstore/sigstore-go v0.5.1 h1:5IhKvtjlQBeLnjKkzMELNG4tIBf+xXQkDzhLV77+/8Y=
|
||||
github.com/sigstore/sigstore-go v0.5.1/go.mod h1:TuOfV7THHqiDaUHuJ5+QN23RP/YoKmsbwJpY+aaYPN0=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.8 h1:2zHmUvaYCwV6LVeTo+OAkTm8ykOGzA9uFlAjwDPAUWM=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.8/go.mod h1:OEhheBplZinUsm7W9BupafztVZV3ldkAxEHbpAeC0Pk=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.9 h1:tgpdvjyoEgYFeTBFe4MHvBKsG+J4E7NVtstChIExVT8=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.9/go.mod h1:wCz6cAZKL/wFumDHX9l8VkVITS2GntrOfs2j/kwH4wo=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.8 h1:RKk4Z+qMaLORUdT7zntwMqKiYAej1VQlCswg0S7xNSY=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.8/go.mod h1:dMJdlBWKHMu2xf0wIKpbo7+QfG+RzVkBB3nHP8EMM5o=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.8 h1:89Xtxj8oqZt3UlSpCP4wApFvnQ2Z/dgowW5QOVhQigI=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.8/go.mod h1:Wa4xn/H3pU/yW/6tHiMXTpObBtBSGC5q29KYFEPKN6o=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.9 h1:liWcl12dfFeQXU0JemQVgdVQx02Fls9UPdrFzVrCWhs=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.9/go.mod h1:Ckx62auqPQvNJWRBAboY+/kHs77gy6L33b6UtB/FB5U=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.8 h1:Zte3Oogkd8m+nu2oK3yHtGmN++TZWh2Lm6q2iSprT1M=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.8/go.mod h1:j00crVw6ki4/WViXflw0zWgNALrAzZT+GbIK8v7Xlz4=
|
||||
github.com/sigstore/timestamp-authority v1.2.2 h1:X4qyutnCQqJ0apMewFyx+3t7Tws00JQ/JonBiu3QvLE=
|
||||
@@ -658,24 +660,24 @@ go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUS
|
||||
go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
|
||||
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
|
||||
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
|
||||
go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
|
||||
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
||||
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
|
||||
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
|
||||
go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
|
||||
go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
|
||||
go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
|
||||
go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
|
||||
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
|
||||
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
|
||||
go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
|
||||
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
||||
go.step.sm/crypto v0.51.1 h1:ktUg/2hetEMiBAqgz502ktZDGoDoGrcHFg3XpkmkvvA=
|
||||
@@ -807,26 +809,26 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.195.0 h1:Ude4N8FvTKnnQJHU48RFI40jOBgIrL8Zqr3/QeST6yU=
|
||||
google.golang.org/api v0.195.0/go.mod h1:DOGRWuv3P8TU8Lnz7uQc4hyNqrBpMtD9ppW3wBJurgc=
|
||||
google.golang.org/api v0.196.0 h1:k/RafYqebaIJBO3+SMnfEGtFVlvp5vSgqTUF54UN/zg=
|
||||
google.golang.org/api v0.196.0/go.mod h1:g9IL21uGkYgvQ5BZg6BAtoGJQIm8r6EgaAbpNey5wBE=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20240823204242-4ba0660f739c h1:TYOEhrQMrNDTAd2rX9m+WgGr8Ku6YNuj1D7OX6rWSok=
|
||||
google.golang.org/genproto v0.0.0-20240823204242-4ba0660f739c/go.mod h1:2rC5OendXvZ8wGEo/cSLheztrZDZaSoHanUcd1xtZnw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240823204242-4ba0660f739c h1:Kqjm4WpoWvwhMPcrAczoTyMySQmYa9Wy2iL6Con4zn8=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240823204242-4ba0660f739c/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU=
|
||||
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed h1:3RgNmBoI9MZhsj3QxC+AP/qQhNwpCLOvYDYYsFrhFt0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
||||
@@ -2,12 +2,13 @@ package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/pkg/signerverifier"
|
||||
"github.com/docker/attest/pkg/tlog"
|
||||
"github.com/docker/attest/signerverifier"
|
||||
"github.com/docker/attest/tlog"
|
||||
"github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
)
|
||||
|
||||
@@ -19,7 +20,10 @@ const (
|
||||
AWSKMSKeyARN = "arn:aws:kms:us-east-1:175142243308:alias/doi-signing" // sandbox
|
||||
)
|
||||
|
||||
var UnsignedTestImage = filepath.Join("..", "..", "test", "testdata", "unsigned-test-image")
|
||||
func UnsignedTestImage(rel ...string) string {
|
||||
rel = append(rel, "test", "testdata", "unsigned-test-image")
|
||||
return filepath.Join(rel...)
|
||||
}
|
||||
|
||||
func CreateTempDir(t *testing.T, dir, pattern string) string {
|
||||
// Create a temporary directory for output oci layout
|
||||
@@ -37,12 +41,11 @@ func CreateTempDir(t *testing.T, dir, pattern string) string {
|
||||
return tempDir
|
||||
}
|
||||
|
||||
//go:embed test-signing-key.pem
|
||||
var signingKey []byte
|
||||
|
||||
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
|
||||
}
|
||||
return signerverifier.LoadKeyPair(priv)
|
||||
return signerverifier.LoadKeyPair(signingKey)
|
||||
}
|
||||
|
||||
func Setup(t *testing.T) (context.Context, dsse.SignerVerifier) {
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/attest/pkg/mirror"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/docker/attest/mirror"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/tuf"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/empty"
|
||||
"github.com/google/go-containerregistry/pkg/v1/mutate"
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/docker/attest/tuf"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/theupdateframework/go-tuf/v2/metadata"
|
||||
)
|
||||
@@ -21,7 +21,7 @@ const (
|
||||
)
|
||||
|
||||
func TestGetTufMetadataMirror(t *testing.T) {
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
|
||||
defer server.Close()
|
||||
|
||||
path := test.CreateTempDir(t, "", "tuf_temp")
|
||||
@@ -39,7 +39,7 @@ func TestGetTufMetadataMirror(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetMetadataManifest(t *testing.T) {
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
|
||||
defer server.Close()
|
||||
|
||||
path := test.CreateTempDir(t, "", "tuf_temp")
|
||||
@@ -78,7 +78,7 @@ func TestGetMetadataManifest(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDelegatedMetadataMirrors(t *testing.T) {
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
|
||||
defer server.Close()
|
||||
|
||||
path := test.CreateTempDir(t, "", "tuf_temp")
|
||||
@@ -3,7 +3,7 @@ package mirror
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/docker/attest/tuf"
|
||||
)
|
||||
|
||||
func NewTUFMirror(root []byte, tufPath, metadataURL, targetsURL string, versionChecker tuf.VersionChecker) (*TUFMirror, error) {
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/empty"
|
||||
"github.com/google/go-containerregistry/pkg/v1/mutate"
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/docker/attest/tuf"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -22,7 +22,7 @@ type Layers struct {
|
||||
}
|
||||
|
||||
func TestGetTufTargetsMirror(t *testing.T) {
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
|
||||
defer server.Close()
|
||||
|
||||
path := test.CreateTempDir(t, "", "tuf_temp")
|
||||
@@ -56,7 +56,7 @@ func TestGetTufTargetsMirror(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTargetDelegationMetadata(t *testing.T) {
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
|
||||
defer server.Close()
|
||||
|
||||
path := test.CreateTempDir(t, "", "tuf_temp")
|
||||
@@ -69,7 +69,7 @@ func TestTargetDelegationMetadata(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDelegatedTargetMirrors(t *testing.T) {
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
|
||||
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
|
||||
defer server.Close()
|
||||
|
||||
path := test.CreateTempDir(t, "", "tuf_temp")
|
||||
@@ -1,8 +1,8 @@
|
||||
package mirror
|
||||
|
||||
import (
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/tuf"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/theupdateframework/go-tuf/v2/metadata"
|
||||
)
|
||||
@@ -6,12 +6,12 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRegistryAuth(t *testing.T) {
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage)
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
||||
require.NoError(t, err)
|
||||
// test cases for ecr, gcr and dockerhub
|
||||
testCases := []struct {
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/layout"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -67,7 +67,7 @@ func TestRefToPurl(t *testing.T) {
|
||||
|
||||
// Test fix for https://github.com/docker/secure-artifacts-team-issues/issues/202
|
||||
func TestImageDigestForPlatform(t *testing.T) {
|
||||
idx, err := layout.ImageIndexFromPath(test.UnsignedTestImage)
|
||||
idx, err := layout.ImageIndexFromPath(test.UnsignedTestImage(".."))
|
||||
assert.NoError(t, err)
|
||||
|
||||
idxm, err := idx.IndexManifest()
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/google/go-containerregistry/pkg/registry"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/empty"
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
|
||||
func TestSavingIndex(t *testing.T) {
|
||||
outputLayout := test.CreateTempDir(t, "", "mirror-test")
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage)
|
||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
||||
require.NoError(t, err)
|
||||
|
||||
server := httptest.NewServer(registry.New())
|
||||
@@ -9,6 +9,9 @@ import (
|
||||
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||
)
|
||||
|
||||
// ensure RegistryImageDetailsResolver implements ImageDetailsResolver.
|
||||
var _ ImageDetailsResolver = &RegistryImageDetailsResolver{}
|
||||
|
||||
type RegistryImageDetailsResolver struct {
|
||||
*ImageSpec
|
||||
descriptor *v1.Descriptor
|
||||
@@ -1,2 +0,0 @@
|
||||
## attest
|
||||
This package implements the top-level signing and verification methods.
|
||||
@@ -1,77 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const (
|
||||
MappingFilename = "mapping.yaml"
|
||||
)
|
||||
|
||||
func LoadLocalMappings(configDir string) (*PolicyMappings, error) {
|
||||
if configDir == "" {
|
||||
return nil, nil
|
||||
}
|
||||
mappings := &policyMappingsFile{}
|
||||
path := filepath.Join(configDir, MappingFilename)
|
||||
mappingFile, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read local policy mapping file %s: %w", path, err)
|
||||
}
|
||||
err = yaml.Unmarshal(mappingFile, mappings)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal policy mapping file %s: %w", path, err)
|
||||
}
|
||||
return expandMappingFile(mappings)
|
||||
}
|
||||
|
||||
func LoadTUFMappings(tufClient tuf.Downloader, localTargetsDir string) (*PolicyMappings, error) {
|
||||
if tufClient == nil {
|
||||
return nil, fmt.Errorf("tuf client not set")
|
||||
}
|
||||
filename := MappingFilename
|
||||
file, err := tufClient.DownloadTarget(filename, filepath.Join(localTargetsDir, filename))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to download policy mapping file %s: %w", filename, err)
|
||||
}
|
||||
mappings := &policyMappingsFile{}
|
||||
|
||||
err = yaml.Unmarshal(file.Data, mappings)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal policy mapping file %s: %w", filename, err)
|
||||
}
|
||||
return expandMappingFile(mappings)
|
||||
}
|
||||
|
||||
func expandMappingFile(mappingFile *policyMappingsFile) (*PolicyMappings, error) {
|
||||
policies := make(map[string]*PolicyMapping)
|
||||
for _, policy := range mappingFile.Policies {
|
||||
policies[policy.ID] = policy
|
||||
}
|
||||
|
||||
var rules []*PolicyRule
|
||||
for _, rule := range mappingFile.Rules {
|
||||
r, err := regexp.Compile(rule.Pattern)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rules = append(rules, &PolicyRule{
|
||||
Pattern: r,
|
||||
PolicyID: rule.PolicyID,
|
||||
Replacement: rule.Replacement,
|
||||
})
|
||||
}
|
||||
|
||||
return &PolicyMappings{
|
||||
Version: mappingFile.Version,
|
||||
Kind: mappingFile.Kind,
|
||||
Policies: policies,
|
||||
Rules: rules,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package policy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/config"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
)
|
||||
|
||||
func CreateImageDetailsResolver(imageSource *oci.ImageSpec) (oci.ImageDetailsResolver, error) {
|
||||
switch imageSource.Type {
|
||||
case oci.OCI:
|
||||
return attestation.NewOCILayoutResolver(imageSource)
|
||||
case oci.Docker:
|
||||
return oci.NewRegistryImageDetailsResolver(imageSource)
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported image source type: %s", imageSource.Type)
|
||||
}
|
||||
|
||||
func CreateAttestationResolver(resolver oci.ImageDetailsResolver, mapping *config.PolicyMapping) (attestation.Resolver, error) {
|
||||
if mapping.Attestations != nil {
|
||||
if mapping.Attestations.Style == config.AttestationStyleAttached {
|
||||
switch resolver := resolver.(type) {
|
||||
case *oci.RegistryImageDetailsResolver:
|
||||
return attestation.NewRegistryResolver(resolver)
|
||||
case *attestation.LayoutResolver:
|
||||
return resolver, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported image details resolver type: %T", resolver)
|
||||
}
|
||||
}
|
||||
if mapping.Attestations.Repo != "" {
|
||||
return attestation.NewReferrersResolver(resolver, attestation.WithReferrersRepo(mapping.Attestations.Repo))
|
||||
}
|
||||
}
|
||||
return attestation.NewReferrersResolver(resolver)
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package policy
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/attestation"
|
||||
)
|
||||
|
||||
type Evaluator interface {
|
||||
@@ -3,7 +3,7 @@ package policy
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/attest/pkg/config"
|
||||
"github.com/docker/attest/config"
|
||||
)
|
||||
|
||||
type matchType string
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/pkg/config"
|
||||
"github.com/docker/attest/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -15,10 +15,11 @@ func TestFindPolicyMatch(t *testing.T) {
|
||||
imageName string
|
||||
mappingDir string
|
||||
|
||||
expectError bool
|
||||
expectedMatchType matchType
|
||||
expectedPolicyID string
|
||||
expectedImageName string
|
||||
expectError bool
|
||||
expectLoadingError bool
|
||||
expectedMatchType matchType
|
||||
expectedPolicyID string
|
||||
expectedImageName string
|
||||
}{
|
||||
{
|
||||
name: "alpine",
|
||||
@@ -79,16 +80,6 @@ func TestFindPolicyMatch(t *testing.T) {
|
||||
expectedPolicyID: "docker-official-images",
|
||||
expectedImageName: "docker.io/library/alpine",
|
||||
},
|
||||
{
|
||||
name: "invalid rewrites",
|
||||
mappingDir: "rewrite-invalid",
|
||||
imageName: "mycoolmirror.org/library/alpine",
|
||||
|
||||
expectError: true,
|
||||
expectedMatchType: matchTypePolicy,
|
||||
expectedPolicyID: "docker-official-images",
|
||||
expectedImageName: "docker.io/library/alpine",
|
||||
},
|
||||
{
|
||||
name: "rewrite loop",
|
||||
mappingDir: "rewrite-loop",
|
||||
@@ -3,7 +3,7 @@ package policy
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/attestation"
|
||||
)
|
||||
|
||||
type MockPolicyEvaluator struct {
|
||||
92
policy/policy.go
Normal file
92
policy/policy.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package policy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/config"
|
||||
"github.com/docker/attest/oci"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
"github.com/package-url/packageurl-go"
|
||||
)
|
||||
|
||||
func CreateImageDetailsResolver(imageSource *oci.ImageSpec) (oci.ImageDetailsResolver, error) {
|
||||
switch imageSource.Type {
|
||||
case oci.OCI:
|
||||
return attestation.NewOCILayoutResolver(imageSource)
|
||||
case oci.Docker:
|
||||
return oci.NewRegistryImageDetailsResolver(imageSource)
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported image source type: %s", imageSource.Type)
|
||||
}
|
||||
|
||||
func CreateAttestationResolver(resolver oci.ImageDetailsResolver, mapping *config.PolicyMapping) (attestation.Resolver, error) {
|
||||
if mapping.Attestations != nil {
|
||||
if mapping.Attestations.Style == config.AttestationStyleAttached {
|
||||
switch resolver := resolver.(type) {
|
||||
case *oci.RegistryImageDetailsResolver:
|
||||
return attestation.NewRegistryResolver(resolver)
|
||||
case *attestation.LayoutResolver:
|
||||
return resolver, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported image details resolver type: %T", resolver)
|
||||
}
|
||||
}
|
||||
if mapping.Attestations.Repo != "" {
|
||||
return attestation.NewReferrersResolver(resolver, attestation.WithReferrersRepo(mapping.Attestations.Repo))
|
||||
}
|
||||
}
|
||||
return attestation.NewReferrersResolver(resolver)
|
||||
}
|
||||
|
||||
// VerifySubject verifies if any of the given subject PURLs matches the image name and platform from resolver.
|
||||
// Tags are not taken into account when attempting to match because sometimes the user may not have specified a tag, and maybe there
|
||||
// isn't a purl subject with that particular tag (because of post build tagging?).
|
||||
func VerifySubject(ctx context.Context, subject []intoto.Subject, resolver attestation.Resolver) error {
|
||||
img, err := resolver.ImageName(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
inputName, err := reference.ParseNormalizedNamed(img)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
descriptor, err := resolver.ImageDescriptor(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
platform, err := resolver.ImagePlatform(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, sub := range subject {
|
||||
if sub.Digest[descriptor.Digest.Algorithm] != descriptor.Digest.Hex {
|
||||
continue
|
||||
}
|
||||
purl, err := packageurl.FromString(sub.Name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if purl.Type != "docker" {
|
||||
continue
|
||||
}
|
||||
if purl.Qualifiers.Map()["platform"] != platform.String() {
|
||||
continue
|
||||
}
|
||||
// ensure reference is normalized before comparing
|
||||
subjectName, err := reference.ParseNormalizedNamed(purl.Name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// this assumes that domain is part of the package URL (some say it should be a qualifier)
|
||||
// buildkit puts the domain in the name, e.g. pkg:docker/ecr.io/foobar/alpine@latest?platform=linux%2Famd64
|
||||
if inputName.Name() == subjectName.Name() {
|
||||
// found a match
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("no matching subject found for image: %s", img)
|
||||
}
|
||||
@@ -2,15 +2,18 @@ package policy_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/config"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/config"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/policy"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/policy"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -32,7 +35,7 @@ func loadAttestation(t *testing.T, path string) *attestation.Envelope {
|
||||
func TestRegoEvaluator_Evaluate(t *testing.T) {
|
||||
ctx, _ := test.Setup(t)
|
||||
resolveErrorStr := "failed to resolve policy by id: policy with id non-existent-policy-id not found"
|
||||
TestDataPath := filepath.Join("..", "..", "test", "testdata")
|
||||
TestDataPath := filepath.Join("..", "test", "testdata")
|
||||
ExampleAttestation := filepath.Join(TestDataPath, "example_attestation.json")
|
||||
|
||||
re := policy.NewRegoEvaluator(true)
|
||||
@@ -173,3 +176,209 @@ func TestCreateAttestationResolver(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifySubject(t *testing.T) {
|
||||
ctx, _ := test.Setup(t)
|
||||
defaultResolver := attestation.MockResolver{}
|
||||
testCases := []struct {
|
||||
name string
|
||||
subject []intoto.Subject
|
||||
img string
|
||||
expectError bool
|
||||
digest string
|
||||
}{
|
||||
{
|
||||
name: "library short",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "alpine",
|
||||
},
|
||||
{
|
||||
name: "with domain and namespace",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/docker.io/library/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "alpine",
|
||||
},
|
||||
{
|
||||
name: "with library",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/library/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "alpine",
|
||||
},
|
||||
{
|
||||
name: "library short with tag",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "alpine:foo",
|
||||
},
|
||||
{
|
||||
name: "library with namespace",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "library/alpine:foo",
|
||||
},
|
||||
{
|
||||
name: "library with domain",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "docker.io/library/alpine:foo",
|
||||
},
|
||||
{
|
||||
name: "domain mismatch",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "ecr.io/library/alpine:foo",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "type mismatch",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:node/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "alpine",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "name mismatch",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "library/debian:latest",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "namespace mismatch",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "unsupported/alpine:latest",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "digest mismatch",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "alpine",
|
||||
digest: "1234",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "platform mismatch",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Farm64",
|
||||
},
|
||||
},
|
||||
img: "alpine",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "malformed purl",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "not-a-purl",
|
||||
},
|
||||
},
|
||||
img: "alpine",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "malformed image in valid purl",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine,bar@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "alpine-broken",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "malformed image name",
|
||||
subject: []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
},
|
||||
},
|
||||
img: "foo bar",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defaultResolver.Image = tc.img
|
||||
// digest from mock resolver
|
||||
tc.subject[0].Digest = map[string]string{"sha256": "da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620"}
|
||||
if tc.digest != "" {
|
||||
tc.subject[0].Digest = map[string]string{"sha256": tc.digest}
|
||||
}
|
||||
err := policy.VerifySubject(ctx, tc.subject, defaultResolver)
|
||||
if tc.expectError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
defaultResolver.Image = "alpine"
|
||||
subject := []intoto.Subject{
|
||||
{
|
||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
Digest: map[string]string{"sha256": "da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620"},
|
||||
},
|
||||
}
|
||||
|
||||
// error getting descriptor
|
||||
defaultResolver.DescriptorFn = func() (*v1.Descriptor, error) {
|
||||
return nil, fmt.Errorf("error")
|
||||
}
|
||||
err := policy.VerifySubject(ctx, subject, defaultResolver)
|
||||
require.Error(t, err)
|
||||
|
||||
// error getting platform
|
||||
defaultResolver.DescriptorFn = nil
|
||||
defaultResolver.PlatformFn = func() (*v1.Platform, error) {
|
||||
return nil, fmt.Errorf("error")
|
||||
}
|
||||
err = policy.VerifySubject(ctx, subject, defaultResolver)
|
||||
require.Error(t, err)
|
||||
|
||||
// error getting image name
|
||||
defaultResolver.PlatformFn = nil
|
||||
defaultResolver.Image = ""
|
||||
defaultResolver.ImangeNameFn = func() (string, error) {
|
||||
return "", fmt.Errorf("error")
|
||||
}
|
||||
err = policy.VerifySubject(ctx, subject, defaultResolver)
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/attestation"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
"github.com/open-policy-agent/opa/ast"
|
||||
"github.com/open-policy-agent/opa/rego"
|
||||
@@ -163,9 +163,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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ func RegoFunctions(resolver attestation.Resolver) []*tester.Builtin {
|
||||
Memoize: true,
|
||||
Nondeterministic: verifyDecl.Nondeterministic,
|
||||
},
|
||||
handleErrors2(verifyInTotoEnvelope)),
|
||||
handleErrors2(verifyInTotoEnvelope(resolver))),
|
||||
},
|
||||
{
|
||||
Decl: attestDecl,
|
||||
@@ -226,41 +226,48 @@ func fetchInTotoAttestations(resolver attestation.Resolver) rego.Builtin1 {
|
||||
}
|
||||
}
|
||||
|
||||
func verifyInTotoEnvelope(rCtx *rego.BuiltinContext, envTerm, optsTerm *ast.Term) (*ast.Term, error) {
|
||||
env := new(attestation.Envelope)
|
||||
opts := new(attestation.VerifyOptions)
|
||||
err := ast.As(envTerm.Value, env)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to cast envelope: %w", err)
|
||||
}
|
||||
err = ast.As(optsTerm.Value, &opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to cast verifier options: %w", err)
|
||||
}
|
||||
|
||||
payload, err := attestation.VerifyDSSE(rCtx.Context, env, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
statement := new(intoto.Statement)
|
||||
|
||||
switch env.PayloadType {
|
||||
case intoto.PayloadType:
|
||||
err = json.Unmarshal(payload, statement)
|
||||
func verifyInTotoEnvelope(resolver attestation.Resolver) rego.Builtin2 {
|
||||
return func(rCtx rego.BuiltinContext, envTerm, optsTerm *ast.Term) (*ast.Term, error) {
|
||||
env := new(attestation.Envelope)
|
||||
opts := new(attestation.VerifyOptions)
|
||||
err := ast.As(envTerm.Value, env)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal statement: %w", err)
|
||||
return nil, fmt.Errorf("failed to cast envelope: %w", err)
|
||||
}
|
||||
err = ast.As(optsTerm.Value, &opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to cast verifier options: %w", err)
|
||||
}
|
||||
// TODO: implement other types of envelope
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported payload type: %s", env.PayloadType)
|
||||
}
|
||||
|
||||
value, err := ast.InterfaceToValue(statement)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
payload, err := attestation.VerifyDSSE(rCtx.Context, env, opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to verify envelope: %w", err)
|
||||
}
|
||||
|
||||
statement := new(intoto.Statement)
|
||||
|
||||
switch env.PayloadType {
|
||||
case intoto.PayloadType:
|
||||
err = json.Unmarshal(payload, statement)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal statement: %w", err)
|
||||
}
|
||||
// TODO: implement other types of envelope
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported payload type: %s", env.PayloadType)
|
||||
}
|
||||
|
||||
err = VerifySubject(rCtx.Context, statement.Subject, resolver)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to verify subject: %w", err)
|
||||
}
|
||||
|
||||
value, err := ast.InterfaceToValue(statement)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ast.NewTerm(value), nil
|
||||
}
|
||||
return ast.NewTerm(value), nil
|
||||
}
|
||||
|
||||
func loadYAML(path string, bs []byte) (interface{}, error) {
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/attest/config"
|
||||
"github.com/docker/attest/internal/util"
|
||||
"github.com/docker/attest/pkg/config"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/docker/attest/tuf"
|
||||
)
|
||||
|
||||
type Resolver struct {
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/policy"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/docker/attest/policy"
|
||||
"github.com/docker/attest/tuf"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -1,8 +1,8 @@
|
||||
package policy
|
||||
|
||||
import (
|
||||
"github.com/docker/attest/pkg/config"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/docker/attest/config"
|
||||
"github.com/docker/attest/tuf"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/attestation"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
)
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/policy"
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/policy"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
v02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -15,13 +15,13 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
NoProvenanceImage = filepath.Join("..", "..", "test", "testdata", "no-provenance-image")
|
||||
PassPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-pass")
|
||||
PassMirrorPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-mirror")
|
||||
PassNoTLPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-no-tl")
|
||||
FailPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-fail")
|
||||
InputsPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-inputs")
|
||||
EmptyPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-no-policies")
|
||||
NoProvenanceImage = filepath.Join("test", "testdata", "no-provenance-image")
|
||||
PassPolicyDir = filepath.Join("test", "testdata", "local-policy-pass")
|
||||
PassMirrorPolicyDir = filepath.Join("test", "testdata", "local-policy-mirror")
|
||||
PassNoTLPolicyDir = filepath.Join("test", "testdata", "local-policy-no-tl")
|
||||
FailPolicyDir = filepath.Join("test", "testdata", "local-policy-fail")
|
||||
InputsPolicyDir = filepath.Join("test", "testdata", "local-policy-inputs")
|
||||
EmptyPolicyDir = filepath.Join("test", "testdata", "local-policy-no-policies")
|
||||
TestTempDir = "attest-sign-test"
|
||||
)
|
||||
|
||||
@@ -35,8 +35,8 @@ func TestSignVerifyOCILayout(t *testing.T) {
|
||||
expectedAttestations int
|
||||
replace bool
|
||||
}{
|
||||
{"signed replaced", test.UnsignedTestImage, 0, 4, true},
|
||||
{"without replace", test.UnsignedTestImage, 4, 4, false},
|
||||
{"signed replaced", test.UnsignedTestImage(), 0, 4, true},
|
||||
{"without replace", test.UnsignedTestImage(), 4, 4, false},
|
||||
// image without provenance doesn't fail
|
||||
{"no provenance (replace)", NoProvenanceImage, 0, 2, true},
|
||||
{"no provenance (no replace)", NoProvenanceImage, 2, 2, false},
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/attest/internal/util"
|
||||
"github.com/docker/attest/pkg/signerverifier"
|
||||
"github.com/docker/attest/signerverifier"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/attest/internal/util"
|
||||
"github.com/docker/attest/pkg/signerverifier"
|
||||
"github.com/docker/attest/signerverifier"
|
||||
"github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user