/
main.go
129 lines (107 loc) · 2.87 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package main
import (
"fmt"
"log"
"os"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/urfave/cli"
"golang.org/x/crypto/ssh/terminal"
)
func main() {
app := cli.NewApp()
app.Name = "config"
app.Usage = "get and set encrypted values from/to AWS SSM"
app.Version = "v0.1.0"
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "profile",
Usage: "AWS `PROFILE` in ~/.aws/credentials",
},
}
app.Commands = []cli.Command{
{
Name: "set",
Usage: "set a secret value to SSM - set <name> <kms key id>",
Action: enforceSession(func(c *cli.Context, client *ssm.SSM) error {
if !isEven(c.NArg()) {
return cli.NewExitError("arguments must be pairs of <name> <key id>", 1)
}
// grab each pair of <name> <key id> and prompt for value
for i := 0; i < (c.NArg() - 1); i += 2 {
name := c.Args().Get(i)
keyId := c.Args().Get(i + 1)
// prompt for value
fmt.Println("Paste your value below...")
fmt.Printf("%s: ", name)
bytes, _ := terminal.ReadPassword(0)
fmt.Println()
// encrypt to SSM
_, err := client.PutParameter(&ssm.PutParameterInput{
Type: aws.String("SecureString"),
KeyId: aws.String(keyId),
Name: aws.String(name),
Value: aws.String(string(bytes)),
})
if err != nil {
return cli.NewExitError(
fmt.Sprintf("could not write parameter %s - %s", name, err.Error()), 1)
}
}
return nil
}),
},
{
Name: "get",
Usage: "get a secret value in SSM - get <name1> <name2> ... <nameN>",
Action: enforceSession(func(c *cli.Context, client *ssm.SSM) error {
if c.NArg() == 0 {
return cli.NewExitError("read needs at least one parameter name to fetch", 1)
}
for _, name := range c.Args() {
resp, err := client.GetParameter(&ssm.GetParameterInput{
Name: aws.String(name),
WithDecryption: aws.Bool(true),
})
if err != nil {
return cli.NewExitError(err.Error(), 1)
}
fmt.Println(*(resp.Parameter.Value))
}
return nil
}),
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
func enforceSession(action func(*cli.Context, *ssm.SSM) error) cli.ActionFunc {
return func(c *cli.Context) error {
defer func() {
if r := recover(); r != nil {
log.Fatal(r)
}
}()
// AWS session
var sess *session.Session
profile := c.GlobalString("profile")
if profile != "" {
// look for profile by name
sess = session.Must(session.NewSessionWithOptions(session.Options{
Profile: profile,
SharedConfigState: session.SharedConfigEnable,
}))
} else {
// no profile provided, lookup by env vars
sess = session.Must(session.NewSession())
}
// SSM client
client := ssm.New(sess)
return action(c, client)
}
}
func isEven(v int) bool {
return v%2 == 0
}