From 3228aef2e2bb6823151b5e3f6637272504976cb1 Mon Sep 17 00:00:00 2001 From: Ingwon Song Date: Wed, 20 Jul 2022 18:41:16 +0000 Subject: [PATCH 1/7] Support the platform specific authentication of krane in "auth get" command --- cmd/crane/cmd/auth.go | 14 ++++++++++---- cmd/crane/cmd/root.go | 2 +- cmd/gcrane/main.go | 2 +- pkg/crane/options.go | 3 +++ 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/cmd/crane/cmd/auth.go b/cmd/crane/cmd/auth.go index 4914aeaee..f10aa757e 100644 --- a/cmd/crane/cmd/auth.go +++ b/cmd/crane/cmd/auth.go @@ -26,19 +26,20 @@ import ( "github.com/docker/cli/cli/config" "github.com/docker/cli/cli/config/types" "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/crane" "github.com/google/go-containerregistry/pkg/name" "github.com/spf13/cobra" ) // NewCmdAuth creates a new cobra.Command for the auth subcommand. -func NewCmdAuth(argv ...string) *cobra.Command { +func NewCmdAuth(options *[]crane.Option, argv ...string) *cobra.Command { cmd := &cobra.Command{ Use: "auth", Short: "Log in or access credentials", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { return cmd.Usage() }, } - cmd.AddCommand(NewCmdAuthGet(argv...), NewCmdAuthLogin(argv...)) + cmd.AddCommand(NewCmdAuthGet(options, argv...), NewCmdAuthLogin(argv...)) return cmd } @@ -62,7 +63,7 @@ func toCreds(config *authn.AuthConfig) credentials { } // NewCmdAuthGet creates a new `crane auth get` command. -func NewCmdAuthGet(argv ...string) *cobra.Command { +func NewCmdAuthGet(options *[]crane.Option, argv ...string) *cobra.Command { if len(argv) == 0 { argv = []string{os.Args[0]} } @@ -85,7 +86,12 @@ func NewCmdAuthGet(argv ...string) *cobra.Command { if err != nil { return err } - authorizer, err := authn.DefaultKeychain.Resolve(reg) + keychain := authn.DefaultKeychain + if options != nil { + opts := crane.GetOptions(*options...) + keychain = opts.Keychain + } + authorizer, err := keychain.Resolve(reg) if err != nil { return err } diff --git a/cmd/crane/cmd/root.go b/cmd/crane/cmd/root.go index d06fe0190..0ea3e1421 100644 --- a/cmd/crane/cmd/root.go +++ b/cmd/crane/cmd/root.go @@ -93,7 +93,7 @@ func New(use, short string, options []crane.Option) *cobra.Command { commands := []*cobra.Command{ NewCmdAppend(&options), - NewCmdAuth("crane", "auth"), + NewCmdAuth(&options, "crane", "auth"), NewCmdBlob(&options), NewCmdCatalog(&options), NewCmdConfig(&options), diff --git a/cmd/gcrane/main.go b/cmd/gcrane/main.go index e3672a36d..3d51bcec1 100644 --- a/cmd/gcrane/main.go +++ b/cmd/gcrane/main.go @@ -42,7 +42,7 @@ func main() { root := cmd.New(use, short, []crane.Option{crane.WithAuthFromKeychain(gcrane.Keychain)}) // Add or override commands. - gcraneCmds := []*cobra.Command{gcmd.NewCmdList(), gcmd.NewCmdGc(), gcmd.NewCmdCopy(), cmd.NewCmdAuth("gcrane", "auth")} + gcraneCmds := []*cobra.Command{gcmd.NewCmdList(), gcmd.NewCmdGc(), gcmd.NewCmdCopy(), cmd.NewCmdAuth(nil, "gcrane", "auth")} // Maintain a map of google-specific commands that we "override". used := make(map[string]bool) diff --git a/pkg/crane/options.go b/pkg/crane/options.go index 2f95e0556..2e992789b 100644 --- a/pkg/crane/options.go +++ b/pkg/crane/options.go @@ -29,6 +29,7 @@ type Options struct { Name []name.Option Remote []remote.Option Platform *v1.Platform + Keychain authn.Keychain } // GetOptions exposes the underlying []remote.Option, []name.Option, and @@ -44,6 +45,7 @@ func makeOptions(opts ...Option) Options { Remote: []remote.Option{ remote.WithAuthFromKeychain(authn.DefaultKeychain), }, + Keychain: authn.DefaultKeychain, } for _, o := range opts { o(&opt) @@ -86,6 +88,7 @@ func WithAuthFromKeychain(keys authn.Keychain) Option { return func(o *Options) { // Replace the default keychain at position 0. o.Remote[0] = remote.WithAuthFromKeychain(keys) + o.Keychain = keys } } From 730452696688e21772e20a0c74709c420dd779af Mon Sep 17 00:00:00 2001 From: Ingwon Song Date: Wed, 20 Jul 2022 20:22:43 +0000 Subject: [PATCH 2/7] Add tests for "krane auth get" --- .github/workflows/ecr-auth.yaml | 14 ++++++++++++++ .github/workflows/ghcr-auth.yaml | 15 +++++++++++++++ cmd/crane/cmd/auth.go | 27 +++++++++++++++++++-------- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ecr-auth.yaml b/.github/workflows/ecr-auth.yaml index 3daaa3a32..7ef38a617 100644 --- a/.github/workflows/ecr-auth.yaml +++ b/.github/workflows/ecr-auth.yaml @@ -39,6 +39,20 @@ jobs: # List the tags krane ls ${{ env.AWS_ACCOUNT }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/go-containerregistry-test + - name: Test krane auth get + ECR + env: + GITHUB_TOKEN: ${{ github.token }} + shell: bash + run: | + CRED1=$(krane auth get ${{ env.AWS_ACCOUNT }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com) + CRED2=$(krane auth get ${{ env.AWS_ACCOUNT }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com) + if [[ "$CRED1" == "" ]] ; then + exit 1 + fi + if [[ "$CRED1" == "$CRED2" ]] ; then + echo "credentials are cached by infrastructure" + fi + crane-ecr-login: runs-on: ubuntu-latest env: diff --git a/.github/workflows/ghcr-auth.yaml b/.github/workflows/ghcr-auth.yaml index caaf7186d..166ea41cc 100644 --- a/.github/workflows/ghcr-auth.yaml +++ b/.github/workflows/ghcr-auth.yaml @@ -30,3 +30,18 @@ jobs: run: | # List the tags krane ls ghcr.io/${{ github.repository }}/testimage + + - name: Test krane auth get + GHCR + env: + GITHUB_TOKEN: ${{ github.token }} + shell: bash + run: | + CRED1=$(krane auth get ghcr.io) + CRED2=$(krane auth get ghcr.io) + if [[ "$CRED1" == "" ]] ; then + exit 1 + fi + if [[ "$CRED1" == "$CRED2" ]] ; then + echo "credentials are cached by infrastructure" + fi + \ No newline at end of file diff --git a/cmd/crane/cmd/auth.go b/cmd/crane/cmd/auth.go index f10aa757e..fad929749 100644 --- a/cmd/crane/cmd/auth.go +++ b/cmd/crane/cmd/auth.go @@ -68,21 +68,32 @@ func NewCmdAuthGet(options *[]crane.Option, argv ...string) *cobra.Command { argv = []string{os.Args[0]} } + baseCmd := strings.Join(argv, " ") eg := fmt.Sprintf(` # Read configured credentials for reg.example.com - echo "reg.example.com" | %s get - {"username":"AzureDiamond","password":"hunter2"}`, strings.Join(argv, " ")) + $ echo "reg.example.com" | %s get + {"username":"AzureDiamond","password":"hunter2"} + # or + $ %s get reg.example.com + {"username":"AzureDiamond","password":"hunter2"}`, baseCmd, baseCmd) return &cobra.Command{ - Use: "get", + Use: "get [REGISTRY_ADDR]", Short: "Implements a credential helper", Example: eg, - Args: cobra.NoArgs, + Args: cobra.MaximumNArgs(1), RunE: func(_ *cobra.Command, args []string) error { - b, err := ioutil.ReadAll(os.Stdin) - if err != nil { - return err + registryAddr := "" + if len(args) == 1 { + registryAddr = args[0] + } else { + b, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return err + } + registryAddr = strings.TrimSpace(string(b)) } - reg, err := name.NewRegistry(strings.TrimSpace(string(b))) + + reg, err := name.NewRegistry(registryAddr) if err != nil { return err } From bb4e0e0d7ac91a5e65b0348e292624f096e13847 Mon Sep 17 00:00:00 2001 From: Ingwon Song Date: Wed, 20 Jul 2022 20:36:33 +0000 Subject: [PATCH 3/7] Update the doc --- cmd/crane/doc/crane_auth_get.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/crane/doc/crane_auth_get.md b/cmd/crane/doc/crane_auth_get.md index 2265b84f0..86686e193 100644 --- a/cmd/crane/doc/crane_auth_get.md +++ b/cmd/crane/doc/crane_auth_get.md @@ -3,7 +3,7 @@ Implements a credential helper ``` -crane auth get [flags] +crane auth get [REGISTRY_ADDR] [flags] ``` ### Examples @@ -12,6 +12,9 @@ crane auth get [flags] # Read configured credentials for reg.example.com echo "reg.example.com" | crane auth get {"username":"AzureDiamond","password":"hunter2"} + # or + crane auth get reg.example.com + {"username":"AzureDiamond","password":"hunter2"} ``` ### Options From 7615ef1806d36230699ed1f86d43fa799b8251d0 Mon Sep 17 00:00:00 2001 From: Ingwon Song Date: Wed, 20 Jul 2022 21:02:57 +0000 Subject: [PATCH 4/7] Use gcrane.Keychain in gcrane --- cmd/crane/cmd/auth.go | 11 +++-------- cmd/crane/cmd/root.go | 2 +- cmd/gcrane/main.go | 5 +++-- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/cmd/crane/cmd/auth.go b/cmd/crane/cmd/auth.go index fad929749..eaaa32622 100644 --- a/cmd/crane/cmd/auth.go +++ b/cmd/crane/cmd/auth.go @@ -32,7 +32,7 @@ import ( ) // NewCmdAuth creates a new cobra.Command for the auth subcommand. -func NewCmdAuth(options *[]crane.Option, argv ...string) *cobra.Command { +func NewCmdAuth(options []crane.Option, argv ...string) *cobra.Command { cmd := &cobra.Command{ Use: "auth", Short: "Log in or access credentials", @@ -63,7 +63,7 @@ func toCreds(config *authn.AuthConfig) credentials { } // NewCmdAuthGet creates a new `crane auth get` command. -func NewCmdAuthGet(options *[]crane.Option, argv ...string) *cobra.Command { +func NewCmdAuthGet(options []crane.Option, argv ...string) *cobra.Command { if len(argv) == 0 { argv = []string{os.Args[0]} } @@ -97,12 +97,7 @@ func NewCmdAuthGet(options *[]crane.Option, argv ...string) *cobra.Command { if err != nil { return err } - keychain := authn.DefaultKeychain - if options != nil { - opts := crane.GetOptions(*options...) - keychain = opts.Keychain - } - authorizer, err := keychain.Resolve(reg) + authorizer, err := crane.GetOptions(options...).Keychain.Resolve(reg) if err != nil { return err } diff --git a/cmd/crane/cmd/root.go b/cmd/crane/cmd/root.go index 0ea3e1421..7950ae7b6 100644 --- a/cmd/crane/cmd/root.go +++ b/cmd/crane/cmd/root.go @@ -93,7 +93,7 @@ func New(use, short string, options []crane.Option) *cobra.Command { commands := []*cobra.Command{ NewCmdAppend(&options), - NewCmdAuth(&options, "crane", "auth"), + NewCmdAuth(options, "crane", "auth"), NewCmdBlob(&options), NewCmdCatalog(&options), NewCmdConfig(&options), diff --git a/cmd/gcrane/main.go b/cmd/gcrane/main.go index 3d51bcec1..a77168420 100644 --- a/cmd/gcrane/main.go +++ b/cmd/gcrane/main.go @@ -38,11 +38,12 @@ const ( ) func main() { + options := []crane.Option{crane.WithAuthFromKeychain(gcrane.Keychain)} // Same as crane, but override usage and keychain. - root := cmd.New(use, short, []crane.Option{crane.WithAuthFromKeychain(gcrane.Keychain)}) + root := cmd.New(use, short, options) // Add or override commands. - gcraneCmds := []*cobra.Command{gcmd.NewCmdList(), gcmd.NewCmdGc(), gcmd.NewCmdCopy(), cmd.NewCmdAuth(nil, "gcrane", "auth")} + gcraneCmds := []*cobra.Command{gcmd.NewCmdList(), gcmd.NewCmdGc(), gcmd.NewCmdCopy(), cmd.NewCmdAuth(options, "gcrane", "auth")} // Maintain a map of google-specific commands that we "override". used := make(map[string]bool) From abede335f7b65e01513eb8a96f9994bf5e8e6d4b Mon Sep 17 00:00:00 2001 From: Ingwon Song Date: Wed, 20 Jul 2022 21:15:20 +0000 Subject: [PATCH 5/7] Fix misaligned doc --- cmd/crane/doc/crane_auth_get.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/crane/doc/crane_auth_get.md b/cmd/crane/doc/crane_auth_get.md index 86686e193..6ff89c1c8 100644 --- a/cmd/crane/doc/crane_auth_get.md +++ b/cmd/crane/doc/crane_auth_get.md @@ -10,10 +10,10 @@ crane auth get [REGISTRY_ADDR] [flags] ``` # Read configured credentials for reg.example.com - echo "reg.example.com" | crane auth get + $ echo "reg.example.com" | crane auth get {"username":"AzureDiamond","password":"hunter2"} # or - crane auth get reg.example.com + $ crane auth get reg.example.com {"username":"AzureDiamond","password":"hunter2"} ``` From 5b6f08fefc453faa68c2789bbb3b81f3f9f944ea Mon Sep 17 00:00:00 2001 From: Ingwon Song Date: Wed, 20 Jul 2022 21:39:36 +0000 Subject: [PATCH 6/7] Remove a space --- cmd/crane/cmd/auth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/crane/cmd/auth.go b/cmd/crane/cmd/auth.go index eaaa32622..e2351ae7d 100644 --- a/cmd/crane/cmd/auth.go +++ b/cmd/crane/cmd/auth.go @@ -72,7 +72,7 @@ func NewCmdAuthGet(options []crane.Option, argv ...string) *cobra.Command { eg := fmt.Sprintf(` # Read configured credentials for reg.example.com $ echo "reg.example.com" | %s get {"username":"AzureDiamond","password":"hunter2"} - # or + # or $ %s get reg.example.com {"username":"AzureDiamond","password":"hunter2"}`, baseCmd, baseCmd) From cce8f740f3955537d8842801ad26566cc20d2aa8 Mon Sep 17 00:00:00 2001 From: Ingwon Song Date: Wed, 20 Jul 2022 22:00:52 +0000 Subject: [PATCH 7/7] Remove unused environment variable from the ECR test --- .github/workflows/ecr-auth.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ecr-auth.yaml b/.github/workflows/ecr-auth.yaml index 7ef38a617..3d5e8d557 100644 --- a/.github/workflows/ecr-auth.yaml +++ b/.github/workflows/ecr-auth.yaml @@ -40,8 +40,6 @@ jobs: krane ls ${{ env.AWS_ACCOUNT }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/go-containerregistry-test - name: Test krane auth get + ECR - env: - GITHUB_TOKEN: ${{ github.token }} shell: bash run: | CRED1=$(krane auth get ${{ env.AWS_ACCOUNT }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com) @@ -52,7 +50,7 @@ jobs: if [[ "$CRED1" == "$CRED2" ]] ; then echo "credentials are cached by infrastructure" fi - + crane-ecr-login: runs-on: ubuntu-latest env: