Skip to content
This repository was archived by the owner on Mar 15, 2024. It is now read-only.

Commit b51a75c

Browse files
author
Michael Weber
committed
Allow ephemeral credentials for any configured node type
Node types can be restricted via splunk/roles/*. By default, any role is allowed ("*") Fixes TE-102, TE-103
1 parent 44d2232 commit b51a75c

File tree

4 files changed

+39
-15
lines changed

4 files changed

+39
-15
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,21 @@ after the configured lease ends, in 5 minutes. We can use `vault
102102
lease [renew|revoke]` to manually alter the length of the lease, up to
103103
the configured maximum time.
104104

105+
For clustered stacks, we create ephemeral credentials for specific nodes:
106+
107+
$ vault read splunk/creds/local-admin/idx.example.com
108+
Key Value
109+
--- -----
110+
lease_id splunk/creds/local-admin/idx.example.com/u2N97uUVVDw3YVaETB1yRK74
111+
lease_duration 30s
112+
lease_renewable true
113+
connection local
114+
password &R1iX5W%$41QGcf^yN2i9%%#tUNf58h!
115+
roles [admin]
116+
url https://idx.example.com:8089
117+
username vault_29079642-4aa1-1979-f402-b3775f2713a7
118+
119+
105120
Rotate the Splunk admin password:
106121

107122
vault write -f splunk/rotate-root/local

path_creds_create.go

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ import (
1212
"github.com/splunk/vault-plugin-splunk/clients/splunk"
1313
)
1414

15-
const (
16-
SEARCHHEAD = "search_head"
17-
INDEXER = "indexer"
18-
)
19-
2015
func (b *backend) pathCredsCreate() *framework.Path {
2116
return &framework.Path{
2217
Pattern: "creds/" + framework.GenericNameRegex("name"),
@@ -129,20 +124,23 @@ func (b *backend) credsReadHandlerStandalone(ctx context.Context, req *logical.R
129124
return resp, nil
130125
}
131126

132-
func findNode(nodeFQDN string, hosts []splunk.ServerInfoEntry) (bool, error) {
127+
func findNode(nodeFQDN string, hosts []splunk.ServerInfoEntry, roleConfig *roleConfig) (bool, error) {
133128
for _, host := range hosts {
134129
// check if node_fqdn is in either of HostFQDN or Host. User might not always the FQDN on the cli input
135130
if host.Content.HostFQDN == nodeFQDN || host.Content.Host == nodeFQDN {
136-
// Return true if the requested node is a search head
131+
// Return true if the requested node type is allowed
132+
if strutil.StrListContains(roleConfig.AllowedNodeTypes, "*") {
133+
return true, nil
134+
}
137135
for _, role := range host.Content.Roles {
138-
if role == SEARCHHEAD {
136+
if strutil.StrListContainsGlob(roleConfig.AllowedNodeTypes, role) {
139137
return true, nil
140138
}
141139
}
142-
return false, fmt.Errorf("host: %s isn't search head; creating ephemeral creds is only supported for search heads", nodeFQDN)
140+
return false, fmt.Errorf("host %q does not have an allowed node type", nodeFQDN)
143141
}
144142
}
145-
return false, fmt.Errorf("host: %s not found", nodeFQDN)
143+
return false, fmt.Errorf("host %q not found", nodeFQDN)
146144
}
147145

148146
func (b *backend) credsReadHandlerMulti(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
@@ -181,7 +179,7 @@ func (b *backend) credsReadHandlerMulti(ctx context.Context, req *logical.Reques
181179
b.Logger().Error("Error while reading SearchPeers from cluster master", err)
182180
return nil, errwrap.Wrapf("unable to read searchpeers from cluster master: {{err}}", err)
183181
}
184-
_, err = findNode(nodeFQDN, nodes)
182+
_, err = findNode(nodeFQDN, nodes, role)
185183
if err != nil {
186184
return nil, err
187185
}
@@ -207,7 +205,6 @@ func (b *backend) credsReadHandlerMulti(ctx context.Context, req *logical.Reques
207205
if err != nil {
208206
return nil, errwrap.Wrapf("error generating new password: {{err}}", err)
209207
}
210-
conn.Params().BaseURL = nodeFQDN
211208
opts := splunk.CreateUserOptions{
212209
Name: username,
213210
Password: passwd,

path_roles.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ func (b *backend) pathRoles() *framework.Path {
3535
Type: framework.TypeCommaStringSlice,
3636
Description: "Comma-separated string or list of Splunk roles.",
3737
},
38+
"allowed_node_types": &framework.FieldSchema{
39+
Type: framework.TypeCommaStringSlice,
40+
Description: trimIndent(`
41+
Comma-separated string or array of node type (glob) patterns that are allowed
42+
to fetch credentials for. If empty, no nodes are allowed. If "*", all
43+
node types are allowed.`),
44+
Default: []string{"*"},
45+
},
3846
"default_app": &framework.FieldSchema{
3947
Type: framework.TypeString,
4048
Description: trimIndent(`
@@ -114,6 +122,9 @@ func (b *backend) rolesWriteHandler(ctx context.Context, req *logical.Request, d
114122
if maxTTLRaw, ok := getValue(data, req.Operation, "max_ttl"); ok {
115123
role.MaxTTL = time.Duration(maxTTLRaw.(int)) * time.Second
116124
}
125+
if allowed_node_types, ok := getValue(data, req.Operation, "allowed_node_types"); ok {
126+
role.AllowedNodeTypes = allowed_node_types.([]string)
127+
}
117128
role.PasswordSpec = DefaultPasswordSpec() // XXX make configurable
118129

119130
if roles, ok := getValue(data, req.Operation, "roles"); ok {

role.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import (
1111
)
1212

1313
type roleConfig struct {
14-
Connection string `json:"connection" structs:"connection"`
15-
DefaultTTL time.Duration `json:"default_ttl" structs:"default_ttl"`
16-
MaxTTL time.Duration `json:"max_ttl" structs:"max_ttl"`
14+
Connection string `json:"connection" structs:"connection"`
15+
DefaultTTL time.Duration `json:"default_ttl" structs:"default_ttl"`
16+
MaxTTL time.Duration `json:"max_ttl" structs:"max_ttl"`
17+
AllowedNodeTypes []string `json:"allowed_node_types" structs:"allowed_node_types"`
1718
PasswordSpec *PasswordSpec `json:"password_spec" structs:"password_spec"`
1819

1920
// Splunk user attributes

0 commit comments

Comments
 (0)