This repository has been archived by the owner on Oct 6, 2019. It is now read-only.
/
login.go
109 lines (93 loc) · 2.73 KB
/
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
package vault
import (
"errors"
"strings"
"github.com/hashicorp/vault/api"
)
// constructs a client with server's vault address and client access token
func (auth AuthInfo) Client() (client *api.Client, err error) {
if client, err = NewVaultClient(); err == nil {
client.SetToken(auth.ID)
}
return client, err
}
// verifies whether auth ID and password are valid
// if valid, creates a client access token and returns the metadata
func (auth *AuthInfo) Login() (map[string]interface{}, error) {
client, err := NewVaultClient()
if err != nil {
return nil, err
}
client.SetToken("")
// supported means there's a mapping to how the login should be performed
t := strings.ToLower(auth.Type)
key, exists := LoginMap[t]
if !exists {
return nil, errors.New("Unsupported authentication type: " + t)
}
// token logins don't require any writes to vault
if t == "token" {
client.SetToken(auth.ID)
}
// github logins are special: they only have one auth piece
// these fields need to be swapped for the frontend to handle them easily
if t == "github" {
auth.Pass = auth.ID
auth.ID = ""
}
// if logging in for the first time with these auth backends
if t == "userpass" || t == "ldap" || t == "github" || t == "okta" {
// fetch a client token by writing to vault auth backend
loginPath := "auth/" + t + "/login/" + auth.ID
// if auth has a different backend name, use that
if auth.Path != "" {
loginPath = "auth/" + auth.Path + "/login/" + auth.ID
}
resp, err := client.Logical().Write(
loginPath,
map[string]interface{}{
key: auth.Pass,
})
if err != nil {
return nil, err
}
// sanity check to make sure client token exists
if resp.Auth == nil || resp.Auth.ClientToken == "" {
return nil, errors.New("Unable to parse vault response")
}
// set the returned client token as the client's auth
client.SetToken(resp.Auth.ClientToken)
}
// user must be able to lookup-self. This is in the default policy
lookupResp, err := client.Auth().Token().LookupSelf()
if err != nil {
return nil, err
}
// set auth type to token, so future requests don't need a login again
auth.Type = "token"
auth.ID = client.Token()
auth.Pass = ""
return lookupResp.Data, nil
}
func (auth AuthInfo) RenewSelf() (*api.Secret, error) {
client, err := auth.Client()
if err != nil {
return nil, err
}
return client.Auth().Token().RenewSelf(0)
}
func (auth AuthInfo) LookupSelf() (*api.Secret, error) {
client, err := auth.Client()
if err != nil {
return nil, err
}
return client.Auth().Token().LookupSelf()
}
// Logging in with different methods requires different secondary keys
var LoginMap = map[string]string{
"token": "",
"userpass": "password",
"github": "token",
"ldap": "password",
"okta": "password",
}