From 7d71be9e1dee829cb8171250689b9d75b5173e27 Mon Sep 17 00:00:00 2001 From: Peter Wagner Date: Thu, 10 Nov 2022 10:49:09 -0500 Subject: [PATCH 1/4] split GCR lookup from docker package --- v2/{docker/uri => container/gcr}/project.go | 2 +- v2/{docker/uri => container/gcr}/project_test.go | 5 +++-- v2/containeranalysis/client.go | 6 +++--- v2/containeranalysis/poll.go | 6 ++---- v2/grafeas/client.go | 6 +++--- v2/grafeas/poll.go | 4 ++-- 6 files changed, 14 insertions(+), 15 deletions(-) rename v2/{docker/uri => container/gcr}/project.go (98%) rename v2/{docker/uri => container/gcr}/project_test.go (87%) diff --git a/v2/docker/uri/project.go b/v2/container/gcr/project.go similarity index 98% rename from v2/docker/uri/project.go rename to v2/container/gcr/project.go index ec397372..b83f4183 100644 --- a/v2/docker/uri/project.go +++ b/v2/container/gcr/project.go @@ -1,4 +1,4 @@ -package uri +package gcr import ( "fmt" diff --git a/v2/docker/uri/project_test.go b/v2/container/gcr/project_test.go similarity index 87% rename from v2/docker/uri/project_test.go rename to v2/container/gcr/project_test.go index a845ad9a..d2ffd788 100644 --- a/v2/docker/uri/project_test.go +++ b/v2/container/gcr/project_test.go @@ -1,9 +1,10 @@ -package uri +package gcr_test import ( "testing" "github.com/docker/distribution/reference" + "github.com/grafeas/voucher/v2/container/gcr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -21,7 +22,7 @@ func TestReferenceToProjectName(t *testing.T) { ref, err := reference.Parse(img) require.NoError(t, err) - project, err := ReferenceToProjectName(ref) + project, err := gcr.ReferenceToProjectName(ref) if expectedProject != "" { assert.NoError(t, err) assert.Equal(t, expectedProject, project) diff --git a/v2/containeranalysis/client.go b/v2/containeranalysis/client.go index 14676d2e..a5fcad97 100644 --- a/v2/containeranalysis/client.go +++ b/v2/containeranalysis/client.go @@ -14,7 +14,7 @@ import ( voucher "github.com/grafeas/voucher/v2" "github.com/grafeas/voucher/v2/attestation" - "github.com/grafeas/voucher/v2/docker/uri" + "github.com/grafeas/voucher/v2/container/gcr" "github.com/grafeas/voucher/v2/repository" "github.com/grafeas/voucher/v2/signer" ) @@ -121,7 +121,7 @@ func (g *Client) GetVulnerabilities(ctx context.Context, ref reference.Canonical return []voucher.Vulnerability{}, err } - project, err := uri.ReferenceToProjectName(ref) + project, err := gcr.ReferenceToProjectName(ref) if nil != err { return []voucher.Vulnerability{}, err } @@ -160,7 +160,7 @@ func (g *Client) Close() { func (g *Client) GetBuildDetail(ctx context.Context, ref reference.Canonical) (repository.BuildDetail, error) { var err error - project, err := uri.ReferenceToProjectName(ref) + project, err := gcr.ReferenceToProjectName(ref) if err != nil { return repository.BuildDetail{}, err } diff --git a/v2/containeranalysis/poll.go b/v2/containeranalysis/poll.go index ccd637a8..fd4c0327 100644 --- a/v2/containeranalysis/poll.go +++ b/v2/containeranalysis/poll.go @@ -12,7 +12,7 @@ import ( grafeas "google.golang.org/genproto/googleapis/grafeas/v1" voucher "github.com/grafeas/voucher/v2" - "github.com/grafeas/voucher/v2/docker/uri" + "github.com/grafeas/voucher/v2/container/gcr" ) const ( @@ -34,9 +34,7 @@ func vulnerabilityFilter(ref reference.Reference) string { func getVulnerabilityDiscoveries(ctx context.Context, client *grafeasv1.Client, ref reference.Reference) ([]*grafeas.DiscoveryOccurrence, error) { occurrences := make([]*grafeas.DiscoveryOccurrence, 0, 50) - var err error - - project, err := uri.ReferenceToProjectName(ref) + project, err := gcr.ReferenceToProjectName(ref) if nil != err { return nil, err } diff --git a/v2/grafeas/client.go b/v2/grafeas/client.go index 32aac1a4..561e7dc3 100644 --- a/v2/grafeas/client.go +++ b/v2/grafeas/client.go @@ -8,7 +8,7 @@ import ( "github.com/docker/distribution/reference" voucher "github.com/grafeas/voucher/v2" "github.com/grafeas/voucher/v2/attestation" - "github.com/grafeas/voucher/v2/docker/uri" + "github.com/grafeas/voucher/v2/container/gcr" "github.com/grafeas/voucher/v2/grafeas/objects" "github.com/grafeas/voucher/v2/repository" "github.com/grafeas/voucher/v2/signer" @@ -100,7 +100,7 @@ func (g *Client) GetVulnerabilities(ctx context.Context, ref reference.Canonical return []voucher.Vulnerability{}, err } - project, err := uri.ReferenceToProjectName(ref) + project, err := gcr.ReferenceToProjectName(ref) if nil != err { return []voucher.Vulnerability{}, err } @@ -132,7 +132,7 @@ func (g *Client) Close() {} // GetBuildDetail gets BuildDetails for the passed image. func (g *Client) GetBuildDetail(ctx context.Context, ref reference.Canonical) (repository.BuildDetail, error) { - project, err := uri.ReferenceToProjectName(ref) + project, err := gcr.ReferenceToProjectName(ref) if nil != err { return repository.BuildDetail{}, err } diff --git a/v2/grafeas/poll.go b/v2/grafeas/poll.go index ae87d705..89d31404 100644 --- a/v2/grafeas/poll.go +++ b/v2/grafeas/poll.go @@ -6,7 +6,7 @@ import ( "github.com/docker/distribution/reference" voucher "github.com/grafeas/voucher/v2" - "github.com/grafeas/voucher/v2/docker/uri" + "github.com/grafeas/voucher/v2/container/gcr" "github.com/grafeas/voucher/v2/grafeas/objects" ) @@ -61,7 +61,7 @@ func pollForDiscoveries(ctx context.Context, c *Client, ref reference.Reference) } func getVulnerabilityDiscoveries(ctx context.Context, g *Client, ref reference.Reference) (items []objects.Occurrence, err error) { - project, err := uri.ReferenceToProjectName(ref) + project, err := gcr.ReferenceToProjectName(ref) if nil != err { return nil, err } From 0a20ddd3090ae14665b5479f8752822200cf67dc Mon Sep 17 00:00:00 2001 From: Peter Wagner Date: Thu, 10 Nov 2022 11:55:26 -0500 Subject: [PATCH 2/4] docker/token: rm GetTokenURI (unused) --- v2/docker/uri/uri.go | 15 --------------- v2/docker/uri/uri_test.go | 3 --- 2 files changed, 18 deletions(-) diff --git a/v2/docker/uri/uri.go b/v2/docker/uri/uri.go index 69a05456..caba788c 100644 --- a/v2/docker/uri/uri.go +++ b/v2/docker/uri/uri.go @@ -8,21 +8,6 @@ import ( digest "github.com/opencontainers/go-digest" ) -// GetTokenURI gets the token URI for the passed repository. -func GetTokenURI(ref reference.Named) string { - hostname := reference.Domain(ref) - repository := reference.Path(ref) - - query := url.Values{} - query.Set("service", hostname) - query.Set("scope", "repository:"+repository+":*") - - u := createURL(ref, "token") - u.RawQuery = query.Encode() - - return u.String() -} - // GetBlobURI gets a blob URI based on the passed repository and // digest. func GetBlobURI(ref reference.Named, digest digest.Digest) string { diff --git a/v2/docker/uri/uri_test.go b/v2/docker/uri/uri_test.go index b110f997..b8731b88 100644 --- a/v2/docker/uri/uri_test.go +++ b/v2/docker/uri/uri_test.go @@ -14,15 +14,12 @@ const ( testDigest = "sha256:cb749360c5198a55859a7f335de3cf4e2f64b60886a2098684a2f9c7ffca81f2" testBlobURL = "https://" + testHostname + "/v2/" + testProject + "/blobs/" + testDigest testManifestURL = "https://" + testHostname + "/v2/" + testProject + "/manifests/" + testDigest - testTokenURL = "https://" + testHostname + "/v2/token?scope=repository%3Atest%2Fproject%3A%2A&service=gcr.io" ) func TestGetBaseURI(t *testing.T) { named, err := reference.ParseNamed(testHostname + "/" + testProject + "@" + testDigest) require.NoError(t, err, "failed to parse uri: %s", err) - assert.Equal(t, testTokenURL, GetTokenURI(named)) - canonicalRef, ok := named.(reference.Canonical) require.True(t, ok) From bd4ffce51caea5796d2f9b8c80a1e0477efb23f0 Mon Sep 17 00:00:00 2001 From: Peter Wagner Date: Thu, 10 Nov 2022 12:16:33 -0500 Subject: [PATCH 3/4] voucher_client: DRY check+verify --- v2/cmd/voucher_client/config.go | 5 --- v2/cmd/voucher_client/output.go | 40 ------------------ v2/cmd/voucher_client/root.go | 74 ++++++++++++++++++++++++++++++--- v2/cmd/voucher_client/submit.go | 59 -------------------------- v2/cmd/voucher_client/verify.go | 55 ------------------------ 5 files changed, 69 insertions(+), 164 deletions(-) delete mode 100644 v2/cmd/voucher_client/output.go delete mode 100644 v2/cmd/voucher_client/submit.go delete mode 100644 v2/cmd/voucher_client/verify.go diff --git a/v2/cmd/voucher_client/config.go b/v2/cmd/voucher_client/config.go index 4a322814..ac76dc0e 100644 --- a/v2/cmd/voucher_client/config.go +++ b/v2/cmd/voucher_client/config.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "strings" - "time" voucher "github.com/grafeas/voucher/v2" "github.com/grafeas/voucher/v2/client" @@ -41,7 +40,3 @@ func getVoucherClient(ctx context.Context) (voucher.Interface, error) { } return client.NewClientContext(ctx, defaultConfig.Server, options...) } - -func newContext() (context.Context, context.CancelFunc) { - return context.WithTimeout(context.Background(), time.Duration(defaultConfig.Timeout)*time.Second) -} diff --git a/v2/cmd/voucher_client/output.go b/v2/cmd/voucher_client/output.go deleted file mode 100644 index 224d8586..00000000 --- a/v2/cmd/voucher_client/output.go +++ /dev/null @@ -1,40 +0,0 @@ -package main - -import ( - "fmt" - "os" - - voucher "github.com/grafeas/voucher/v2" -) - -// errorf prints a formatted string to standard error. -func errorf(format string, v interface{}) { - _, _ = fmt.Fprintf(os.Stderr, format+"\n", v) -} - -// formatResponse returns the response as a string. -func formatResponse(resp *voucher.Response) string { - output := "" - if resp.Success { - fmt.Println("image is approved") - } else { - fmt.Println("image was rejected") - } - for _, result := range resp.Results { - if result.Success { - output += fmt.Sprintf(" ✓ passed %s", result.Name) - if !result.Attested { - output += ", but wasn't attested" - } - } else { - output += fmt.Sprintf(" ✗ failed %s", result.Name) - } - - if "" != result.Err { - output += fmt.Sprintf(", err: %s", result.Err) - } - output += "\n" - } - - return output -} diff --git a/v2/cmd/voucher_client/root.go b/v2/cmd/voucher_client/root.go index a98c9d1f..1238e350 100644 --- a/v2/cmd/voucher_client/root.go +++ b/v2/cmd/voucher_client/root.go @@ -1,10 +1,14 @@ package main import ( + "context" "errors" "fmt" "os" + "time" + "github.com/docker/distribution/reference" + voucher "github.com/grafeas/voucher/v2" homedir "github.com/mitchellh/go-homedir" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -19,7 +23,7 @@ var ( var rootCmd = &cobra.Command{ Use: "voucher_client", Short: "voucher_client sends images to a Voucher server to be reviewed", - Long: `voucher_client is a frontend for Voucher server, which allows users to send + Long: `voucher_client is a frontend for Voucher server, which allows users to send images for analysis. It automatically resolves tags to digests when it encounters them.`, Args: func(cmd *cobra.Command, args []string) error { @@ -29,14 +33,74 @@ them.`, return nil }, Run: func(cmd *cobra.Command, args []string) { - if verify { - LookupAndVerify(args) - return + if err := clientRun(args); err != nil { + _, _ = fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) } - LookupAndCheck(args) }, } +func clientRun(args []string) error { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(defaultConfig.Timeout)*time.Second) + defer cancel() + + client, err := getVoucherClient(ctx) + if err != nil { + return fmt.Errorf("creating client failed: %w", err) + } + + canonicalRef, err := lookupCanonical(ctx, args[0]) + if err != nil { + return fmt.Errorf("getting canonical reference failed: %w", err) + } + + var op func(context.Context, string, reference.Canonical) (voucher.Response, error) + if verify { + op = client.Verify + } else { + op = client.Check + } + + resp, err := op(ctx, getCheck(), canonicalRef) + if err != nil { + return fmt.Errorf("remote operation failed: %w", err) + } + fmt.Println(formatResponse(&resp)) + + if !resp.Success { + return fmt.Errorf("image failed to pass required check(s)") + } + + return nil +} + +// formatResponse returns the response as a string. +func formatResponse(resp *voucher.Response) string { + output := "" + if resp.Success { + fmt.Println("image is approved") + } else { + fmt.Println("image was rejected") + } + for _, result := range resp.Results { + if result.Success { + output += fmt.Sprintf(" ✓ passed %s", result.Name) + if !result.Attested { + output += ", but wasn't attested" + } + } else { + output += fmt.Sprintf(" ✗ failed %s", result.Name) + } + + if "" != result.Err { + output += fmt.Sprintf(", err: %s", result.Err) + } + output += "\n" + } + + return output +} + // init initializes the configuration and the flags. func init() { cobra.OnInitialize(initConfig) diff --git a/v2/cmd/voucher_client/submit.go b/v2/cmd/voucher_client/submit.go deleted file mode 100644 index 71a37439..00000000 --- a/v2/cmd/voucher_client/submit.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "context" - "errors" - "fmt" - "os" - - "github.com/docker/distribution/reference" - - voucher "github.com/grafeas/voucher/v2" -) - -var errImageCheckFailed = errors.New("image failed to pass required check(s)") - -// check checks the passed image to the voucher server. -func check(ctx context.Context, client voucher.Interface, check string, canonicalRef reference.Canonical) error { - fmt.Printf("Submitting image to Voucher: %s\n", canonicalRef.String()) - - voucherResp, err := client.Check(ctx, check, canonicalRef) - if nil != err { - return fmt.Errorf("signing image failed: %s", err) - } - - fmt.Println(formatResponse(&voucherResp)) - - if !voucherResp.Success { - return errImageCheckFailed - } - - return nil -} - -// LookupAndCheck looks up the passed image, and checks it with the Voucher -// server. -func LookupAndCheck(args []string) { - var err error - - ctx, cancel := newContext() - defer cancel() - - client, err := getVoucherClient(ctx) - if nil != err { - errorf("creating client failed: %s", err) - os.Exit(1) - } - - canonicalRef, err := lookupCanonical(ctx, args[0]) - if nil != err { - errorf("getting canonical reference failed: %s", err) - os.Exit(1) - } - - err = check(ctx, client, getCheck(), canonicalRef) - if nil != err { - errorf("checking image with voucher failed: %s", err) - os.Exit(1) - } -} diff --git a/v2/cmd/voucher_client/verify.go b/v2/cmd/voucher_client/verify.go deleted file mode 100644 index 4fcca29a..00000000 --- a/v2/cmd/voucher_client/verify.go +++ /dev/null @@ -1,55 +0,0 @@ -package main - -import ( - "context" - "fmt" - "os" - - "github.com/docker/distribution/reference" - - voucher "github.com/grafeas/voucher/v2" -) - -// verifyImage submits the passed image to the voucher server for verification. -func verifyImage(ctx context.Context, client voucher.Interface, check string, canonicalRef reference.Canonical) error { - fmt.Printf("Verifying image with Voucher: %s\n", canonicalRef.String()) - - voucherResp, err := client.Verify(ctx, check, canonicalRef) - if nil != err { - return fmt.Errorf("verifying image failed: %s", err) - } - - fmt.Println(formatResponse(&voucherResp)) - - if !voucherResp.Success { - return errImageCheckFailed - } - - return nil -} - -// LookupAndVerify looks up the passed image, and submits it with the Voucher server. -func LookupAndVerify(args []string) { - var err error - - ctx, cancel := newContext() - defer cancel() - - client, err := getVoucherClient(ctx) - if nil != err { - errorf("creating client failed: %s", err) - os.Exit(1) - } - - canonicalRef, err := lookupCanonical(ctx, args[0]) - if nil != err { - errorf("getting canonical reference failed: %s", err) - os.Exit(1) - } - - err = verifyImage(ctx, client, getCheck(), canonicalRef) - if nil != err { - errorf("verifying image with voucher failed: %s", err) - os.Exit(1) - } -} From 7b0b58db02b4a88c4ab8d7a3177c2ac408877847 Mon Sep 17 00:00:00 2001 From: Peter Wagner Date: Thu, 10 Nov 2022 16:31:08 -0500 Subject: [PATCH 4/4] voucher_client: go-containerregistry --- v2/client/check.go | 5 +- v2/client/client.go | 7 +-- v2/client/client_test.go | 15 +---- v2/client/verify.go | 4 +- v2/cmd/voucher_client/digest.go | 37 ------------ v2/cmd/voucher_client/lookup.go | 38 ------------ v2/cmd/voucher_client/root.go | 21 ++++--- v2/container/gcr/project.go | 12 +--- v2/container/resolve.go | 50 +++++++++++++++ v2/container/resolver_test.go | 61 +++++++++++++++++++ v2/go.mod | 45 ++++++++------ v2/go.sum | 104 ++++++++++++++++++++------------ v2/interface.go | 6 +- 13 files changed, 225 insertions(+), 180 deletions(-) delete mode 100644 v2/cmd/voucher_client/digest.go delete mode 100644 v2/cmd/voucher_client/lookup.go create mode 100644 v2/container/resolve.go create mode 100644 v2/container/resolver_test.go diff --git a/v2/client/check.go b/v2/client/check.go index 7da24827..a30abc49 100644 --- a/v2/client/check.go +++ b/v2/client/check.go @@ -4,13 +4,12 @@ import ( "context" "path" - "github.com/docker/distribution/reference" voucher "github.com/grafeas/voucher/v2" ) // Check executes a request to a Voucher server, to the appropriate check URI, and -// with the passed reference.Canonical. Returns a voucher.Response and an error. -func (c *Client) Check(ctx context.Context, check string, image reference.Canonical) (voucher.Response, error) { +// with the passed image. Returns a voucher.Response and an error. +func (c *Client) Check(ctx context.Context, check string, image string) (voucher.Response, error) { url := c.toVoucherCheckURL(check) resp, err := c.doVoucherRequest(ctx, url, image) if err != nil { diff --git a/v2/client/client.go b/v2/client/client.go index 1135cb15..28683df9 100644 --- a/v2/client/client.go +++ b/v2/client/client.go @@ -11,7 +11,6 @@ import ( "net/url" "strings" - "github.com/docker/distribution/reference" voucher "github.com/grafeas/voucher/v2" "golang.org/x/oauth2" "golang.org/x/oauth2/google" @@ -145,9 +144,9 @@ func (c *Client) CopyURL() *url.URL { return &urlCopy } -func (c *Client) newVoucherRequest(ctx context.Context, url string, image reference.Canonical) (*http.Request, error) { +func (c *Client) newVoucherRequest(ctx context.Context, url string, image string) (*http.Request, error) { voucherReq := voucher.Request{ - ImageURL: image.String(), + ImageURL: image, } var buf bytes.Buffer @@ -168,7 +167,7 @@ func (c *Client) newVoucherRequest(ctx context.Context, url string, image refere return req, nil } -func (c *Client) doVoucherRequest(ctx context.Context, url string, image reference.Canonical) (*voucher.Response, error) { +func (c *Client) doVoucherRequest(ctx context.Context, url string, image string) (*voucher.Response, error) { req, err := c.newVoucherRequest(ctx, url, image) if err != nil { return nil, fmt.Errorf("could create voucher request: %w", err) diff --git a/v2/client/client_test.go b/v2/client/client_test.go index ff10bef5..a421f931 100644 --- a/v2/client/client_test.go +++ b/v2/client/client_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - "github.com/docker/distribution/reference" "github.com/grafeas/voucher/v2" "github.com/grafeas/voucher/v2/client" "github.com/stretchr/testify/assert" @@ -57,7 +56,7 @@ func TestVoucher_Check(t *testing.T) { c, err := client.NewClient(srv.URL) require.NoError(t, err) - res, err := c.Check(context.Background(), "diy", canonical(t, image)) + res, err := c.Check(context.Background(), "diy", image) require.NoError(t, err) assert.True(t, res.Success) } @@ -72,7 +71,7 @@ func TestVoucher_CustomUserAgent(t *testing.T) { c, err := client.NewClientContext(context.Background(), srv.URL, client.WithUserAgent(customUserAgent)) require.NoError(t, err) - res, err := c.Check(context.Background(), "diy", canonical(t, image)) + res, err := c.Check(context.Background(), "diy", image) require.NoError(t, err) assert.True(t, res.Success) } @@ -85,7 +84,7 @@ func TestVoucher_Verify(t *testing.T) { c, err := client.NewClient(srv.URL) require.NoError(t, err) - res, err := c.Verify(context.Background(), "diy", canonical(t, image)) + res, err := c.Verify(context.Background(), "diy", image) require.NoError(t, err) assert.True(t, res.Success) } @@ -135,11 +134,3 @@ func (v *mockVoucher) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(res) } - -func canonical(t *testing.T, image string) reference.Canonical { - ref, err := reference.Parse(image) - require.NoError(t, err) - canonical, ok := ref.(reference.Canonical) - require.True(t, ok) - return canonical -} diff --git a/v2/client/verify.go b/v2/client/verify.go index f0eeb18e..9522427a 100644 --- a/v2/client/verify.go +++ b/v2/client/verify.go @@ -4,12 +4,10 @@ import ( "context" "path" - "github.com/docker/distribution/reference" - voucher "github.com/grafeas/voucher/v2" ) -func (c *Client) Verify(ctx context.Context, check string, image reference.Canonical) (voucher.Response, error) { +func (c *Client) Verify(ctx context.Context, check string, image string) (voucher.Response, error) { url := c.toVoucherVerifyURL(check) resp, err := c.doVoucherRequest(ctx, url, image) if err != nil { diff --git a/v2/cmd/voucher_client/digest.go b/v2/cmd/voucher_client/digest.go deleted file mode 100644 index 57d54dca..00000000 --- a/v2/cmd/voucher_client/digest.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - - "github.com/docker/distribution/reference" - - "github.com/grafeas/voucher/v2/docker" -) - -// getCanonicalReference gets the canonical image reference for the passed -// image reference. If the passed reference is not already a canonical image -// reference, this method will connect to the registry to get the current digest -// and create the canonical reference from the original reference and that digest. -// -// This is because Binary Authorization only supports canonical image references, -// as a non-canonical image reference could refer to multiple versions of the same -// image (with different contents). -func getCanonicalReference(client *http.Client, ref reference.Reference) (reference.Canonical, error) { - if canonicalRef, ok := ref.(reference.Canonical); ok { - return canonicalRef, nil - } - - if taggedRef, ok := ref.(reference.NamedTagged); ok { - imageDigest, err := docker.GetDigestFromTagged(client, taggedRef) - if nil != err { - return nil, fmt.Errorf("getting digest from tag failed: %s", err) - } - canonicalRef, err := reference.WithDigest(reference.TrimNamed(taggedRef), imageDigest) - if nil != err { - return nil, fmt.Errorf("making canonical reference failed: %s", err) - } - return canonicalRef, nil - } - return nil, fmt.Errorf("reference cannot be converted to a canonical reference") -} diff --git a/v2/cmd/voucher_client/lookup.go b/v2/cmd/voucher_client/lookup.go deleted file mode 100644 index 5452126d..00000000 --- a/v2/cmd/voucher_client/lookup.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import ( - "context" - "fmt" - - "github.com/docker/distribution/reference" - - voucher "github.com/grafeas/voucher/v2" - "github.com/grafeas/voucher/v2/auth/google" -) - -// lookupCanonical looks up the canonical version of the passed image path. -func lookupCanonical(ctx context.Context, image string) (reference.Canonical, error) { - var ok bool - var namedRef reference.Named - - ref, err := reference.Parse(image) - if nil != err { - return nil, fmt.Errorf("parsing image reference failed: %s", err) - } - - if namedRef, ok = ref.(reference.Named); !ok { - return nil, fmt.Errorf("couldn't get named version of reference: %s", err) - } - - voucherClient, err := voucher.AuthToClient(ctx, google.NewAuth(), namedRef) - if nil != err { - return nil, fmt.Errorf("creating authenticated client failed: %s", err) - } - - canonicalRef, err := getCanonicalReference(voucherClient, namedRef) - if nil != err { - err = fmt.Errorf("getting image digest failed: %s", err) - } - - return canonicalRef, err -} diff --git a/v2/cmd/voucher_client/root.go b/v2/cmd/voucher_client/root.go index 1238e350..8577fb62 100644 --- a/v2/cmd/voucher_client/root.go +++ b/v2/cmd/voucher_client/root.go @@ -7,8 +7,9 @@ import ( "os" "time" - "github.com/docker/distribution/reference" + "github.com/google/go-containerregistry/pkg/v1/google" voucher "github.com/grafeas/voucher/v2" + "github.com/grafeas/voucher/v2/container" homedir "github.com/mitchellh/go-homedir" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -44,24 +45,28 @@ func clientRun(args []string) error { ctx, cancel := context.WithTimeout(context.Background(), time.Duration(defaultConfig.Timeout)*time.Second) defer cancel() - client, err := getVoucherClient(ctx) + // Attempt google auth, but don't worry if it fails: + googleAuth, _ := google.NewEnvAuthenticator() + resolver := container.NewResolver(googleAuth) + digest, err := resolver.ToDigest(ctx, args[0]) if err != nil { - return fmt.Errorf("creating client failed: %w", err) + return fmt.Errorf("getting canonical reference failed: %w", err) } - canonicalRef, err := lookupCanonical(ctx, args[0]) + client, err := getVoucherClient(ctx) if err != nil { - return fmt.Errorf("getting canonical reference failed: %w", err) + return fmt.Errorf("creating client failed: %w", err) } - - var op func(context.Context, string, reference.Canonical) (voucher.Response, error) + var op func(context.Context, string, string) (voucher.Response, error) if verify { op = client.Verify + fmt.Printf("Verifying %s\n", digest) } else { op = client.Check + fmt.Printf("Checking %s\n", digest) } - resp, err := op(ctx, getCheck(), canonicalRef) + resp, err := op(ctx, getCheck(), digest.String()) if err != nil { return fmt.Errorf("remote operation failed: %w", err) } diff --git a/v2/container/gcr/project.go b/v2/container/gcr/project.go index b83f4183..9a09cab3 100644 --- a/v2/container/gcr/project.go +++ b/v2/container/gcr/project.go @@ -7,14 +7,6 @@ import ( "github.com/docker/distribution/reference" ) -type ErrNoProjectInReference struct { - ref reference.Reference -} - -func (err *ErrNoProjectInReference) Error() string { - return fmt.Sprintf("could not find project path in reference \"%s\"", err.ref) -} - // ReferenceToProjectName returns what should be the GCR project name for an // image reference. // @@ -31,7 +23,5 @@ func ReferenceToProjectName(ref reference.Reference) (string, error) { } } - return "", &ErrNoProjectInReference{ - ref: ref, - } + return "", fmt.Errorf("could not find project path in reference %q", ref) } diff --git a/v2/container/resolve.go b/v2/container/resolve.go new file mode 100644 index 00000000..331b49b3 --- /dev/null +++ b/v2/container/resolve.go @@ -0,0 +1,50 @@ +package container + +import ( + "context" + "fmt" + + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/remote" +) + +type Resolver struct { + auth authn.Authenticator +} + +func NewResolver(auth authn.Authenticator) *Resolver { + return &Resolver{ + auth: auth, + } +} + +func (r *Resolver) ToDigest(ctx context.Context, ref string) (*name.Digest, error) { + // Parse reference, it might already contain a digest: + parsedRef, err := name.ParseReference(ref, name.WeakValidation) + if err != nil { + return nil, fmt.Errorf("parsing reference failed: %w", err) + } + if digest, ok := parsedRef.(name.Digest); ok { + return &digest, nil + } + + // Fetch the remote ImageIndex/manifest list, and return its digest: + opts := []remote.Option{remote.WithContext(ctx)} + if r.auth != nil { + opts = append(opts, remote.WithAuth(r.auth)) + } + remoteImg, err := remote.Index(parsedRef, opts...) + if err != nil { + return nil, fmt.Errorf("getting remote image index failed: %w", err) + } + digest, err := remoteImg.Digest() + if err != nil { + return nil, fmt.Errorf("getting image digest failed: %w", err) + } + digestedRef, err := name.NewDigest(fmt.Sprintf("%s:%s@%s", parsedRef.Context().Name(), parsedRef.Identifier(), digest)) + if err != nil { + return nil, fmt.Errorf("parsing digest failed: %w", err) + } + return &digestedRef, nil +} diff --git a/v2/container/resolver_test.go b/v2/container/resolver_test.go new file mode 100644 index 00000000..af0b9091 --- /dev/null +++ b/v2/container/resolver_test.go @@ -0,0 +1,61 @@ +package container_test + +import ( + "context" + "testing" + + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/v1/google" + "github.com/grafeas/voucher/v2/container" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestResolver_Resolve(t *testing.T) { + t.Skip("depends on external tags which change over time - please update before running") + + googleAuth, err := google.NewEnvAuthenticator() + require.NoError(t, err) + cases := map[string]struct { + ref string + expected string + auth authn.Authenticator + }{ + "dockerhub multi-arch tag": { + ref: "debian:bullseye", + expected: "index.docker.io/library/debian:bullseye@sha256:bfe6615d017d1eebe19f349669de58cda36c668ef916e618be78071513c690e5", + }, + "dockerhub multi-arch tag+digest": { + ref: "debian:bullseye@sha256:bfe6615d017d1eebe19f349669de58cda36c668ef916e618be78071513c690e5", + expected: "debian:bullseye@sha256:bfe6615d017d1eebe19f349669de58cda36c668ef916e618be78071513c690e5", + }, + "dockerhub single-arch tag+digest": { + ref: "debian:bullseye@sha256:725ea075576e253aff7f205e8ff1f07d28ee28cb98089fb6d50eda013aeaeca5", + expected: "debian:bullseye@sha256:725ea075576e253aff7f205e8ff1f07d28ee28cb98089fb6d50eda013aeaeca5", + }, + "gcr latest": { + ref: "gcr.io/distroless/static-debian11", + expected: "gcr.io/distroless/static-debian11:latest@sha256:5759d194607e472ff80fff5833442d3991dd89b219c96552837a2c8f74058617", + auth: googleAuth, + }, + "gcr tag+digest": { + ref: "gcr.io/distroless/static-debian11:latest@sha256:5759d194607e472ff80fff5833442d3991dd89b219c96552837a2c8f74058617", + expected: "gcr.io/distroless/static-debian11:latest@sha256:5759d194607e472ff80fff5833442d3991dd89b219c96552837a2c8f74058617", + auth: googleAuth, + }, + "gcr tag": { + ref: "gcr.io/distroless/static-debian11:debug", + expected: "gcr.io/distroless/static-debian11:debug@sha256:c66a6ecb5aa7704a68c89d3ead1398adc7f16e214dda5f5f8e5d44351bcbf67d", + auth: googleAuth, + }, + } + + for label, tc := range cases { + t.Run(label, func(t *testing.T) { + res := container.NewResolver(tc.auth) + resolved, err := res.ToDigest(context.Background(), tc.ref) + require.NoError(t, err) + assert.Equal(t, tc.expected, resolved.String()) + }) + } +} diff --git a/v2/go.mod b/v2/go.mod index d2a254fa..ecefdf05 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -13,18 +13,18 @@ require ( github.com/Shopify/ejson v1.2.0 github.com/antihax/optional v1.0.0 github.com/bradleyfalzon/ghinstallation v1.1.1 - github.com/docker/distribution v2.6.0-rc.1.0.20180913220339-b089e9168825+incompatible - github.com/docker/docker v1.13.2-0.20170524085120-eef6495eddab + github.com/docker/distribution v2.8.1+incompatible + github.com/docker/docker v20.10.20+incompatible github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 github.com/golang/mock v1.6.0 github.com/googleapis/gax-go/v2 v2.1.1 github.com/gorilla/mux v1.6.2 github.com/mennanov/fieldmask-utils v0.0.0-20190703161732-eca3212cf9f3 github.com/mitchellh/go-homedir v1.1.0 - github.com/opencontainers/go-digest v1.0.0-rc1 + github.com/opencontainers/go-digest v1.0.0 github.com/shurcooL/githubv4 v0.0.0-20190718010115-4ba037080260 - github.com/sirupsen/logrus v1.6.0 - github.com/spf13/cobra v0.0.3 + github.com/sirupsen/logrus v1.9.0 + github.com/spf13/cobra v1.6.0 github.com/spf13/viper v1.4.0 github.com/stretchr/testify v1.7.1 go.mozilla.org/sops/v3 v3.7.1 @@ -34,13 +34,15 @@ require ( go.opentelemetry.io/otel/metric v0.32.1 go.opentelemetry.io/otel/sdk v1.10.0 go.opentelemetry.io/otel/sdk/metric v0.32.1 - golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 - golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b + golang.org/x/crypto v0.1.0 + golang.org/x/oauth2 v0.1.0 google.golang.org/api v0.63.0 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa google.golang.org/grpc v1.49.0 ) +require github.com/google/go-containerregistry v0.12.0 + require ( cloud.google.com/go v0.99.0 // indirect filippo.io/age v1.0.0-beta7 // indirect @@ -64,8 +66,10 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect github.com/dimchansky/utfbom v1.1.0 // indirect + github.com/docker/cli v20.10.20+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-units v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad // indirect github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect @@ -73,10 +77,11 @@ require ( github.com/fsnotify/fsnotify v1.4.7 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.3 // indirect - github.com/google/go-cmp v0.5.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-github/v29 v29.0.2 // indirect github.com/google/go-querystring v1.0.0 // indirect github.com/gorilla/context v1.1.1 // indirect @@ -92,16 +97,16 @@ require ( github.com/hashicorp/vault/api v1.0.4 // indirect github.com/hashicorp/vault/sdk v0.1.13 // indirect github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect + github.com/kr/pretty v0.2.1 // indirect github.com/lib/pq v1.2.0 // indirect github.com/magiconair/properties v1.8.0 // indirect github.com/mattn/go-colorable v0.0.9 // indirect github.com/mattn/go-isatty v0.0.3 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/mitchellh/mapstructure v1.1.2 // indirect - github.com/opencontainers/image-spec v1.0.1 // indirect + github.com/opencontainers/image-spec v1.1.0-rc2 // indirect github.com/pelletier/go-toml v1.2.0 // indirect github.com/pierrec/lz4 v2.0.5+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect @@ -113,7 +118,7 @@ require ( github.com/spf13/afero v1.1.2 // indirect github.com/spf13/cast v1.3.0 // indirect github.com/spf13/jwalterweatherman v1.0.0 // indirect - github.com/spf13/pflag v1.0.3 // indirect + github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.1.1 // indirect go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a // indirect go.opencensus.io v0.23.0 // indirect @@ -121,17 +126,17 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.32.1 // indirect go.opentelemetry.io/otel/trace v1.10.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect - golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect - golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect + golang.org/x/net v0.1.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.1.0 // indirect + golang.org/x/term v0.1.0 // indirect + golang.org/x/text v0.4.0 // indirect + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/ini.v1 v1.44.0 // indirect gopkg.in/square/go-jose.v2 v2.3.1 // indirect gopkg.in/urfave/cli.v1 v1.20.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107172259-749611fa9fcc // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/v2/go.sum b/v2/go.sum index 14aed4b4..8228986c 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -61,8 +61,8 @@ filippo.io/age v1.0.0-beta7/go.mod h1:chAuTrTb0FTTmKtvs6fQTGhYTvH9AigjN1uEUsvLdZ filippo.io/edwards25519 v1.0.0-alpha.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o= github.com/Azure/azure-sdk-for-go v31.2.0+incompatible h1:kZFnTLmdQYNGfakatSivKHUfUnDZhqNdchHD4oIhp5k= github.com/Azure/azure-sdk-for-go v31.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= @@ -94,8 +94,8 @@ github.com/DataDog/datadog-api-client-go v1.3.0 h1:HK7SJ6tNZkGUYPZiUAK7nuq915cFg github.com/DataDog/datadog-api-client-go v1.3.0/go.mod h1:QzaQF1cDO1/BIQG1fz14VrY+6RECUGkiwzDCtVbfP5c= github.com/DataDog/datadog-go v3.4.0+incompatible h1:LZ0OTmlvhCBT0VYUvhGu8Lrc7WqNCj6Zw9HnMi0V6mA= github.com/DataDog/datadog-go v3.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -148,11 +148,13 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/stargz-snapshotter/estargz v0.12.1 h1:+7nYmHJb0tEkcRaAW+MHqoKaJYZmkikupxCqVtmPuY0= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -161,14 +163,19 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= -github.com/docker/distribution v2.6.0-rc.1.0.20180913220339-b089e9168825+incompatible h1:GtuXC39S7vcASS86IaAHbZlH96ZxPjtZv+lWxY4T4M4= -github.com/docker/distribution v2.6.0-rc.1.0.20180913220339-b089e9168825+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v1.13.2-0.20170524085120-eef6495eddab h1:cAULc3RyTtKm1ArjTOwjzpVRMzxGSoG+/3wBgDhsv+Q= -github.com/docker/docker v1.13.2-0.20170524085120-eef6495eddab/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v20.10.20+incompatible h1:lWQbHSHUFs7KraSN2jOJK7zbMS2jNCHI4mt4xUFUVQ4= +github.com/docker/cli v20.10.20+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.20+incompatible h1:kH9tx6XO+359d+iAkumyKDc5Q1kOwPuAUaeri48nD6E= +github.com/docker/docker v20.10.20+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad h1:Qk76DOWdOp+GlyDKBAG3Klr9cn7N+LcYc82AZ2S7+cA= @@ -211,6 +218,8 @@ github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr6 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= @@ -265,8 +274,10 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-containerregistry v0.12.0 h1:nidOEtFYlgPCRqxCKj/4c/js940HVWplCWc5ftdfdUA= +github.com/google/go-containerregistry v0.12.0/go.mod h1:sdIK+oHQO7B93xI8UweYdl887YhuIwg9vz8BSLH3+8k= github.com/google/go-github/v29 v29.0.2 h1:opYN6Wc7DOz7Ku3Oh4l7prmkOMwEcQxpFtxdU8N8Pts= github.com/google/go-github/v29 v29.0.2/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= @@ -351,8 +362,8 @@ github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 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= @@ -364,13 +375,14 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +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.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -402,10 +414,12 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= +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.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= @@ -441,6 +455,7 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= @@ -453,8 +468,8 @@ github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f/go.mod h1:AuYgA5K github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -466,12 +481,13 @@ github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= +github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -487,6 +503,7 @@ github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMT github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -541,8 +558,9 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -578,6 +596,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -618,9 +637,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -637,8 +655,8 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y= +golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -650,8 +668,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -702,7 +720,6 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -710,13 +727,13 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -726,12 +743,13 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -772,6 +790,7 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= @@ -780,12 +799,14 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -948,8 +969,8 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.44.0 h1:YRJzTUp0kSYWUVFF5XAbDFfyiqwsl0Vb9R8TVP5eRi0= @@ -969,9 +990,12 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107172259-749611fa9fcc h1:XANm4xAMEQhRdWKqaL0qmhGDv7RuobwCO97TIlktaQE= gopkg.in/yaml.v3 v3.0.0-20210107172259-749611fa9fcc/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/v2/interface.go b/v2/interface.go index 12bed0f4..982ba990 100644 --- a/v2/interface.go +++ b/v2/interface.go @@ -2,13 +2,11 @@ package voucher import ( "context" - - "github.com/docker/distribution/reference" ) // Interface represents an interface to the Voucher API. Typically Voucher API // clients would implement it. type Interface interface { - Check(ctx context.Context, check string, image reference.Canonical) (Response, error) - Verify(ctx context.Context, check string, image reference.Canonical) (Response, error) + Check(ctx context.Context, check string, image string) (Response, error) + Verify(ctx context.Context, check string, image string) (Response, error) }