-
Notifications
You must be signed in to change notification settings - Fork 0
/
commands.go
103 lines (86 loc) · 2.99 KB
/
commands.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
package main
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sts"
"os"
"os/exec"
"strings"
"syscall"
)
func filterExistingCredentials(list []string) []string {
var result []string
for _, item := range list {
if !strings.HasPrefix(item, "AWS_ACCESS_KEY_ID=") &&
!strings.HasPrefix(item, "AWS_SECRET_ACCESS_KEY=") &&
!strings.HasPrefix(item, "AWS_SESSION_TOKEN=") &&
!strings.HasPrefix(item, "AWS_DEFAULT_REGION=") {
result = append(result, item)
}
}
return result
}
// Encrypts data from stdin and writes to stdout
func executeCommand(iamProfile string, durationSeconds int64, args []string) {
// Human readable name of this session shown in AWS logs, for debugging purposes
hostname, err := os.Hostname()
sessionName := fmt.Sprintf("%s-%s-%s",
defaults(os.Getenv("USER"), "unknown"),
defaults(hostname, os.Getenv("HOST"), os.Getenv("HOSTNAME"), "unknown"),
randSeq(8))
// Initialize the session
var accessKeyID, secretAccessKey, sessionToken, region string
// Force enable Shared Config to support $AWS_DEFAULT_REGION and ~/.aws/config profiles
sess, err := session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
})
check(err, "Failed to initialize the AWS session")
if iamProfile != "" {
svc := sts.New(sess)
// Assume role given by ARN
params := &sts.AssumeRoleInput{
RoleArn: aws.String(iamProfile), // Required
RoleSessionName: aws.String(sessionName), // Required
DurationSeconds: aws.Int64(durationSeconds),
// ExternalId: aws.String("externalIdType"),
// Policy: aws.String("sessionPolicyDocumentType"),
// SerialNumber: aws.String("serialNumberType"),
// TokenCode: aws.String("tokenCodeType"),
}
resp, err := svc.AssumeRole(params)
check(err, "Failed to assume role")
accessKeyID = *resp.Credentials.AccessKeyId
secretAccessKey = *resp.Credentials.SecretAccessKey
sessionToken = *resp.Credentials.SessionToken
region = *sess.Config.Region
} else {
// Output the session credentials
creds, err := sess.Config.Credentials.Get()
check(err, "Failed to retrive credentials from session")
accessKeyID = creds.AccessKeyID
secretAccessKey = creds.SecretAccessKey
sessionToken = creds.SessionToken
region = *sess.Config.Region
}
// Default to launch a subshell
binary := defaults(os.Getenv("SHELL"), "/bin/sh")
// Resolve absolute path of binary
if len(args) >= 1 {
binary, err = exec.LookPath(args[0])
check(err)
}
// Inject the temporary credentials
env := append(filterExistingCredentials(os.Environ()),
fmt.Sprintf("AWS_ACCESS_KEY_ID=%s", accessKeyID),
fmt.Sprintf("AWS_SECRET_ACCESS_KEY=%s", secretAccessKey))
if sessionToken != "" {
env = append(env, fmt.Sprintf("AWS_SESSION_TOKEN=%s", sessionToken))
}
if region != "" {
env = append(env, fmt.Sprintf("AWS_DEFAULT_REGION=%s", region))
}
// Execute subcommand
err = syscall.Exec(binary, args, env)
check(err)
}