Skip to content

Commit c138f56

Browse files
committed
Create a prompt subpackage
1 parent 958d075 commit c138f56

File tree

10 files changed

+90
-64
lines changed

10 files changed

+90
-64
lines changed

add.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"os"
55

66
"github.com/99designs/aws-vault/keyring"
7+
"github.com/99designs/aws-vault/prompt"
78
"github.com/aws/aws-sdk-go/aws/credentials"
89
)
910

@@ -25,10 +26,10 @@ func AddCommand(ui Ui, input AddCommandInput) {
2526
}
2627
} else {
2728
var err error
28-
if accessKeyId, err = prompt("Enter Access Key ID: "); err != nil {
29+
if accessKeyId, err = prompt.TerminalPrompt("Enter Access Key ID: "); err != nil {
2930
ui.Error.Fatal(err)
3031
}
31-
if secretKey, err = promptPassword("Enter Secret Access Key: "); err != nil {
32+
if secretKey, err = prompt.TerminalPrompt("Enter Secret Access Key: "); err != nil {
3233
ui.Error.Fatal(err)
3334
}
3435
}

dialog/dialog_darwin.go

-45
This file was deleted.

exec.go

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"github.com/99designs/aws-vault/keyring"
12+
"github.com/99designs/aws-vault/prompt"
1213
"github.com/aws/aws-sdk-go/aws/awserr"
1314
"github.com/aws/aws-sdk-go/aws/credentials"
1415
)
@@ -20,6 +21,7 @@ type ExecCommandInput struct {
2021
Keyring keyring.Keyring
2122
Duration time.Duration
2223
MfaToken string
24+
MfaPrompt prompt.PromptFunc
2325
StartServer bool
2426
Signals chan os.Signal
2527
NoSession bool
@@ -51,6 +53,7 @@ func ExecCommand(ui Ui, input ExecCommandInput) {
5153
creds, err := NewVaultCredentials(input.Keyring, input.Profile, VaultOptions{
5254
SessionDuration: input.Duration,
5355
MfaToken: input.MfaToken,
56+
MfaPrompt: input.MfaPrompt,
5457
})
5558
if err != nil {
5659
ui.Error.Fatal(err)

login.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,24 @@ import (
99
"net/url"
1010

1111
"github.com/99designs/aws-vault/keyring"
12+
"github.com/99designs/aws-vault/prompt"
1213
"github.com/aws/aws-sdk-go/aws/awserr"
1314
"github.com/aws/aws-sdk-go/aws/credentials"
1415
"github.com/skratchdot/open-golang/open"
1516
)
1617

1718
type LoginCommandInput struct {
18-
Profile string
19-
Keyring keyring.Keyring
20-
MfaToken string
19+
Profile string
20+
Keyring keyring.Keyring
21+
MfaToken string
22+
MfaPrompt prompt.PromptFunc
2123
}
2224

2325
func LoginCommand(ui Ui, input LoginCommandInput) {
2426
provider, err := NewVaultProvider(input.Keyring, input.Profile, VaultOptions{
2527
AssumeRoleDuration: MaxAssumeRoleDuration,
2628
MfaToken: input.MfaToken,
29+
MfaPrompt: input.MfaPrompt,
2730
})
2831
if err != nil {
2932
ui.Error.Fatal(err)

main.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package main
22

33
import (
4+
"fmt"
45
"io/ioutil"
56
"log"
67
"os"
78
"os/signal"
89

910
"github.com/99designs/aws-vault/keyring"
11+
"github.com/99designs/aws-vault/prompt"
1012
"gopkg.in/alecthomas/kingpin.v2"
1113
)
1214

@@ -28,7 +30,9 @@ func (w logWriter) Write(b []byte) (int, error) {
2830
}
2931

3032
func main() {
33+
3134
var (
35+
prompts = prompt.Available()
3236
debug = kingpin.Flag("debug", "Show debugging output").Bool()
3337
add = kingpin.Command("add", "Adds credentials, prompts if none provided")
3438
addProfile = add.Arg("profile", "Name of the profile").Required().String()
@@ -38,6 +42,7 @@ func main() {
3842
execNoSession = exec.Flag("no-session", "Use root credentials, no session created").Short('n').Bool()
3943
execSessDuration = exec.Flag("session-ttl", "Expiration time for aws session").Default("4h").OverrideDefaultFromEnvar("AWS_SESSION_TTL").Short('t').Duration()
4044
execMfaToken = exec.Flag("mfa-token", "The mfa token to use").Short('m').String()
45+
execMfaPrompt = exec.Flag("mfa-prompt", fmt.Sprintf("Prompt to use for mfa, from %v", prompts)).Default("terminal").OverrideDefaultFromEnvar("AWS_VAULT_PROMPT").Enum(prompts...)
4146
execServer = exec.Flag("server", "Run the server in the background for credentials").Short('s').Bool()
4247
execProfile = exec.Arg("profile", "Name of the profile").Required().String()
4348
execCmd = exec.Arg("cmd", "Command to execute").Default(os.Getenv("SHELL")).String()
@@ -48,6 +53,7 @@ func main() {
4853
login = kingpin.Command("login", "Generate a login link for the AWS Console")
4954
loginProfile = login.Arg("profile", "Name of the profile").Required().String()
5055
loginMfaToken = login.Flag("mfa-token", "The mfa token to use").Short('t').String()
56+
loginMfaPrompt = login.Flag("mfa-prompt", fmt.Sprintf("Prompt to use for mfa, from %v", prompts)).Default("terminal").OverrideDefaultFromEnvar("AWS_VAULT_PROMPT").Enum(prompts...)
5157
server = kingpin.Command("server", "Run an ec2 instance role server locally")
5258
)
5359

@@ -109,15 +115,17 @@ func main() {
109115
Duration: *execSessDuration,
110116
Signals: signals,
111117
MfaToken: *execMfaToken,
118+
MfaPrompt: prompt.Method(*execMfaPrompt),
112119
StartServer: *execServer,
113120
NoSession: *execNoSession,
114121
})
115122

116123
case login.FullCommand():
117124
LoginCommand(ui, LoginCommandInput{
118-
Profile: *loginProfile,
119-
Keyring: keyring,
120-
MfaToken: *loginMfaToken,
125+
Profile: *loginProfile,
126+
Keyring: keyring,
127+
MfaToken: *loginMfaToken,
128+
MfaPrompt: prompt.Method(*loginMfaPrompt),
121129
})
122130

123131
case server.FullCommand():

prompt/cocoa.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// +build darwin
2+
3+
package prompt
4+
5+
import (
6+
"fmt"
7+
"os/exec"
8+
"strings"
9+
)
10+
11+
func CocoaPrompt(prompt string) (string, error) {
12+
cmd := exec.Command("/usr/bin/osascript", "-e", fmt.Sprintf(`
13+
display dialog "%s" default answer "" buttons {"OK", "Cancel"} default button 1
14+
text returned of the result
15+
return result`,
16+
prompt))
17+
18+
out, err := cmd.Output()
19+
if err != nil {
20+
return "", err
21+
}
22+
23+
return strings.TrimSpace(string(out)), nil
24+
}
25+
26+
func init() {
27+
Methods["cocoa"] = CocoaPrompt
28+
}

prompt/prompt.go

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package prompt
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
)
7+
8+
type PromptFunc func(string) (string, error)
9+
10+
var Methods = map[string]PromptFunc{
11+
"terminal": TerminalPrompt,
12+
}
13+
14+
var errPromptAborted = errors.New("User cancelled prompt with no value")
15+
16+
func Available() []string {
17+
methods := []string{}
18+
for k := range Methods {
19+
methods = append(methods, k)
20+
}
21+
return methods
22+
}
23+
24+
func Method(s string) PromptFunc {
25+
m, ok := Methods[s]
26+
if !ok {
27+
panic(fmt.Sprintf("Prompt method %q doesn't exist", s))
28+
}
29+
return m
30+
}

prompt.go prompt/terminal.go

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,19 @@
1-
package main
1+
package prompt
22

33
import (
44
"bufio"
55
"fmt"
66
"os"
77
"strings"
8-
9-
"github.com/bgentry/speakeasy"
108
)
119

12-
func prompt(prompt string) (string, error) {
10+
func TerminalPrompt(prompt string) (string, error) {
11+
fmt.Fprint(os.Stderr, prompt)
12+
1313
reader := bufio.NewReader(os.Stdin)
14-
fmt.Print(prompt)
1514
text, err := reader.ReadString('\n')
1615
if err != nil {
1716
return "", err
1817
}
1918
return strings.TrimSpace(text), nil
2019
}
21-
22-
func promptPassword(prompt string) (string, error) {
23-
return speakeasy.Ask(prompt)
24-
}

provider.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"time"
99

1010
"github.com/99designs/aws-vault/keyring"
11+
"github.com/99designs/aws-vault/prompt"
1112
"github.com/aws/aws-sdk-go/aws"
1213
"github.com/aws/aws-sdk-go/aws/credentials"
1314
"github.com/aws/aws-sdk-go/service/sts"
@@ -33,6 +34,7 @@ type VaultOptions struct {
3334
AssumeRoleDuration time.Duration
3435
ExpiryWindow time.Duration
3536
MfaToken string
37+
MfaPrompt prompt.PromptFunc
3638
}
3739

3840
func (o VaultOptions) Validate() error {
@@ -171,7 +173,7 @@ func (p *VaultProvider) getSessionToken(creds *credentials.Value) (sts.Credentia
171173
if mfa, ok := p.profiles[p.profile]["mfa_serial"]; ok {
172174
params.SerialNumber = aws.String(mfa)
173175
if p.MfaToken == "" {
174-
token, err := prompt(fmt.Sprintf("Enter token for %s: ", mfa))
176+
token, err := p.MfaPrompt(fmt.Sprintf("Enter token for %s: ", mfa))
175177
if err != nil {
176178
return sts.Credentials{}, err
177179
}

rm.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
"github.com/99designs/aws-vault/keyring"
7+
"github.com/99designs/aws-vault/prompt"
78
)
89

910
type RemoveCommandInput struct {
@@ -15,7 +16,7 @@ type RemoveCommandInput struct {
1516
func RemoveCommand(ui Ui, input RemoveCommandInput) {
1617
if !input.SessionsOnly {
1718
provider := &KeyringProvider{Keyring: input.Keyring, Profile: input.Profile}
18-
r, err := prompt(fmt.Sprintf("Delete credentials for profile %q? (Y|n)", input.Profile))
19+
r, err := prompt.TerminalPrompt(fmt.Sprintf("Delete credentials for profile %q? (Y|n)", input.Profile))
1920
if err != nil {
2021
ui.Error.Fatal(err)
2122
} else if r == "N" || r == "n" {

0 commit comments

Comments
 (0)