forked from hashicorp/vault
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cli.go
163 lines (128 loc) · 4.4 KB
/
cli.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
156
157
158
159
160
161
162
163
package awsauth
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/helper/awsutil"
)
type CLIHandler struct{}
// Generates the necessary data to send to the Vault server for generating a token
// This is useful for other API clients to use
func GenerateLoginData(accessKey, secretKey, sessionToken, headerValue string) (map[string]interface{}, error) {
loginData := make(map[string]interface{})
credConfig := &awsutil.CredentialsConfig{
AccessKey: accessKey,
SecretKey: secretKey,
SessionToken: sessionToken,
}
creds, err := credConfig.GenerateCredentialChain()
if err != nil {
return nil, err
}
if creds == nil {
return nil, fmt.Errorf("could not compile valid credential providers from static config, environment, shared, or instance metadata")
}
_, err = creds.Get()
if err != nil {
return nil, fmt.Errorf("failed to retrieve credentials from credential chain: %v", err)
}
// Use the credentials we've found to construct an STS session
stsSession, err := session.NewSessionWithOptions(session.Options{
Config: aws.Config{Credentials: creds},
})
if err != nil {
return nil, err
}
var params *sts.GetCallerIdentityInput
svc := sts.New(stsSession)
stsRequest, _ := svc.GetCallerIdentityRequest(params)
// Inject the required auth header value, if supplied, and then sign the request including that header
if headerValue != "" {
stsRequest.HTTPRequest.Header.Add(iamServerIdHeader, headerValue)
}
stsRequest.Sign()
// Now extract out the relevant parts of the request
headersJson, err := json.Marshal(stsRequest.HTTPRequest.Header)
if err != nil {
return nil, err
}
requestBody, err := ioutil.ReadAll(stsRequest.HTTPRequest.Body)
if err != nil {
return nil, err
}
loginData["iam_http_request_method"] = stsRequest.HTTPRequest.Method
loginData["iam_request_url"] = base64.StdEncoding.EncodeToString([]byte(stsRequest.HTTPRequest.URL.String()))
loginData["iam_request_headers"] = base64.StdEncoding.EncodeToString(headersJson)
loginData["iam_request_body"] = base64.StdEncoding.EncodeToString(requestBody)
return loginData, nil
}
func (h *CLIHandler) Auth(c *api.Client, m map[string]string) (*api.Secret, error) {
mount, ok := m["mount"]
if !ok {
mount = "aws"
}
role, ok := m["role"]
if !ok {
role = ""
}
headerValue, ok := m["header_value"]
if !ok {
headerValue = ""
}
loginData, err := GenerateLoginData(m["aws_access_key_id"], m["aws_secret_access_key"], m["aws_security_token"], headerValue)
if err != nil {
return nil, err
}
if loginData == nil {
return nil, fmt.Errorf("got nil response from GenerateLoginData")
}
loginData["role"] = role
path := fmt.Sprintf("auth/%s/login", mount)
secret, err := c.Logical().Write(path, loginData)
if err != nil {
return nil, err
}
if secret == nil {
return nil, fmt.Errorf("empty response from credential provider")
}
return secret, nil
}
func (h *CLIHandler) Help() string {
help := `
Usage: vault login -method=aws [CONFIG K=V...]
The AWS auth method allows users to authenticate with AWS IAM
credentials. The AWS IAM credentials may be specified in a number of ways,
listed in order of precedence below:
1. Explicitly via the command line (not recommended)
2. Via the standard AWS environment variables (AWS_ACCESS_KEY, etc.)
3. Via the ~/.aws/credentials file
4. Via EC2 instance profile
Authenticate using locally stored credentials:
$ vault login -method=aws
Authenticate by passing keys:
$ vault login -method=aws aws_access_key_id=... aws_secret_access_key=...
Configuration:
aws_access_key_id=<string>
Explicit AWS access key ID
aws_secret_access_key=<string>
Explicit AWS secret access key
aws_security_token=<string>
Explicit AWS security token for temporary credentials
header_value=<string>
Value for the x-vault-aws-iam-server-id header in requests
mount=<string>
Path where the AWS credential method is mounted. This is usually provided
via the -path flag in the "vault login" command, but it can be specified
here as well. If specified here, it takes precedence over the value for
-path. The default value is "aws".
role=<string>
Name of the role to request a token against
`
return strings.TrimSpace(help)
}