Skip to content

Commit fa0f160

Browse files
authored
Merge branch 'main' into dapr-state-store-clickhouse
2 parents 5808737 + 21649a9 commit fa0f160

File tree

4 files changed

+363
-16
lines changed

4 files changed

+363
-16
lines changed

common/authentication/aws/client_fake.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,18 @@ func (m *MockParameterStore) DescribeParametersWithContext(ctx context.Context,
4343
type MockSecretManager struct {
4444
GetSecretValueFn func(context.Context, *secretsmanager.GetSecretValueInput, ...request.Option) (*secretsmanager.GetSecretValueOutput, error)
4545
secretsmanageriface.SecretsManagerAPI
46+
47+
ListSecretsFn func(context.Context, *secretsmanager.ListSecretsInput, ...request.Option) (*secretsmanager.ListSecretsOutput, error)
4648
}
4749

4850
func (m *MockSecretManager) GetSecretValueWithContext(ctx context.Context, input *secretsmanager.GetSecretValueInput, option ...request.Option) (*secretsmanager.GetSecretValueOutput, error) {
4951
return m.GetSecretValueFn(ctx, input, option...)
5052
}
5153

54+
func (m *MockSecretManager) ListSecretsWithContext(ctx context.Context, input *secretsmanager.ListSecretsInput, option ...request.Option) (*secretsmanager.ListSecretsOutput, error) {
55+
return m.ListSecretsFn(ctx, input, option...)
56+
}
57+
5258
type MockDynamoDB struct {
5359
GetItemWithContextFn func(ctx context.Context, input *dynamodb.GetItemInput, op ...request.Option) (*dynamodb.GetItemOutput, error)
5460
PutItemWithContextFn func(ctx context.Context, input *dynamodb.PutItemInput, op ...request.Option) (*dynamodb.PutItemOutput, error)

secretstores/aws/secretmanager/metadata.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,10 @@ metadata:
1616
description: |
1717
The Secrets manager endpoint. The AWS SDK will generate a default endpoint if not specified. Useful for local testing with AWS LocalStack
1818
example: '"http://localhost:4566"'
19-
type: string
19+
type: string
20+
- name: multipleKeyValuesPerSecret
21+
required: false
22+
description: |
23+
A boolean value to indicate if the secrets with multiple key/values should break keys out.
24+
example: "true"
25+
type: bool

secretstores/aws/secretmanager/secretmanager.go

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,18 @@ func NewSecretManager(logger logger.Logger) secretstores.SecretStore {
4040
}
4141

4242
type SecretManagerMetaData struct {
43-
Region string `json:"region" mapstructure:"region" mdignore:"true"`
44-
AccessKey string `json:"accessKey" mapstructure:"accessKey" mdignore:"true"`
45-
SecretKey string `json:"secretKey" mapstructure:"secretKey" mdignore:"true"`
46-
SessionToken string `json:"sessionToken" mapstructure:"sessionToken" mdignore:"true"`
47-
Endpoint string `json:"endpoint" mapstructure:"endpoint"`
43+
Region string `json:"region" mapstructure:"region" mdignore:"true"`
44+
AccessKey string `json:"accessKey" mapstructure:"accessKey" mdignore:"true"`
45+
SecretKey string `json:"secretKey" mapstructure:"secretKey" mdignore:"true"`
46+
SessionToken string `json:"sessionToken" mapstructure:"sessionToken" mdignore:"true"`
47+
Endpoint string `json:"endpoint" mapstructure:"endpoint"`
48+
MultipleKeyValuesPerSecret bool `json:"multipleKeyValuesPerSecret" mapstructure:"multipleKeyValuesPerSecret"`
4849
}
4950

5051
type smSecretStore struct {
51-
authProvider awsAuth.Provider
52-
logger logger.Logger
52+
authProvider awsAuth.Provider
53+
logger logger.Logger
54+
multipleKeyValuesPerSecret bool
5355
}
5456

5557
// Init creates an AWS secret manager client.
@@ -67,6 +69,7 @@ func (s *smSecretStore) Init(ctx context.Context, metadata secretstores.Metadata
6769
SessionToken: meta.SessionToken,
6870
Endpoint: meta.Endpoint,
6971
}
72+
s.multipleKeyValuesPerSecret = meta.MultipleKeyValuesPerSecret
7073

7174
provider, err := awsAuth.NewProvider(ctx, opts, awsAuth.GetConfig(opts))
7275
if err != nil {
@@ -76,6 +79,40 @@ func (s *smSecretStore) Init(ctx context.Context, metadata secretstores.Metadata
7679
return nil
7780
}
7881

82+
func convertMapAnyToString(m map[string]any) map[string]string {
83+
result := make(map[string]string, len(m))
84+
for k, v := range m {
85+
switch v := v.(type) {
86+
case string:
87+
result[k] = v
88+
default:
89+
jVal, _ := json.Marshal(v)
90+
result[k] = string(jVal)
91+
}
92+
}
93+
return result
94+
}
95+
96+
func (s *smSecretStore) formatSecret(output *secretsmanager.GetSecretValueOutput) map[string]string {
97+
result := map[string]string{}
98+
99+
if output.Name != nil && output.SecretString != nil {
100+
if s.multipleKeyValuesPerSecret {
101+
data := map[string]any{}
102+
if err := json.Unmarshal([]byte(*output.SecretString), &data); err != nil {
103+
result[*output.Name] = *output.SecretString
104+
} else {
105+
// In case of a nested JSON value, we need to stringify it
106+
result = convertMapAnyToString(data)
107+
}
108+
} else {
109+
result[*output.Name] = *output.SecretString
110+
}
111+
}
112+
113+
return result
114+
}
115+
79116
// GetSecret retrieves a secret using a key and returns a map of decrypted string/string values.
80117
func (s *smSecretStore) GetSecret(ctx context.Context, req secretstores.GetSecretRequest) (secretstores.GetSecretResponse, error) {
81118
var versionID *string
@@ -98,9 +135,7 @@ func (s *smSecretStore) GetSecret(ctx context.Context, req secretstores.GetSecre
98135
resp := secretstores.GetSecretResponse{
99136
Data: map[string]string{},
100137
}
101-
if output.Name != nil && output.SecretString != nil {
102-
resp.Data[*output.Name] = *output.SecretString
103-
}
138+
resp.Data = s.formatSecret(output)
104139

105140
return resp, nil
106141
}
@@ -131,9 +166,7 @@ func (s *smSecretStore) BulkGetSecret(ctx context.Context, req secretstores.Bulk
131166
return secretstores.BulkGetSecretResponse{Data: nil}, fmt.Errorf("couldn't get secret: %s", *entry.Name)
132167
}
133168

134-
if entry.Name != nil && secrets.SecretString != nil {
135-
resp.Data[*entry.Name] = map[string]string{*entry.Name: *secrets.SecretString}
136-
}
169+
resp.Data[*entry.Name] = s.formatSecret(secrets)
137170
}
138171

139172
nextToken = output.NextToken
@@ -160,7 +193,11 @@ func (s *smSecretStore) getSecretManagerMetadata(spec secretstores.Metadata) (*S
160193

161194
// Features returns the features available in this secret store.
162195
func (s *smSecretStore) Features() []secretstores.Feature {
163-
return []secretstores.Feature{} // No Feature supported.
196+
if s.multipleKeyValuesPerSecret {
197+
return []secretstores.Feature{secretstores.FeatureMultipleKeyValuesPerSecret}
198+
}
199+
200+
return []secretstores.Feature{}
164201
}
165202

166203
func (s *smSecretStore) GetComponentMetadata() (metadataInfo metadata.MetadataMap) {

0 commit comments

Comments
 (0)