Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79bbc9b55b | ||
|
|
47669993c6 | ||
|
|
7414fb7339 | ||
|
|
0e1005d0f7 | ||
|
|
94f69c75d2 | ||
|
|
b2e8166079 | ||
|
|
8c4ee60f50 | ||
|
|
9b6234f0ae | ||
|
|
17b0978b44 | ||
|
|
7ff20a9328 | ||
|
|
273b61ebd6 | ||
|
|
eda0b23910 | ||
|
|
4a82bb9981 | ||
|
|
84c0b116a7 | ||
|
|
16f65fefeb | ||
|
|
e39a4ea9f3 | ||
|
|
2e4f8f79bd |
@@ -3,6 +3,7 @@ package attestation
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/attest/version"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
"github.com/package-url/packageurl-go"
|
||||
)
|
||||
@@ -22,9 +23,12 @@ type VSAPredicate struct {
|
||||
}
|
||||
|
||||
type VSAVerifier struct {
|
||||
ID string `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Version VerifierVersion `json:"version"`
|
||||
}
|
||||
|
||||
type VerifierVersion map[string]string
|
||||
|
||||
type VSAPolicy struct {
|
||||
URI string `json:"uri,omitempty"`
|
||||
Digest map[string]string `json:"digest"`
|
||||
@@ -44,3 +48,16 @@ func ToVSAResourceURI(sub intoto.Subject) (string, error) {
|
||||
purl.Qualifiers = packageurl.QualifiersFromMap(quals)
|
||||
return purl.String(), nil
|
||||
}
|
||||
|
||||
func GetVerifierVersion(fetcher version.Fetcher) (VerifierVersion, error) {
|
||||
attestVersion, err := fetcher.Get()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get attest version: %w", err)
|
||||
}
|
||||
if attestVersion == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return VerifierVersion{
|
||||
version.ThisModulePath: attestVersion.String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
18
go.mod
18
go.mod
@@ -1,12 +1,10 @@
|
||||
module github.com/docker/attest
|
||||
|
||||
go 1.22.7
|
||||
|
||||
toolchain go1.22.8
|
||||
go 1.22.8
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver/v3 v3.3.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.43
|
||||
github.com/aws/aws-sdk-go-v2/config v1.28.0
|
||||
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8
|
||||
github.com/containerd/containerd/v2 v2.0.0-rc.5
|
||||
github.com/containerd/platforms v0.2.1
|
||||
@@ -22,12 +20,12 @@ require (
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.8.0
|
||||
github.com/sigstore/cosign/v2 v2.4.1
|
||||
github.com/sigstore/rekor v1.3.6
|
||||
github.com/sigstore/sigstore v1.8.9
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.9
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.9
|
||||
github.com/sigstore/sigstore v1.8.10
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.10
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.10
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/theupdateframework/go-tuf/v2 v2.0.2
|
||||
google.golang.org/api v0.200.0
|
||||
google.golang.org/api v0.201.0
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
@@ -35,7 +33,7 @@ require (
|
||||
replace github.com/google/go-containerregistry => github.com/docker/go-containerregistry v0.0.0-20240808132857-c8bfc44af7c8
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.115.1 // indirect
|
||||
cloud.google.com/go v0.116.0 // indirect
|
||||
cloud.google.com/go/auth v0.9.8 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.2 // indirect
|
||||
@@ -57,7 +55,7 @@ require (
|
||||
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.12.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.37.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 // indirect
|
||||
|
||||
28
go.sum
28
go.sum
@@ -1,6 +1,6 @@
|
||||
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 v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
|
||||
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
|
||||
cloud.google.com/go/auth v0.9.8 h1:+CSJ0Gw9iVeSENVCKJoLHhdUykDgXSc4Qn+gu2BRtR8=
|
||||
cloud.google.com/go/auth v0.9.8/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
|
||||
@@ -101,8 +101,8 @@ 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.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI=
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.2/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.43 h1:p33fDDihFC390dhhuv8nOmX419wjOSDQRb+USt20RrU=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.43/go.mod h1:pYhbtvg1siOOg8h5an77rXle9tVG8T+BWLWAo7cOukc=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.28.0 h1:FosVYWcqEtWNxHn8gB/Vs6jOlNwSoyOCA/g/sxyySOQ=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.28.0/go.mod h1:pYhbtvg1siOOg8h5an77rXle9tVG8T+BWLWAo7cOukc=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.41 h1:7gXo+Axmp+R4Z+AK8YFQO0ZV3L0gizGINCOWxSLY9W8=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.41/go.mod h1:u4Eb8d3394YLubphT4jLEwN1rLNq2wFOlT6OuxFwPzU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 h1:TMH3f/SCAWdNtXXVPPu5D6wrr4G5hI1rAxbcocKfC7Q=
|
||||
@@ -121,8 +121,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkv
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 h1:s7NA1SOw8q/5c0wr8477yOPp0z+uBaXBnLE0XYb0POA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2/go.mod h1:fnjjWyAW/Pj5HYOxl9LJqWtEwS7W2qgcRLWP+uWbss0=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.7 h1:v0D1LeMkA/X+JHAZWERrr+sUGOt8KrCZKnJA6KszkcE=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.7/go.mod h1:K9lwD0Rsx9+NSaJKsdAdlDK4b2G4KKOEve9PzHxPoMI=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.37.2 h1:tfBABi5R6aSZlhgTWHxL+opYUDOnIGoNcJLwVYv0jLM=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.37.2/go.mod h1:dZYFcQwuoh+cLOlFnZItijZptmyDhRIkOKWFO1CfzV8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 h1:bSYXVyUzoTHoKalBmwaZxs97HU9DWWI3ehHSAMa7xOk=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.2/go.mod h1:skMqY7JElusiOUjMJMOv1jJsP7YUg7DrhgqZZWuzu1U=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 h1:AhmO1fHINP9vFYUE0LHzCWg/LfUWUF+zFPEcY9QXb7o=
|
||||
@@ -529,16 +529,16 @@ github.com/sigstore/protobuf-specs v0.3.2 h1:nCVARCN+fHjlNCk3ThNXwrZRqIommIeNKWw
|
||||
github.com/sigstore/protobuf-specs v0.3.2/go.mod h1:RZ0uOdJR4OB3tLQeAyWoJFbNCBFrPQdcokntde4zRBA=
|
||||
github.com/sigstore/rekor v1.3.6 h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8=
|
||||
github.com/sigstore/rekor v1.3.6/go.mod h1:JDTSNNMdQ/PxdsS49DJkJ+pRJCO/83nbR5p3aZQteXc=
|
||||
github.com/sigstore/sigstore v1.8.9 h1:NiUZIVWywgYuVTxXmRoTT4O4QAGiTEKup4N1wdxFadk=
|
||||
github.com/sigstore/sigstore v1.8.9/go.mod h1:d9ZAbNDs8JJfxJrYmulaTazU3Pwr8uLL9+mii4BNR3w=
|
||||
github.com/sigstore/sigstore v1.8.10 h1:r4t+TYzJlG9JdFxMy+um9GZhZ2N1hBTyTex0AHEZxFs=
|
||||
github.com/sigstore/sigstore v1.8.10/go.mod h1:BekjqxS5ZtHNJC4u3Q3Stvfx2eyisbW/lUZzmPU2u4A=
|
||||
github.com/sigstore/sigstore-go v0.6.1 h1:tGkkv1oDIER+QYU5MrjqlttQOVDWfSkmYwMqkJhB/cg=
|
||||
github.com/sigstore/sigstore-go v0.6.1/go.mod h1:Xe5GHmUeACRFbomUWzVkf/xYCn8xVifb9DgqJrV2dIw=
|
||||
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/aws v1.8.10 h1:e5GfVngPjGap/N3ODefayt7vKIPS1/v3hWLZ9+4MrN4=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.10/go.mod h1:HOr3AdFPKdND2FNl/sUD5ZifPl1OMJvrbf9xIaaWcus=
|
||||
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.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/gcp v1.8.10 h1:Xre51HdjIIaVo5ox5zyL+6h0tkrx7Ke9Neh7fLmmZK0=
|
||||
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.10/go.mod h1:VNfdklQDbyGJog8S7apdxiEfmYmCkKyxrsCL9xprkTY=
|
||||
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=
|
||||
@@ -750,8 +750,8 @@ 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.200.0 h1:0ytfNWn101is6e9VBoct2wrGDjOi5vn7jw5KtaQgDrU=
|
||||
google.golang.org/api v0.200.0/go.mod h1:Tc5u9kcbjO7A8SwGlYj4IiVifJU01UqXtEgDMYmBmV8=
|
||||
google.golang.org/api v0.201.0 h1:+7AD9JNM3tREtawRMu8sOjSbb8VYcYXJG/2eEOmfDu0=
|
||||
google.golang.org/api v0.201.0/go.mod h1:HVY0FCHVs89xIW9fzf/pBvOEm+OolHa86G/txFezyq4=
|
||||
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=
|
||||
|
||||
@@ -33,13 +33,17 @@ func (e *InvalidVersionError) Error() string {
|
||||
}
|
||||
|
||||
func NewDefaultVersionChecker() *DefaultVersionChecker {
|
||||
return &DefaultVersionChecker{}
|
||||
return &DefaultVersionChecker{
|
||||
VersionFetcher: version.NewGoVersionFetcher(),
|
||||
}
|
||||
}
|
||||
|
||||
type DefaultVersionChecker struct{}
|
||||
type DefaultVersionChecker struct {
|
||||
VersionFetcher version.Fetcher
|
||||
}
|
||||
|
||||
func (vc *DefaultVersionChecker) CheckVersion(client Downloader) error {
|
||||
attestVersion, err := version.Get()
|
||||
attestVersion, err := vc.VersionFetcher.Get()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get version: %w", err)
|
||||
}
|
||||
|
||||
61
tuf/version_test.go
Normal file
61
tuf/version_test.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package tuf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/docker/attest/internal/test"
|
||||
"github.com/docker/attest/version"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
invalidVersion = "0.0.1"
|
||||
validVersion = "v1.0.0-0"
|
||||
versionConstraint = ">=v1.0.0-0"
|
||||
)
|
||||
|
||||
func TestDefaultVersionChecker(t *testing.T) {
|
||||
testDir := test.CreateTempDir(t, "", "tuf_temp")
|
||||
versionConstraintsPath := filepath.Join(testDir, "version-constraints")
|
||||
err := os.WriteFile(versionConstraintsPath, []byte(versionConstraint), 0o600)
|
||||
assert.NoError(t, err)
|
||||
tufClient := NewMockTufClient(testDir)
|
||||
|
||||
expectedError := fmt.Sprintf("%s version %s does not satisfy constraints %s: %s is less than %s", version.ThisModulePath, invalidVersion, versionConstraint, invalidVersion, validVersion)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
expectedError string
|
||||
version string
|
||||
}{
|
||||
{name: "version is less than the minimum", expectedError: expectedError, version: "0.0.1"},
|
||||
{name: "version is equal to the minimum", version: "1.0.0"},
|
||||
{name: "version is greater than the minimum", version: "1.0.1"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
checker := NewDefaultVersionChecker()
|
||||
checker.VersionFetcher = &MockVersionFetcher{version: tc.version}
|
||||
err := checker.CheckVersion(tufClient)
|
||||
if tc.expectedError != "" {
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, tc.expectedError, err.Error())
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type MockVersionFetcher struct {
|
||||
version string
|
||||
}
|
||||
|
||||
func (m *MockVersionFetcher) Get() (*semver.Version, error) {
|
||||
return semver.NewVersion(m.version)
|
||||
}
|
||||
@@ -19,10 +19,11 @@ func Set(ctx context.Context, userAgent string) context.Context {
|
||||
|
||||
// Get retrieves the HTTP user agent from the context.
|
||||
func Get(ctx context.Context) string {
|
||||
fetcher := version.NewGoVersionFetcher()
|
||||
if ua, ok := ctx.Value(userAgentKey).(string); ok {
|
||||
return ua
|
||||
}
|
||||
version, err := version.Get()
|
||||
version, err := fetcher.Get()
|
||||
if err != nil || version == nil {
|
||||
return defaultUserAgent
|
||||
}
|
||||
|
||||
20
verify.go
20
verify.go
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/docker/attest/oci"
|
||||
"github.com/docker/attest/policy"
|
||||
"github.com/docker/attest/tuf"
|
||||
"github.com/docker/attest/version"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
)
|
||||
|
||||
@@ -21,6 +22,7 @@ type ImageVerifier struct {
|
||||
opts *policy.Options
|
||||
tufClient tuf.Downloader
|
||||
attestationVerifier attestation.Verifier
|
||||
versionFetcher version.Fetcher
|
||||
}
|
||||
|
||||
func NewImageVerifier(ctx context.Context, opts *policy.Options) (*ImageVerifier, error) {
|
||||
@@ -46,6 +48,7 @@ func NewImageVerifier(ctx context.Context, opts *policy.Options) (*ImageVerifier
|
||||
opts: opts,
|
||||
tufClient: tufClient,
|
||||
attestationVerifier: attestationVerifier,
|
||||
versionFetcher: version.NewGoVersionFetcher(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -93,7 +96,7 @@ func (verifier *ImageVerifier) Verify(ctx context.Context, src *oci.ImageSpec) (
|
||||
return nil, fmt.Errorf("failed to create attestation resolver: %w", err)
|
||||
}
|
||||
evaluator := policy.NewRegoEvaluator(verifier.opts.Debug, verifier.attestationVerifier)
|
||||
result, err = verifyAttestations(ctx, resolver, evaluator, resolvedPolicy, verifier.opts)
|
||||
result, err = verifier.verifyAttestations(ctx, resolver, evaluator, resolvedPolicy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to evaluate policy: %w", err)
|
||||
}
|
||||
@@ -141,7 +144,7 @@ func defaultLocalTargetsDir() (string, error) {
|
||||
return filepath.Join(homeDir, ".docker", "tuf"), nil
|
||||
}
|
||||
|
||||
func toVerificationResult(p *policy.Policy, input *policy.Input, result *policy.Result) (*VerificationResult, error) {
|
||||
func toVerificationResult(p *policy.Policy, input *policy.Input, result *policy.Result, versionFetcher version.Fetcher) (*VerificationResult, error) {
|
||||
dgst, err := oci.SplitDigest(input.Digest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to split digest: %w", err)
|
||||
@@ -168,6 +171,10 @@ func toVerificationResult(p *policy.Policy, input *policy.Input, result *policy.
|
||||
}
|
||||
|
||||
vsaPolicy := attestation.VSAPolicy{URI: result.Summary.PolicyURI, DownloadLocation: p.URI, Digest: p.Digest}
|
||||
attestVersion, err := attestation.GetVerifierVersion(versionFetcher)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get verifier version: %w", err)
|
||||
}
|
||||
|
||||
return &VerificationResult{
|
||||
Policy: p,
|
||||
@@ -182,7 +189,8 @@ func toVerificationResult(p *policy.Policy, input *policy.Input, result *policy.
|
||||
},
|
||||
Predicate: attestation.VSAPredicate{
|
||||
Verifier: attestation.VSAVerifier{
|
||||
ID: result.Summary.Verifier,
|
||||
ID: result.Summary.Verifier,
|
||||
Version: attestVersion,
|
||||
},
|
||||
TimeVerified: time.Now().UTC().Format(time.RFC3339),
|
||||
ResourceURI: resourceURI,
|
||||
@@ -195,7 +203,7 @@ func toVerificationResult(p *policy.Policy, input *policy.Input, result *policy.
|
||||
}, nil
|
||||
}
|
||||
|
||||
func verifyAttestations(ctx context.Context, resolver attestation.Resolver, evaluator policy.Evaluator, resolvedPolicy *policy.Policy, opts *policy.Options) (*VerificationResult, error) {
|
||||
func (verifier *ImageVerifier) verifyAttestations(ctx context.Context, resolver attestation.Resolver, evaluator policy.Evaluator, resolvedPolicy *policy.Policy) (*VerificationResult, error) {
|
||||
desc, err := resolver.ImageDescriptor(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get image descriptor: %w", err)
|
||||
@@ -247,7 +255,7 @@ func verifyAttestations(ctx context.Context, resolver attestation.Resolver, eval
|
||||
Domain: reference.Domain(ref),
|
||||
NormalizedName: reference.Path(ref),
|
||||
FamiliarName: reference.FamiliarName(ref),
|
||||
Parameters: opts.Parameters,
|
||||
Parameters: verifier.opts.Parameters,
|
||||
}
|
||||
// rego has null strings
|
||||
if tag != "" {
|
||||
@@ -257,7 +265,7 @@ func verifyAttestations(ctx context.Context, resolver attestation.Resolver, eval
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("policy evaluation failed: %w", err)
|
||||
}
|
||||
verificationResult, err := toVerificationResult(resolvedPolicy, input, result)
|
||||
verificationResult, err := toVerificationResult(resolvedPolicy, input, result, verifier.versionFetcher)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert to policy result: %w", err)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/attest/attestation"
|
||||
"github.com/docker/attest/internal/test"
|
||||
@@ -17,6 +18,7 @@ import (
|
||||
"github.com/docker/attest/policy"
|
||||
"github.com/docker/attest/tlog"
|
||||
"github.com/docker/attest/tuf"
|
||||
"github.com/docker/attest/version"
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
"github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -32,9 +34,16 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
LinuxAMD64 = "linux/amd64"
|
||||
LinuxAMD64 = "linux/amd64"
|
||||
TestVerifierVersion = "9.9.9"
|
||||
)
|
||||
|
||||
type MockVersionFetcher struct{}
|
||||
|
||||
func (m *MockVersionFetcher) Get() (*semver.Version, error) {
|
||||
return semver.NewVersion(TestVerifierVersion)
|
||||
}
|
||||
|
||||
func TestVerifyAttestations(t *testing.T) {
|
||||
ex, err := os.ReadFile(ExampleAttestation)
|
||||
assert.NoError(t, err)
|
||||
@@ -62,7 +71,9 @@ func TestVerifyAttestations(t *testing.T) {
|
||||
return policy.AllowedResult(), tc.policyEvaluationError
|
||||
},
|
||||
}
|
||||
_, err := verifyAttestations(ctx, resolver, &mockPE, &policy.Policy{ResolvedName: ""}, &policy.Options{})
|
||||
verifier, err := NewImageVerifier(ctx, &policy.Options{})
|
||||
require.NoError(t, err)
|
||||
_, err = verifier.verifyAttestations(ctx, resolver, &mockPE, &policy.Policy{ResolvedName: ""})
|
||||
if tc.expectedError != nil {
|
||||
if assert.Error(t, err) {
|
||||
assert.Equal(t, tc.expectedError.Error(), err.Error())
|
||||
@@ -102,7 +113,10 @@ func TestVSA(t *testing.T) {
|
||||
AttestationStyle: mapping.AttestationStyleAttached,
|
||||
DisableTUF: true,
|
||||
}
|
||||
results, err := Verify(ctx, spec, policyOpts)
|
||||
verifier, err := NewImageVerifier(ctx, policyOpts)
|
||||
require.NoError(t, err)
|
||||
verifier.versionFetcher = &MockVersionFetcher{}
|
||||
results, err := verifier.Verify(ctx, spec)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, OutcomeSuccess, results.Outcome)
|
||||
assert.Empty(t, results.Violations)
|
||||
@@ -135,6 +149,7 @@ func TestVSA(t *testing.T) {
|
||||
assert.NotEmpty(t, digest)
|
||||
assert.Contains(t, []string{"application/vnd.in-toto.provenance+dsse", "application/vnd.in-toto.spdx+dsse"}, input.MediaType)
|
||||
}
|
||||
assert.Equal(t, TestVerifierVersion, attestationPredicate.Verifier.Version[version.ThisModulePath])
|
||||
}
|
||||
|
||||
func TestVerificationFailure(t *testing.T) {
|
||||
|
||||
@@ -9,9 +9,19 @@ import (
|
||||
|
||||
const ThisModulePath = "github.com/docker/attest"
|
||||
|
||||
type Fetcher interface {
|
||||
Get() (*semver.Version, error)
|
||||
}
|
||||
|
||||
type GoModVersionFetcher struct{}
|
||||
|
||||
func NewGoVersionFetcher() *GoModVersionFetcher {
|
||||
return &GoModVersionFetcher{}
|
||||
}
|
||||
|
||||
// Get returns the version of the attest module.
|
||||
// this can return nil if the version can't be determined (without an error).
|
||||
func Get() (*semver.Version, error) {
|
||||
func (*GoModVersionFetcher) Get() (*semver.Version, error) {
|
||||
var attestMod *debug.Module
|
||||
bi, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
|
||||
Reference in New Issue
Block a user