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