/
vault_aws_login.go
155 lines (129 loc) · 4.65 KB
/
vault_aws_login.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package goawsvault
import (
"net/http"
"time"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/defaults"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/builtin/credential/aws"
log "github.com/sirupsen/logrus"
)
// consts.
const (
httpClientTimeout = 10 * time.Second
)
var httpClient = &http.Client{
Timeout: httpClientTimeout,
}
// LoginWithinAwsEcsContainerAutomatically If the aws ecs container is running under a specific aws assume role,
// and this role is configured on Vault server side, then this method will query the aws assume role's credential in
// ECS container automatically and return a Vault client with valid token.
// NO need any other classic AWS credentials(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY)
func LoginWithinAwsEcsContainerAutomatically(vaultHost string, awsRegion string) *api.Client {
token, err := getTokenInAwsEcsContainer(vaultHost, awsRegion)
if err != nil {
panic(err)
}
client, err := api.NewClient(&api.Config{Address: vaultHost, HttpClient: httpClient})
if err != nil {
panic(err)
}
client.SetToken(token)
return client
}
// LoginByAwsRoleArn A classic AWS credentials(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) is required for this function
// to execute AWS API to query the specific role. In general, you need to setup the AWS credential in env vars like
// this:
// _=os.Setenv("AWS_ACCESS_KEY_ID","AKKKAFYN9K3AUY74SNY39")
// _=os.Setenv("AWS_SECRET_ACCESS_KEY","ZTL9288NXdymfhxcISMOCU+AsYy9O3RsiDptABm8")
// Please note that you need to setup the trust configuration in AWS role console to make sure this credential have permission to
// query the awsRoleArn.
func LoginByAwsRoleArn(vaultHost string, awsRoleArn string, awsRegion string) *api.Client {
token, err := getTokenByAwsRoleArn(vaultHost, awsRoleArn, awsRegion)
if err != nil {
panic(err)
}
client, err := api.NewClient(&api.Config{Address: vaultHost, HttpClient: httpClient})
if err != nil {
panic(err)
}
client.SetToken(token)
return client
}
// Login In general, this method just call the vault login path you specified here.
// We usually use this to login in local env for developers. e.g:
// loginPath: auth/mycompany-dev/login
// data: map[string]interface{}{"role_id": "developer"}
func Login(vaultHost string, loginPath string, data map[string]interface{}) *api.Client {
token, err := getToken(vaultHost, loginPath, data)
if err != nil {
panic(err)
}
client, err := api.NewClient(&api.Config{Address: vaultHost, HttpClient: httpClient})
if err != nil {
panic(err)
}
client.SetToken(token)
return client
}
func getToken(vaultHost string, loginPath string, data map[string]interface{}) (string, error) {
client, err := api.NewClient(&api.Config{Address: vaultHost, HttpClient: httpClient})
if err != nil {
return "", err //nolintwrapcheck
}
secret, err := client.Logical().Write(loginPath, data)
if err != nil {
log.WithError(err).Fatal("failed to login to dev model")
}
tokenID, err := secret.TokenID()
if err != nil {
log.WithError(err).Fatal("failed extract token from secret")
}
log.Info("Got dev model vault token")
return tokenID, nil
}
func getTokenInAwsEcsContainer(vaultHost string, awsRegion string) (string, error) {
ds := defaults.Get()
credsProvider := defaults.RemoteCredProvider(*ds.Config, ds.Handlers)
creds := credentials.NewCredentials(credsProvider)
_, err := creds.Get()
if err != nil {
return "", err //nolintwrapcheck
}
log.Info("Get container AWS ECS credential success!")
data, err := awsauth.GenerateLoginData(creds, "", awsRegion)
if err != nil {
return "", err //nolintwrapcheck
}
client, err := api.NewClient(&api.Config{Address: vaultHost, HttpClient: httpClient})
if err != nil {
return "", err //nolintwrapcheck
}
secret, err := client.Logical().Write("auth/aws/login", data)
if err != nil {
return "", err //nolintwrapcheck
}
token := secret.Auth.ClientToken
return token, nil
}
func getTokenByAwsRoleArn(vaultHost string, awsRoleArn string, awsRegion string) (string, error) {
sess := session.Must(session.NewSession())
log.Info("awsRole: " + awsRoleArn + " REGION: " + awsRegion)
creds := stscreds.NewCredentials(sess, awsRoleArn)
data, err := awsauth.GenerateLoginData(creds, "", awsRegion)
if err != nil {
return "", err //nolintwrapcheck
}
client, err := api.NewClient(&api.Config{Address: vaultHost, HttpClient: httpClient})
if err != nil {
return "", err //nolintwrapcheck
}
secret, err := client.Logical().Write("auth/aws/login", data)
if err != nil {
return "", err //nolintwrapcheck
}
token := secret.Auth.ClientToken
return token, nil
}