From b864b27c90a971c172406e47e873eccf11e2ed14 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Fri, 7 Aug 2020 11:18:12 +0200 Subject: [PATCH 01/26] 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 02/26] 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 03/26] 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 04/26] 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 05/26] 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 06/26] 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 07/26] 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 08/26] 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 09/26] 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 10/26] 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 11/26] 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 12/26] 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 13/26] 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 14/26] 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 15/26] 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 16/26] 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 17/26] 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 ac08b032073847547e148a0d25ee28b4c103d0e0 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 7 Sep 2020 16:12:02 +0200 Subject: [PATCH 18/26] 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 19/26] 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 20/26] 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 21/26] 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 22/26] 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 23/26] 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 24/26] 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 25/26] 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 26/26] 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)