From 1751229475aa147969ddaa97decfde26b4244342 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 30 Jun 2020 12:47:02 +0200 Subject: [PATCH 01/70] Pass newClientFunc to environment struct. --- internals/secrethub/env_source.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 607d3e6f..9f0f4495 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -24,6 +24,7 @@ import ( type environment struct { io ui.IO + newClient newClientFunc osEnv []string readFile func(filename string) ([]byte, error) osStat func(filename string) (os.FileInfo, error) @@ -35,9 +36,10 @@ type environment struct { secretsEnvDir string } -func newEnvironment(io ui.IO) *environment { +func newEnvironment(io ui.IO, newClient newClientFunc) *environment { return &environment{ io: io, + newClient: newClient, osEnv: os.Environ(), readFile: ioutil.ReadFile, osStat: os.Stat, From 19f55406b420798ee2e94771978b591a486c29dc Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 30 Jun 2020 13:04:34 +0200 Subject: [PATCH 02/70] Pass newClientFunc to environment --- internals/secrethub/env.go | 2 +- internals/secrethub/env_ls.go | 4 ++-- internals/secrethub/env_read.go | 2 +- internals/secrethub/run.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internals/secrethub/env.go b/internals/secrethub/env.go index 845d50f3..5e653311 100644 --- a/internals/secrethub/env.go +++ b/internals/secrethub/env.go @@ -24,5 +24,5 @@ func (cmd *EnvCommand) Register(r command.Registerer) { clause := r.Command("env", "[BETA] Manage environment variables.").Hidden() clause.HelpLong("This command is hidden because it is still in beta. Future versions may break.") NewEnvReadCommand(cmd.io, cmd.newClient).Register(clause) - NewEnvListCommand(cmd.io).Register(clause) + NewEnvListCommand(cmd.io, cmd.newClient).Register(clause) } diff --git a/internals/secrethub/env_ls.go b/internals/secrethub/env_ls.go index e4835701..9f811c5f 100644 --- a/internals/secrethub/env_ls.go +++ b/internals/secrethub/env_ls.go @@ -14,10 +14,10 @@ type EnvListCommand struct { } // NewEnvListCommand creates a new EnvListCommand. -func NewEnvListCommand(io ui.IO) *EnvListCommand { +func NewEnvListCommand(io ui.IO, clientFunc newClientFunc) *EnvListCommand { return &EnvListCommand{ io: io, - environment: newEnvironment(io), + environment: newEnvironment(io, clientFunc), } } diff --git a/internals/secrethub/env_read.go b/internals/secrethub/env_read.go index 028b2f69..af216e25 100644 --- a/internals/secrethub/env_read.go +++ b/internals/secrethub/env_read.go @@ -20,7 +20,7 @@ func NewEnvReadCommand(io ui.IO, newClient newClientFunc) *EnvReadCommand { return &EnvReadCommand{ io: io, newClient: newClient, - environment: newEnvironment(io), + environment: newEnvironment(io, newClient), } } diff --git a/internals/secrethub/run.go b/internals/secrethub/run.go index 939726f4..db770e20 100644 --- a/internals/secrethub/run.go +++ b/internals/secrethub/run.go @@ -63,7 +63,7 @@ func NewRunCommand(io ui.IO, newClient newClientFunc) *RunCommand { return &RunCommand{ io: io, osEnv: os.Environ(), - environment: newEnvironment(io), + environment: newEnvironment(io, newClient), newClient: newClient, } } From c6640ad1a066bbb5002ddadd7ef50b5beff11c44 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 30 Jun 2020 14:25:43 +0200 Subject: [PATCH 03/70] Implement --secrets-dir flag --- internals/secrethub/env_source.go | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 9f0f4495..63bd7acd 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -33,6 +33,7 @@ type environment struct { templateVars map[string]string templateVersion string dontPromptMissingTemplateVar bool + secretsDir string secretsEnvDir string } @@ -55,6 +56,7 @@ func (env *environment) register(clause *cli.CommandClause) { clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&env.templateVars) clause.Flag("template-version", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.").Default("auto").StringVar(&env.templateVersion) clause.Flag("no-prompt", "Do not prompt when a template variable is missing and return an error instead.").BoolVar(&env.dontPromptMissingTemplateVar) + clause.Flag("secrets-dir", "Path to a directory from which to inject all secrets. The environment variable storing each secret will be the secret's uppercase relative path with '_' instead of the path delimiter.").StringVar(&env.secretsDir) clause.Flag("env", "The name of the environment prepared by the set command (default is `default`)").Default("default").Hidden().StringVar(&env.secretsEnvDir) } @@ -118,6 +120,12 @@ func (env *environment) env() (map[string]value, error) { referenceEnv := newReferenceEnv(osEnvMap) sources = append(sources, referenceEnv) + // --secrets-dir flag + if env.secretsDir != "" { + secretsDirEnv := newSecretsDirEnv(env.newClient, env.secretsDir) + sources = append(sources, secretsDirEnv) + } + // --envar flag // TODO: Validate the flags when parsing by implementing the Flag interface for EnvFlags. flagEnv, err := NewEnvFlags(env.envar) @@ -175,6 +183,44 @@ func newSecretValue(path string) value { return &secretValue{path: path} } +type secretsDirEnv struct { + clientFunc newClientFunc + dirPath string +} + +func (s *secretsDirEnv) env() (map[string]value, error) { + client, err := s.clientFunc() + if err != nil { + return nil, err + } + + tree, err := client.Dirs().GetTree(s.dirPath, -1, false) + if err != nil { + return nil, err + } + + result := make(map[string]value, tree.SecretCount()) + for id := range tree.Secrets { + path, err := tree.AbsSecretPath(id) + if err != nil { + return nil, err + } + envVarName := strings.TrimPrefix(path.String(), s.dirPath) + envVarName = strings.TrimPrefix(envVarName, "/") + envVarName = strings.ReplaceAll(envVarName, "/", "_") + envVarName = strings.ToUpper(envVarName) + result[envVarName] = newSecretValue(path.String()) + } + return result, nil +} + +func newSecretsDirEnv(clientFunc newClientFunc, dirPath string) *secretsDirEnv { + return &secretsDirEnv{ + clientFunc: clientFunc, + dirPath: dirPath, + } +} + // EnvFlags defines environment variables sourced from command-line flags. type EnvFlags map[string]string From 65b3c07ecabe26e2eda01a0aa59848b6d7258b52 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 30 Jun 2020 14:43:04 +0200 Subject: [PATCH 04/70] Implement error in case of environment variable name collision when sourcing with --secrets-dir --- internals/secrethub/env_source.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 63bd7acd..aefb3f55 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "errors" + "fmt" "io" "io/ioutil" "os" @@ -199,7 +200,7 @@ func (s *secretsDirEnv) env() (map[string]value, error) { return nil, err } - result := make(map[string]value, tree.SecretCount()) + paths := make(map[string]string, tree.SecretCount()) for id := range tree.Secrets { path, err := tree.AbsSecretPath(id) if err != nil { @@ -209,7 +210,15 @@ func (s *secretsDirEnv) env() (map[string]value, error) { envVarName = strings.TrimPrefix(envVarName, "/") envVarName = strings.ReplaceAll(envVarName, "/", "_") envVarName = strings.ToUpper(envVarName) - result[envVarName] = newSecretValue(path.String()) + if prevPath, found := paths[envVarName]; found { + return nil, fmt.Errorf("secrets at path %s and %s map to the same environment variable: %s. Rename one of the secrets or source them in a different way", prevPath, path, envVarName) + } + paths[envVarName] = path.String() + } + + result := make(map[string]value, tree.SecretCount()) + for name, path := range paths { + result[name] = newSecretValue(path) } return result, nil } From aef4c80d310e7f871fd9c9b0db230b4a438b5ca6 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 30 Jun 2020 15:25:37 +0200 Subject: [PATCH 05/70] Test auto-splat and make custom error struct for name collision error --- internals/secrethub/env_source.go | 16 +++- internals/secrethub/env_source_test.go | 117 +++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 internals/secrethub/env_source_test.go diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index aefb3f55..9d8c5406 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -23,6 +23,16 @@ import ( "gopkg.in/yaml.v2" ) +type errNameCollision struct { + name string + firstPath string + secondPath string +} + +func (e errNameCollision) Error() string { + return fmt.Sprintf("secrets at path %s and %s map to the same environment variable: %s. Rename one of the secrets or source them in a different way", e.firstPath, e.secondPath, e.name) +} + type environment struct { io ui.IO newClient newClientFunc @@ -211,7 +221,11 @@ func (s *secretsDirEnv) env() (map[string]value, error) { envVarName = strings.ReplaceAll(envVarName, "/", "_") envVarName = strings.ToUpper(envVarName) if prevPath, found := paths[envVarName]; found { - return nil, fmt.Errorf("secrets at path %s and %s map to the same environment variable: %s. Rename one of the secrets or source them in a different way", prevPath, path, envVarName) + return nil, errNameCollision{ + name: envVarName, + firstPath: prevPath, + secondPath: path.String(), + } } paths[envVarName] = path.String() } diff --git a/internals/secrethub/env_source_test.go b/internals/secrethub/env_source_test.go new file mode 100644 index 00000000..5f54f439 --- /dev/null +++ b/internals/secrethub/env_source_test.go @@ -0,0 +1,117 @@ +package secrethub + +import ( + "testing" + + "github.com/secrethub/secrethub-go/internals/api" + "github.com/secrethub/secrethub-go/internals/api/uuid" + "github.com/secrethub/secrethub-go/internals/assert" + "github.com/secrethub/secrethub-go/pkg/secrethub" + "github.com/secrethub/secrethub-go/pkg/secrethub/fakeclient" +) + +func TestSecretsDirEnv(t *testing.T) { + const dirPath = "namespace/repo" + testUUID1 := uuid.New() + testUUID2 := uuid.New() + testUUID3 := uuid.New() + testUUID4 := uuid.New() + + cases := map[string]struct { + clientFunc newClientFunc + expectedValues []string + err error + }{ + "success": { + clientFunc: func() (secrethub.ClientInterface, error) { + return fakeclient.Client{ + DirService: &fakeclient.DirService{ + GetTreeFunc: func(path string, depth int, ancestors bool) (*api.Tree, error) { + return &api.Tree{ + ParentPath: "namespace", + RootDir: &api.Dir{ + DirID: testUUID1, + Name: "repo", + }, + Dirs: map[uuid.UUID]*api.Dir{ + testUUID2: { + DirID: testUUID2, + ParentID: &testUUID1, + Name: "foo", + }, + }, + Secrets: map[uuid.UUID]*api.Secret{ + testUUID3: { + SecretID: testUUID3, + DirID: testUUID2, + Name: "bar", + }, + }, + }, nil + }, + }, + }, nil + }, + expectedValues: []string{"FOO_BAR"}, + }, + "name collision": { + clientFunc: func() (secrethub.ClientInterface, error) { + return fakeclient.Client{ + DirService: &fakeclient.DirService{ + GetTreeFunc: func(path string, depth int, ancestors bool) (*api.Tree, error) { + return &api.Tree{ + ParentPath: "namespace", + RootDir: &api.Dir{ + DirID: testUUID1, + Name: "repo", + }, + Dirs: map[uuid.UUID]*api.Dir{ + testUUID2: { + DirID: testUUID2, + ParentID: &testUUID1, + Name: "foo", + }, + }, + Secrets: map[uuid.UUID]*api.Secret{ + testUUID3: { + SecretID: testUUID3, + DirID: testUUID2, + Name: "bar", + }, + testUUID4: { + SecretID: testUUID4, + DirID: testUUID1, + Name: "foo_bar", + }, + }, + }, nil + }, + }, + }, nil + }, + err: errNameCollision{ + name: "FOO_BAR", + firstPath: "namespace/repo/foo/bar", + secondPath: "namespace/repo/foo_bar", + }, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + source := newSecretsDirEnv(tc.clientFunc, dirPath) + secrets, err := source.env() + if tc.err != nil && err != nil { + assert.Equal(t, err, tc.err) + } else { + assert.OK(t, err) + assert.Equal(t, len(secrets), len(tc.expectedValues)) + for _, name := range tc.expectedValues { + if _, ok := secrets[name]; !ok { + t.Errorf("expected but not found env var with name: %s", name) + } + } + } + }) + } +} From 3aec7f4cc0a9d0057c5d6faffbc60859426c3341 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 30 Jun 2020 15:31:25 +0200 Subject: [PATCH 06/70] Refactor secrets dir env var sourcing --- internals/secrethub/env_source.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 9d8c5406..0695dc24 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -212,22 +212,21 @@ func (s *secretsDirEnv) env() (map[string]value, error) { paths := make(map[string]string, tree.SecretCount()) for id := range tree.Secrets { - path, err := tree.AbsSecretPath(id) + secretPath, err := tree.AbsSecretPath(id) if err != nil { return nil, err } - envVarName := strings.TrimPrefix(path.String(), s.dirPath) - envVarName = strings.TrimPrefix(envVarName, "/") - envVarName = strings.ReplaceAll(envVarName, "/", "_") - envVarName = strings.ToUpper(envVarName) + path := secretPath.String() + + envVarName := s.envVarName(path) if prevPath, found := paths[envVarName]; found { return nil, errNameCollision{ name: envVarName, firstPath: prevPath, - secondPath: path.String(), + secondPath: path, } } - paths[envVarName] = path.String() + paths[envVarName] = path } result := make(map[string]value, tree.SecretCount()) @@ -237,6 +236,14 @@ func (s *secretsDirEnv) env() (map[string]value, error) { return result, nil } +func (s *secretsDirEnv) envVarName(path string) string { + envVarName := strings.TrimPrefix(path, s.dirPath) + envVarName = strings.TrimPrefix(envVarName, "/") + envVarName = strings.ReplaceAll(envVarName, "/", "_") + envVarName = strings.ToUpper(envVarName) + return envVarName +} + func newSecretsDirEnv(clientFunc newClientFunc, dirPath string) *secretsDirEnv { return &secretsDirEnv{ clientFunc: clientFunc, From ab8f8e88fab8561a182cb190a104194d3787bd12 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 30 Jun 2020 15:31:48 +0200 Subject: [PATCH 07/70] Fix error checking in test --- internals/secrethub/env_source_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/env_source_test.go b/internals/secrethub/env_source_test.go index 5f54f439..33577cf2 100644 --- a/internals/secrethub/env_source_test.go +++ b/internals/secrethub/env_source_test.go @@ -101,7 +101,7 @@ func TestSecretsDirEnv(t *testing.T) { t.Run(name, func(t *testing.T) { source := newSecretsDirEnv(tc.clientFunc, dirPath) secrets, err := source.env() - if tc.err != nil && err != nil { + if tc.err != nil { assert.Equal(t, err, tc.err) } else { assert.OK(t, err) From 313e3a81cb8f8856d788e8311bed163d3e874dbd Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 30 Jun 2020 15:58:34 +0200 Subject: [PATCH 08/70] Add precedence test for --secrets-dir and simpler test case for --secrets-dir --- internals/secrethub/env_source_test.go | 25 ++++++++++++ internals/secrethub/run_test.go | 56 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/internals/secrethub/env_source_test.go b/internals/secrethub/env_source_test.go index 33577cf2..0dce4bb1 100644 --- a/internals/secrethub/env_source_test.go +++ b/internals/secrethub/env_source_test.go @@ -23,6 +23,31 @@ func TestSecretsDirEnv(t *testing.T) { err error }{ "success": { + clientFunc: func() (secrethub.ClientInterface, error) { + return fakeclient.Client{ + DirService: &fakeclient.DirService{ + GetTreeFunc: func(path string, depth int, ancestors bool) (*api.Tree, error) { + return &api.Tree{ + ParentPath: "namespace", + RootDir: &api.Dir{ + DirID: testUUID1, + Name: "repo", + }, + Secrets: map[uuid.UUID]*api.Secret{ + testUUID2: { + SecretID: testUUID2, + DirID: testUUID1, + Name: "foo", + }, + }, + }, nil + }, + }, + }, nil + }, + expectedValues: []string{"FOO"}, + }, + "success secret in dir": { clientFunc: func() (secrethub.ClientInterface, error) { return fakeclient.Client{ DirService: &fakeclient.DirService{ diff --git a/internals/secrethub/run_test.go b/internals/secrethub/run_test.go index fb6d4295..8113aef6 100644 --- a/internals/secrethub/run_test.go +++ b/internals/secrethub/run_test.go @@ -10,6 +10,8 @@ import ( "strings" "testing" + "github.com/secrethub/secrethub-go/internals/api/uuid" + "github.com/secrethub/secrethub-cli/internals/cli/ui/fakeui" "github.com/secrethub/secrethub-cli/internals/secrethub/tpl" @@ -657,6 +659,9 @@ func osStatFunc(name string, err error) func(string) (os.FileInfo, error) { } func TestRunCommand_environment(t *testing.T) { + testUUID1 := uuid.New() + testUUID2 := uuid.New() + cases := map[string]struct { command RunCommand expectedEnv []string @@ -765,6 +770,57 @@ func TestRunCommand_environment(t *testing.T) { expectedEnv: []string{"TEST=bbb"}, }, // TODO Add test case for: envar flag has precedence over secret reference - requires refactoring of fakeclient + "secrets-dir flag has precedence over secret reference": { + command: RunCommand{ + environment: &environment{ + newClient: func() (secrethub.ClientInterface, error) { + return fakeclient.Client{ + DirService: &fakeclient.DirService{ + GetTreeFunc: func(path string, depth int, ancestors bool) (*api.Tree, error) { + return &api.Tree{ + ParentPath: "namespace", + RootDir: &api.Dir{ + DirID: testUUID1, + Name: "repo", + }, + Secrets: map[uuid.UUID]*api.Secret{ + testUUID2: { + SecretID: testUUID2, + DirID: testUUID1, + Name: "foo", + }, + }, + }, nil + }, + }, + }, nil + }, + secretsDir: "namespace/repo", + dontPromptMissingTemplateVar: true, + templateVersion: "2", + osEnv: []string{"FOO=secrethub://test/test/test"}, + osStat: osStatFunc("secrethub.env", os.ErrNotExist), + }, + newClient: func() (secrethub.ClientInterface, error) { + return fakeclient.Client{ + SecretService: &fakeclient.SecretService{ + VersionService: &fakeclient.SecretVersionService{ + GetWithDataFunc: func(path string) (*api.SecretVersion, error) { + if path == "test/test/test" { + return &api.SecretVersion{Data: []byte("bbb")}, nil + } else if path == "namespace/repo/foo" { + return &api.SecretVersion{Data: []byte("aaa")}, nil + } + return nil, api.ErrSecretNotFound + }, + }, + }, + }, nil + }, + }, + expectedSecrets: []string{"aaa"}, + expectedEnv: []string{"FOO=aaa"}, + }, "secret reference has precedence over .env file": { command: RunCommand{ environment: &environment{ From b20ea96a059e8fe8f7bc8b868662f4d3170968c1 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 30 Jun 2020 16:12:58 +0200 Subject: [PATCH 09/70] Add comments --- internals/secrethub/env_source.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 0695dc24..4b438118 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -194,11 +194,15 @@ func newSecretValue(path string) value { return &secretValue{path: path} } +// secretsDirEnv sources environment variables from the directory specified with the --secrets-dir flag. type secretsDirEnv struct { clientFunc newClientFunc dirPath string } +// env returns a map of environment variables containing all secrets from the specified path. +// The variable names are the relative paths of their corresponding secrets in uppercase snake case. +// An error is returned if two secret paths map to the same variable name. func (s *secretsDirEnv) env() (map[string]value, error) { client, err := s.clientFunc() if err != nil { @@ -236,6 +240,8 @@ func (s *secretsDirEnv) env() (map[string]value, error) { return result, nil } +// envVarName returns the environment variable name corresponding to the secret on the specified path +// by converting the relative path to uppercase snake case. func (s *secretsDirEnv) envVarName(path string) string { envVarName := strings.TrimPrefix(path, s.dirPath) envVarName = strings.TrimPrefix(envVarName, "/") From 92d1e17c3249c77de3b1a0f1088edf546c049e4b Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Mon, 6 Jul 2020 10:23:09 +0200 Subject: [PATCH 10/70] Rename clientFunc -> newClient --- internals/secrethub/env_ls.go | 4 ++-- internals/secrethub/env_source.go | 12 ++++++------ internals/secrethub/env_source_test.go | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/internals/secrethub/env_ls.go b/internals/secrethub/env_ls.go index 9f811c5f..c1cac212 100644 --- a/internals/secrethub/env_ls.go +++ b/internals/secrethub/env_ls.go @@ -14,10 +14,10 @@ type EnvListCommand struct { } // NewEnvListCommand creates a new EnvListCommand. -func NewEnvListCommand(io ui.IO, clientFunc newClientFunc) *EnvListCommand { +func NewEnvListCommand(io ui.IO, newClient newClientFunc) *EnvListCommand { return &EnvListCommand{ io: io, - environment: newEnvironment(io, clientFunc), + environment: newEnvironment(io, newClient), } } diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 4b438118..be974629 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -196,15 +196,15 @@ func newSecretValue(path string) value { // secretsDirEnv sources environment variables from the directory specified with the --secrets-dir flag. type secretsDirEnv struct { - clientFunc newClientFunc - dirPath string + newClient newClientFunc + dirPath string } // env returns a map of environment variables containing all secrets from the specified path. // The variable names are the relative paths of their corresponding secrets in uppercase snake case. // An error is returned if two secret paths map to the same variable name. func (s *secretsDirEnv) env() (map[string]value, error) { - client, err := s.clientFunc() + client, err := s.newClient() if err != nil { return nil, err } @@ -250,10 +250,10 @@ func (s *secretsDirEnv) envVarName(path string) string { return envVarName } -func newSecretsDirEnv(clientFunc newClientFunc, dirPath string) *secretsDirEnv { +func newSecretsDirEnv(newClient newClientFunc, dirPath string) *secretsDirEnv { return &secretsDirEnv{ - clientFunc: clientFunc, - dirPath: dirPath, + newClient: newClient, + dirPath: dirPath, } } diff --git a/internals/secrethub/env_source_test.go b/internals/secrethub/env_source_test.go index 0dce4bb1..915e5b09 100644 --- a/internals/secrethub/env_source_test.go +++ b/internals/secrethub/env_source_test.go @@ -18,12 +18,12 @@ func TestSecretsDirEnv(t *testing.T) { testUUID4 := uuid.New() cases := map[string]struct { - clientFunc newClientFunc + newClient newClientFunc expectedValues []string err error }{ "success": { - clientFunc: func() (secrethub.ClientInterface, error) { + newClient: func() (secrethub.ClientInterface, error) { return fakeclient.Client{ DirService: &fakeclient.DirService{ GetTreeFunc: func(path string, depth int, ancestors bool) (*api.Tree, error) { @@ -48,7 +48,7 @@ func TestSecretsDirEnv(t *testing.T) { expectedValues: []string{"FOO"}, }, "success secret in dir": { - clientFunc: func() (secrethub.ClientInterface, error) { + newClient: func() (secrethub.ClientInterface, error) { return fakeclient.Client{ DirService: &fakeclient.DirService{ GetTreeFunc: func(path string, depth int, ancestors bool) (*api.Tree, error) { @@ -80,7 +80,7 @@ func TestSecretsDirEnv(t *testing.T) { expectedValues: []string{"FOO_BAR"}, }, "name collision": { - clientFunc: func() (secrethub.ClientInterface, error) { + newClient: func() (secrethub.ClientInterface, error) { return fakeclient.Client{ DirService: &fakeclient.DirService{ GetTreeFunc: func(path string, depth int, ancestors bool) (*api.Tree, error) { @@ -124,7 +124,7 @@ func TestSecretsDirEnv(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { - source := newSecretsDirEnv(tc.clientFunc, dirPath) + source := newSecretsDirEnv(tc.newClient, dirPath) secrets, err := source.env() if tc.err != nil { assert.Equal(t, err, tc.err) From ed273f9f2a64395db6c54946d5228a27748cfe10 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Mon, 6 Jul 2020 10:25:06 +0200 Subject: [PATCH 11/70] Update --secrets-dir description Co-authored-by: Simon Barendse --- internals/secrethub/env_source.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index be974629..5139519d 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -67,7 +67,7 @@ func (env *environment) register(clause *cli.CommandClause) { clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&env.templateVars) clause.Flag("template-version", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.").Default("auto").StringVar(&env.templateVersion) clause.Flag("no-prompt", "Do not prompt when a template variable is missing and return an error instead.").BoolVar(&env.dontPromptMissingTemplateVar) - clause.Flag("secrets-dir", "Path to a directory from which to inject all secrets. The environment variable storing each secret will be the secret's uppercase relative path with '_' instead of the path delimiter.").StringVar(&env.secretsDir) + clause.Flag("secrets-dir", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.").StringVar(&env.secretsDir) clause.Flag("env", "The name of the environment prepared by the set command (default is `default`)").Default("default").Hidden().StringVar(&env.secretsEnvDir) } From 9ef11e190d6b1d9545c5dab8781ce16e9699c729 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Mon, 6 Jul 2020 10:25:33 +0200 Subject: [PATCH 12/70] Update internals/secrethub/env_source.go Co-authored-by: Simon Barendse --- internals/secrethub/env_source.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 5139519d..aa9551da 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -233,7 +233,7 @@ func (s *secretsDirEnv) env() (map[string]value, error) { paths[envVarName] = path } - result := make(map[string]value, tree.SecretCount()) + result := make(map[string]value, len(paths)) for name, path := range paths { result[name] = newSecretValue(path) } From 5cc73a36727d1358fd361669a18d1007985635cc Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Mon, 6 Jul 2020 10:34:37 +0200 Subject: [PATCH 13/70] Rename UUIDs in test --- internals/secrethub/env_source_test.go | 50 +++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/internals/secrethub/env_source_test.go b/internals/secrethub/env_source_test.go index 915e5b09..a6ecad93 100644 --- a/internals/secrethub/env_source_test.go +++ b/internals/secrethub/env_source_test.go @@ -12,10 +12,10 @@ import ( func TestSecretsDirEnv(t *testing.T) { const dirPath = "namespace/repo" - testUUID1 := uuid.New() - testUUID2 := uuid.New() - testUUID3 := uuid.New() - testUUID4 := uuid.New() + rootDirUUID := uuid.New() + subDirUUID := uuid.New() + secretUUID1 := uuid.New() + secretUUID2 := uuid.New() cases := map[string]struct { newClient newClientFunc @@ -30,13 +30,13 @@ func TestSecretsDirEnv(t *testing.T) { return &api.Tree{ ParentPath: "namespace", RootDir: &api.Dir{ - DirID: testUUID1, + DirID: rootDirUUID, Name: "repo", }, Secrets: map[uuid.UUID]*api.Secret{ - testUUID2: { - SecretID: testUUID2, - DirID: testUUID1, + secretUUID1: { + SecretID: secretUUID1, + DirID: rootDirUUID, Name: "foo", }, }, @@ -55,20 +55,20 @@ func TestSecretsDirEnv(t *testing.T) { return &api.Tree{ ParentPath: "namespace", RootDir: &api.Dir{ - DirID: testUUID1, + DirID: rootDirUUID, Name: "repo", }, Dirs: map[uuid.UUID]*api.Dir{ - testUUID2: { - DirID: testUUID2, - ParentID: &testUUID1, + subDirUUID: { + DirID: subDirUUID, + ParentID: &rootDirUUID, Name: "foo", }, }, Secrets: map[uuid.UUID]*api.Secret{ - testUUID3: { - SecretID: testUUID3, - DirID: testUUID2, + secretUUID1: { + SecretID: secretUUID1, + DirID: subDirUUID, Name: "bar", }, }, @@ -87,25 +87,25 @@ func TestSecretsDirEnv(t *testing.T) { return &api.Tree{ ParentPath: "namespace", RootDir: &api.Dir{ - DirID: testUUID1, + DirID: rootDirUUID, Name: "repo", }, Dirs: map[uuid.UUID]*api.Dir{ - testUUID2: { - DirID: testUUID2, - ParentID: &testUUID1, + subDirUUID: { + DirID: subDirUUID, + ParentID: &rootDirUUID, Name: "foo", }, }, Secrets: map[uuid.UUID]*api.Secret{ - testUUID3: { - SecretID: testUUID3, - DirID: testUUID2, + secretUUID1: { + SecretID: secretUUID1, + DirID: subDirUUID, Name: "bar", }, - testUUID4: { - SecretID: testUUID4, - DirID: testUUID1, + secretUUID2: { + SecretID: secretUUID2, + DirID: rootDirUUID, Name: "foo_bar", }, }, From 0345d6a6903bf17cd212b4a1fcf1b76d8619219f Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Mon, 6 Jul 2020 10:42:37 +0200 Subject: [PATCH 14/70] Change precedence of --secrets-dir flag --- internals/secrethub/env_source.go | 12 ++++++------ internals/secrethub/run_test.go | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index aa9551da..242d4f59 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -90,6 +90,12 @@ func (env *environment) env() (map[string]value, error) { sources = append(sources, dirSource) } + // --secrets-dir flag + if env.secretsDir != "" { + secretsDirEnv := newSecretsDirEnv(env.newClient, env.secretsDir) + sources = append(sources, secretsDirEnv) + } + //secrethub.env file if env.envFile == "" { _, err := env.osStat(defaultEnvFile) @@ -131,12 +137,6 @@ func (env *environment) env() (map[string]value, error) { referenceEnv := newReferenceEnv(osEnvMap) sources = append(sources, referenceEnv) - // --secrets-dir flag - if env.secretsDir != "" { - secretsDirEnv := newSecretsDirEnv(env.newClient, env.secretsDir) - sources = append(sources, secretsDirEnv) - } - // --envar flag // TODO: Validate the flags when parsing by implementing the Flag interface for EnvFlags. flagEnv, err := NewEnvFlags(env.envar) diff --git a/internals/secrethub/run_test.go b/internals/secrethub/run_test.go index 8113aef6..3618ce5c 100644 --- a/internals/secrethub/run_test.go +++ b/internals/secrethub/run_test.go @@ -770,7 +770,7 @@ func TestRunCommand_environment(t *testing.T) { expectedEnv: []string{"TEST=bbb"}, }, // TODO Add test case for: envar flag has precedence over secret reference - requires refactoring of fakeclient - "secrets-dir flag has precedence over secret reference": { + "secret reference has precedence over secrets-dir flag": { command: RunCommand{ environment: &environment{ newClient: func() (secrethub.ClientInterface, error) { @@ -818,8 +818,8 @@ func TestRunCommand_environment(t *testing.T) { }, nil }, }, - expectedSecrets: []string{"aaa"}, - expectedEnv: []string{"FOO=aaa"}, + expectedSecrets: []string{"bbb"}, + expectedEnv: []string{"FOO=bbb"}, }, "secret reference has precedence over .env file": { command: RunCommand{ From dfa86e5015f95af57d5b1c4ed2588d16c97806d9 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Mon, 6 Jul 2020 12:06:37 +0200 Subject: [PATCH 15/70] Add tests for new precedence rules Added a test for checking that --secrets-dir has precedence over the os environment and a tests for checking that .env files have precedence over secrets loaded with --secrets-dir. --- internals/secrethub/run_test.go | 101 ++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/internals/secrethub/run_test.go b/internals/secrethub/run_test.go index 3618ce5c..a2925e95 100644 --- a/internals/secrethub/run_test.go +++ b/internals/secrethub/run_test.go @@ -769,6 +769,107 @@ func TestRunCommand_environment(t *testing.T) { expectedSecrets: []string{"bbb"}, expectedEnv: []string{"TEST=bbb"}, }, + "env file has precedence over secrets-dir flag": { + command: RunCommand{ + environment: &environment{ + newClient: func() (secrethub.ClientInterface, error) { + return fakeclient.Client{ + DirService: &fakeclient.DirService{ + GetTreeFunc: func(path string, depth int, ancestors bool) (*api.Tree, error) { + return &api.Tree{ + ParentPath: "namespace", + RootDir: &api.Dir{ + DirID: testUUID1, + Name: "repo", + }, + Secrets: map[uuid.UUID]*api.Secret{ + testUUID2: { + SecretID: testUUID2, + DirID: testUUID1, + Name: "foo", + }, + }, + }, nil + }, + }, + }, nil + }, + secretsDir: "namespace/repo", + dontPromptMissingTemplateVar: true, + templateVersion: "2", + osEnv: []string{"FOO=bbb"}, + osStat: osStatFunc("secrethub.env", nil), + readFile: readFileFunc("secrethub.env", "FOO= {{ other/secret/path }}"), + }, + newClient: func() (secrethub.ClientInterface, error) { + return fakeclient.Client{ + SecretService: &fakeclient.SecretService{ + VersionService: &fakeclient.SecretVersionService{ + GetWithDataFunc: func(path string) (*api.SecretVersion, error) { + if path == "namespace/repo/foo" { + return &api.SecretVersion{Data: []byte("aaa")}, nil + } else if path == "other/secret/path" { + return &api.SecretVersion{Data: []byte("bbb")}, nil + } + return nil, api.ErrSecretNotFound + }, + }, + }, + }, nil + }, + }, + expectedSecrets: []string{"bbb"}, + expectedEnv: []string{"FOO=bbb"}, + }, + "secrets-dir flag has precedence over os environment": { + command: RunCommand{ + environment: &environment{ + newClient: func() (secrethub.ClientInterface, error) { + return fakeclient.Client{ + DirService: &fakeclient.DirService{ + GetTreeFunc: func(path string, depth int, ancestors bool) (*api.Tree, error) { + return &api.Tree{ + ParentPath: "namespace", + RootDir: &api.Dir{ + DirID: testUUID1, + Name: "repo", + }, + Secrets: map[uuid.UUID]*api.Secret{ + testUUID2: { + SecretID: testUUID2, + DirID: testUUID1, + Name: "foo", + }, + }, + }, nil + }, + }, + }, nil + }, + secretsDir: "namespace/repo", + dontPromptMissingTemplateVar: true, + templateVersion: "2", + osEnv: []string{"FOO=bbb"}, + osStat: osStatFunc("secrethub.env", os.ErrNotExist), + }, + newClient: func() (secrethub.ClientInterface, error) { + return fakeclient.Client{ + SecretService: &fakeclient.SecretService{ + VersionService: &fakeclient.SecretVersionService{ + GetWithDataFunc: func(path string) (*api.SecretVersion, error) { + if path == "namespace/repo/foo" { + return &api.SecretVersion{Data: []byte("aaa")}, nil + } + return nil, api.ErrSecretNotFound + }, + }, + }, + }, nil + }, + }, + expectedSecrets: []string{"aaa"}, + expectedEnv: []string{"FOO=aaa"}, + }, // TODO Add test case for: envar flag has precedence over secret reference - requires refactoring of fakeclient "secret reference has precedence over secrets-dir flag": { command: RunCommand{ From 42aaa374006ba5987821b31d95ea3bbb9e09a33b Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Mon, 6 Jul 2020 12:10:43 +0200 Subject: [PATCH 16/70] Improve naming of UUIDs in run_test.go --- internals/secrethub/run_test.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/internals/secrethub/run_test.go b/internals/secrethub/run_test.go index a2925e95..f4182706 100644 --- a/internals/secrethub/run_test.go +++ b/internals/secrethub/run_test.go @@ -659,8 +659,8 @@ func osStatFunc(name string, err error) func(string) (os.FileInfo, error) { } func TestRunCommand_environment(t *testing.T) { - testUUID1 := uuid.New() - testUUID2 := uuid.New() + rootDirUUID := uuid.New() + secretUUID := uuid.New() cases := map[string]struct { command RunCommand @@ -779,13 +779,13 @@ func TestRunCommand_environment(t *testing.T) { return &api.Tree{ ParentPath: "namespace", RootDir: &api.Dir{ - DirID: testUUID1, + DirID: rootDirUUID, Name: "repo", }, Secrets: map[uuid.UUID]*api.Secret{ - testUUID2: { - SecretID: testUUID2, - DirID: testUUID1, + secretUUID: { + SecretID: secretUUID, + DirID: rootDirUUID, Name: "foo", }, }, @@ -831,13 +831,13 @@ func TestRunCommand_environment(t *testing.T) { return &api.Tree{ ParentPath: "namespace", RootDir: &api.Dir{ - DirID: testUUID1, + DirID: rootDirUUID, Name: "repo", }, Secrets: map[uuid.UUID]*api.Secret{ - testUUID2: { - SecretID: testUUID2, - DirID: testUUID1, + secretUUID: { + SecretID: secretUUID, + DirID: rootDirUUID, Name: "foo", }, }, @@ -881,13 +881,13 @@ func TestRunCommand_environment(t *testing.T) { return &api.Tree{ ParentPath: "namespace", RootDir: &api.Dir{ - DirID: testUUID1, + DirID: rootDirUUID, Name: "repo", }, Secrets: map[uuid.UUID]*api.Secret{ - testUUID2: { - SecretID: testUUID2, - DirID: testUUID1, + secretUUID: { + SecretID: secretUUID, + DirID: rootDirUUID, Name: "foo", }, }, From 722cb64bee77e115fdabf6cfdfb2c550a429d680 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Mon, 6 Jul 2020 12:31:04 +0200 Subject: [PATCH 17/70] Fix linter error --- internals/secrethub/run_test.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/internals/secrethub/run_test.go b/internals/secrethub/run_test.go index f4182706..87ed68a0 100644 --- a/internals/secrethub/run_test.go +++ b/internals/secrethub/run_test.go @@ -662,6 +662,8 @@ func TestRunCommand_environment(t *testing.T) { rootDirUUID := uuid.New() secretUUID := uuid.New() + const secretPathFoo = "namespace/repo/foo" + cases := map[string]struct { command RunCommand expectedEnv []string @@ -806,7 +808,7 @@ func TestRunCommand_environment(t *testing.T) { SecretService: &fakeclient.SecretService{ VersionService: &fakeclient.SecretVersionService{ GetWithDataFunc: func(path string) (*api.SecretVersion, error) { - if path == "namespace/repo/foo" { + if path == secretPathFoo { return &api.SecretVersion{Data: []byte("aaa")}, nil } else if path == "other/secret/path" { return &api.SecretVersion{Data: []byte("bbb")}, nil @@ -857,7 +859,7 @@ func TestRunCommand_environment(t *testing.T) { SecretService: &fakeclient.SecretService{ VersionService: &fakeclient.SecretVersionService{ GetWithDataFunc: func(path string) (*api.SecretVersion, error) { - if path == "namespace/repo/foo" { + if path == secretPathFoo { return &api.SecretVersion{Data: []byte("aaa")}, nil } return nil, api.ErrSecretNotFound @@ -909,7 +911,7 @@ func TestRunCommand_environment(t *testing.T) { GetWithDataFunc: func(path string) (*api.SecretVersion, error) { if path == "test/test/test" { return &api.SecretVersion{Data: []byte("bbb")}, nil - } else if path == "namespace/repo/foo" { + } else if path == secretPathFoo { return &api.SecretVersion{Data: []byte("aaa")}, nil } return nil, api.ErrSecretNotFound From 76c35e2c76deaa53335faedbb99b9c74b922dc46 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Mon, 20 Jul 2020 13:47:26 +0300 Subject: [PATCH 18/70] added variables for flags --- internals/secrethub/tree.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 3fd756c3..418578fc 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -13,9 +13,12 @@ import ( // TreeCommand lists the contents of a directory at a given path in a tree-like format. type TreeCommand struct { - path api.DirPath - io ui.IO - newClient newClientFunc + path api.DirPath + io ui.IO + fullPaths bool + noIndentation bool + noReport bool + newClient newClientFunc } // NewTreeCommand creates a new TreeCommand. From d5d5fce307af1eaa45c20b96fad68105579adbc6 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Mon, 20 Jul 2020 14:33:49 +0300 Subject: [PATCH 19/70] First version of tree flags --- internals/secrethub/tree.go | 50 +++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 418578fc..077e7259 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -41,7 +41,7 @@ func (cmd *TreeCommand) Run() error { return err } - printTree(t, cmd.io.Output()) + cmd.printTree(t, cmd.io.Output()) return nil } @@ -50,26 +50,44 @@ func (cmd *TreeCommand) Register(r command.Registerer) { clause := r.Command("tree", "List contents of a directory in a tree-like format.") clause.Arg("dir-path", "The path to to show contents for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) + clause.Flag("full-paths", "Print the full paths of the directories and secrets.").Short('f').BoolVar(&cmd.fullPaths) + clause.Flag("no-indentation", "Print the content without indentation.").Short('i').BoolVar(&cmd.noIndentation) + clause.Flag("no-report", "Skip the report at the bottom.").BoolVar(&cmd.noReport) + command.BindAction(clause, cmd.Run) } // printTree recursively prints the tree's contents in a tree-like structure. -func printTree(t *api.Tree, w io.Writer) { +func (cmd *TreeCommand) printTree(t *api.Tree, w io.Writer) { name := colorizeByStatus(t.RootDir.Status, t.RootDir.Name) fmt.Fprintf(w, "%s/\n", name) - printDirContentsRecursively(t.RootDir, "", w) - - fmt.Fprintf(w, - "\n%s, %s\n", - pluralize("directory", "directories", t.DirCount()), - pluralize("secret", "secrets", t.SecretCount()), - ) + var format [4]string + if cmd.noIndentation { + format[0] = "%s%s/\n" + format[1] = "%s%s/\n" + format[2] = "" + format[3] = "" + } else { + format[0] = "%s└── %s/\n" + format[1] = "%s├── %s/\n" + format[2] = " " + format[3] = "│ " + } + printDirContentsRecursively(t.RootDir, "", w, format) + + if !cmd.noReport { + fmt.Fprintf(w, + "\n%s, %s\n", + pluralize("directory", "directories", t.DirCount()), + pluralize("secret", "secrets", t.SecretCount()), + ) + } } // printDirContentsRecursively is a recursive function that prints the directory's contents // in a tree-like structure, subdirs first followed by secrets. -func printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer) { +func printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer, format [4]string) { sort.Sort(api.SortDirByName(dir.SubDirs)) sort.Sort(api.SortSecretByName(dir.Secrets)) @@ -81,11 +99,11 @@ func printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer) { name := colorizeByStatus(sub.Status, sub.Name) if i == total-1 { - fmt.Fprintf(w, "%s└── %s/\n", prefix, name) - printDirContentsRecursively(sub, prefix+" ", w) + fmt.Fprintf(w, format[0], prefix, name) + printDirContentsRecursively(sub, prefix+format[2], w, format) } else { - fmt.Fprintf(w, "%s├── %s/\n", prefix, name) - printDirContentsRecursively(sub, prefix+"│ ", w) + fmt.Fprintf(w, format[1], prefix, name) + printDirContentsRecursively(sub, prefix+format[3], w, format) } i++ } @@ -94,9 +112,9 @@ func printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer) { name := colorizeByStatus(secret.Status, secret.Name) if i == total-1 { - fmt.Fprintf(w, "%s└── %s\n", prefix, name) + fmt.Fprintf(w, format[0], prefix, name) } else { - fmt.Fprintf(w, "%s├── %s\n", prefix, name) + fmt.Fprintf(w, format[1], prefix, name) } i++ } From 1ee09549dbba705103dbc2b20ab97ac747fdfae6 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Mon, 20 Jul 2020 15:43:44 +0300 Subject: [PATCH 20/70] All flags are implemented --- internals/secrethub/tree.go | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 077e7259..8db8b9e6 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -60,22 +60,25 @@ func (cmd *TreeCommand) Register(r command.Registerer) { // printTree recursively prints the tree's contents in a tree-like structure. func (cmd *TreeCommand) printTree(t *api.Tree, w io.Writer) { name := colorizeByStatus(t.RootDir.Status, t.RootDir.Name) - fmt.Fprintf(w, "%s/\n", name) + fmt.Fprintf(w, "%s\n", name) var format [4]string if cmd.noIndentation { - format[0] = "%s%s/\n" - format[1] = "%s%s/\n" + format[0] = "%s%s%s\n" + format[1] = "%s%s%s\n" format[2] = "" format[3] = "" } else { - format[0] = "%s└── %s/\n" - format[1] = "%s├── %s/\n" + format[0] = "%s└── %s%s\n" + format[1] = "%s├── %s%s\n" format[2] = " " format[3] = "│ " } - printDirContentsRecursively(t.RootDir, "", w, format) - + if cmd.fullPaths { + cmd.printDirContentsRecursively(t.RootDir, "", w, format, t.RootDir.Name) + } else { + cmd.printDirContentsRecursively(t.RootDir, "", w, format, "") + } if !cmd.noReport { fmt.Fprintf(w, "\n%s, %s\n", @@ -87,23 +90,29 @@ func (cmd *TreeCommand) printTree(t *api.Tree, w io.Writer) { // printDirContentsRecursively is a recursive function that prints the directory's contents // in a tree-like structure, subdirs first followed by secrets. -func printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer, format [4]string) { +func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer, format [4]string, prevPath string) { sort.Sort(api.SortDirByName(dir.SubDirs)) sort.Sort(api.SortSecretByName(dir.Secrets)) total := len(dir.SubDirs) + len(dir.Secrets) + if !cmd.fullPaths { + prevPath = "" + } else { + prevPath += "/" + } + i := 0 for _, sub := range dir.SubDirs { name := colorizeByStatus(sub.Status, sub.Name) if i == total-1 { - fmt.Fprintf(w, format[0], prefix, name) - printDirContentsRecursively(sub, prefix+format[2], w, format) + fmt.Fprintf(w, format[0], prefix, prevPath, name) + cmd.printDirContentsRecursively(sub, prefix+format[2], w, format, prevPath + name.(string)) } else { - fmt.Fprintf(w, format[1], prefix, name) - printDirContentsRecursively(sub, prefix+format[3], w, format) + fmt.Fprintf(w, format[1], prefix, prevPath, name) + cmd.printDirContentsRecursively(sub, prefix+format[3], w, format, prevPath + name.(string)) } i++ } @@ -112,9 +121,9 @@ func printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer, forma name := colorizeByStatus(secret.Status, secret.Name) if i == total-1 { - fmt.Fprintf(w, format[0], prefix, name) + fmt.Fprintf(w, format[0], prefix, prevPath, name) } else { - fmt.Fprintf(w, format[1], prefix, name) + fmt.Fprintf(w, format[1], prefix, prevPath, name) } i++ } From d0a09cfcee6df5d486f3de157b8bda5b334fd712 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Mon, 20 Jul 2020 15:46:54 +0300 Subject: [PATCH 21/70] Fix lint (format code) --- internals/secrethub/tree.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 8db8b9e6..3524fb3f 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -109,10 +109,10 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, if i == total-1 { fmt.Fprintf(w, format[0], prefix, prevPath, name) - cmd.printDirContentsRecursively(sub, prefix+format[2], w, format, prevPath + name.(string)) + cmd.printDirContentsRecursively(sub, prefix+format[2], w, format, prevPath+name.(string)) } else { fmt.Fprintf(w, format[1], prefix, prevPath, name) - cmd.printDirContentsRecursively(sub, prefix+format[3], w, format, prevPath + name.(string)) + cmd.printDirContentsRecursively(sub, prefix+format[3], w, format, prevPath+name.(string)) } i++ } From 4ec68e7e4a110d0c13c86b6242024079aca42a7e Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Mon, 20 Jul 2020 21:04:36 +0300 Subject: [PATCH 22/70] fixed most of the issues pointed by Simon in code review --- internals/secrethub/tree.go | 38 ++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 3524fb3f..96602e6a 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -53,13 +53,21 @@ func (cmd *TreeCommand) Register(r command.Registerer) { clause.Flag("full-paths", "Print the full paths of the directories and secrets.").Short('f').BoolVar(&cmd.fullPaths) clause.Flag("no-indentation", "Print the content without indentation.").Short('i').BoolVar(&cmd.noIndentation) clause.Flag("no-report", "Skip the report at the bottom.").BoolVar(&cmd.noReport) + clause.Flag("noreport", "Skip the report at the bottom.").BoolVar(&cmd.noReport) command.BindAction(clause, cmd.Run) } // printTree recursively prints the tree's contents in a tree-like structure. func (cmd *TreeCommand) printTree(t *api.Tree, w io.Writer) { - name := colorizeByStatus(t.RootDir.Status, t.RootDir.Name) + + rootDirName := func() string { + if cmd.fullPaths { + return cmd.path.Value() + } + return t.RootDir.Name + }() + name := colorizeByStatus(t.RootDir.Status, rootDirName) fmt.Fprintf(w, "%s\n", name) var format [4]string @@ -75,7 +83,7 @@ func (cmd *TreeCommand) printTree(t *api.Tree, w io.Writer) { format[3] = "│ " } if cmd.fullPaths { - cmd.printDirContentsRecursively(t.RootDir, "", w, format, t.RootDir.Name) + cmd.printDirContentsRecursively(t.RootDir, "", w, format, cmd.path.Value()) } else { cmd.printDirContentsRecursively(t.RootDir, "", w, format, "") } @@ -97,33 +105,37 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, total := len(dir.SubDirs) + len(dir.Secrets) - if !cmd.fullPaths { - prevPath = "" - } else { + if cmd.fullPaths { prevPath += "/" + } else { + prevPath = "" } i := 0 for _, sub := range dir.SubDirs { - name := colorizeByStatus(sub.Status, sub.Name) + colorName := colorizeByStatus(sub.Status, sub.Name) + colorPrefix := colorizeByStatus(sub.Status, prefix) + colorPrevPath := colorizeByStatus(sub.Status, prevPath) if i == total-1 { - fmt.Fprintf(w, format[0], prefix, prevPath, name) - cmd.printDirContentsRecursively(sub, prefix+format[2], w, format, prevPath+name.(string)) + fmt.Fprintf(w, format[0], colorPrefix, colorPrevPath, colorName) + cmd.printDirContentsRecursively(sub, prefix+format[2], w, format, prevPath+sub.Name) } else { - fmt.Fprintf(w, format[1], prefix, prevPath, name) - cmd.printDirContentsRecursively(sub, prefix+format[3], w, format, prevPath+name.(string)) + fmt.Fprintf(w, format[1], colorPrefix, colorPrevPath, colorName) + cmd.printDirContentsRecursively(sub, prefix+format[3], w, format, prevPath+sub.Name) } i++ } for _, secret := range dir.Secrets { - name := colorizeByStatus(secret.Status, secret.Name) + colorName := colorizeByStatus(secret.Status, secret.Name) + colorPrefix := colorizeByStatus(secret.Status, prefix) + colorPrevPath := colorizeByStatus(secret.Status, prevPath) if i == total-1 { - fmt.Fprintf(w, format[0], prefix, prevPath, name) + fmt.Fprintf(w, format[0], colorPrefix, colorPrevPath, colorName) } else { - fmt.Fprintf(w, format[1], prefix, prevPath, name) + fmt.Fprintf(w, format[1], colorPrefix, colorPrevPath, colorName) } i++ } From ab8361fbd2bb3240e4b6b5f36e6cc96b49dcd6a9 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Tue, 21 Jul 2020 14:52:01 +0300 Subject: [PATCH 23/70] potential fix for the colour issue --- internals/secrethub/tree.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 96602e6a..7907447a 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -114,14 +114,13 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, i := 0 for _, sub := range dir.SubDirs { colorName := colorizeByStatus(sub.Status, sub.Name) - colorPrefix := colorizeByStatus(sub.Status, prefix) colorPrevPath := colorizeByStatus(sub.Status, prevPath) if i == total-1 { - fmt.Fprintf(w, format[0], colorPrefix, colorPrevPath, colorName) + fmt.Fprintf(w, format[0], prefix, colorPrevPath, colorName) cmd.printDirContentsRecursively(sub, prefix+format[2], w, format, prevPath+sub.Name) } else { - fmt.Fprintf(w, format[1], colorPrefix, colorPrevPath, colorName) + fmt.Fprintf(w, format[1], prefix, colorPrevPath, colorName) cmd.printDirContentsRecursively(sub, prefix+format[3], w, format, prevPath+sub.Name) } i++ @@ -129,13 +128,12 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, for _, secret := range dir.Secrets { colorName := colorizeByStatus(secret.Status, secret.Name) - colorPrefix := colorizeByStatus(secret.Status, prefix) colorPrevPath := colorizeByStatus(secret.Status, prevPath) if i == total-1 { - fmt.Fprintf(w, format[0], colorPrefix, colorPrevPath, colorName) + fmt.Fprintf(w, format[0], prefix, colorPrevPath, colorName) } else { - fmt.Fprintf(w, format[1], colorPrefix, colorPrevPath, colorName) + fmt.Fprintf(w, format[1], prefix, colorPrevPath, colorName) } i++ } From 9ca6da6817d0a1c66617b437b85eceed0a0b9533 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Tue, 21 Jul 2020 15:15:48 +0300 Subject: [PATCH 24/70] restructured code following to Simon's benchmark --- internals/secrethub/tree.go | 58 ++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 7907447a..4bc74c63 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -63,29 +63,17 @@ func (cmd *TreeCommand) printTree(t *api.Tree, w io.Writer) { rootDirName := func() string { if cmd.fullPaths { - return cmd.path.Value() + return cmd.path.Value() + "/" } - return t.RootDir.Name + return t.RootDir.Name + "/" }() name := colorizeByStatus(t.RootDir.Status, rootDirName) fmt.Fprintf(w, "%s\n", name) - var format [4]string - if cmd.noIndentation { - format[0] = "%s%s%s\n" - format[1] = "%s%s%s\n" - format[2] = "" - format[3] = "" - } else { - format[0] = "%s└── %s%s\n" - format[1] = "%s├── %s%s\n" - format[2] = " " - format[3] = "│ " - } if cmd.fullPaths { - cmd.printDirContentsRecursively(t.RootDir, "", w, format, cmd.path.Value()) + cmd.printDirContentsRecursively(t.RootDir, "", w, cmd.path.Value()) } else { - cmd.printDirContentsRecursively(t.RootDir, "", w, format, "") + cmd.printDirContentsRecursively(t.RootDir, "", w, "") } if !cmd.noReport { fmt.Fprintf(w, @@ -98,7 +86,7 @@ func (cmd *TreeCommand) printTree(t *api.Tree, w io.Writer) { // printDirContentsRecursively is a recursive function that prints the directory's contents // in a tree-like structure, subdirs first followed by secrets. -func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer, format [4]string, prevPath string) { +func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer, prevPath string) { sort.Sort(api.SortDirByName(dir.SubDirs)) sort.Sort(api.SortSecretByName(dir.Secrets)) @@ -113,27 +101,39 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, i := 0 for _, sub := range dir.SubDirs { - colorName := colorizeByStatus(sub.Status, sub.Name) - colorPrevPath := colorizeByStatus(sub.Status, prevPath) - if i == total-1 { - fmt.Fprintf(w, format[0], prefix, colorPrevPath, colorName) - cmd.printDirContentsRecursively(sub, prefix+format[2], w, format, prevPath+sub.Name) + name := sub.Name + if cmd.fullPaths { + name = prevPath + name + } + colorName := colorizeByStatus(sub.Status, name) + + if cmd.noIndentation { + fmt.Fprintf(w, "%s/\n", colorName) + cmd.printDirContentsRecursively(sub, prefix, w, name) + } else if i == total-1 { + fmt.Fprintf(w, "%s└── %s/\n", prefix, colorName) + cmd.printDirContentsRecursively(sub, prefix + " ", w, name) } else { - fmt.Fprintf(w, format[1], prefix, colorPrevPath, colorName) - cmd.printDirContentsRecursively(sub, prefix+format[3], w, format, prevPath+sub.Name) + fmt.Fprintf(w, "%s├── %s/\n", prefix, colorName) + cmd.printDirContentsRecursively(sub, prefix + "│ ", w, name) } i++ } for _, secret := range dir.Secrets { - colorName := colorizeByStatus(secret.Status, secret.Name) - colorPrevPath := colorizeByStatus(secret.Status, prevPath) + name := secret.Name + if cmd.fullPaths { + name = prevPath + name + } + colorName := colorizeByStatus(secret.Status, name) - if i == total-1 { - fmt.Fprintf(w, format[0], prefix, colorPrevPath, colorName) + if cmd.noIndentation { + fmt.Fprintf(w, "%s\n", colorName) + } else if i == total-1 { + fmt.Fprintf(w, "%s└── %s\n", prefix, colorName) } else { - fmt.Fprintf(w, format[1], prefix, colorPrevPath, colorName) + fmt.Fprintf(w, "%s├── %s\n", prefix, colorName) } i++ } From d32665a26cbbe35dbea893ed586553ad4af3c086 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Tue, 21 Jul 2020 15:18:12 +0300 Subject: [PATCH 25/70] linter fix --- internals/secrethub/tree.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 4bc74c63..acc9c743 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -113,10 +113,10 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, cmd.printDirContentsRecursively(sub, prefix, w, name) } else if i == total-1 { fmt.Fprintf(w, "%s└── %s/\n", prefix, colorName) - cmd.printDirContentsRecursively(sub, prefix + " ", w, name) + cmd.printDirContentsRecursively(sub, prefix+" ", w, name) } else { fmt.Fprintf(w, "%s├── %s/\n", prefix, colorName) - cmd.printDirContentsRecursively(sub, prefix + "│ ", w, name) + cmd.printDirContentsRecursively(sub, prefix+"│ ", w, name) } i++ } From 03b2f7532e7d61bc0f6e3043fbf2745e3240c5a4 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Tue, 21 Jul 2020 15:36:50 +0300 Subject: [PATCH 26/70] Fix directory last slash coloring --- internals/secrethub/tree.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index acc9c743..24de1bcf 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -88,6 +88,12 @@ func (cmd *TreeCommand) printTree(t *api.Tree, w io.Writer) { // in a tree-like structure, subdirs first followed by secrets. func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer, prevPath string) { + const ( + format1 = "%s\n" + format2 = "%s└── %s\n" + format3 = "%s├── %s\n" + ) + sort.Sort(api.SortDirByName(dir.SubDirs)) sort.Sort(api.SortSecretByName(dir.Secrets)) @@ -106,16 +112,16 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, if cmd.fullPaths { name = prevPath + name } - colorName := colorizeByStatus(sub.Status, name) + colorName := colorizeByStatus(sub.Status, name + "/") if cmd.noIndentation { - fmt.Fprintf(w, "%s/\n", colorName) + fmt.Fprintf(w, format1, colorName) cmd.printDirContentsRecursively(sub, prefix, w, name) } else if i == total-1 { - fmt.Fprintf(w, "%s└── %s/\n", prefix, colorName) + fmt.Fprintf(w, format2, prefix, colorName) cmd.printDirContentsRecursively(sub, prefix+" ", w, name) } else { - fmt.Fprintf(w, "%s├── %s/\n", prefix, colorName) + fmt.Fprintf(w, format3, prefix, colorName) cmd.printDirContentsRecursively(sub, prefix+"│ ", w, name) } i++ @@ -129,11 +135,11 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, colorName := colorizeByStatus(secret.Status, name) if cmd.noIndentation { - fmt.Fprintf(w, "%s\n", colorName) + fmt.Fprintf(w, format1, colorName) } else if i == total-1 { - fmt.Fprintf(w, "%s└── %s\n", prefix, colorName) + fmt.Fprintf(w, format2, prefix, colorName) } else { - fmt.Fprintf(w, "%s├── %s\n", prefix, colorName) + fmt.Fprintf(w, format3, prefix, colorName) } i++ } From 1dd658bf69b9230d6ddd16361ff47d6b8b258f16 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Tue, 21 Jul 2020 15:39:54 +0300 Subject: [PATCH 27/70] Fix lint --- internals/secrethub/tree.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 24de1bcf..1ddf6825 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -112,7 +112,7 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, if cmd.fullPaths { name = prevPath + name } - colorName := colorizeByStatus(sub.Status, name + "/") + colorName := colorizeByStatus(sub.Status, name+"/") if cmd.noIndentation { fmt.Fprintf(w, format1, colorName) From 6cfaf184c01ec382138b980d0e165e17f62c5cb8 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 21 Jul 2020 17:38:32 +0200 Subject: [PATCH 28/70] Fix masker data race --- internals/cli/masker/stream.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internals/cli/masker/stream.go b/internals/cli/masker/stream.go index ce28f79a..8cc1f276 100644 --- a/internals/cli/masker/stream.go +++ b/internals/cli/masker/stream.go @@ -120,5 +120,8 @@ func (b *indexedBuffer) upToIndex(index int64) []byte { } n := int(index - b.currentIndex) b.currentIndex = index - return b.buffer.Next(n) + bufferSlice := b.buffer.Next(n) + res := make([]byte, len(bufferSlice)) + copy(res, bufferSlice) + return res } From a81fdd802c01e79730f83426fbdbae2165eb817d Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Tue, 21 Jul 2020 20:04:32 +0300 Subject: [PATCH 29/70] Put the print formats in the print functions to improve readability --- internals/secrethub/tree.go | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 1ddf6825..5eb5381f 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -88,12 +88,6 @@ func (cmd *TreeCommand) printTree(t *api.Tree, w io.Writer) { // in a tree-like structure, subdirs first followed by secrets. func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, w io.Writer, prevPath string) { - const ( - format1 = "%s\n" - format2 = "%s└── %s\n" - format3 = "%s├── %s\n" - ) - sort.Sort(api.SortDirByName(dir.SubDirs)) sort.Sort(api.SortSecretByName(dir.Secrets)) @@ -115,13 +109,13 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, colorName := colorizeByStatus(sub.Status, name+"/") if cmd.noIndentation { - fmt.Fprintf(w, format1, colorName) + fmt.Fprintf(w, "%s\n", colorName) cmd.printDirContentsRecursively(sub, prefix, w, name) } else if i == total-1 { - fmt.Fprintf(w, format2, prefix, colorName) + fmt.Fprintf(w, "%s└── %s\n", prefix, colorName) cmd.printDirContentsRecursively(sub, prefix+" ", w, name) } else { - fmt.Fprintf(w, format3, prefix, colorName) + fmt.Fprintf(w, "%s├── %s\n", prefix, colorName) cmd.printDirContentsRecursively(sub, prefix+"│ ", w, name) } i++ @@ -135,11 +129,11 @@ func (cmd *TreeCommand) printDirContentsRecursively(dir *api.Dir, prefix string, colorName := colorizeByStatus(secret.Status, name) if cmd.noIndentation { - fmt.Fprintf(w, format1, colorName) + fmt.Fprintf(w, "%s\n", colorName) } else if i == total-1 { - fmt.Fprintf(w, format2, prefix, colorName) + fmt.Fprintf(w, "%s└── %s\n", prefix, colorName) } else { - fmt.Fprintf(w, format3, prefix, colorName) + fmt.Fprintf(w, "%s├── %s\n", prefix, colorName) } i++ } From a5a27bf16405a43fd96f54c97aa378edc5adff7e Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Tue, 21 Jul 2020 22:38:58 +0300 Subject: [PATCH 30/70] First version of the tests --- internals/secrethub/tree_test.go | 253 +++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 internals/secrethub/tree_test.go diff --git a/internals/secrethub/tree_test.go b/internals/secrethub/tree_test.go new file mode 100644 index 00000000..9b542752 --- /dev/null +++ b/internals/secrethub/tree_test.go @@ -0,0 +1,253 @@ +package secrethub + +import ( + "bytes" + "testing" + + "github.com/secrethub/secrethub-cli/internals/cli/ui" + "github.com/secrethub/secrethub-go/internals/api" + "github.com/secrethub/secrethub-go/internals/api/uuid" + "github.com/secrethub/secrethub-go/internals/assert" + "github.com/secrethub/secrethub-go/pkg/secrethub" +) + +func TestSimpleTree(t *testing.T) { + uuid0, _ := uuid.FromString("0") + uuid1, _ := uuid.FromString("1") + uuid2, _ := uuid.FromString("2") + tree := &api.Tree{ + RootDir: &api.Dir{ + Name: "test/repo", + DirID: uuid0, + SubDirs: []*api.Dir{ + { + Name: "happy", + DirID: uuid1, + ParentID: &uuid0, + }, + { + Name: "secretFolder", + DirID: uuid2, + ParentID: &uuid0, + Secrets: []*api.Secret{ + {Name: "found you"}, + }, + }, + }, + Secrets: []*api.Secret{ + {Name: "mySecret"}, + }, + }, + Dirs: map[uuid.UUID]*api.Dir{ + uuid.New(): { + DirID: uuid0, + ParentID: &uuid0, + }, + uuid.New(): { + Name: "happy", + DirID: uuid1, + ParentID: &uuid0, + }, + uuid.New(): { + Name: "secretFolder", + DirID: uuid2, + ParentID: &uuid0, + Secrets: []*api.Secret{ + {Name: "found you"}, + }, + }, + }, + Secrets: map[uuid.UUID]*api.Secret{ + uuid.New(): {Name: "found you"}, + uuid.New(): {Name: "mySecret"}, + }, + } + cases := map[string]struct { + cmd *TreeCommand + expectedOutput string + }{ + "simple tree": { + cmd: &TreeCommand{ + io: ui.NewUserIO(), + newClient: func() (secrethub.ClientInterface, error) { + return &secrethub.Client{}, nil + }, + }, + expectedOutput: "test/repo/\n" + + "├── happy/\n" + + "├── secretFolder/\n" + + "│ └── found you\n" + + "└── mySecret\n\n" + + "2 directories, 2 secrets\n", + }, + "full path": { + cmd: &TreeCommand{ + path: "test/repo", + io: ui.NewUserIO(), + fullPaths: true, + newClient: func() (secrethub.ClientInterface, error) { + return &secrethub.Client{}, nil + }, + }, + expectedOutput: "test/repo/\n" + + "├── test/repo/happy/\n" + + "├── test/repo/secretFolder/\n" + + "│ └── test/repo/secretFolder/found you\n" + + "└── test/repo/mySecret\n\n" + + "2 directories, 2 secrets\n", + }, + "no indent": { + cmd: &TreeCommand{ + io: ui.NewUserIO(), + noIndentation: true, + newClient: func() (secrethub.ClientInterface, error) { + return &secrethub.Client{}, nil + }, + }, + expectedOutput: "test/repo/\n" + + "happy/\n" + + "secretFolder/\n" + + "found you\n" + + "mySecret\n\n" + + "2 directories, 2 secrets\n", + }, + "no report": { + cmd: &TreeCommand{ + io: ui.NewUserIO(), + noReport: true, + newClient: func() (secrethub.ClientInterface, error) { + return &secrethub.Client{}, nil + }, + }, + expectedOutput: "test/repo/\n" + + "├── happy/\n" + + "├── secretFolder/\n" + + "│ └── found you\n" + + "└── mySecret\n", + }, + "all flags": { + cmd: &TreeCommand{ + path: "test/repo", + io: ui.NewUserIO(), + fullPaths: true, + noIndentation: true, + noReport: true, + newClient: func() (secrethub.ClientInterface, error) { + return &secrethub.Client{}, nil + }, + }, + expectedOutput: "test/repo/\n" + + "test/repo/happy/\n" + + "test/repo/secretFolder/\n" + + "test/repo/secretFolder/found you\n" + + "test/repo/mySecret\n", + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + w := &bytes.Buffer{} + tc.cmd.printTree(tree, w) + assert.Equal(t, w.String(), tc.expectedOutput) + }) + } +} + +func TestTreeColoring(t *testing.T) { + uuid0, _ := uuid.FromString("0") + uuid1, _ := uuid.FromString("1") + uuid2, _ := uuid.FromString("2") + tree := &api.Tree{ + RootDir: &api.Dir{ + Name: "test/repo", + Status: "flagged", + DirID: uuid0, + SubDirs: []*api.Dir{ + { + Name: "happy", + DirID: uuid1, + ParentID: &uuid0, + }, + { + Name: "secretFolder", + DirID: uuid2, + ParentID: &uuid0, + Status: "flagged", + Secrets: []*api.Secret{ + { + Name: "found you", + Status: "flagged", + }, + }, + }, + }, + Secrets: []*api.Secret{ + {Name: "mySecret"}, + }, + }, + Dirs: map[uuid.UUID]*api.Dir{ + uuid.New(): { + DirID: uuid0, + ParentID: &uuid0, + }, + uuid.New(): { + Name: "happy", + DirID: uuid1, + ParentID: &uuid0, + }, + uuid.New(): { + Name: "secretFolder", + DirID: uuid2, + ParentID: &uuid0, + Secrets: []*api.Secret{ + {Name: "found you"}, + }, + }, + }, + Secrets: map[uuid.UUID]*api.Secret{ + uuid.New(): {Name: "found you"}, + uuid.New(): {Name: "mySecret"}, + }, + } + cases := map[string]struct { + cmd *TreeCommand + expectedOutput string + }{ + "simple tree": { + cmd: &TreeCommand{ + newClient: func() (secrethub.ClientInterface, error) { + return &secrethub.Client{}, nil + }, + }, + expectedOutput: "test/repo/\n" + + "├── happy/\n" + + "├── secretFolder/\n" + + "│ └── found you\n" + + "└── mySecret\n\n" + + "2 directories, 2 secrets\n", + }, + "full path": { + cmd: &TreeCommand{ + path: "test/repo", + fullPaths: true, + newClient: func() (secrethub.ClientInterface, error) { + return &secrethub.Client{}, nil + }, + }, + expectedOutput: "test/repo/\n" + + "├── test/repo/happy/\n" + + "├── test/repo/secretFolder/\n" + + "│ └── test/repo/secretFolder/found you\n" + + "└── test/repo/mySecret\n\n" + + "2 directories, 2 secrets\n", + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + w := &bytes.Buffer{} + tc.cmd.printTree(tree, w) + assert.Equal(t, w.String(), tc.expectedOutput) + }) + } +} From 519e5b21aeea17430ce714a5e0ab2dbc8ec2deed Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Tue, 21 Jul 2020 23:17:00 +0300 Subject: [PATCH 31/70] Small test adjustments (to be discussed) --- internals/secrethub/tree_test.go | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/internals/secrethub/tree_test.go b/internals/secrethub/tree_test.go index 9b542752..b3677807 100644 --- a/internals/secrethub/tree_test.go +++ b/internals/secrethub/tree_test.go @@ -14,20 +14,14 @@ import ( func TestSimpleTree(t *testing.T) { uuid0, _ := uuid.FromString("0") uuid1, _ := uuid.FromString("1") - uuid2, _ := uuid.FromString("2") tree := &api.Tree{ RootDir: &api.Dir{ Name: "test/repo", DirID: uuid0, SubDirs: []*api.Dir{ - { - Name: "happy", - DirID: uuid1, - ParentID: &uuid0, - }, { Name: "secretFolder", - DirID: uuid2, + DirID: uuid1, ParentID: &uuid0, Secrets: []*api.Secret{ {Name: "found you"}, @@ -43,14 +37,9 @@ func TestSimpleTree(t *testing.T) { DirID: uuid0, ParentID: &uuid0, }, - uuid.New(): { - Name: "happy", - DirID: uuid1, - ParentID: &uuid0, - }, uuid.New(): { Name: "secretFolder", - DirID: uuid2, + DirID: uuid1, ParentID: &uuid0, Secrets: []*api.Secret{ {Name: "found you"}, @@ -74,11 +63,10 @@ func TestSimpleTree(t *testing.T) { }, }, expectedOutput: "test/repo/\n" + - "├── happy/\n" + "├── secretFolder/\n" + "│ └── found you\n" + "└── mySecret\n\n" + - "2 directories, 2 secrets\n", + "1 directory, 2 secrets\n", }, "full path": { cmd: &TreeCommand{ @@ -90,11 +78,10 @@ func TestSimpleTree(t *testing.T) { }, }, expectedOutput: "test/repo/\n" + - "├── test/repo/happy/\n" + "├── test/repo/secretFolder/\n" + "│ └── test/repo/secretFolder/found you\n" + "└── test/repo/mySecret\n\n" + - "2 directories, 2 secrets\n", + "1 directory, 2 secrets\n", }, "no indent": { cmd: &TreeCommand{ @@ -105,11 +92,10 @@ func TestSimpleTree(t *testing.T) { }, }, expectedOutput: "test/repo/\n" + - "happy/\n" + "secretFolder/\n" + "found you\n" + "mySecret\n\n" + - "2 directories, 2 secrets\n", + "1 directory, 2 secrets\n", }, "no report": { cmd: &TreeCommand{ @@ -120,7 +106,6 @@ func TestSimpleTree(t *testing.T) { }, }, expectedOutput: "test/repo/\n" + - "├── happy/\n" + "├── secretFolder/\n" + "│ └── found you\n" + "└── mySecret\n", @@ -137,7 +122,6 @@ func TestSimpleTree(t *testing.T) { }, }, expectedOutput: "test/repo/\n" + - "test/repo/happy/\n" + "test/repo/secretFolder/\n" + "test/repo/secretFolder/found you\n" + "test/repo/mySecret\n", @@ -245,7 +229,7 @@ func TestTreeColoring(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { - w := &bytes.Buffer{} + w := new(bytes.Buffer) tc.cmd.printTree(tree, w) assert.Equal(t, w.String(), tc.expectedOutput) }) From 115c168c5019ba18583f2c61d632b18c1e4bdaa7 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 22 Jul 2020 13:38:23 +0200 Subject: [PATCH 32/70] Change indexedBuffer upToIndex -> writeUpToIndex This change ensures that the underlying buffer is protected by the mutex, by enforcing that all writes happen before the call to mutex.Unlock, while also ensuring high performance for the masker. --- internals/cli/masker/stream.go | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/internals/cli/masker/stream.go b/internals/cli/masker/stream.go index 8cc1f276..f70ad8b9 100644 --- a/internals/cli/masker/stream.go +++ b/internals/cli/masker/stream.go @@ -3,6 +3,7 @@ package masker import ( "bytes" "io" + "io/ioutil" "sync" "time" ) @@ -64,16 +65,14 @@ func (s *stream) flush(n int) error { if exists { // Get any unprocessed bytes before this match to the destination. - beforeMatch := s.buf.upToIndex(i) - - _, err := s.dest.Write(beforeMatch) + bytesBeforeMatch, err := s.buf.writeUpToIndex(s.dest, i) if err != nil { return err } // Only write the redaction text if there were bytes between this match and the previous match // or this is the first flush for the buffer. - if len(beforeMatch) > 0 || s.buf.currentIndex == 0 { + if bytesBeforeMatch > 0 || s.buf.currentIndex == 0 { _, err = s.dest.Write([]byte("")) if err != nil { return err @@ -81,14 +80,14 @@ func (s *stream) flush(n int) error { } // Drop all bytes until the end of the mask. - _ = s.buf.upToIndex(i + int64(length)) + _, _ = s.buf.writeUpToIndex(ioutil.Discard, i+int64(length)) delete(s.matches, i) } } // Write all bytes after the last match. - _, err := s.dest.Write(s.buf.upToIndex(endIndex)) + _, err := s.buf.writeUpToIndex(s.dest, endIndex) if err != nil { return err } @@ -109,19 +108,17 @@ func (b *indexedBuffer) write(p []byte) (n int, err error) { return b.buffer.Write(p) } -// upToIndex pops and returns all bytes in the buffer up to the given index. -// If all bytes up to this given index have already been returned previously, an empty slice is returned. -func (b *indexedBuffer) upToIndex(index int64) []byte { +// writeUpToIndex pops all bytes in the buffer up to the given index and writes them to the given writer. +// The number of bytes written and any errors encountered are returned +func (b *indexedBuffer) writeUpToIndex(w io.Writer, index int64) (int, error) { b.mutex.Lock() defer b.mutex.Unlock() if index < b.currentIndex { - return []byte{} + return 0, nil } n := int(index - b.currentIndex) b.currentIndex = index bufferSlice := b.buffer.Next(n) - res := make([]byte, len(bufferSlice)) - copy(res, bufferSlice) - return res + return w.Write(bufferSlice) } From d5e6cb7111074818131c78308bc420c3bec33e73 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 22 Jul 2020 14:17:16 +0200 Subject: [PATCH 33/70] Make secrethub demo init do nothing on subsequent runs --- internals/demo/init.go | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/internals/demo/init.go b/internals/demo/init.go index 4f9e6c68..2efd5d02 100644 --- a/internals/demo/init.go +++ b/internals/demo/init.go @@ -64,8 +64,15 @@ func (cmd *InitCommand) Run() error { } _, err = client.Repos().Create(repoPath) - if err == api.ErrRepoAlreadyExists && cmd.repo == "" { - return fmt.Errorf("demo repo %s already exists, use --repo to specify another repo to use", repoPath) + if err == api.ErrRepoAlreadyExists { + demoRepo, err := cmd.isDemoRepo(client, repoPath) + if err != nil { + return err + } + if demoRepo { + return nil + } + return fmt.Errorf("repo %s already exists and is not a demo repo, use --repo to specify another repo to use", repoPath) } else if err != nil { return err } @@ -89,3 +96,34 @@ func (cmd *InitCommand) Run() error { return nil } + +// isDemoRepo checks whether the repo on the given path is a demo repository. +// It returns true iff the repository contains exactly two secrets named username and password. +func (cmd *InitCommand) isDemoRepo(client secrethub.ClientInterface, repoPath string) (bool, error) { + repo, err := client.Repos().Get(repoPath) + if err != nil { + return false, err + } + if repo.SecretCount != 2 { + return false, nil + } + + usernamePath := secretpath.Join(repoPath, "username") + exists, err := client.Secrets().Exists(usernamePath) + if err != nil { + return false, err + } + if !exists { + return false, nil + } + + passwordPath := secretpath.Join(repoPath, "password") + exists, err = client.Secrets().Exists(passwordPath) + if err != nil { + return false, err + } + if !exists { + return false, nil + } + return true, nil +} From 131816df3d31dc37e4081ace63d82c056953ecea Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Wed, 22 Jul 2020 17:30:48 +0300 Subject: [PATCH 34/70] Adjusted tests with coloring --- internals/secrethub/tree_test.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/internals/secrethub/tree_test.go b/internals/secrethub/tree_test.go index b3677807..5cd40c83 100644 --- a/internals/secrethub/tree_test.go +++ b/internals/secrethub/tree_test.go @@ -2,6 +2,7 @@ package secrethub import ( "bytes" + "github.com/fatih/color" "testing" "github.com/secrethub/secrethub-cli/internals/cli/ui" @@ -138,13 +139,14 @@ func TestSimpleTree(t *testing.T) { } func TestTreeColoring(t *testing.T) { + color.NoColor = false uuid0, _ := uuid.FromString("0") uuid1, _ := uuid.FromString("1") uuid2, _ := uuid.FromString("2") tree := &api.Tree{ RootDir: &api.Dir{ Name: "test/repo", - Status: "flagged", + Status: api.StatusFlagged, DirID: uuid0, SubDirs: []*api.Dir{ { @@ -156,11 +158,11 @@ func TestTreeColoring(t *testing.T) { Name: "secretFolder", DirID: uuid2, ParentID: &uuid0, - Status: "flagged", + Status: api.StatusFlagged, Secrets: []*api.Secret{ { Name: "found you", - Status: "flagged", + Status: api.StatusFlagged, }, }, }, @@ -203,10 +205,10 @@ func TestTreeColoring(t *testing.T) { return &secrethub.Client{}, nil }, }, - expectedOutput: "test/repo/\n" + + expectedOutput: red.Sprint("test/repo/") + "\n" + "├── happy/\n" + - "├── secretFolder/\n" + - "│ └── found you\n" + + "├── " + red.Sprint("secretFolder/") + "\n" + + "│ └── " + red.Sprint("found you") + "\n" + "└── mySecret\n\n" + "2 directories, 2 secrets\n", }, @@ -218,10 +220,10 @@ func TestTreeColoring(t *testing.T) { return &secrethub.Client{}, nil }, }, - expectedOutput: "test/repo/\n" + + expectedOutput: red.Sprint("test/repo/") + "\n" + "├── test/repo/happy/\n" + - "├── test/repo/secretFolder/\n" + - "│ └── test/repo/secretFolder/found you\n" + + "├── " + red.Sprint("test/repo/secretFolder/") + "\n" + + "│ └── " + red.Sprint("test/repo/secretFolder/found you") + "\n" + "└── test/repo/mySecret\n\n" + "2 directories, 2 secrets\n", }, From 889cd0ebec93355a089c7bc33483fbe0c61aa60d Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Wed, 22 Jul 2020 17:34:38 +0300 Subject: [PATCH 35/70] Fix lint --- internals/secrethub/tree_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/tree_test.go b/internals/secrethub/tree_test.go index 5cd40c83..eb857cb0 100644 --- a/internals/secrethub/tree_test.go +++ b/internals/secrethub/tree_test.go @@ -2,9 +2,9 @@ package secrethub import ( "bytes" - "github.com/fatih/color" "testing" + "github.com/fatih/color" "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-go/internals/api" "github.com/secrethub/secrethub-go/internals/api/uuid" From e537898abc6cc078804e14e3116cd47027de7cc6 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 22 Jul 2020 17:44:44 +0200 Subject: [PATCH 36/70] Add error handling --- internals/cli/masker/stream.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internals/cli/masker/stream.go b/internals/cli/masker/stream.go index f70ad8b9..d3c85de1 100644 --- a/internals/cli/masker/stream.go +++ b/internals/cli/masker/stream.go @@ -80,7 +80,10 @@ func (s *stream) flush(n int) error { } // Drop all bytes until the end of the mask. - _, _ = s.buf.writeUpToIndex(ioutil.Discard, i+int64(length)) + _, err = s.buf.writeUpToIndex(ioutil.Discard, i+int64(length)) + if err != nil { + return err + } delete(s.matches, i) } From 50624b97209ed3c38c9df4d20ff16c1eb76b68bb Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Thu, 23 Jul 2020 12:59:40 +0300 Subject: [PATCH 37/70] Add the suggestions provided in the review --- internals/secrethub/tree.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 5eb5381f..e026b27f 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -50,10 +50,10 @@ func (cmd *TreeCommand) Register(r command.Registerer) { clause := r.Command("tree", "List contents of a directory in a tree-like format.") clause.Arg("dir-path", "The path to to show contents for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) - clause.Flag("full-paths", "Print the full paths of the directories and secrets.").Short('f').BoolVar(&cmd.fullPaths) - clause.Flag("no-indentation", "Print the content without indentation.").Short('i').BoolVar(&cmd.noIndentation) - clause.Flag("no-report", "Skip the report at the bottom.").BoolVar(&cmd.noReport) - clause.Flag("noreport", "Skip the report at the bottom.").BoolVar(&cmd.noReport) + clause.Flag("full-paths", "Print the full path of each directory and secret.").Short('f').BoolVar(&cmd.fullPaths) + clause.Flag("no-indentation", "Don't print indentation lines.").Short('i').BoolVar(&cmd.noIndentation) + clause.Flag("no-report", "Turn off secret/directory count at end of tree listing.").BoolVar(&cmd.noReport) + clause.Flag("noreport", "Turn off secret/directory count at end of tree listing.").Hidden().BoolVar(&cmd.noReport) command.BindAction(clause, cmd.Run) } From b864b27c90a971c172406e47e873eccf11e2ed14 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 7 Aug 2020 11:18:12 +0200 Subject: [PATCH 38/70] Point client to commit containing setup code functionality --- go.mod | 4 +--- go.sum | 18 ++---------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 227fefe6..38aef076 100644 --- a/go.mod +++ b/go.mod @@ -17,14 +17,12 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.30.0 + github.com/secrethub/secrethub-go v0.30.1-0.20200806155048-6ef6e5b1cb1a github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 - golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sys v0.0.0-20200501052902-10377860bb8e golang.org/x/text v0.3.2 google.golang.org/api v0.26.0 - google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 gopkg.in/yaml.v2 v2.2.2 gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index 4a4de5e0..395541e1 100644 --- a/go.sum +++ b/go.sum @@ -162,22 +162,8 @@ github.com/secrethub/demo-app v0.1.0 h1:HwPPxuiSvx4TBE7Qppzu3A9eHqmsBrIz4Ko8u8pq github.com/secrethub/demo-app v0.1.0/go.mod h1:ymjm8+WXTSDTFqsGVBNVmHSnwtZMYi7KptHvpo/fLH4= github.com/secrethub/secrethub-cli v0.30.0/go.mod h1:dC0wd40v+iQdV83/0rUrOa01LYq+8Yj2AtJB1vzh2ao= github.com/secrethub/secrethub-go v0.21.0/go.mod h1:rc2IfKKBJ4L0wGec0u4XnF5/pe0FFPE4Q1MWfrFso7s= -github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36 h1:kRVdL7PRfR80xjpOxFy1O0JROVpILWc2FZWE7Ni2Z2M= -github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add h1:+DzHsSjht15ycb7GFmyfmQ39gy8ZtA7FjWfJbWUPIYk= -github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a h1:rtFQLsSWGkdqd6LQFbgHsG/be60Cpqv8tc1w4XoKgKM= -github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91 h1:10KZJ3o7hodrTO1xAP1uNhDWSlLV9Bh9RqRFtiNCYJ4= -github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4 h1:TszZ+u/DRpPjaAGwEFSQNHkWhG4QR3KBxQJ66NfTAMk= -github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d h1:tADItWP+YXaGLD1ZMFocxDaKKVcu8wXgEulbcUmX4Ec= -github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597 h1:uC9ODMKaqBo1k8fxmFSWGkLr05TgEd3t4mHqJ8Jo9Gc= -github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.30.0 h1:Nh1twPDwPbYQj/cYc1NG+j7sv76LZiXLPovyV83tZj0= -github.com/secrethub/secrethub-go v0.30.0/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= +github.com/secrethub/secrethub-go v0.30.1-0.20200806155048-6ef6e5b1cb1a h1:xiYTF8biKz8vDTdWwXRF9VrsqXyxAValjRTYkFR1R4Q= +github.com/secrethub/secrethub-go v0.30.1-0.20200806155048-6ef6e5b1cb1a/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= From 7870a58e2d72869b7bdd607f1f0377c565763165 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 7 Aug 2020 13:07:12 +0200 Subject: [PATCH 39/70] Factor out start repo creation and org creation from signup command --- internals/secrethub/signup.go | 98 +++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 39 deletions(-) diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index 2d8f3eca..3eb745ee 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -4,6 +4,8 @@ import ( "fmt" "time" + "github.com/secrethub/secrethub-go/pkg/secrethub" + "github.com/secrethub/secrethub-cli/internals/cli/progress" "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" @@ -166,66 +168,84 @@ func (cmd *SignUpCommand) Run() error { return err } - // create a start repository and write a fist secret to it, so that - // the user can start by reading their first secret. - // This is intended to smoothen onboarding. - repoPath := secretpath.Join(cmd.username, "start") - _, err = client.Repos().Create(secretpath.Join(repoPath)) + secretPath, err := createStartRepo(client, cmd.username, cmd.fullName) if err != nil { cmd.progressPrinter.Stop() return err } - secretPath := secretpath.Join(repoPath, "hello") - message := fmt.Sprintf("Welcome %s! This is your first secret. To write a new version of this secret, run:\n\n secrethub write %s", cmd.fullName, secretPath) + cmd.progressPrinter.Stop() + fmt.Fprint(cmd.io.Output(), "Created your account.\n\n") - _, err = client.Secrets().Write(secretPath, []byte(message)) + err = createWorkspace(client, cmd.io, cmd.org, cmd.orgDescription, cmd.progressPrinter) if err != nil { - cmd.progressPrinter.Stop() return err } - cmd.progressPrinter.Stop() - fmt.Fprint(cmd.io.Output(), "Created your account.\n\n") + fmt.Fprintf(cmd.io.Output(), "Setup complete. To read your first secret, run:\n\n secrethub read %s\n\n", secretPath) - createWorkspace := cmd.org != "" - if !createWorkspace { - createWorkspace, err = ui.AskYesNo(cmd.io, "Do you want to create a shared workspace for your team?", ui.DefaultYes) + return nil +} + +// createStartRepo creates a start repository and writes a fist secret to it, so that +// the user can start by reading their first secret. It returns the secret's path. +// This is intended to smoothen onboarding. +func createStartRepo(client secrethub.ClientInterface, username string, fullName string) (string, error) { + repoPath := secretpath.Join(username, "start") + _, err := client.Repos().Create(secretpath.Join(repoPath)) + if err != nil { + return "", err + } + + secretPath := secretpath.Join(repoPath, "hello") + message := fmt.Sprintf("Welcome %s! This is your first secret. To write a new version of this secret, run:\n\n secrethub write %s", fullName, secretPath) + + _, err = client.Secrets().Write(secretPath, []byte(message)) + if err != nil { + return "", err + } + return secretPath, nil +} + +// createWorkspace c +func createWorkspace(client secrethub.ClientInterface, io ui.IO, org string, orgDescription string, progressPrinter progress.Printer) error { + if org == "" { + createWorkspace, err := ui.AskYesNo(io, "Do you want to create a shared workspace for your team?", ui.DefaultYes) if err != nil { return err } - fmt.Fprintln(cmd.io.Output()) + fmt.Fprintln(io.Output()) if !createWorkspace { - fmt.Fprint(cmd.io.Output(), "You can create a shared workspace later using `secrethub org init`.\n\n") + fmt.Fprint(io.Output(), "You can create a shared workspace later using `secrethub org init`.\n\n") + return nil } } - if createWorkspace { - if cmd.org == "" { - cmd.org, err = ui.AskAndValidate(cmd.io, "Workspace name (e.g. your company name): ", 2, api.ValidateOrgName) - if err != nil { - return err - } - } - if cmd.orgDescription == "" { - cmd.orgDescription, err = ui.AskAndValidate(cmd.io, "A description (max 144 chars) for your team workspace so others will recognize it:\n", 2, api.ValidateOrgDescription) - if err != nil { - return err - } - } - fmt.Fprint(cmd.io.Output(), "Creating your shared workspace...") - cmd.progressPrinter.Start() - _, err := client.Orgs().Create(cmd.org, cmd.orgDescription) - cmd.progressPrinter.Stop() - if err == api.ErrOrgAlreadyExists { - fmt.Fprintf(cmd.io.Output(), "The workspace %s already exists. If it is your organization, ask a colleague to invite you to the workspace. You can also create a new one using `secrethub org init`.\n", cmd.org) - } else if err != nil { + var err error + if org == "" { + org, err = ui.AskAndValidate(io, "Workspace name (e.g. your company name): ", 2, api.ValidateOrgName) + if err != nil { return err - } else { - fmt.Fprint(cmd.io.Output(), "Created your shared workspace.\n\n") } } - fmt.Fprintf(cmd.io.Output(), "Setup complete. To read your first secret, run:\n\n secrethub read %s\n\n", secretPath) + if orgDescription == "" { + orgDescription, err = ui.AskAndValidate(io, "A description (max 144 chars) for your team workspace so others will recognize it:\n", 2, api.ValidateOrgDescription) + if err != nil { + return err + } + } + + fmt.Fprint(io.Output(), "Creating your shared workspace...") + progressPrinter.Start() + _, err = client.Orgs().Create(org, orgDescription) + progressPrinter.Stop() + if err == api.ErrOrgAlreadyExists { + fmt.Fprintf(io.Output(), "The workspace %s already exists. If it is your organization, ask a colleague to invite you to the workspace. You can also create a new one using `secrethub org init`.\n", org) + } else if err != nil { + return err + } else { + fmt.Fprint(io.Output(), "Created your shared workspace.\n\n") + } return nil } From c716eb5e335a919725f468fa066e182588c49518 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 7 Aug 2020 13:07:49 +0200 Subject: [PATCH 40/70] Implement init --setup-code flag --- internals/secrethub/init.go | 103 +++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index dce0c9ac..91226d8b 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -6,6 +6,8 @@ import ( "os" "time" + "github.com/secrethub/secrethub-go/internals/api" + "github.com/secrethub/secrethub-cli/internals/cli/progress" "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" @@ -17,6 +19,7 @@ import ( // InitCommand configures the user's SecretHub account for use on this machine. type InitCommand struct { backupCode string + setupCode string force bool io ui.IO newClient newClientFunc @@ -40,6 +43,7 @@ func NewInitCommand(io ui.IO, newClient newClientFunc, newClientWithoutCredentia func (cmd *InitCommand) Register(r command.Registerer) { clause := r.Command("init", "Initialize the SecretHub client for first use on this device.") clause.Flag("backup-code", "The backup code used to restore an existing account to this device.").StringVar(&cmd.backupCode) + clause.Flag("setup-code", "The setup code used to configure the CLI to use an account created on the website.").StringVar(&cmd.setupCode) registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, cmd.Run) @@ -50,11 +54,16 @@ type InitMode int const ( InitModeSignup InitMode = iota + 1 InitModeBackupCode + InitModeSetupCode ) // Run configures the user's SecretHub account for use on this machine. // If an account was already configured, the user is prompted for confirmation to overwrite it. func (cmd *InitCommand) Run() error { + if cmd.setupCode != "" && cmd.backupCode != "" { + return ErrFlagsConflict("--backup-code and --setup-code") + } + credentialPath := cmd.credentialStore.ConfigDir().Credential().Path() if cmd.credentialStore.ConfigDir().Credential().Exists() && !cmd.force { @@ -76,7 +85,9 @@ func (cmd *InitCommand) Run() error { } var mode InitMode - if cmd.backupCode != "" { + if cmd.setupCode != "" { + mode = InitModeSetupCode + } else if cmd.backupCode != "" { mode = InitModeBackupCode } @@ -87,6 +98,7 @@ func (cmd *InitCommand) Run() error { option, err := ui.Choose(cmd.io, "How do you want to initialize your SecretHub account on this device?", []string{ "Signup for a new account", + "Use a setup code to set up an account created through the website", "Use a backup code to recover an existing account", }, 3) if err != nil { @@ -97,6 +109,8 @@ func (cmd *InitCommand) Run() error { case 0: mode = InitModeSignup case 1: + mode = InitModeSetupCode + case 2: mode = InitModeBackupCode } } @@ -111,6 +125,93 @@ func (cmd *InitCommand) Run() error { force: cmd.force, } return signupCommand.Run() + case InitModeSetupCode: + setupCode := cmd.setupCode + if setupCode == "" { + var err error + setupCode, err = ui.AskAndValidate(cmd.io, "What is your setup code?\n", 3, api.ValidateSetupCode) + if err != nil { + return err + } + } + + fmt.Fprintf( + cmd.io.Output(), + "An account credential will be generated and stored at %s. "+ + "Losing this credential means you lose the ability to decrypt your secrets. "+ + "So keep it safe.\n", + credentialPath, + ) + + // Only prompt for a passphrase when the user hasn't used --force. + // Otherwise, we assume the passphrase was intentionally not + // configured to output a plaintext credential. + var passphrase string + if !cmd.credentialStore.IsPassphraseSet() && !cmd.force { + var err error + passphrase, err = ui.AskPassphrase(cmd.io, "Please enter a passphrase to protect your local credential (leave empty for no passphrase): ", "Enter the same passphrase again: ", 3) + if err != nil { + return err + } + } + + fmt.Fprint(cmd.io.Output(), "Setting up your account...") + cmd.progressPrinter.Start() + + var client secrethub.ClientInterface + client, err := secrethub.NewClient(secrethub.WithSetupCode(setupCode)) + if err != nil { + return err + } + + credential := credentials.CreateKey() + _, err = client.Credentials().Create(credential, "") + if err != nil { + return err + } + + exportKey := credential.Key + if passphrase != "" { + exportKey = exportKey.Passphrase(credentials.FromString(passphrase)) + } + + encodedCredential, err := credential.Export() + if err != nil { + cmd.progressPrinter.Stop() + return err + } + + err = cmd.credentialStore.ConfigDir().Credential().Write(encodedCredential) + if err != nil { + cmd.progressPrinter.Stop() + return err + } + + client, err = cmd.newClient() + if err != nil { + return err + } + + me, err := client.Me().GetUser() + if err != nil { + return err + } + + secretPath, err := createStartRepo(client, me.Username, me.FullName) + if err != nil { + cmd.progressPrinter.Stop() + return err + } + cmd.progressPrinter.Stop() + fmt.Fprint(cmd.io.Output(), "Created your account.\n\n") + + err = createWorkspace(client, cmd.io, "", "", cmd.progressPrinter) + if err != nil { + return err + } + + fmt.Fprintf(cmd.io.Output(), "Setup complete. To read your first secret, run:\n\n secrethub read %s\n\n", secretPath) + return nil case InitModeBackupCode: backupCode := cmd.backupCode From 0e6359b6700784683a74a301359b34d74bfefbec Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Mon, 10 Aug 2020 11:17:34 +0200 Subject: [PATCH 41/70] Update go client version and fix client creation in init command --- go.mod | 2 +- go.sum | 4 ++-- internals/secrethub/init.go | 8 ++++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 38aef076..306d85cc 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.30.1-0.20200806155048-6ef6e5b1cb1a + github.com/secrethub/secrethub-go v0.30.1-0.20200807145938-681a4665c550 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/sys v0.0.0-20200501052902-10377860bb8e diff --git a/go.sum b/go.sum index 395541e1..2b83cc5b 100644 --- a/go.sum +++ b/go.sum @@ -162,8 +162,8 @@ github.com/secrethub/demo-app v0.1.0 h1:HwPPxuiSvx4TBE7Qppzu3A9eHqmsBrIz4Ko8u8pq github.com/secrethub/demo-app v0.1.0/go.mod h1:ymjm8+WXTSDTFqsGVBNVmHSnwtZMYi7KptHvpo/fLH4= github.com/secrethub/secrethub-cli v0.30.0/go.mod h1:dC0wd40v+iQdV83/0rUrOa01LYq+8Yj2AtJB1vzh2ao= github.com/secrethub/secrethub-go v0.21.0/go.mod h1:rc2IfKKBJ4L0wGec0u4XnF5/pe0FFPE4Q1MWfrFso7s= -github.com/secrethub/secrethub-go v0.30.1-0.20200806155048-6ef6e5b1cb1a h1:xiYTF8biKz8vDTdWwXRF9VrsqXyxAValjRTYkFR1R4Q= -github.com/secrethub/secrethub-go v0.30.1-0.20200806155048-6ef6e5b1cb1a/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= +github.com/secrethub/secrethub-go v0.30.1-0.20200807145938-681a4665c550 h1:CBeQpW1CYfaXgGgC3CtxmYqZq5YLlG/HknE3UD8zsms= +github.com/secrethub/secrethub-go v0.30.1-0.20200807145938-681a4665c550/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 91226d8b..07fec6a2 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -158,8 +158,12 @@ func (cmd *InitCommand) Run() error { fmt.Fprint(cmd.io.Output(), "Setting up your account...") cmd.progressPrinter.Start() - var client secrethub.ClientInterface - client, err := secrethub.NewClient(secrethub.WithSetupCode(setupCode)) + client, err := cmd.newClient() + if err != nil { + return err + } + + err = secrethub.WithSetupCode(setupCode)(client.(*secrethub.Client)) if err != nil { return err } From 141368740af1afb1e018b2a343b31f9bb747f26d Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Mon, 10 Aug 2020 12:33:10 +0200 Subject: [PATCH 42/70] Update creating client with setup code --- internals/secrethub/app.go | 2 +- internals/secrethub/client_factory.go | 13 +++++++++++++ internals/secrethub/init.go | 11 ++++------- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index e95a9c8b..a5de69a8 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -173,7 +173,7 @@ func (app *App) registerCommands() { NewEnvCommand(app.io, app.clientFactory.NewClient).Register(app.cli) // Commands - NewInitCommand(app.io, app.clientFactory.NewUnauthenticatedClient, app.clientFactory.NewClientWithCredentials, app.credentialStore).Register(app.cli) + NewInitCommand(app.io, app.clientFactory.NewUnauthenticatedClient, app.clientFactory.NewClientWithCredentials, app.clientFactory.NewClientWithSetupCode, app.credentialStore).Register(app.cli) NewSignUpCommand(app.io, app.clientFactory.NewUnauthenticatedClient, app.credentialStore).Register(app.cli) NewWriteCommand(app.io, app.clientFactory.NewClient).Register(app.cli) NewReadCommand(app.io, app.clientFactory.NewClient).Register(app.cli) diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index bd50bad2..24bbf4d8 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -20,6 +20,7 @@ type ClientFactory interface { // NewClient returns a new SecretHub client. NewClient() (secrethub.ClientInterface, error) NewClientWithCredentials(credentials.Provider) (secrethub.ClientInterface, error) + NewClientWithSetupCode(code string) (secrethub.ClientInterface, error) NewUnauthenticatedClient() (secrethub.ClientInterface, error) Register(FlagRegisterer) } @@ -88,6 +89,18 @@ func (f *clientFactory) NewClientWithCredentials(provider credentials.Provider) return client, nil } +func (f *clientFactory) NewClientWithSetupCode(code string) (secrethub.ClientInterface, error) { + options := f.baseClientOptions() + options = append(options, secrethub.WithSetupCode(code)) + + client, err := secrethub.NewClient(options...) + if err != nil { + return nil, err + } + + return client, nil +} + func (f *clientFactory) NewUnauthenticatedClient() (secrethub.ClientInterface, error) { options := f.baseClientOptions() diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 07fec6a2..8b9cbebc 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -24,16 +24,18 @@ type InitCommand struct { io ui.IO newClient newClientFunc newClientWithoutCredentials func(credentials.Provider) (secrethub.ClientInterface, error) + newClientWithSetupCode func(string) (secrethub.ClientInterface, error) credentialStore CredentialConfig progressPrinter progress.Printer } // NewInitCommand creates a new InitCommand. -func NewInitCommand(io ui.IO, newClient newClientFunc, newClientWithoutCredentials func(credentials.Provider) (secrethub.ClientInterface, error), credentialStore CredentialConfig) *InitCommand { +func NewInitCommand(io ui.IO, newClient newClientFunc, newClientWithoutCredentials func(credentials.Provider) (secrethub.ClientInterface, error), newClientWithSetupCode func(string) (secrethub.ClientInterface, error), credentialStore CredentialConfig) *InitCommand { return &InitCommand{ io: io, newClient: newClient, newClientWithoutCredentials: newClientWithoutCredentials, + newClientWithSetupCode: newClientWithSetupCode, credentialStore: credentialStore, progressPrinter: progress.NewPrinter(io.Output(), 500*time.Millisecond), } @@ -158,12 +160,7 @@ func (cmd *InitCommand) Run() error { fmt.Fprint(cmd.io.Output(), "Setting up your account...") cmd.progressPrinter.Start() - client, err := cmd.newClient() - if err != nil { - return err - } - - err = secrethub.WithSetupCode(setupCode)(client.(*secrethub.Client)) + client, err := cmd.newClientWithSetupCode(setupCode) if err != nil { return err } From 03a3ccdff6d964550ea403f1f729f47dcd9977a9 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Wed, 12 Aug 2020 10:57:19 +0200 Subject: [PATCH 43/70] Rename client constructor functions in init command The new names reflect the kind of clients they create, making it easier to spot which type of client is used where. --- internals/secrethub/init.go | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 8b9cbebc..6ea15666 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -18,26 +18,26 @@ import ( // InitCommand configures the user's SecretHub account for use on this machine. type InitCommand struct { - backupCode string - setupCode string - force bool - io ui.IO - newClient newClientFunc - newClientWithoutCredentials func(credentials.Provider) (secrethub.ClientInterface, error) - newClientWithSetupCode func(string) (secrethub.ClientInterface, error) - credentialStore CredentialConfig - progressPrinter progress.Printer + backupCode string + setupCode string + force bool + io ui.IO + newUnauthenticatedClient newClientFunc + newClientWithCredentials func(credentials.Provider) (secrethub.ClientInterface, error) + newClientWithSetupCode func(string) (secrethub.ClientInterface, error) + credentialStore CredentialConfig + progressPrinter progress.Printer } // NewInitCommand creates a new InitCommand. -func NewInitCommand(io ui.IO, newClient newClientFunc, newClientWithoutCredentials func(credentials.Provider) (secrethub.ClientInterface, error), newClientWithSetupCode func(string) (secrethub.ClientInterface, error), credentialStore CredentialConfig) *InitCommand { +func NewInitCommand(io ui.IO, newUnauthenticatedClient newClientFunc, newClientWithCredentials func(credentials.Provider) (secrethub.ClientInterface, error), newClientWithSetupCode func(string) (secrethub.ClientInterface, error), credentialStore CredentialConfig) *InitCommand { return &InitCommand{ - io: io, - newClient: newClient, - newClientWithoutCredentials: newClientWithoutCredentials, - newClientWithSetupCode: newClientWithSetupCode, - credentialStore: credentialStore, - progressPrinter: progress.NewPrinter(io.Output(), 500*time.Millisecond), + io: io, + newUnauthenticatedClient: newUnauthenticatedClient, + newClientWithCredentials: newClientWithCredentials, + newClientWithSetupCode: newClientWithSetupCode, + credentialStore: credentialStore, + progressPrinter: progress.NewPrinter(io.Output(), 500*time.Millisecond), } } @@ -121,7 +121,7 @@ func (cmd *InitCommand) Run() error { case InitModeSignup: signupCommand := SignUpCommand{ io: cmd.io, - newClient: cmd.newClient, + newClient: cmd.newUnauthenticatedClient, credentialStore: cmd.credentialStore, progressPrinter: cmd.progressPrinter, force: cmd.force, @@ -188,7 +188,7 @@ func (cmd *InitCommand) Run() error { return err } - client, err = cmd.newClient() + client, err = cmd.newUnauthenticatedClient() if err != nil { return err } @@ -224,7 +224,7 @@ func (cmd *InitCommand) Run() error { } } - client, err := cmd.newClientWithoutCredentials(credentials.UseBackupCode(backupCode)) + client, err := cmd.newClientWithCredentials(credentials.UseBackupCode(backupCode)) if err != nil { return err } From 89197ac446e2e097172bec922dfaf29b708e5716 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Wed, 12 Aug 2020 14:13:41 +0200 Subject: [PATCH 44/70] Update secrethub-go --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 306d85cc..f020a7f0 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.30.1-0.20200807145938-681a4665c550 + github.com/secrethub/secrethub-go v0.30.1-0.20200812113929-edff110cddfc github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/sys v0.0.0-20200501052902-10377860bb8e diff --git a/go.sum b/go.sum index 2b83cc5b..26306d92 100644 --- a/go.sum +++ b/go.sum @@ -164,6 +164,8 @@ github.com/secrethub/secrethub-cli v0.30.0/go.mod h1:dC0wd40v+iQdV83/0rUrOa01LYq github.com/secrethub/secrethub-go v0.21.0/go.mod h1:rc2IfKKBJ4L0wGec0u4XnF5/pe0FFPE4Q1MWfrFso7s= github.com/secrethub/secrethub-go v0.30.1-0.20200807145938-681a4665c550 h1:CBeQpW1CYfaXgGgC3CtxmYqZq5YLlG/HknE3UD8zsms= github.com/secrethub/secrethub-go v0.30.1-0.20200807145938-681a4665c550/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= +github.com/secrethub/secrethub-go v0.30.1-0.20200812113929-edff110cddfc h1:dN6YUlRQ3MwHc1QGWsMMazzFPWxWSOlp1afIzs4ycQo= +github.com/secrethub/secrethub-go v0.30.1-0.20200812113929-edff110cddfc/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= From 6c51f89390ed04b158e263c6bfeff7a7fa1ba85c Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Wed, 12 Aug 2020 15:17:46 +0200 Subject: [PATCH 45/70] Suggestions from code review --- internals/secrethub/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 6ea15666..f3c4a94e 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -188,7 +188,7 @@ func (cmd *InitCommand) Run() error { return err } - client, err = cmd.newUnauthenticatedClient() + client, err = cmd.newClientWithCredentials(credential) if err != nil { return err } From ea32ad2cfa9db555018ab1042ae5e891159b869d Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Wed, 12 Aug 2020 15:26:47 +0200 Subject: [PATCH 46/70] Update secrethub-go to develop --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index f020a7f0..973b4023 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.30.1-0.20200812113929-edff110cddfc + github.com/secrethub/secrethub-go v0.30.1-0.20200812121649-846d80e97296 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/sys v0.0.0-20200501052902-10377860bb8e diff --git a/go.sum b/go.sum index 26306d92..44f0d06a 100644 --- a/go.sum +++ b/go.sum @@ -166,6 +166,8 @@ github.com/secrethub/secrethub-go v0.30.1-0.20200807145938-681a4665c550 h1:CBeQp github.com/secrethub/secrethub-go v0.30.1-0.20200807145938-681a4665c550/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= github.com/secrethub/secrethub-go v0.30.1-0.20200812113929-edff110cddfc h1:dN6YUlRQ3MwHc1QGWsMMazzFPWxWSOlp1afIzs4ycQo= github.com/secrethub/secrethub-go v0.30.1-0.20200812113929-edff110cddfc/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= +github.com/secrethub/secrethub-go v0.30.1-0.20200812121649-846d80e97296 h1:IsbGXusKlVYSThYYepv80H0S9dXYOWMHDSNgoEamt1c= +github.com/secrethub/secrethub-go v0.30.1-0.20200812121649-846d80e97296/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= From 8ba5ff09771e8ef0cf8f973cbd1cbface828567a Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Thu, 13 Aug 2020 16:18:54 +0200 Subject: [PATCH 47/70] Rephrase setup code entry in init command options prompt Co-authored-by: Joris Coenen --- internals/secrethub/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index f3c4a94e..2647ff91 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -100,7 +100,7 @@ func (cmd *InitCommand) Run() error { option, err := ui.Choose(cmd.io, "How do you want to initialize your SecretHub account on this device?", []string{ "Signup for a new account", - "Use a setup code to set up an account created through the website", + "Use a setup code to set up an account created on the SecretHub website", "Use a backup code to recover an existing account", }, 3) if err != nil { From 0ca80679ab3f474a0486b16fa0ce02503e47a196 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 14 Aug 2020 13:23:49 +0200 Subject: [PATCH 48/70] Fix godoc --- internals/secrethub/signup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index 3eb745ee..846300eb 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -207,7 +207,7 @@ func createStartRepo(client secrethub.ClientInterface, username string, fullName return secretPath, nil } -// createWorkspace c +// createWorkspace creates a new org with the given name and description. func createWorkspace(client secrethub.ClientInterface, io ui.IO, org string, orgDescription string, progressPrinter progress.Printer) error { if org == "" { createWorkspace, err := ui.AskYesNo(io, "Do you want to create a shared workspace for your team?", ui.DefaultYes) From 9e2ae0bdaaa08dda5f45372691e7efb9ebc8604f Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 14 Aug 2020 13:35:03 +0200 Subject: [PATCH 49/70] Deduplicate credential writing --- internals/secrethub/init.go | 14 +------------- internals/secrethub/signup.go | 30 ++++++++++++++++++------------ 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 2647ff91..183beb9a 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -171,20 +171,8 @@ func (cmd *InitCommand) Run() error { return err } - exportKey := credential.Key - if passphrase != "" { - exportKey = exportKey.Passphrase(credentials.FromString(passphrase)) - } - - encodedCredential, err := credential.Export() + err = writeNewCredential(credential, passphrase, cmd.credentialStore.ConfigDir().Credential()) if err != nil { - cmd.progressPrinter.Stop() - return err - } - - err = cmd.credentialStore.ConfigDir().Credential().Write(encodedCredential) - if err != nil { - cmd.progressPrinter.Stop() return err } diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index 846300eb..6809624c 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -4,6 +4,8 @@ import ( "fmt" "time" + "github.com/secrethub/secrethub-go/pkg/secrethub/configdir" + "github.com/secrethub/secrethub-go/pkg/secrethub" "github.com/secrethub/secrethub-cli/internals/cli/progress" @@ -152,19 +154,8 @@ func (cmd *SignUpCommand) Run() error { return err } - exportKey := credential.Key - if passphrase != "" { - exportKey = exportKey.Passphrase(credentials.FromString(passphrase)) - } - - encodedCredential, err := credential.Export() - if err != nil { - cmd.progressPrinter.Stop() - return err - } - err = cmd.credentialStore.ConfigDir().Credential().Write(encodedCredential) + err = writeNewCredential(credential, passphrase, cmd.credentialStore.ConfigDir().Credential()) if err != nil { - cmd.progressPrinter.Stop() return err } @@ -249,3 +240,18 @@ func createWorkspace(client secrethub.ClientInterface, io ui.IO, org string, org } return nil } + +// writeCredential writes the given credential to the configuration directory. +func writeNewCredential(credential *credentials.KeyCreator, passphrase string, credentialFile *configdir.CredentialFile) error { + exportKey := credential.Key + if passphrase != "" { + exportKey = exportKey.Passphrase(credentials.FromString(passphrase)) + } + + encodedCredential, err := credential.Export() + if err != nil { + return err + } + + return credentialFile.Write(encodedCredential) +} From 541410bed5fc11c67486273cbd5eafcde955ebfc Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 14 Aug 2020 13:49:20 +0200 Subject: [PATCH 50/70] Stop progress printer on error --- internals/secrethub/init.go | 5 +++++ internals/secrethub/signup.go | 1 + 2 files changed, 6 insertions(+) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 183beb9a..8e3a47f5 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -162,27 +162,32 @@ func (cmd *InitCommand) Run() error { client, err := cmd.newClientWithSetupCode(setupCode) if err != nil { + cmd.progressPrinter.Stop() return err } credential := credentials.CreateKey() _, err = client.Credentials().Create(credential, "") if err != nil { + cmd.progressPrinter.Stop() return err } err = writeNewCredential(credential, passphrase, cmd.credentialStore.ConfigDir().Credential()) if err != nil { + cmd.progressPrinter.Stop() return err } client, err = cmd.newClientWithCredentials(credential) if err != nil { + cmd.progressPrinter.Stop() return err } me, err := client.Me().GetUser() if err != nil { + cmd.progressPrinter.Stop() return err } diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index 6809624c..a9642f81 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -156,6 +156,7 @@ func (cmd *SignUpCommand) Run() error { err = writeNewCredential(credential, passphrase, cmd.credentialStore.ConfigDir().Credential()) if err != nil { + cmd.progressPrinter.Stop() return err } From 77afc35c70fde177b7188a5bff1cff9bb6e1cf04 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 14 Aug 2020 13:52:21 +0200 Subject: [PATCH 51/70] Deduplicate credential creation message --- internals/secrethub/init.go | 8 +------- internals/secrethub/signup.go | 12 +++++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 8e3a47f5..24e7c635 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -137,13 +137,7 @@ func (cmd *InitCommand) Run() error { } } - fmt.Fprintf( - cmd.io.Output(), - "An account credential will be generated and stored at %s. "+ - "Losing this credential means you lose the ability to decrypt your secrets. "+ - "So keep it safe.\n", - credentialPath, - ) + fmt.Fprintf(cmd.io.Output(), credentialCreationMessage, credentialPath) // Only prompt for a passphrase when the user hasn't used --force. // Otherwise, we assume the passphrase was intentionally not diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index a9642f81..f9187c46 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -22,6 +22,10 @@ var ( ErrLocalAccountFound = errMain.Code("local_account_found").Error("found a local account configuration. To overwrite it, run the same command with the --force or -f flag.") ) +const credentialCreationMessage = "An account credential will be generated and stored at %s. " + + "Losing this credential means you lose the ability to decrypt your secrets. " + + "So keep it safe.\n" + // SignUpCommand signs up a new user and configures his account for use on this machine. type SignUpCommand struct { username string @@ -120,13 +124,7 @@ func (cmd *SignUpCommand) Run() error { } } - fmt.Fprintf( - cmd.io.Output(), - "An account credential will be generated and stored at %s. "+ - "Losing this credential means you lose the ability to decrypt your secrets. "+ - "So keep it safe.\n", - credentialPath, - ) + fmt.Fprintf(cmd.io.Output(), credentialCreationMessage, credentialPath) // Only prompt for a passphrase when the user hasn't used --force. // Otherwise, we assume the passphrase was intentionally not From 9d142c5534e051cee5cfcc612ab69cddd2fbf0c9 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 14 Aug 2020 14:00:39 +0200 Subject: [PATCH 52/70] Add device name prompt to init with setup code and deduplicate device name prompting --- internals/secrethub/init.go | 41 ++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 24e7c635..5b01e58a 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -151,6 +151,11 @@ func (cmd *InitCommand) Run() error { } } + deviceName, err := promptForDeviceName(cmd.io) + if err != nil { + return err + } + fmt.Fprint(cmd.io.Output(), "Setting up your account...") cmd.progressPrinter.Start() @@ -161,7 +166,7 @@ func (cmd *InitCommand) Run() error { } credential := credentials.CreateKey() - _, err = client.Credentials().Create(credential, "") + _, err = client.Credentials().Create(credential, deviceName) if err != nil { cmd.progressPrinter.Stop() return err @@ -235,19 +240,9 @@ func (cmd *InitCommand) Run() error { return nil } - deviceName := "" - question := "What is the name of this device?" - hostName, err := os.Hostname() - if err == nil { - deviceName, err = ui.AskWithDefault(cmd.io, question, hostName) - if err != nil { - return err - } - } else { - deviceName, err = ui.Ask(cmd.io, question) - if err != nil { - return err - } + deviceName, err := promptForDeviceName(cmd.io) + if err != nil { + return err } // Only prompt for a passphrase when the user hasn't used --force. @@ -286,3 +281,21 @@ func (cmd *InitCommand) Run() error { return errors.New("invalid option") } } + +func promptForDeviceName(io ui.IO) (string, error) { + deviceName := "" + question := "What is the name of this device?" + hostName, err := os.Hostname() + if err == nil { + deviceName, err = ui.AskWithDefault(io, question, hostName) + if err != nil { + return "", err + } + } else { + deviceName, err = ui.Ask(io, question) + if err != nil { + return "", err + } + } + return deviceName, nil +} From 5c020c204ce54a7a0289a0b768c60b924af0794c Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 14 Aug 2020 14:21:19 +0200 Subject: [PATCH 53/70] Factor out asking for passphrase --- internals/secrethub/init.go | 2 +- internals/secrethub/signup.go | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 5b01e58a..7d9ced75 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -251,7 +251,7 @@ func (cmd *InitCommand) Run() error { var passphrase string if !cmd.credentialStore.IsPassphraseSet() && !cmd.force { var err error - passphrase, err = ui.AskPassphrase(cmd.io, "Please enter a passphrase to protect your local credential (leave empty for no passphrase): ", "Enter the same passphrase again: ", 3) + passphrase, err = askCredentialPassphrase(cmd.io) if err != nil { return err } diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index f9187c46..321d7060 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -132,7 +132,7 @@ func (cmd *SignUpCommand) Run() error { var passphrase string if !cmd.credentialStore.IsPassphraseSet() && !cmd.force { var err error - passphrase, err = ui.AskPassphrase(cmd.io, "Please enter a passphrase to protect your local credential (leave empty for no passphrase): ", "Enter the same passphrase again: ", 3) + passphrase, err = askCredentialPassphrase(cmd.io) if err != nil { return err } @@ -254,3 +254,8 @@ func writeNewCredential(credential *credentials.KeyCreator, passphrase string, c return credentialFile.Write(encodedCredential) } + +// askCredentialPassphrase prompts the user for a passphrase to protect the local credential. +func askCredentialPassphrase(io ui.IO) (string, error) { + return ui.AskPassphrase(io, "Please enter a passphrase to protect your local credential (leave empty for no passphrase): ", "Enter the same passphrase again: ", 3) +} From 702e2f9103500f288d7d014b21c1905c3e73a093 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 14 Aug 2020 14:38:02 +0200 Subject: [PATCH 54/70] Remove with setup code option and make setup code a credential provider This commit also makes the cli point to the version of the client containing the required changes. --- go.mod | 2 +- go.sum | 2 ++ internals/secrethub/app.go | 2 +- internals/secrethub/client_factory.go | 13 ------------- internals/secrethub/init.go | 6 ++---- 5 files changed, 6 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 973b4023..0c50c01d 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.30.1-0.20200812121649-846d80e97296 + github.com/secrethub/secrethub-go v0.30.1-0.20200814123323-7aac428a99e4 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/sys v0.0.0-20200501052902-10377860bb8e diff --git a/go.sum b/go.sum index 44f0d06a..f967fb14 100644 --- a/go.sum +++ b/go.sum @@ -168,6 +168,8 @@ github.com/secrethub/secrethub-go v0.30.1-0.20200812113929-edff110cddfc h1:dN6YU github.com/secrethub/secrethub-go v0.30.1-0.20200812113929-edff110cddfc/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= github.com/secrethub/secrethub-go v0.30.1-0.20200812121649-846d80e97296 h1:IsbGXusKlVYSThYYepv80H0S9dXYOWMHDSNgoEamt1c= github.com/secrethub/secrethub-go v0.30.1-0.20200812121649-846d80e97296/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= +github.com/secrethub/secrethub-go v0.30.1-0.20200814123323-7aac428a99e4 h1:zIOs8q0BK5pI55Fa8y3MMuxIfD7nAv9sh+3GbOiT6hM= +github.com/secrethub/secrethub-go v0.30.1-0.20200814123323-7aac428a99e4/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index a5de69a8..e95a9c8b 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -173,7 +173,7 @@ func (app *App) registerCommands() { NewEnvCommand(app.io, app.clientFactory.NewClient).Register(app.cli) // Commands - NewInitCommand(app.io, app.clientFactory.NewUnauthenticatedClient, app.clientFactory.NewClientWithCredentials, app.clientFactory.NewClientWithSetupCode, app.credentialStore).Register(app.cli) + NewInitCommand(app.io, app.clientFactory.NewUnauthenticatedClient, app.clientFactory.NewClientWithCredentials, app.credentialStore).Register(app.cli) NewSignUpCommand(app.io, app.clientFactory.NewUnauthenticatedClient, app.credentialStore).Register(app.cli) NewWriteCommand(app.io, app.clientFactory.NewClient).Register(app.cli) NewReadCommand(app.io, app.clientFactory.NewClient).Register(app.cli) diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index 24bbf4d8..bd50bad2 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -20,7 +20,6 @@ type ClientFactory interface { // NewClient returns a new SecretHub client. NewClient() (secrethub.ClientInterface, error) NewClientWithCredentials(credentials.Provider) (secrethub.ClientInterface, error) - NewClientWithSetupCode(code string) (secrethub.ClientInterface, error) NewUnauthenticatedClient() (secrethub.ClientInterface, error) Register(FlagRegisterer) } @@ -89,18 +88,6 @@ func (f *clientFactory) NewClientWithCredentials(provider credentials.Provider) return client, nil } -func (f *clientFactory) NewClientWithSetupCode(code string) (secrethub.ClientInterface, error) { - options := f.baseClientOptions() - options = append(options, secrethub.WithSetupCode(code)) - - client, err := secrethub.NewClient(options...) - if err != nil { - return nil, err - } - - return client, nil -} - func (f *clientFactory) NewUnauthenticatedClient() (secrethub.ClientInterface, error) { options := f.baseClientOptions() diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 7d9ced75..e810de53 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -24,18 +24,16 @@ type InitCommand struct { io ui.IO newUnauthenticatedClient newClientFunc newClientWithCredentials func(credentials.Provider) (secrethub.ClientInterface, error) - newClientWithSetupCode func(string) (secrethub.ClientInterface, error) credentialStore CredentialConfig progressPrinter progress.Printer } // NewInitCommand creates a new InitCommand. -func NewInitCommand(io ui.IO, newUnauthenticatedClient newClientFunc, newClientWithCredentials func(credentials.Provider) (secrethub.ClientInterface, error), newClientWithSetupCode func(string) (secrethub.ClientInterface, error), credentialStore CredentialConfig) *InitCommand { +func NewInitCommand(io ui.IO, newUnauthenticatedClient newClientFunc, newClientWithCredentials func(credentials.Provider) (secrethub.ClientInterface, error), credentialStore CredentialConfig) *InitCommand { return &InitCommand{ io: io, newUnauthenticatedClient: newUnauthenticatedClient, newClientWithCredentials: newClientWithCredentials, - newClientWithSetupCode: newClientWithSetupCode, credentialStore: credentialStore, progressPrinter: progress.NewPrinter(io.Output(), 500*time.Millisecond), } @@ -159,7 +157,7 @@ func (cmd *InitCommand) Run() error { fmt.Fprint(cmd.io.Output(), "Setting up your account...") cmd.progressPrinter.Start() - client, err := cmd.newClientWithSetupCode(setupCode) + client, err := cmd.newClientWithCredentials(credentials.NewSetupCode(setupCode)) if err != nil { cmd.progressPrinter.Stop() return err From 2a80a7dbea7c7229526b4578e32f48eb38bbfc28 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Fri, 4 Sep 2020 14:55:46 +0200 Subject: [PATCH 55/70] Refer to web signup in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 70b7b65f..e924bbfa 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

- Get Started + Get Started View Docs


@@ -23,7 +23,7 @@ The SecretHub CLI provides the command-line interface to interact with the Secre ## Get started -Follow the [Getting Started Guide][getting-started] to quickly get up and running with SecretHub :rocket: +[Set up SecretHub on your machine](https://signup.secrethub.io/) to quickly get up and running :rocket: ## Usage From b9444ac7d20c0dc4e76af9fa554a5196da36363d Mon Sep 17 00:00:00 2001 From: Floris van der Grinten Date: Mon, 7 Sep 2020 11:57:48 +0200 Subject: [PATCH 56/70] Remove redundant Get Started section from README --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index e924bbfa..ed360104 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,6 @@ The SecretHub CLI provides the command-line interface to interact with the Secre > [SecretHub][secrethub] is a secret management tool that works for every engineer. Securely provision passwords and keys throughout your entire stack with just a few lines of code. -## Get started - -[Set up SecretHub on your machine](https://signup.secrethub.io/) to quickly get up and running :rocket: - ## Usage Below you can find a selection of some of the most-used SecretHub commands. Run `secrethub --help` or the [CLI reference docs][cli-reference-docs] for a complete list of all commands. From ac08b032073847547e148a0d25ee28b4c103d0e0 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 16:12:02 +0200 Subject: [PATCH 57/70] Deduplicate passphrase prompt Co-authored-by: Floris van der Grinten --- internals/secrethub/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index e810de53..5dd43aa6 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -143,7 +143,7 @@ func (cmd *InitCommand) Run() error { var passphrase string if !cmd.credentialStore.IsPassphraseSet() && !cmd.force { var err error - passphrase, err = ui.AskPassphrase(cmd.io, "Please enter a passphrase to protect your local credential (leave empty for no passphrase): ", "Enter the same passphrase again: ", 3) + passphrase, err = askCredentialPassphrase(cmd.io) if err != nil { return err } From 465b8da80e898acfef90fb1653f4c2571204d354 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 16:34:24 +0200 Subject: [PATCH 58/70] Remove prompt for setup code There is no valid use case where a user would have to enter it manually, so we can better remove this altogehter and direct users to the website. --- internals/secrethub/init.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 5dd43aa6..156dc8be 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -6,8 +6,6 @@ import ( "os" "time" - "github.com/secrethub/secrethub-go/internals/api" - "github.com/secrethub/secrethub-cli/internals/cli/progress" "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" @@ -128,11 +126,8 @@ func (cmd *InitCommand) Run() error { case InitModeSetupCode: setupCode := cmd.setupCode if setupCode == "" { - var err error - setupCode, err = ui.AskAndValidate(cmd.io, "What is your setup code?\n", 3, api.ValidateSetupCode) - if err != nil { - return err - } + fmt.Fprintln(cmd.io.Output(), "If you have signed up on https://signup.secrethub.io, just copy the provided `secrethub init` command to get your CLI set up.") + return nil } fmt.Fprintf(cmd.io.Output(), credentialCreationMessage, credentialPath) From 6b89e825097ef0573f5095f36453f0071b002207 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 16:37:01 +0200 Subject: [PATCH 59/70] Remove signup from `secrethub init` prompt --- internals/secrethub/init.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 5dd43aa6..1dc4de9c 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -97,7 +97,6 @@ func (cmd *InitCommand) Run() error { } option, err := ui.Choose(cmd.io, "How do you want to initialize your SecretHub account on this device?", []string{ - "Signup for a new account", "Use a setup code to set up an account created on the SecretHub website", "Use a backup code to recover an existing account", }, 3) @@ -107,10 +106,8 @@ func (cmd *InitCommand) Run() error { switch option { case 0: - mode = InitModeSignup - case 1: mode = InitModeSetupCode - case 2: + case 1: mode = InitModeBackupCode } } From 6afcad1d673a751d4ebfa11ce60e3025acfc9e3b Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 16:41:47 +0200 Subject: [PATCH 60/70] Add an option to secrethub init to clarify signup --- internals/secrethub/init.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 1dc4de9c..a768b1db 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -97,17 +97,22 @@ func (cmd *InitCommand) Run() error { } option, err := ui.Choose(cmd.io, "How do you want to initialize your SecretHub account on this device?", []string{ + "I do not yet have a SecretHub account", "Use a setup code to set up an account created on the SecretHub website", "Use a backup code to recover an existing account", }, 3) if err != nil { return err } + fmt.Fprintln(cmd.io.Output()) switch option { case 0: - mode = InitModeSetupCode + fmt.Fprintln(cmd.io.Output(), "Go to https://signup.secrethub.io/ and follow the steps to create an account and get it set up on this machine.") + return nil case 1: + mode = InitModeSetupCode + case 2: mode = InitModeBackupCode } } From 552354eec7381cccf68e366651f110c8e64ea1bd Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 16:45:07 +0200 Subject: [PATCH 61/70] Refer to web signup in CLI help text --- internals/secrethub/app.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index e95a9c8b..7409eb71 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -79,6 +79,8 @@ func NewApp() *App { io := ui.NewUserIO() store := NewCredentialConfig(io) help := "The SecretHub command-line interface is a unified tool to manage your infrastructure secrets with SecretHub.\n\n" + + "If you do not yet have a SecretHub account, go here to create one:\n\n" + + " https://signup.secrethub.io/\n\n" + "For a step-by-step introduction, check out:\n\n" + " https://secrethub.io/docs/getting-started/\n\n" + "To get help, see:\n\n" + From 953c4089732cefb90e646d83ab5135c192fb8de4 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 16:46:23 +0200 Subject: [PATCH 62/70] Hide signup command --- internals/secrethub/signup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index 321d7060..b4bc22a3 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -52,7 +52,7 @@ func NewSignUpCommand(io ui.IO, newClient newClientFunc, credentialStore Credent // Register registers the command, arguments and flags on the provided Registerer. func (cmd *SignUpCommand) Register(r command.Registerer) { - clause := r.Command("signup", "Create a free personal developer account.") + clause := r.Command("signup", "Create a free personal developer account.").Hidden() clause.Flag("username", "The username you would like to use on SecretHub.").StringVar(&cmd.username) clause.Flag("full-name", "Your full name.").StringVar(&cmd.fullName) clause.Flag("email", "Your (work) email address we will use for all correspondence.").StringVar(&cmd.email) From 0418d9fac55f54394546e3b9606f3a4f811c9900 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 16:48:23 +0200 Subject: [PATCH 63/70] Refer to web signup in missing credential errror --- internals/secrethub/credential_store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/credential_store.go b/internals/secrethub/credential_store.go index 09f2ccf2..d6ca2d3a 100644 --- a/internals/secrethub/credential_store.go +++ b/internals/secrethub/credential_store.go @@ -11,7 +11,7 @@ import ( // Errors var ( - ErrCredentialNotExist = errMain.Code("credential_not_exist").Error("could not find credential file. Run `secrethub signup` to create an account.") + ErrCredentialNotExist = errMain.Code("credential_not_exist").Error("could not find credential file. Go to https://signup.secrethub.io/ to create an account or run `secrethub init` to use an already existing account on this machine.") ) // CredentialConfig handles the configuration necessary for local credentials. From d47736930c66522091b71a49a63edc55c307c4fe Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 16:50:54 +0200 Subject: [PATCH 64/70] Rephrase to be more consistent with other options --- internals/secrethub/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index a768b1db..691ba18e 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -97,7 +97,7 @@ func (cmd *InitCommand) Run() error { } option, err := ui.Choose(cmd.io, "How do you want to initialize your SecretHub account on this device?", []string{ - "I do not yet have a SecretHub account", + "Create a new SecretHub account", "Use a setup code to set up an account created on the SecretHub website", "Use a backup code to recover an existing account", }, 3) From f72659325c28b60f6292526863901ece328b908d Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 16:53:12 +0200 Subject: [PATCH 65/70] Do not list setup code option There is no reason why a user would have to get there when he is not copying a command with a --setup-code flag. --- internals/secrethub/init.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 156dc8be..5f364ec1 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -96,7 +96,6 @@ func (cmd *InitCommand) Run() error { option, err := ui.Choose(cmd.io, "How do you want to initialize your SecretHub account on this device?", []string{ "Signup for a new account", - "Use a setup code to set up an account created on the SecretHub website", "Use a backup code to recover an existing account", }, 3) if err != nil { @@ -107,8 +106,6 @@ func (cmd *InitCommand) Run() error { case 0: mode = InitModeSignup case 1: - mode = InitModeSetupCode - case 2: mode = InitModeBackupCode } } @@ -125,10 +122,6 @@ func (cmd *InitCommand) Run() error { return signupCommand.Run() case InitModeSetupCode: setupCode := cmd.setupCode - if setupCode == "" { - fmt.Fprintln(cmd.io.Output(), "If you have signed up on https://signup.secrethub.io, just copy the provided `secrethub init` command to get your CLI set up.") - return nil - } fmt.Fprintf(cmd.io.Output(), credentialCreationMessage, credentialPath) From 26b6d99c9569e98c6e1ad6d07a924a3a673b8daa Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Mon, 7 Sep 2020 16:55:10 +0200 Subject: [PATCH 66/70] Upgrade secrethub-go to v0.31.0 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 227fefe6..512f6a63 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.30.0 + github.com/secrethub/secrethub-go v0.31.0 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index 4a4de5e0..3c09732b 100644 --- a/go.sum +++ b/go.sum @@ -178,6 +178,8 @@ github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597 h1:uC9OD github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/secrethub/secrethub-go v0.30.0 h1:Nh1twPDwPbYQj/cYc1NG+j7sv76LZiXLPovyV83tZj0= github.com/secrethub/secrethub-go v0.30.0/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= +github.com/secrethub/secrethub-go v0.31.0 h1:0KoG0KHBOa5knkvf3K0f6sKuPSQ5VGPXLD4ttC9Eul8= +github.com/secrethub/secrethub-go v0.31.0/go.mod h1:ZIco8Y0G0Pi0Vb7pQROjvEKgSreZiRMLhAbzWUneUSQ= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= From 08f9ba4a3eb6d7695e1c2eab04e26d4d27aba151 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 17:37:44 +0200 Subject: [PATCH 67/70] Fix incorrect int to string conversion This line breaks compilation under go 1.15 --- internals/cli/filemode/filemode.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internals/cli/filemode/filemode.go b/internals/cli/filemode/filemode.go index c293405d..acce3364 100644 --- a/internals/cli/filemode/filemode.go +++ b/internals/cli/filemode/filemode.go @@ -2,6 +2,7 @@ package filemode import ( + "fmt" "os" "strconv" @@ -47,7 +48,7 @@ func (m *FileMode) Set(value string) error { // String implements the flag.Value interface. func (m FileMode) String() string { - return string(m) + return fmt.Sprint(m) } // FileMode returns the file mode as an os.FileMode. From 8b610dabb1f7f4cd089a32d0162fae11f868e7d6 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Mon, 7 Sep 2020 17:50:52 +0200 Subject: [PATCH 68/70] Fix infinite recursive call fmt.Sprint would call the String function on the FileMode, which again would call fmt.Sprint, looping like this forever. Instead, we now call the String function that's already implemented on os.FileMode --- internals/cli/filemode/filemode.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internals/cli/filemode/filemode.go b/internals/cli/filemode/filemode.go index acce3364..5f579771 100644 --- a/internals/cli/filemode/filemode.go +++ b/internals/cli/filemode/filemode.go @@ -2,7 +2,6 @@ package filemode import ( - "fmt" "os" "strconv" @@ -48,7 +47,7 @@ func (m *FileMode) Set(value string) error { // String implements the flag.Value interface. func (m FileMode) String() string { - return fmt.Sprint(m) + return m.FileMode().String() } // FileMode returns the file mode as an os.FileMode. From 5d4a17a4060ddd58e6eb6370fdd34693c26daebe Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 18:31:43 +0200 Subject: [PATCH 69/70] Output as base-8 string instead of letters Previous implementation outputted something like -rw-r--r-- instead of 0644. --- internals/cli/filemode/filemode.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/cli/filemode/filemode.go b/internals/cli/filemode/filemode.go index 5f579771..91634e65 100644 --- a/internals/cli/filemode/filemode.go +++ b/internals/cli/filemode/filemode.go @@ -47,7 +47,7 @@ func (m *FileMode) Set(value string) error { // String implements the flag.Value interface. func (m FileMode) String() string { - return m.FileMode().String() + return fmt.Sprintf("%#o", m.FileMode().Perm()) } // FileMode returns the file mode as an os.FileMode. From ca4a54fe31fa1acf096224344c9e4b5ae87ad17a Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 18:45:21 +0200 Subject: [PATCH 70/70] Add missing import --- internals/cli/filemode/filemode.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internals/cli/filemode/filemode.go b/internals/cli/filemode/filemode.go index 91634e65..656767e7 100644 --- a/internals/cli/filemode/filemode.go +++ b/internals/cli/filemode/filemode.go @@ -2,6 +2,7 @@ package filemode import ( + "fmt" "os" "strconv"