forked from hashicorp/vault
-
Notifications
You must be signed in to change notification settings - Fork 2
/
cli.go
136 lines (114 loc) · 4.21 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
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")
}
// 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) (string, 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 "", err
}
if loginData == nil {
return "", 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 "", err
}
if secret == nil {
return "", fmt.Errorf("empty response from credential provider")
}
return secret.Auth.ClientToken, nil
}
func (h *CLIHandler) Help() string {
help := `
The AWS credential provider allows you to authenticate with
AWS IAM credentials. To use it, you specify valid AWS IAM credentials
in one of a number of ways. They can be specified explicitly on the
command line (which in general you should not do), via the standard AWS
environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and
AWS_SECURITY_TOKEN), via the ~/.aws/credentials file, or via an EC2
instance profile (in that order).
Example: vault auth -method=aws
If you need to explicitly pass in credentials, you would do it like this:
Example: vault auth -method=aws aws_access_key_id=<access key> aws_secret_access_key=<secret key> aws_security_token=<token>
Key/Value Pairs:
mount=aws The mountpoint for the AWS credential provider.
Defaults to "aws"
aws_access_key_id=<access key> Explicitly specified AWS access key
aws_secret_access_key=<secret key> Explicitly specified AWS secret key
aws_security_token=<token> Security token for temporary credentials
header_value The Value of the X-Vault-AWS-IAM-Server-ID header.
role The name of the role you're requesting a token for
`
return strings.TrimSpace(help)
}