-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathcli.go
150 lines (118 loc) · 3.68 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
// Copyright © 2019, Oracle and/or its affiliates.
package ociauth
import (
"fmt"
"net/http"
"net/url"
"strings"
"github.com/hashicorp/vault/api"
"github.com/oracle/oci-go-sdk/v59/common"
"github.com/oracle/oci-go-sdk/v59/common/auth"
)
type CLIHandler struct{}
func (h *CLIHandler) Help() string {
help := `
Usage: vault login -method=oci auth_type=apikey
vault login -method=oci auth_type=instance
The OCI auth method allows users to authenticate with OCI
credentials. The OCI credentials may be specified in a number of ways,
listed below:
1. API Key
2. Instance Principal
Authenticate using API key:
First create a configuration file as explained in https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/sdkconfig.htm
Then login using the following command:
$ vault login -method=oci auth_type=apikey role=<RoleName>
Authenticate using Instance Principal:
https://docs.cloud.oracle.com/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm
$ vault login -method=oci auth_type=instance role=<RoleName>
Configuration:
auth_type=<string>
Enter one of following:
apikey (or) ak
instance (or) ip
`
return strings.TrimSpace(help)
}
func (h *CLIHandler) Auth(c *api.Client, m map[string]string) (*api.Secret, error) {
mount, ok := m["mount"]
if !ok {
mount = "oci"
}
mount = strings.TrimSuffix(mount, "/")
role, ok := m["role"]
if !ok {
return nil, fmt.Errorf("'role' is required")
}
role = strings.ToLower(role)
path := fmt.Sprintf(PathBaseFormat, mount, role)
signingPath := PathVersionBase + path
data, err := CreateLoginData(c.Address(), m, signingPath)
if err != nil {
return nil, err
}
// Now try to login
secret, err := c.Logical().Write(path, data)
if err != nil {
return nil, err
}
return secret, nil
}
// CreateLoginData creates the interface required for a login request, signed using the corresponding OCI Identity Principal
func CreateLoginData(addr string, m map[string]string, path string) (map[string]interface{}, error) {
authType, ok := m["auth_type"]
if !ok {
return nil, fmt.Errorf("'auth_type' is required")
}
var headerFunc func(string, string) (http.Header, error)
switch strings.ToLower(authType) {
case "ip", "instance":
headerFunc = GetSignedInstanceRequestHeaders
case "ak", "apikey":
headerFunc = GetSignedAPIRequestHeaders
default:
return nil, fmt.Errorf("unsupported auth_type %q", authType)
}
headers, err := headerFunc(addr, path)
if err != nil {
return nil, err
}
return map[string]interface{}{
"request_headers": headers,
}, nil
}
func GetSignedInstanceRequestHeaders(addr, path string) (http.Header, error) {
ip, err := auth.InstancePrincipalConfigurationProvider()
if err != nil {
return nil, err
}
c, err := NewOciClientWithConfigurationProvider(ip)
if err != nil {
return nil, err
}
return getSignedRequestHeaders(addr, &c, path)
}
func GetSignedAPIRequestHeaders(addr, path string) (http.Header, error) {
c, err := NewOciClientWithConfigurationProvider(common.DefaultConfigProvider())
if err != nil {
return nil, err
}
return getSignedRequestHeaders(addr, &c, path)
}
func getSignedRequestHeaders(addr string, client *OciClient, path string) (http.Header, error) {
clientURL, err := url.Parse(addr)
if err != nil {
return nil, err
}
client.Host = addr
request, err := client.ConstructLoginRequest(path)
if err != nil {
return nil, err
}
request.Host = clientURL.Host
request.Header.Set("host", request.Host)
// ref: https://tools.ietf.org/html/draft-cavage-http-signatures-06#section-2.3
request.Header.Set("(request-target)",
fmt.Sprintf("%s %s", strings.ToLower(request.Method), request.URL.RequestURI()))
return request.Header, nil
}