feat!: remove MockTUFClient (#135)
* feat! remove MockTUFClient *Breaking* - use LocalPolicyDir and nil TUFClient instead Other: - add stateful Verifier
This commit is contained in:
@@ -31,6 +31,7 @@ func ExampleVerify_remote() {
|
||||
LocalTargetsDir: filepath.Join(home, ".docker", "policy"), // location to store policy files downloaded from TUF
|
||||
LocalPolicyDir: "", // overrides TUF policy for local policy files if set
|
||||
PolicyID: "", // set to ignore policy mapping and select a policy by id
|
||||
DisableTUF: false, // set to disable TUF and rely on local policy files
|
||||
}
|
||||
|
||||
src, err := oci.ParseImageSpec(image, oci.WithPlatform(platform))
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/docker/attest/pkg/attestation"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/policy"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
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"
|
||||
@@ -28,7 +27,6 @@ var (
|
||||
|
||||
func TestSignVerifyOCILayout(t *testing.T) {
|
||||
ctx, signer := test.Setup(t)
|
||||
ctx = tuf.WithDownloader(ctx, tuf.NewMockTufClient(EmptyPolicyDir, test.CreateTempDir(t, "", "tuf-dest")))
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -45,6 +43,7 @@ func TestSignVerifyOCILayout(t *testing.T) {
|
||||
}
|
||||
policyOpts := &policy.Options{
|
||||
LocalPolicyDir: PassPolicyDir,
|
||||
DisableTUF: true,
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
@@ -17,26 +17,41 @@ import (
|
||||
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
||||
)
|
||||
|
||||
func Verify(ctx context.Context, src *oci.ImageSpec, opts *policy.Options) (result *VerificationResult, err error) {
|
||||
// so that we can resolve mapping from the image name earlier
|
||||
detailsResolver, err := policy.CreateImageDetailsResolver(src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create image details resolver: %w", err)
|
||||
}
|
||||
err = populateDefaultOptions(opts)
|
||||
type Verifier interface {
|
||||
Verify(ctx context.Context, src *oci.ImageSpec) (result *VerificationResult, err error)
|
||||
}
|
||||
|
||||
type tufVerifier struct {
|
||||
opts *policy.Options
|
||||
tufClient tuf.Downloader
|
||||
}
|
||||
|
||||
func NewVerifier(opts *policy.Options) (Verifier, error) {
|
||||
err := populateDefaultOptions(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tufClient, ok := tuf.GetDownloader(ctx)
|
||||
if !ok {
|
||||
var tufClient tuf.Downloader
|
||||
if !opts.DisableTUF {
|
||||
tufClient, err = tuf.NewClient(opts.TUFClientOptions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create TUF client: %w", err)
|
||||
}
|
||||
}
|
||||
return &tufVerifier{
|
||||
opts: opts,
|
||||
tufClient: tufClient,
|
||||
}, nil
|
||||
}
|
||||
|
||||
pctx, err := policy.ResolvePolicy(ctx, tufClient, detailsResolver, opts)
|
||||
func (v *tufVerifier) Verify(ctx context.Context, src *oci.ImageSpec) (result *VerificationResult, err error) {
|
||||
// so that we can resolve mapping from the image name earlier
|
||||
detailsResolver, err := policy.CreateImageDetailsResolver(src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create image details resolver: %w", err)
|
||||
}
|
||||
|
||||
pctx, err := policy.ResolvePolicy(ctx, v.tufClient, detailsResolver, v.opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve policy: %w", err)
|
||||
}
|
||||
@@ -47,14 +62,14 @@ func Verify(ctx context.Context, src *oci.ImageSpec, opts *policy.Options) (resu
|
||||
}, nil
|
||||
}
|
||||
// this is overriding the mapping with a referrers config. Useful for testing if nothing else
|
||||
if opts.ReferrersRepo != "" {
|
||||
if v.opts.ReferrersRepo != "" {
|
||||
pctx.Mapping.Attestations = &config.AttestationConfig{
|
||||
Repo: opts.ReferrersRepo,
|
||||
Repo: v.opts.ReferrersRepo,
|
||||
Style: config.AttestationStyleReferrers,
|
||||
}
|
||||
} else if opts.AttestationStyle == config.AttestationStyleAttached {
|
||||
} else if v.opts.AttestationStyle == config.AttestationStyleAttached {
|
||||
pctx.Mapping.Attestations = &config.AttestationConfig{
|
||||
Repo: opts.ReferrersRepo,
|
||||
Repo: v.opts.ReferrersRepo,
|
||||
Style: config.AttestationStyleAttached,
|
||||
}
|
||||
}
|
||||
@@ -70,15 +85,27 @@ func Verify(ctx context.Context, src *oci.ImageSpec, opts *policy.Options) (resu
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func Verify(ctx context.Context, src *oci.ImageSpec, opts *policy.Options) (result *VerificationResult, err error) {
|
||||
verifier, err := NewVerifier(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return verifier.Verify(ctx, src)
|
||||
}
|
||||
|
||||
func populateDefaultOptions(opts *policy.Options) (err error) {
|
||||
if opts.LocalPolicyDir == "" && opts.DisableTUF {
|
||||
return fmt.Errorf("local policy dir must be set if not using TUF")
|
||||
}
|
||||
if opts.LocalTargetsDir == "" {
|
||||
opts.LocalTargetsDir, err = defaultLocalTargetsDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if opts.TUFClientOptions == nil {
|
||||
if opts.DisableTUF && opts.TUFClientOptions != nil {
|
||||
return fmt.Errorf("TUF client options set but TUF disabled")
|
||||
} else if opts.TUFClientOptions == nil && !opts.DisableTUF {
|
||||
opts.TUFClientOptions = tuf.NewDockerDefaultClientOptions(opts.LocalTargetsDir)
|
||||
}
|
||||
|
||||
@@ -88,7 +115,6 @@ func populateDefaultOptions(opts *policy.Options) (err error) {
|
||||
if opts.ReferrersRepo != "" && opts.AttestationStyle != config.AttestationStyleReferrers {
|
||||
return fmt.Errorf("referrers repo specified but attestation source not set to referrers")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,6 @@ func TestVerifyAttestations(t *testing.T) {
|
||||
func TestVSA(t *testing.T) {
|
||||
ctx, signer := test.Setup(t)
|
||||
ctx = policy.WithPolicyEvaluator(ctx, policy.NewRegoEvaluator(true))
|
||||
ctx = tuf.WithDownloader(ctx, tuf.NewMockTufClient(EmptyPolicyDir, test.CreateTempDir(t, "", "tuf-dest")))
|
||||
// setup an image with signed attestations
|
||||
outputLayout := test.CreateTempDir(t, "", TestTempDir)
|
||||
|
||||
@@ -93,6 +92,7 @@ func TestVSA(t *testing.T) {
|
||||
policyOpts := &policy.Options{
|
||||
LocalPolicyDir: PassPolicyDir,
|
||||
AttestationStyle: config.AttestationStyleAttached,
|
||||
DisableTUF: true,
|
||||
}
|
||||
results, err := Verify(ctx, spec, policyOpts)
|
||||
require.NoError(t, err)
|
||||
@@ -123,7 +123,6 @@ func TestVSA(t *testing.T) {
|
||||
func TestVerificationFailure(t *testing.T) {
|
||||
ctx, signer := test.Setup(t)
|
||||
ctx = policy.WithPolicyEvaluator(ctx, policy.NewRegoEvaluator(true))
|
||||
ctx = tuf.WithDownloader(ctx, tuf.NewMockTufClient(EmptyPolicyDir, test.CreateTempDir(t, "", "tuf-dest")))
|
||||
// setup an image with signed attestations
|
||||
outputLayout := test.CreateTempDir(t, "", TestTempDir)
|
||||
|
||||
@@ -146,6 +145,7 @@ func TestVerificationFailure(t *testing.T) {
|
||||
policyOpts := &policy.Options{
|
||||
LocalPolicyDir: FailPolicyDir,
|
||||
AttestationStyle: config.AttestationStyleAttached,
|
||||
DisableTUF: true,
|
||||
}
|
||||
results, err := Verify(ctx, spec, policyOpts)
|
||||
require.NoError(t, err)
|
||||
@@ -176,16 +176,14 @@ func TestVerificationFailure(t *testing.T) {
|
||||
func TestSignVerify(t *testing.T) {
|
||||
ctx, signer := test.Setup(t)
|
||||
ctx = policy.WithPolicyEvaluator(ctx, policy.NewRegoEvaluator(true))
|
||||
ctx = tuf.WithDownloader(ctx, tuf.NewMockTufClient(EmptyPolicyDir, test.CreateTempDir(t, "", "tuf-dest")))
|
||||
// setup an image with signed attestations
|
||||
outputLayout := test.CreateTempDir(t, "", TestTempDir)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
signTL bool
|
||||
policyDir string
|
||||
imageName string
|
||||
|
||||
name string
|
||||
signTL bool
|
||||
policyDir string
|
||||
imageName string
|
||||
expectedNonSuccess Outcome
|
||||
}{
|
||||
{name: "happy path", signTL: true, policyDir: PassNoTLPolicyDir},
|
||||
@@ -223,6 +221,7 @@ func TestSignVerify(t *testing.T) {
|
||||
|
||||
policyOpts := &policy.Options{
|
||||
LocalPolicyDir: tc.policyDir,
|
||||
DisableTUF: true,
|
||||
}
|
||||
results, err := Verify(ctx, spec, policyOpts)
|
||||
require.NoError(t, err)
|
||||
@@ -251,6 +250,8 @@ func TestDefaultOptions(t *testing.T) {
|
||||
attestationStyle config.AttestationStyle
|
||||
referrersRepo string
|
||||
expectedError string
|
||||
disableTuf bool
|
||||
localPolicyDir string
|
||||
}{
|
||||
{name: "empty"},
|
||||
{name: "tufClient provided", tufOpts: &tuf.ClientOptions{MetadataSource: "a", TargetsSource: "b"}},
|
||||
@@ -258,6 +259,8 @@ func TestDefaultOptions(t *testing.T) {
|
||||
{name: "attestationStyle provided", attestationStyle: config.AttestationStyleAttached},
|
||||
{name: "referrersRepo provided", referrersRepo: "referrers"},
|
||||
{name: "referrersRepo provided with attached", referrersRepo: "referrers", attestationStyle: config.AttestationStyleAttached, expectedError: "referrers repo specified but attestation source not set to referrers"},
|
||||
{name: "tuf disabled and no local-policy-dir", disableTuf: true, expectedError: "local policy dir must be set if not using TUF"},
|
||||
{name: "tuf disabled but options set", disableTuf: true, tufOpts: &tuf.ClientOptions{MetadataSource: "a", TargetsSource: "b"}, localPolicyDir: "foo", expectedError: "TUF client options set but TUF disabled"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@@ -269,6 +272,8 @@ func TestDefaultOptions(t *testing.T) {
|
||||
LocalTargetsDir: tc.localTargetsDir,
|
||||
AttestationStyle: tc.attestationStyle,
|
||||
ReferrersRepo: tc.referrersRepo,
|
||||
DisableTUF: tc.disableTuf,
|
||||
LocalPolicyDir: tc.localPolicyDir,
|
||||
}
|
||||
|
||||
err = populateDefaultOptions(opts)
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/docker/attest/pkg/config"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/policy"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/google/go-containerregistry/pkg/registry"
|
||||
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||
@@ -28,14 +27,12 @@ var (
|
||||
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")
|
||||
EmptyTUFDir = filepath.Join("..", "..", "test", "testdata", "local-policy-no-policies")
|
||||
TestTempDir = "attest-sign-test"
|
||||
)
|
||||
|
||||
func TestAttestationReferenceTypes(t *testing.T) {
|
||||
ctx, signer := test.Setup(t)
|
||||
ctx = policy.WithPolicyEvaluator(ctx, policy.NewRegoEvaluator(true))
|
||||
ctx = tuf.WithDownloader(ctx, tuf.NewMockTufClient(EmptyTUFDir, test.CreateTempDir(t, "", "tuf-dest")))
|
||||
platforms := []string{"linux/amd64", "linux/arm64"}
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
@@ -142,6 +139,7 @@ func TestAttestationReferenceTypes(t *testing.T) {
|
||||
|
||||
policyOpts := &policy.Options{
|
||||
LocalPolicyDir: LocalPolicy,
|
||||
DisableTUF: true,
|
||||
}
|
||||
|
||||
if tc.referrersRepo != "" {
|
||||
@@ -185,7 +183,6 @@ func TestAttestationReferenceTypes(t *testing.T) {
|
||||
|
||||
func TestReferencesInDifferentRepo(t *testing.T) {
|
||||
ctx, signer := test.Setup(t)
|
||||
ctx = tuf.WithDownloader(ctx, tuf.NewMockTufClient(EmptyTUFDir, test.CreateTempDir(t, "", "tuf-dest")))
|
||||
repoName := "repo"
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
@@ -273,6 +270,7 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
||||
referencedImage := fmt.Sprintf("%s@%s", indexName, mf.Digest.String())
|
||||
policyOpts := &policy.Options{
|
||||
LocalPolicyDir: PassPolicyDir,
|
||||
DisableTUF: true,
|
||||
}
|
||||
src, err := oci.ParseImageSpec(referencedImage)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -167,15 +167,16 @@ func resolvePolicyByID(opts *Options, tufClient tuf.Downloader) (*Policy, error)
|
||||
return resolveLocalPolicy(opts, policy, "", "")
|
||||
}
|
||||
}
|
||||
|
||||
// must check tuf
|
||||
tufMappings, err := config.LoadTUFMappings(tufClient, opts.LocalTargetsDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load tuf policy mappings by id: %w", err)
|
||||
}
|
||||
policy := tufMappings.Policies[opts.PolicyID]
|
||||
if policy != nil {
|
||||
return resolveTUFPolicy(opts, tufClient, policy, "", "")
|
||||
if !opts.DisableTUF {
|
||||
// must check tuf
|
||||
tufMappings, err := config.LoadTUFMappings(tufClient, opts.LocalTargetsDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load tuf policy mappings by id: %w", err)
|
||||
}
|
||||
policy := tufMappings.Policies[opts.PolicyID]
|
||||
if policy != nil {
|
||||
return resolveTUFPolicy(opts, tufClient, policy, "", "")
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("policy with id %s not found", opts.PolicyID)
|
||||
}
|
||||
@@ -209,29 +210,31 @@ func ResolvePolicy(ctx context.Context, tufClient tuf.Downloader, detailsResolve
|
||||
if match.matchType == matchTypePolicy {
|
||||
return resolveLocalPolicy(opts, match.policy, imageName, match.matchedName)
|
||||
}
|
||||
// must check tuf
|
||||
tufMappings, err := config.LoadTUFMappings(tufClient, opts.LocalTargetsDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load tuf policy mappings as fallback: %w", err)
|
||||
}
|
||||
if !opts.DisableTUF {
|
||||
// must check tuf
|
||||
tufMappings, err := config.LoadTUFMappings(tufClient, opts.LocalTargetsDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load tuf policy mappings as fallback: %w", err)
|
||||
}
|
||||
|
||||
// it's a mirror of a tuf policy
|
||||
if match.matchType == matchTypeMatchNoPolicy {
|
||||
for _, mapping := range tufMappings.Policies {
|
||||
if mapping.ID == match.rule.PolicyID {
|
||||
return resolveTUFPolicy(opts, tufClient, mapping, imageName, match.matchedName)
|
||||
// it's a mirror of a tuf policy
|
||||
if match.matchType == matchTypeMatchNoPolicy {
|
||||
for _, mapping := range tufMappings.Policies {
|
||||
if mapping.ID == match.rule.PolicyID {
|
||||
return resolveTUFPolicy(opts, tufClient, mapping, imageName, match.matchedName)
|
||||
}
|
||||
}
|
||||
}
|
||||
// try to resolve a tuf policy directly
|
||||
match, err = findPolicyMatch(imageName, tufMappings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if match.matchType == matchTypePolicy {
|
||||
return resolveTUFPolicy(opts, tufClient, match.policy, imageName, match.matchedName)
|
||||
}
|
||||
}
|
||||
|
||||
// try to resolve a tuf policy directly
|
||||
match, err = findPolicyMatch(imageName, tufMappings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if match.matchType == matchTypePolicy {
|
||||
return resolveTUFPolicy(opts, tufClient, match.policy, imageName, match.matchedName)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/docker/attest/pkg/config"
|
||||
"github.com/docker/attest/pkg/oci"
|
||||
"github.com/docker/attest/pkg/policy"
|
||||
"github.com/docker/attest/pkg/tuf"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -51,15 +50,15 @@ func TestRegoEvaluator_Evaluate(t *testing.T) {
|
||||
policyID string
|
||||
resolveErrorStr string
|
||||
}{
|
||||
{repo: "testdata/mock-tuf-allow", expectSuccess: true, resolver: defaultResolver},
|
||||
{repo: "testdata/mock-tuf-allow", expectSuccess: true, resolver: defaultResolver, policyID: "docker-official-images"},
|
||||
{repo: "testdata/mock-tuf-allow", resolver: defaultResolver, policyID: "non-existent-policy-id", resolveErrorStr: resolveErrorStr},
|
||||
{repo: "testdata/mock-tuf-deny", resolver: defaultResolver},
|
||||
{repo: "testdata/mock-tuf-verify-sig", expectSuccess: true, resolver: defaultResolver},
|
||||
{repo: "testdata/mock-tuf-wrong-key", resolver: defaultResolver},
|
||||
{repo: "testdata/mock-tuf-allow-canonical", expectSuccess: true, isCanonical: true, resolver: defaultResolver},
|
||||
{repo: "testdata/mock-tuf-allow-canonical", resolver: defaultResolver},
|
||||
{repo: "testdata/mock-tuf-no-rego", resolver: defaultResolver, resolveErrorStr: "no policy file found in policy mapping"},
|
||||
{repo: "testdata/policies/allow", expectSuccess: true, resolver: defaultResolver},
|
||||
{repo: "testdata/policies/allow", expectSuccess: true, resolver: defaultResolver, policyID: "docker-official-images"},
|
||||
{repo: "testdata/policies/allow", resolver: defaultResolver, policyID: "non-existent-policy-id", resolveErrorStr: resolveErrorStr},
|
||||
{repo: "testdata/policies/deny", resolver: defaultResolver},
|
||||
{repo: "testdata/policies/verify-sig", expectSuccess: true, resolver: defaultResolver},
|
||||
{repo: "testdata/policies/wrong-key", resolver: defaultResolver},
|
||||
{repo: "testdata/policies/allow-canonical", expectSuccess: true, isCanonical: true, resolver: defaultResolver},
|
||||
{repo: "testdata/policies/allow-canonical", resolver: defaultResolver},
|
||||
{repo: "testdata/policies/no-rego", resolver: defaultResolver, resolveErrorStr: "no policy file found in policy mapping"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
@@ -72,11 +71,12 @@ func TestRegoEvaluator_Evaluate(t *testing.T) {
|
||||
input.Tag = "test"
|
||||
}
|
||||
|
||||
tufClient := tuf.NewMockTufClient(tc.repo, test.CreateTempDir(t, "", "tuf-dest"))
|
||||
if tc.policy == nil {
|
||||
tc.policy = &policy.Options{
|
||||
LocalTargetsDir: test.CreateTempDir(t, "", "tuf-targets"),
|
||||
PolicyID: tc.policyID,
|
||||
LocalPolicyDir: tc.repo,
|
||||
DisableTUF: true,
|
||||
}
|
||||
}
|
||||
imageName, err := tc.resolver.ImageName(ctx)
|
||||
@@ -87,7 +87,7 @@ func TestRegoEvaluator_Evaluate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
resolver, err := policy.CreateImageDetailsResolver(src)
|
||||
require.NoError(t, err)
|
||||
policy, err := policy.ResolvePolicy(ctx, tufClient, resolver, tc.policy)
|
||||
policy, err := policy.ResolvePolicy(ctx, nil, resolver, tc.policy)
|
||||
if tc.resolveErrorStr != "" {
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tc.resolveErrorStr)
|
||||
@@ -108,7 +108,7 @@ func TestRegoEvaluator_Evaluate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadingMappings(t *testing.T) {
|
||||
policyMappings, err := config.LoadLocalMappings(filepath.Join("testdata", "mock-tuf-allow"))
|
||||
policyMappings, err := config.LoadLocalMappings(filepath.Join("testdata", "policies", "allow"))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, len(policyMappings.Rules), 3)
|
||||
for _, mirror := range policyMappings.Rules {
|
||||
|
||||
@@ -28,6 +28,7 @@ type Result struct {
|
||||
|
||||
type Options struct {
|
||||
TUFClientOptions *tuf.ClientOptions
|
||||
DisableTUF bool
|
||||
LocalTargetsDir string
|
||||
LocalPolicyDir string
|
||||
PolicyID string
|
||||
|
||||
@@ -1,67 +1,5 @@
|
||||
package tuf
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/attest/internal/util"
|
||||
)
|
||||
|
||||
type MockTufClient struct {
|
||||
srcPath string
|
||||
dstPath string
|
||||
}
|
||||
|
||||
func NewMockTufClient(srcPath string, dstPath string) *MockTufClient {
|
||||
if srcPath == "" {
|
||||
panic("srcPath must be set")
|
||||
}
|
||||
if dstPath == "" {
|
||||
panic("dstPath must be set")
|
||||
}
|
||||
return &MockTufClient{
|
||||
srcPath: srcPath,
|
||||
dstPath: dstPath,
|
||||
}
|
||||
}
|
||||
|
||||
func (dc *MockTufClient) DownloadTarget(target string, filePath string) (file *TargetFile, err error) {
|
||||
targetPath := filepath.Join(dc.srcPath, target)
|
||||
src, err := os.Open(targetPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
var dstFilePath string
|
||||
if filePath == "" {
|
||||
dstFilePath = filepath.Join(dc.dstPath, filepath.FromSlash(target))
|
||||
} else {
|
||||
dstFilePath = filePath
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(dstFilePath), os.ModePerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dst, err := os.Create(dstFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
// reading from tee will read from src and write to dst at the same time
|
||||
tee := io.TeeReader(src, dst)
|
||||
|
||||
b, err := io.ReadAll(tee)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &TargetFile{ActualFilePath: dstFilePath, TargetURI: targetPath, Data: b, Digest: util.SHA256Hex(b)}, nil
|
||||
}
|
||||
|
||||
type MockVersionChecker struct {
|
||||
err error
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package tuf
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
@@ -21,24 +20,6 @@ import (
|
||||
"github.com/theupdateframework/go-tuf/v2/metadata/updater"
|
||||
)
|
||||
|
||||
type tufCtxKeyType struct{}
|
||||
|
||||
var DownloaderCtxKey tufCtxKeyType
|
||||
|
||||
// WithDownloader sets Downloader in context.
|
||||
func WithDownloader(ctx context.Context, downloader Downloader) context.Context {
|
||||
return context.WithValue(ctx, DownloaderCtxKey, downloader)
|
||||
}
|
||||
|
||||
// GetDownloader returns the Downloader from context and `true` if it exists, otherwise `nil` and `false`.
|
||||
func GetDownloader(ctx context.Context) (Downloader, bool) {
|
||||
t, ok := ctx.Value(DownloaderCtxKey).(Downloader)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
return t, true
|
||||
}
|
||||
|
||||
type Source string
|
||||
|
||||
const (
|
||||
|
||||
Reference in New Issue
Block a user