forked from hashicorp/vault
/
secret_creds.go
139 lines (116 loc) · 3.43 KB
/
secret_creds.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
package database
import (
"fmt"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
)
const SecretCredsType = "creds"
func secretCreds(b *databaseBackend) *framework.Secret {
return &framework.Secret{
Type: SecretCredsType,
Fields: map[string]*framework.FieldSchema{},
Renew: b.secretCredsRenew(),
Revoke: b.secretCredsRevoke(),
}
}
func (b *databaseBackend) secretCredsRenew() framework.OperationFunc {
return func(req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
// Get the username from the internal data
usernameRaw, ok := req.Secret.InternalData["username"]
if !ok {
return nil, fmt.Errorf("secret is missing username internal data")
}
username, ok := usernameRaw.(string)
roleNameRaw, ok := req.Secret.InternalData["role"]
if !ok {
return nil, fmt.Errorf("could not find role with name: %s", req.Secret.InternalData["role"])
}
role, err := b.Role(req.Storage, roleNameRaw.(string))
if err != nil {
return nil, err
}
if role == nil {
return nil, fmt.Errorf("error during renew: could not find role with name %s", req.Secret.InternalData["role"])
}
f := framework.LeaseExtend(role.DefaultTTL, role.MaxTTL, b.System())
resp, err := f(req, data)
if err != nil {
return nil, err
}
// Grab the read lock
b.RLock()
var unlockFunc func() = b.RUnlock
// Get the Database object
db, ok := b.getDBObj(role.DBName)
if !ok {
// Upgrade lock
b.RUnlock()
b.Lock()
unlockFunc = b.Unlock
// Create a new DB object
db, err = b.createDBObj(req.Storage, role.DBName)
if err != nil {
unlockFunc()
return nil, fmt.Errorf("cound not retrieve db with name: %s, got error: %s", role.DBName, err)
}
}
// Make sure we increase the VALID UNTIL endpoint for this user.
if expireTime := resp.Secret.ExpirationTime(); !expireTime.IsZero() {
err := db.RenewUser(role.Statements, username, expireTime)
// Unlock
unlockFunc()
if err != nil {
b.closeIfShutdown(role.DBName, err)
return nil, err
}
}
return resp, nil
}
}
func (b *databaseBackend) secretCredsRevoke() framework.OperationFunc {
return func(req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
// Get the username from the internal data
usernameRaw, ok := req.Secret.InternalData["username"]
if !ok {
return nil, fmt.Errorf("secret is missing username internal data")
}
username, ok := usernameRaw.(string)
var resp *logical.Response
roleNameRaw, ok := req.Secret.InternalData["role"]
if !ok {
return nil, fmt.Errorf("no role name was provided")
}
role, err := b.Role(req.Storage, roleNameRaw.(string))
if err != nil {
return nil, err
}
if role == nil {
return nil, fmt.Errorf("error during revoke: could not find role with name %s", req.Secret.InternalData["role"])
}
// Grab the read lock
b.RLock()
var unlockFunc func() = b.RUnlock
// Get our connection
db, ok := b.getDBObj(role.DBName)
if !ok {
// Upgrade lock
b.RUnlock()
b.Lock()
unlockFunc = b.Unlock
// Create a new DB object
db, err = b.createDBObj(req.Storage, role.DBName)
if err != nil {
unlockFunc()
return nil, fmt.Errorf("cound not retrieve db with name: %s, got error: %s", role.DBName, err)
}
}
err = db.RevokeUser(role.Statements, username)
// Unlock
unlockFunc()
if err != nil {
b.closeIfShutdown(role.DBName, err)
return nil, err
}
return resp, nil
}
}