From 906e1b43056bd1b0649dc8156df93a8f56dcdad6 Mon Sep 17 00:00:00 2001 From: Amine Chouki Date: Thu, 22 Jul 2021 16:28:33 -0400 Subject: [PATCH 1/3] Add a post-login message to promote personal access tokens Signed-off-by: Amine Chouki --- cli/mobycli/exec.go | 8 ++- pkg/utils/pat_suggest.go | 75 ++++++++++++++++++++++++++++ pkg/utils/pat_suggest_test.go | 94 +++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 pkg/utils/pat_suggest.go create mode 100644 pkg/utils/pat_suggest_test.go diff --git a/cli/mobycli/exec.go b/cli/mobycli/exec.go index 367b0ce36..bf6c91154 100644 --- a/cli/mobycli/exec.go +++ b/cli/mobycli/exec.go @@ -77,10 +77,14 @@ func Exec(root *cobra.Command) { fmt.Fprintln(os.Stderr, err) os.Exit(1) } - command := metrics.GetCommand(os.Args[1:]) - if command == "build" && !metrics.HasQuietFlag(os.Args[1:]) { + commandArgs := os.Args[1:] + command := metrics.GetCommand(commandArgs) + if command == "build" && !metrics.HasQuietFlag(commandArgs) { utils.DisplayScanSuggestMsg() } + if command == "login" && !metrics.HasQuietFlag(commandArgs) { + utils.DisplayPATSuggestMsg(commandArgs) + } metrics.Track(store.DefaultContextType, os.Args[1:], compose.SuccessStatus) os.Exit(0) diff --git a/pkg/utils/pat_suggest.go b/pkg/utils/pat_suggest.go new file mode 100644 index 000000000..6bf1a9948 --- /dev/null +++ b/pkg/utils/pat_suggest.go @@ -0,0 +1,75 @@ +/* + Copyright 2020 Docker Compose CLI authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package utils + +import ( + "fmt" + "os" + "strings" + + "github.com/docker/cli/cli/config" + "github.com/docker/docker/registry" + "github.com/google/uuid" +) + +const ( + // patSuggestMsg is a message to suggest the use of PAT (personal access tokens). + patSuggestMsg = `Logging in with your password grants your terminal complete access to your account. +For better security, log in with a limited-privilege personal access token. Learn more at https://docs.docker.com/docker-hub/access-tokens/` + + // patPrefix represents a docker personal access token prefix. + patPrefix = "dckrp_" +) + +// DisplayPATSuggestMsg displays a message suggesting users to use PATs instead of passwords to reduce scope. +func DisplayPATSuggestMsg(cmdArgs []string) { + if os.Getenv("DOCKER_PAT_SUGGEST") == "false" { + return + } + if !isUsingDefaultRegistry(cmdArgs) { + return + } + authCfg, err := config.LoadDefaultConfigFile(os.Stderr).GetAuthConfig(registry.IndexServer) + if err != nil { + return + } + if !isUsingPassword(authCfg.Password) { + return + } + fmt.Fprintf(os.Stderr, "\n"+patSuggestMsg+"\n") +} + +func isUsingDefaultRegistry(cmdArgs []string) bool { + for i := 1; i < len(cmdArgs); i++ { + if strings.HasPrefix(cmdArgs[i], "-") { + i++ + continue + } + return cmdArgs[i] == registry.IndexServer + } + return true +} + +func isUsingPassword(pass string) bool { + if _, err := uuid.Parse(pass); err == nil { + return false + } + if strings.HasPrefix(pass, patPrefix) { + return false + } + return true +} diff --git a/pkg/utils/pat_suggest_test.go b/pkg/utils/pat_suggest_test.go new file mode 100644 index 000000000..7708b34c7 --- /dev/null +++ b/pkg/utils/pat_suggest_test.go @@ -0,0 +1,94 @@ +/* + Copyright 2020 Docker Compose CLI authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package utils + +import ( + "testing" + + "github.com/docker/docker/registry" + "gotest.tools/assert" +) + +func TestIsUsingDefaultRegistry(t *testing.T) { + testCases := []struct { + name string + input []string + expected bool + }{ + { + "without flags", + []string{"login"}, + true, + }, + { + "login with flags", + []string{"login", "-u", "test", "-p", "testpass"}, + true, + }, + { + "login to default registry", + []string{"login", registry.IndexServer}, + true, + }, + { + "login to different registry", + []string{"login", "registry.example.com"}, + false, + }, + { + "login with flags to different registry", + []string{"login", "-u", "test", "-p", "testpass", "registry.example.com"}, + false, + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + result := isUsingDefaultRegistry(testCase.input) + assert.Equal(t, testCase.expected, result) + }) + } +} + +func TestIsUsingPassword(t *testing.T) { + testCases := []struct { + name string + input string + expected bool + }{ + { + "regular password", + "mypass", + true, + }, + { + "personal access token", + "1508b8bd-b80c-452d-9a7a-ee5607c41bcd", + false, + }, + { + "prefixed personal access token", + "dckrp_ee5607c41bcd", + false, + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + result := isUsingPassword(testCase.input) + assert.Equal(t, testCase.expected, result) + }) + } +} From e16d0b48ddac77ca399e5138441ac3ebb291677c Mon Sep 17 00:00:00 2001 From: Amine Chouki Date: Thu, 22 Jul 2021 16:46:27 -0400 Subject: [PATCH 2/3] use github.com/hashicorp/go-uuid Signed-off-by: Amine Chouki --- pkg/utils/pat_suggest.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/utils/pat_suggest.go b/pkg/utils/pat_suggest.go index 6bf1a9948..1574a7f06 100644 --- a/pkg/utils/pat_suggest.go +++ b/pkg/utils/pat_suggest.go @@ -23,7 +23,7 @@ import ( "github.com/docker/cli/cli/config" "github.com/docker/docker/registry" - "github.com/google/uuid" + "github.com/hashicorp/go-uuid" ) const ( @@ -65,7 +65,7 @@ func isUsingDefaultRegistry(cmdArgs []string) bool { } func isUsingPassword(pass string) bool { - if _, err := uuid.Parse(pass); err == nil { + if _, err := uuid.ParseUUID(pass); err == nil { return false } if strings.HasPrefix(pass, patPrefix) { From 5c427ef70211b43a79827be7d06e61ffd5ab67ba Mon Sep 17 00:00:00 2001 From: Amine Chouki Date: Fri, 23 Jul 2021 10:55:31 -0400 Subject: [PATCH 3/3] Move pat_suggest.go into `cli` package Signed-off-by: Amine Chouki --- cli/mobycli/exec.go | 2 +- {pkg/utils => cli/mobycli}/pat_suggest.go | 6 +++--- {pkg/utils => cli/mobycli}/pat_suggest_test.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename {pkg/utils => cli/mobycli}/pat_suggest.go (93%) rename {pkg/utils => cli/mobycli}/pat_suggest_test.go (99%) diff --git a/cli/mobycli/exec.go b/cli/mobycli/exec.go index bf6c91154..552987f85 100644 --- a/cli/mobycli/exec.go +++ b/cli/mobycli/exec.go @@ -83,7 +83,7 @@ func Exec(root *cobra.Command) { utils.DisplayScanSuggestMsg() } if command == "login" && !metrics.HasQuietFlag(commandArgs) { - utils.DisplayPATSuggestMsg(commandArgs) + displayPATSuggestMsg(commandArgs) } metrics.Track(store.DefaultContextType, os.Args[1:], compose.SuccessStatus) diff --git a/pkg/utils/pat_suggest.go b/cli/mobycli/pat_suggest.go similarity index 93% rename from pkg/utils/pat_suggest.go rename to cli/mobycli/pat_suggest.go index 1574a7f06..24e5363cf 100644 --- a/pkg/utils/pat_suggest.go +++ b/cli/mobycli/pat_suggest.go @@ -14,7 +14,7 @@ limitations under the License. */ -package utils +package mobycli import ( "fmt" @@ -35,8 +35,8 @@ For better security, log in with a limited-privilege personal access token. Lear patPrefix = "dckrp_" ) -// DisplayPATSuggestMsg displays a message suggesting users to use PATs instead of passwords to reduce scope. -func DisplayPATSuggestMsg(cmdArgs []string) { +// displayPATSuggestMsg displays a message suggesting users to use PATs instead of passwords to reduce scope. +func displayPATSuggestMsg(cmdArgs []string) { if os.Getenv("DOCKER_PAT_SUGGEST") == "false" { return } diff --git a/pkg/utils/pat_suggest_test.go b/cli/mobycli/pat_suggest_test.go similarity index 99% rename from pkg/utils/pat_suggest_test.go rename to cli/mobycli/pat_suggest_test.go index 7708b34c7..8d229829a 100644 --- a/pkg/utils/pat_suggest_test.go +++ b/cli/mobycli/pat_suggest_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package utils +package mobycli import ( "testing"