Skip to content

Commit 3023f29

Browse files
committed
fixed a bug with subdirectory paths not being expanded correctly while using kv v2 engines
1 parent 4f15101 commit 3023f29

File tree

2 files changed

+61
-18
lines changed

2 files changed

+61
-18
lines changed

service/secret/vault/vault.go

+27-18
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ import (
1616

1717
// VaultSecrets implements a secret.Store backed by Hashicorp Vault
1818
type VaultSecrets struct {
19-
client *api.Client
20-
path string
21-
version int
22-
renewal time.Duration
19+
client *api.Client
20+
enginepath string
21+
path string
22+
version int
23+
renewal time.Duration
2324
}
2425

2526
var _ secret.Store = &VaultSecrets{}
@@ -31,7 +32,6 @@ func New(addr, basepath, token string, renewal time.Duration) (v *VaultSecrets,
3132
}
3233

3334
v = &VaultSecrets{
34-
path: basepath,
3535
renewal: renewal,
3636
}
3737

@@ -47,19 +47,17 @@ func New(addr, basepath, token string, renewal time.Duration) (v *VaultSecrets,
4747
return nil, errors.Wrap(err, "failed to connect to vault server")
4848
}
4949

50-
enginepath := strings.Split(basepath, "/")[0]
51-
if len(enginepath) == 0 {
52-
enginepath = basepath
53-
}
50+
// engine is the first component of base, then the rest is the actual path.
51+
v.enginepath, v.path = splitPath(basepath)
5452

55-
if v.version, err = getKVEngineVersion(v.client, enginepath); err != nil {
56-
return nil, errors.Wrapf(err, "failed to determine KV engine version at '/%s'", enginepath)
53+
if v.version, err = getKVEngineVersion(v.client, v.enginepath); err != nil {
54+
return nil, errors.Wrapf(err, "failed to determine KV engine version at '/%s'", v.enginepath)
5755
}
5856

5957
zap.L().Debug("created new vault client for secrets engine",
6058
zap.Int("kv_version", v.version),
6159
zap.String("basepath", basepath),
62-
zap.String("enginepath", enginepath))
60+
zap.String("enginepath", v.enginepath))
6361

6462
return v, nil
6563
}
@@ -112,30 +110,41 @@ func (v *VaultSecrets) Renew(ctx context.Context) error {
112110
return nil
113111
}
114112

113+
func splitPath(basepath string) (string, string) {
114+
basepath = strings.Trim(basepath, "/")
115+
s := strings.SplitN(basepath, "/", 2)
116+
if len(s[0]) == 0 {
117+
return basepath, "/"
118+
} else if len(s) == 1 {
119+
return basepath, "/"
120+
}
121+
return s[0], s[1]
122+
}
123+
115124
// builds the correct path to a secret based on the kv version
116125
func (v *VaultSecrets) buildPath(item string) string {
117126
if v.version == 1 {
118-
return path.Join(v.path, item)
119-
} else {
120-
return path.Join(v.path, "data", item)
127+
path.Split(v.path)
128+
return path.Join(v.enginepath, v.path, item)
121129
}
130+
return path.Join(v.enginepath, "data", v.path, item)
122131
}
123132

124133
// pulls out the kv secret data for v1 and v2 secrets
125134
func kvToMap(version int, data map[string]interface{}) (env map[string]string, err error) {
126135
if version == 1 {
127136
env = make(map[string]string)
128137
for k, v := range data {
129-
env[k] = v.(string)
138+
env[k] = v.(string) //nolint:err - we know it's a string already
130139
}
131140
} else if version == 2 {
132141
env = make(map[string]string)
133142
if kv, ok := data["data"].(map[string]interface{}); ok {
134143
for k, v := range kv {
135-
env[k] = v.(string)
144+
env[k] = v.(string) //nolint:err - we know it's a string already
136145
}
137146
} else {
138-
return nil, errors.New("could not interpret KV v2 response data as hashtable, this is likely a change in the KV v2 API, please open an issue.")
147+
return nil, errors.New("could not interpret KV v2 response data as hashtable, this is likely a change in the KV v2 API, please open an issue")
139148
}
140149
} else {
141150
return nil, errors.Errorf("unrecognised KV version: %d", version)

service/secret/vault/vault_test.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package vault
2+
3+
import "testing"
4+
5+
func Test_splitPath(t *testing.T) {
6+
type args struct {
7+
basepath string
8+
}
9+
tests := []struct {
10+
name string
11+
args args
12+
want string
13+
want1 string
14+
}{
15+
{"simple", args{basepath: "kv"}, "kv", "/"},
16+
{"simple", args{basepath: "/kv"}, "kv", "/"},
17+
{"simple", args{basepath: "/kv/"}, "kv", "/"},
18+
{"simple", args{basepath: "/kv/subdir"}, "kv", "subdir"},
19+
{"simple", args{basepath: "/kv/subdir/"}, "kv", "subdir"},
20+
{"simple", args{basepath: "/kv/subdir/subsubdir"}, "kv", "subdir/subsubdir"},
21+
{"simple", args{basepath: "/kv/subdir/subsubdir/"}, "kv", "subdir/subsubdir"},
22+
}
23+
for _, tt := range tests {
24+
t.Run(tt.name, func(t *testing.T) {
25+
got, got1 := splitPath(tt.args.basepath)
26+
if got != tt.want {
27+
t.Errorf("splitPath() got = '%v', want '%v'", got, tt.want)
28+
}
29+
if got1 != tt.want1 {
30+
t.Errorf("splitPath() got1 = '%v', want '%v'", got1, tt.want1)
31+
}
32+
})
33+
}
34+
}

0 commit comments

Comments
 (0)