-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
cert.go
142 lines (112 loc) · 3.03 KB
/
cert.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
package cert
import (
"context"
"errors"
"fmt"
"net/http"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/command/agent/auth"
)
type certMethod struct {
logger hclog.Logger
mountPath string
name string
caCert string
clientCert string
clientKey string
// Client is the cached client to use if cert info was provided.
client *api.Client
}
var _ auth.AuthMethodWithClient = &certMethod{}
func NewCertAuthMethod(conf *auth.AuthConfig) (auth.AuthMethod, error) {
if conf == nil {
return nil, errors.New("empty config")
}
// Not concerned if the conf.Config is empty as the 'name'
// parameter is optional when using TLS Auth
c := &certMethod{
logger: conf.Logger,
mountPath: conf.MountPath,
}
if conf.Config != nil {
nameRaw, ok := conf.Config["name"]
if !ok {
nameRaw = ""
}
c.name, ok = nameRaw.(string)
if !ok {
return nil, errors.New("could not convert 'name' config value to string")
}
caCertRaw, ok := conf.Config["ca_cert"]
if ok {
c.caCert, ok = caCertRaw.(string)
if !ok {
return nil, errors.New("could not convert 'ca_cert' config value to string")
}
}
clientCertRaw, ok := conf.Config["client_cert"]
if ok {
c.clientCert, ok = clientCertRaw.(string)
if !ok {
return nil, errors.New("could not convert 'cert_file' config value to string")
}
}
clientKeyRaw, ok := conf.Config["client_key"]
if ok {
c.clientKey, ok = clientKeyRaw.(string)
if !ok {
return nil, errors.New("could not convert 'cert_key' config value to string")
}
}
}
return c, nil
}
func (c *certMethod) Authenticate(_ context.Context, client *api.Client) (string, http.Header, map[string]interface{}, error) {
c.logger.Trace("beginning authentication")
authMap := map[string]interface{}{}
if c.name != "" {
authMap["name"] = c.name
}
return fmt.Sprintf("%s/login", c.mountPath), nil, authMap, nil
}
func (c *certMethod) NewCreds() chan struct{} {
return nil
}
func (c *certMethod) CredSuccess() {}
func (c *certMethod) Shutdown() {}
// AuthClient uses the existing client's address and returns a new client with
// the auto-auth method's certificate information if that's provided in its
// config map.
func (c *certMethod) AuthClient(client *api.Client) (*api.Client, error) {
c.logger.Trace("deriving auth client to use")
clientToAuth := client
if c.caCert != "" || (c.clientKey != "" && c.clientCert != "") {
// Return cached client if present
if c.client != nil {
return c.client, nil
}
config := api.DefaultConfig()
if config.Error != nil {
return nil, config.Error
}
config.Address = client.Address()
t := &api.TLSConfig{
CACert: c.caCert,
ClientCert: c.clientCert,
ClientKey: c.clientKey,
}
// Setup TLS config
if err := config.ConfigureTLS(t); err != nil {
return nil, err
}
var err error
clientToAuth, err = api.NewClient(config)
if err != nil {
return nil, err
}
// Cache the client for future use
c.client = clientToAuth
}
return clientToAuth, nil
}