@@ -9,13 +9,18 @@ import (
9
9
"github.com/hashicorp/vault/logical"
10
10
"github.com/hashicorp/vault/logical/framework"
11
11
"github.com/splunk/vault-plugin-splunk/clients/splunk"
12
+ "strings"
12
13
)
13
14
15
+ const (
16
+ SEARCHHEAD = "search_head"
17
+ INDEXER = "indexer"
18
+ )
14
19
func (b * backend ) pathCredsCreate () * framework.Path {
15
20
return & framework.Path {
16
21
Pattern : "creds/" + framework .GenericNameRegex ("name" ),
17
22
Fields : map [string ]* framework.FieldSchema {
18
- "name" : & framework. FieldSchema {
23
+ "name" : {
19
24
Type : framework .TypeString ,
20
25
Description : "Name of the role" ,
21
26
},
@@ -30,7 +35,30 @@ func (b *backend) pathCredsCreate() *framework.Path {
30
35
}
31
36
}
32
37
33
- func (b * backend ) credsReadHandler (ctx context.Context , req * logical.Request , d * framework.FieldData ) (* logical.Response , error ) {
38
+ func (b * backend ) pathCredsCreateMulti () * framework.Path {
39
+ return & framework.Path {
40
+ Pattern : "creds/" + framework .GenericNameRegex ("name" ) + "/" + framework .GenericNameRegex ("node_fqdn" ),
41
+ Fields : map [string ]* framework.FieldSchema {
42
+ "name" : {
43
+ Type : framework .TypeString ,
44
+ Description : "Name of the role" ,
45
+ },
46
+ "node_fqdn" : {
47
+ Type : framework .TypeString ,
48
+ Description : "FQDN for the Splunk Stack node" ,
49
+ },
50
+ },
51
+
52
+ Callbacks : map [logical.Operation ]framework.OperationFunc {
53
+ logical .ReadOperation : b .credsReadHandler ,
54
+ },
55
+
56
+ HelpSynopsis : pathCredsCreateHelpSyn ,
57
+ HelpDescription : pathCredsCreateHelpDesc ,
58
+ }
59
+ }
60
+
61
+ func (b * backend ) credsReadHandlerStandalone (ctx context.Context , req * logical.Request , d * framework.FieldData ) (* logical.Response , error ) {
34
62
name := d .Get ("name" ).(string )
35
63
role , err := roleConfigLoad (ctx , req .Storage , name )
36
64
if err != nil {
@@ -100,6 +128,122 @@ func (b *backend) credsReadHandler(ctx context.Context, req *logical.Request, d
100
128
return resp , nil
101
129
}
102
130
131
+ func findNode (nodeFQDN string , hosts []splunk.ServerInfoEntry ) (bool , error ) {
132
+ for _ , host := range hosts {
133
+ // check if node_fqdn is in either of HostFQDN or Host. User might not always the FQDN on the cli input
134
+ if strings .Contains (host .Content .HostFQDN , nodeFQDN ) || strings .Contains (host .Content .Host , nodeFQDN ) {
135
+ // Return true if the requested node is a search head
136
+ for _ , role := range host .Content .Roles {
137
+ if role == SEARCHHEAD {
138
+ return true , nil
139
+ }
140
+ }
141
+ return false , fmt .Errorf ("host: %s isn't search head; creating ephemeral creds is only supported for search heads" , nodeFQDN )
142
+ }
143
+ }
144
+ return false , fmt .Errorf ("host: %s not found" , nodeFQDN )
145
+ }
146
+
147
+ func (b * backend ) credsReadHandlerMulti (ctx context.Context , req * logical.Request , d * framework.FieldData ) (* logical.Response , error ) {
148
+ name := d .Get ("name" ).(string )
149
+ node , _ := d .GetOk ("node_fqdn" )
150
+ nodeFQDN := node .(string )
151
+ role , err := roleConfigLoad (ctx , req .Storage , name )
152
+ if err != nil {
153
+ return nil , err
154
+ }
155
+ if role == nil {
156
+ return logical .ErrorResponse (fmt .Sprintf ("role not found: %q" , name )), nil
157
+ }
158
+
159
+ config , err := connectionConfigLoad (ctx , req .Storage , role .Connection )
160
+ if err != nil {
161
+ return nil , err
162
+ }
163
+ // Check if isStandalone is set
164
+ if config .IsStandalone {
165
+ return nil , fmt .Errorf ("expected is_standalone to be set for connection: %q" , role .Connection )
166
+ }
167
+
168
+ // If role name isn't in allowed roles, send back a permission denied.
169
+ if ! strutil .StrListContains (config .AllowedRoles , "*" ) && ! strutil .StrListContainsGlob (config .AllowedRoles , name ) {
170
+ return nil , fmt .Errorf ("%q is not an allowed role for connection %q" , name , role .Connection )
171
+ }
172
+
173
+ conn , err := b .ensureConnection (ctx , role .Connection , config )
174
+ if err != nil {
175
+ return nil , err
176
+ }
177
+
178
+ nodes , _ , err := conn .Deployment .GetSearchPeers ()
179
+ if err != nil {
180
+ b .Logger ().Error ("Error while reading SearchPeers from cluster master" , err )
181
+ return nil , fmt .Errorf ("unable to read searchpeers from cluster master" )
182
+ }
183
+ _ , err = findNode (nodeFQDN , nodes )
184
+ if err != nil {
185
+ return nil , err
186
+ }
187
+
188
+ /*
189
+ // Generate credentials
190
+ userUUID, err := uuid.GenerateUUID()
191
+ if err != nil {
192
+ return nil, err
193
+ }
194
+ userPrefix := role.UserPrefix
195
+ if role.UserPrefix == defaultUserPrefix {
196
+ userPrefix = fmt.Sprintf("%s_%s", role.UserPrefix, req.DisplayName)
197
+ }
198
+ username := fmt.Sprintf("%s_%s", userPrefix, userUUID)
199
+ passwd, err := uuid.GenerateUUID()
200
+ if err != nil {
201
+ return nil, errwrap.Wrapf("error generating new password {{err}}", err)
202
+ }
203
+ opts := splunk.CreateUserOptions{
204
+ Name: username,
205
+ Password: passwd,
206
+ Roles: role.Roles,
207
+ DefaultApp: role.DefaultApp,
208
+ Email: role.Email,
209
+ TZ: role.TZ,
210
+ }
211
+ if _, _, err := conn.AccessControl.Authentication.Users.Create(&opts); err != nil {
212
+ return nil, err
213
+ }
214
+
215
+ resp := b.Secret(secretCredsType).Response(map[string]interface{}{
216
+ // return to user
217
+ "username": username,
218
+ "password": passwd,
219
+ "roles": role.Roles,
220
+ "connection": role.Connection,
221
+ "url": conn.Params().BaseURL,
222
+ }, map[string]interface{}{
223
+ // store (with lease)
224
+ "username": username,
225
+ "role": name,
226
+ "connection": role.Connection,
227
+ })
228
+ resp.Secret.TTL = role.DefaultTTL
229
+ resp.Secret.MaxTTL = role.MaxTTL
230
+
231
+ return resp, nil
232
+ */
233
+ return nil , fmt .Errorf ("XXX" )
234
+ }
235
+ func (b * backend ) credsReadHandler (ctx context.Context , req * logical.Request , d * framework.FieldData ) (* logical.Response , error ) {
236
+ name := d .Get ("name" ).(string )
237
+ node_fqdn , present := d .GetOk ("node_fqdn" )
238
+ // if node_fqdn is specified then the treat the request for a multi-node deployment
239
+ if present {
240
+ b .Logger ().Debug (fmt .Sprintf ("node_fqdn: [%s] specified for role: [%s]. using clustered mode getting temporary creds" , node_fqdn .(string ), name ))
241
+ return b .credsReadHandlerMulti (ctx , req , d )
242
+ }
243
+ b .Logger ().Debug (fmt .Sprintf ("node_fqdn not specified for role: [%s]. using standalone mode getting temporary creds" , name ))
244
+ return b .credsReadHandlerStandalone (ctx , req , d )
245
+ }
246
+
103
247
const pathCredsCreateHelpSyn = `
104
248
Request Splunk credentials for a certain role.
105
249
`
0 commit comments