Skip to content
This repository was archived by the owner on Feb 16, 2023. It is now read-only.

Commit d0c23fb

Browse files
authored
Merge branch 'develop' into feature/upgrade-secrethub-go
2 parents 26b6d99 + 589a0dd commit d0c23fb

6 files changed

Lines changed: 213 additions & 92 deletions

File tree

go.mod

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ require (
2020
github.com/secrethub/secrethub-go v0.31.0
2121
github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07
2222
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
23-
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
2423
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e
2524
golang.org/x/text v0.3.2
2625
google.golang.org/api v0.26.0
27-
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84
2826
gopkg.in/yaml.v2 v2.2.2
2927
gotest.tools v2.2.0+incompatible
3028
)

internals/cli/filemode/filemode.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
package filemode
33

44
import (
5+
"fmt"
56
"os"
67
"strconv"
78

@@ -47,7 +48,7 @@ func (m *FileMode) Set(value string) error {
4748

4849
// String implements the flag.Value interface.
4950
func (m FileMode) String() string {
50-
return string(m)
51+
return fmt.Sprintf("%#o", m.FileMode().Perm())
5152
}
5253

5354
// FileMode returns the file mode as an os.FileMode.

internals/secrethub/app.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ func NewApp() *App {
7979
io := ui.NewUserIO()
8080
store := NewCredentialConfig(io)
8181
help := "The SecretHub command-line interface is a unified tool to manage your infrastructure secrets with SecretHub.\n\n" +
82+
"If you do not yet have a SecretHub account, go here to create one:\n\n" +
83+
" https://signup.secrethub.io/\n\n" +
8284
"For a step-by-step introduction, check out:\n\n" +
8385
" https://secrethub.io/docs/getting-started/\n\n" +
8486
"To get help, see:\n\n" +

internals/secrethub/credential_store.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111

1212
// Errors
1313
var (
14-
ErrCredentialNotExist = errMain.Code("credential_not_exist").Error("could not find credential file. Run `secrethub signup` to create an account.")
14+
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.")
1515
)
1616

1717
// CredentialConfig handles the configuration necessary for local credentials.

internals/secrethub/init.go

Lines changed: 122 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,32 @@ import (
1616

1717
// InitCommand configures the user's SecretHub account for use on this machine.
1818
type InitCommand struct {
19-
backupCode string
20-
force bool
21-
io ui.IO
22-
newClient newClientFunc
23-
newClientWithoutCredentials func(credentials.Provider) (secrethub.ClientInterface, error)
24-
credentialStore CredentialConfig
25-
progressPrinter progress.Printer
19+
backupCode string
20+
setupCode string
21+
force bool
22+
io ui.IO
23+
newUnauthenticatedClient newClientFunc
24+
newClientWithCredentials func(credentials.Provider) (secrethub.ClientInterface, error)
25+
credentialStore CredentialConfig
26+
progressPrinter progress.Printer
2627
}
2728

2829
// NewInitCommand creates a new InitCommand.
29-
func NewInitCommand(io ui.IO, newClient newClientFunc, newClientWithoutCredentials func(credentials.Provider) (secrethub.ClientInterface, error), credentialStore CredentialConfig) *InitCommand {
30+
func NewInitCommand(io ui.IO, newUnauthenticatedClient newClientFunc, newClientWithCredentials func(credentials.Provider) (secrethub.ClientInterface, error), credentialStore CredentialConfig) *InitCommand {
3031
return &InitCommand{
31-
io: io,
32-
newClient: newClient,
33-
newClientWithoutCredentials: newClientWithoutCredentials,
34-
credentialStore: credentialStore,
35-
progressPrinter: progress.NewPrinter(io.Output(), 500*time.Millisecond),
32+
io: io,
33+
newUnauthenticatedClient: newUnauthenticatedClient,
34+
newClientWithCredentials: newClientWithCredentials,
35+
credentialStore: credentialStore,
36+
progressPrinter: progress.NewPrinter(io.Output(), 500*time.Millisecond),
3637
}
3738
}
3839

3940
// Register registers the command, arguments and flags on the provided Registerer.
4041
func (cmd *InitCommand) Register(r command.Registerer) {
4142
clause := r.Command("init", "Initialize the SecretHub client for first use on this device.")
4243
clause.Flag("backup-code", "The backup code used to restore an existing account to this device.").StringVar(&cmd.backupCode)
44+
clause.Flag("setup-code", "The setup code used to configure the CLI to use an account created on the website.").StringVar(&cmd.setupCode)
4345
registerForceFlag(clause).BoolVar(&cmd.force)
4446

4547
command.BindAction(clause, cmd.Run)
@@ -50,11 +52,16 @@ type InitMode int
5052
const (
5153
InitModeSignup InitMode = iota + 1
5254
InitModeBackupCode
55+
InitModeSetupCode
5356
)
5457

5558
// Run configures the user's SecretHub account for use on this machine.
5659
// If an account was already configured, the user is prompted for confirmation to overwrite it.
5760
func (cmd *InitCommand) Run() error {
61+
if cmd.setupCode != "" && cmd.backupCode != "" {
62+
return ErrFlagsConflict("--backup-code and --setup-code")
63+
}
64+
5865
credentialPath := cmd.credentialStore.ConfigDir().Credential().Path()
5966

6067
if cmd.credentialStore.ConfigDir().Credential().Exists() && !cmd.force {
@@ -76,7 +83,9 @@ func (cmd *InitCommand) Run() error {
7683
}
7784

7885
var mode InitMode
79-
if cmd.backupCode != "" {
86+
if cmd.setupCode != "" {
87+
mode = InitModeSetupCode
88+
} else if cmd.backupCode != "" {
8089
mode = InitModeBackupCode
8190
}
8291

@@ -86,16 +95,18 @@ func (cmd *InitCommand) Run() error {
8695
}
8796
option, err := ui.Choose(cmd.io, "How do you want to initialize your SecretHub account on this device?",
8897
[]string{
89-
"Signup for a new account",
98+
"Sign up for a new account",
9099
"Use a backup code to recover an existing account",
91100
}, 3)
92101
if err != nil {
93102
return err
94103
}
104+
fmt.Fprintln(cmd.io.Output())
95105

96106
switch option {
97107
case 0:
98-
mode = InitModeSignup
108+
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.")
109+
return nil
99110
case 1:
100111
mode = InitModeBackupCode
101112
}
@@ -105,12 +116,83 @@ func (cmd *InitCommand) Run() error {
105116
case InitModeSignup:
106117
signupCommand := SignUpCommand{
107118
io: cmd.io,
108-
newClient: cmd.newClient,
119+
newClient: cmd.newUnauthenticatedClient,
109120
credentialStore: cmd.credentialStore,
110121
progressPrinter: cmd.progressPrinter,
111122
force: cmd.force,
112123
}
113124
return signupCommand.Run()
125+
case InitModeSetupCode:
126+
setupCode := cmd.setupCode
127+
128+
fmt.Fprintf(cmd.io.Output(), credentialCreationMessage, credentialPath)
129+
130+
// Only prompt for a passphrase when the user hasn't used --force.
131+
// Otherwise, we assume the passphrase was intentionally not
132+
// configured to output a plaintext credential.
133+
var passphrase string
134+
if !cmd.credentialStore.IsPassphraseSet() && !cmd.force {
135+
var err error
136+
passphrase, err = askCredentialPassphrase(cmd.io)
137+
if err != nil {
138+
return err
139+
}
140+
}
141+
142+
deviceName, err := promptForDeviceName(cmd.io)
143+
if err != nil {
144+
return err
145+
}
146+
147+
fmt.Fprint(cmd.io.Output(), "Setting up your account...")
148+
cmd.progressPrinter.Start()
149+
150+
client, err := cmd.newClientWithCredentials(credentials.NewSetupCode(setupCode))
151+
if err != nil {
152+
cmd.progressPrinter.Stop()
153+
return err
154+
}
155+
156+
credential := credentials.CreateKey()
157+
_, err = client.Credentials().Create(credential, deviceName)
158+
if err != nil {
159+
cmd.progressPrinter.Stop()
160+
return err
161+
}
162+
163+
err = writeNewCredential(credential, passphrase, cmd.credentialStore.ConfigDir().Credential())
164+
if err != nil {
165+
cmd.progressPrinter.Stop()
166+
return err
167+
}
168+
169+
client, err = cmd.newClientWithCredentials(credential)
170+
if err != nil {
171+
cmd.progressPrinter.Stop()
172+
return err
173+
}
174+
175+
me, err := client.Me().GetUser()
176+
if err != nil {
177+
cmd.progressPrinter.Stop()
178+
return err
179+
}
180+
181+
secretPath, err := createStartRepo(client, me.Username, me.FullName)
182+
if err != nil {
183+
cmd.progressPrinter.Stop()
184+
return err
185+
}
186+
cmd.progressPrinter.Stop()
187+
fmt.Fprint(cmd.io.Output(), "Created your account.\n\n")
188+
189+
err = createWorkspace(client, cmd.io, "", "", cmd.progressPrinter)
190+
if err != nil {
191+
return err
192+
}
193+
194+
fmt.Fprintf(cmd.io.Output(), "Setup complete. To read your first secret, run:\n\n secrethub read %s\n\n", secretPath)
195+
return nil
114196
case InitModeBackupCode:
115197
backupCode := cmd.backupCode
116198

@@ -122,7 +204,7 @@ func (cmd *InitCommand) Run() error {
122204
}
123205
}
124206

125-
client, err := cmd.newClientWithoutCredentials(credentials.UseBackupCode(backupCode))
207+
client, err := cmd.newClientWithCredentials(credentials.UseBackupCode(backupCode))
126208
if err != nil {
127209
return err
128210
}
@@ -146,19 +228,9 @@ func (cmd *InitCommand) Run() error {
146228
return nil
147229
}
148230

149-
deviceName := ""
150-
question := "What is the name of this device?"
151-
hostName, err := os.Hostname()
152-
if err == nil {
153-
deviceName, err = ui.AskWithDefault(cmd.io, question, hostName)
154-
if err != nil {
155-
return err
156-
}
157-
} else {
158-
deviceName, err = ui.Ask(cmd.io, question)
159-
if err != nil {
160-
return err
161-
}
231+
deviceName, err := promptForDeviceName(cmd.io)
232+
if err != nil {
233+
return err
162234
}
163235

164236
// Only prompt for a passphrase when the user hasn't used --force.
@@ -167,7 +239,7 @@ func (cmd *InitCommand) Run() error {
167239
var passphrase string
168240
if !cmd.credentialStore.IsPassphraseSet() && !cmd.force {
169241
var err error
170-
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)
242+
passphrase, err = askCredentialPassphrase(cmd.io)
171243
if err != nil {
172244
return err
173245
}
@@ -197,3 +269,21 @@ func (cmd *InitCommand) Run() error {
197269
return errors.New("invalid option")
198270
}
199271
}
272+
273+
func promptForDeviceName(io ui.IO) (string, error) {
274+
deviceName := ""
275+
question := "What is the name of this device?"
276+
hostName, err := os.Hostname()
277+
if err == nil {
278+
deviceName, err = ui.AskWithDefault(io, question, hostName)
279+
if err != nil {
280+
return "", err
281+
}
282+
} else {
283+
deviceName, err = ui.Ask(io, question)
284+
if err != nil {
285+
return "", err
286+
}
287+
}
288+
return deviceName, nil
289+
}

0 commit comments

Comments
 (0)