forked from argoproj-labs/argocd-vault-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeepersecretsmanager.go
158 lines (129 loc) · 3.97 KB
/
keepersecretsmanager.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package backends
import (
"fmt"
"github.com/argoproj-labs/argocd-vault-plugin/pkg/utils"
ksm "github.com/keeper-security/secrets-manager-go/core"
)
// KeeperClient is an interface containing the aspects of the keeper api that the backend needs.
type KeeperClient interface {
GetSecrets(ids []string) ([]*ksm.Record, error)
}
// KeeperSecretsManager is a struct for working with a Keeper Secrets Manager backend
type KeeperSecretsManager struct {
client KeeperClient
}
// NewKeeperSecretsManagerBackend returns a new Keeper Secrets Manager backend.
func NewKeeperSecretsManagerBackend(client KeeperClient) *KeeperSecretsManager {
return &KeeperSecretsManager{
client: client,
}
}
// Login currently does nothing.
func (k *KeeperSecretsManager) Login() error {
return nil
}
func buildSecretsMap(secretsMap map[string]interface{}, fieldMap map[string]interface{}) error {
var label string
var fieldType string
// we start by getting the label from the type,
if fieldMapType, ok := fieldMap["type"]; ok {
if typeString, ok := fieldMapType.(string); ok {
label = typeString
fieldType = typeString
}
}
// if there is a more specific label, then we use that instead
if labelField, ok := fieldMap["label"]; ok {
if labelStr, ok := labelField.(string); ok {
label = labelStr
}
}
if label == "" {
utils.VerboseToStdErr("secret's field does not have a \"label\"")
return nil
}
if fieldType == "" {
utils.VerboseToStdErr("secret's field does not have a \"type\"")
return nil
}
var value interface{}
switch fieldType {
case "note":
fallthrough
case "url":
fallthrough
case "text":
fallthrough
case "login":
fallthrough
case "password":
fallthrough
default:
if fieldValues, ok := fieldMap["value"]; ok {
sliceValues, ok := fieldValues.([]interface{})
if !ok {
utils.VerboseToStdErr("secret's field value is not a []interface %T for field %s", fieldValues, label)
return nil
}
if len(sliceValues) == 1 {
value = sliceValues[0]
}
if len(sliceValues) == 0 {
value = nil
}
}
}
if value != nil {
secretsMap[label] = value
}
return nil
}
// GetSecrets gets secrets from Keeper Secrets Manager. It does not currently
// implement anything related to versions or annotations.
func (a *KeeperSecretsManager) GetSecrets(path string, version string, annotations map[string]string) (map[string]interface{}, error) {
records, err := a.client.GetSecrets([]string{
path,
})
if err != nil {
return nil, fmt.Errorf("could not access secret %s, error: %s", path, err)
}
utils.VerboseToStdErr("Keeper Secrets Manager getting path %s", path)
if len(records) == 0 {
return nil, fmt.Errorf("no secrets could be found with the given path: %s", path)
}
if len(records) > 1 {
return nil, fmt.Errorf("unexpectedly multiple secrets were found with the given path: %s", path)
}
utils.VerboseToStdErr("Keeper Secrets Manager decoding record %s", records[0].Title())
dict := records[0].RecordDict
secretMap := map[string]interface{}{}
if fields, ok := dict["custom"]; ok {
if fieldsSlice, ok := fields.([]interface{}); ok {
for _, field := range fieldsSlice {
if fieldMap, ok := field.(map[string]interface{}); ok {
buildSecretsMap(secretMap, fieldMap)
}
}
}
}
if fields, ok := dict["fields"]; ok {
if fieldsSlice, ok := fields.([]interface{}); ok {
for _, field := range fieldsSlice {
if fieldMap, ok := field.(map[string]interface{}); ok {
buildSecretsMap(secretMap, fieldMap)
}
}
}
}
utils.VerboseToStdErr("Keeper Secrets Manager constructed map %s", secretMap)
return secretMap, nil
}
// GetIndividualSecret returns the specified secret. It simply wraps the
// GetSecrets call, and currently ignores the version parameter.
func (v *KeeperSecretsManager) GetIndividualSecret(kvpath, secretName, version string, annotations map[string]string) (interface{}, error) {
secrets, err := v.GetSecrets(kvpath, version, annotations)
if err != nil {
return nil, err
}
return secrets[secretName], nil
}