/
ssm.go
126 lines (109 loc) · 3.79 KB
/
ssm.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
package aws
import (
"context"
"errors"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ssm"
"github.com/mitchellh/mapstructure"
"github.com/rs/zerolog/log"
"github.com/rapdev-io/datadog-secret-backend/secret"
)
type AwsSsmParameterStoreBackendConfig struct {
AwsSession AwsSessionBackendConfig `mapstructure:"aws_session"`
BackendType string `mapstructure:"backend_type"`
ParameterPath string `mapstructure:"parameter_path"`
Parameters []string `mapstructure:"parameters"`
}
type AwsSsmParameterStoreBackend struct {
BackendId string
Config AwsSsmParameterStoreBackendConfig
Secret map[string]string
}
func NewAwsSsmParameterStoreBackend(backendId string, bc map[string]interface{}) (
*AwsSsmParameterStoreBackend, error) {
backendConfig := AwsSsmParameterStoreBackendConfig{}
err := mapstructure.Decode(bc, &backendConfig)
if err != nil {
log.Error().Err(err).Str("backend_id", backendId).
Msg("failed to map backend configuration")
return nil, err
}
secretValue := make(map[string]string, 0)
cfg, err := NewAwsConfigFromBackendConfig(backendId, backendConfig.AwsSession)
if err != nil {
log.Error().Err(err).Str("backend_id", backendId).
Msg("failed to initialize aws session")
return nil, err
}
client := ssm.NewFromConfig(*cfg)
// GetParametersByPath
if backendConfig.ParameterPath != "" {
input := &ssm.GetParametersByPathInput{
Path: &backendConfig.ParameterPath,
Recursive: aws.Bool(true),
WithDecryption: aws.Bool(true),
}
pager := ssm.NewGetParametersByPathPaginator(client, input)
for pager.HasMorePages() {
out, err := pager.NextPage(context.TODO())
if err != nil {
log.Error().Err(err).
Str("backend_id", backendId).
Str("backend_type", backendConfig.BackendType).
Str("parameter_path", backendConfig.ParameterPath).
Strs("parameters", backendConfig.Parameters).
Str("aws_access_key_id", backendConfig.AwsSession.AwsAccessKeyId).
Str("aws_profile", backendConfig.AwsSession.AwsProfile).
Str("aws_region", backendConfig.AwsSession.AwsRegion).
Msg("failed to retrieve parameters from path")
return nil, err
}
for _, parameter := range out.Parameters {
secretValue[*parameter.Name] = *parameter.Value
}
}
}
// GetParameters
if len(backendConfig.Parameters) > 0 {
input := &ssm.GetParametersInput{
Names: backendConfig.Parameters,
WithDecryption: aws.Bool(true),
}
out, err := client.GetParameters(context.TODO(), input)
if err != nil {
log.Error().Err(err).
Str("backend_id", backendId).
Str("backend_type", backendConfig.BackendType).
Strs("parameters", backendConfig.Parameters).
Str("aws_access_key_id", backendConfig.AwsSession.AwsAccessKeyId).
Str("aws_profile", backendConfig.AwsSession.AwsProfile).
Str("aws_region", backendConfig.AwsSession.AwsRegion).
Msg("failed to retrieve parameters")
return nil, err
}
// handle invalid parameters?
for _, parameter := range out.Parameters {
secretValue[*parameter.Name] = *parameter.Value
}
}
backend := &AwsSsmParameterStoreBackend{
BackendId: backendId,
Config: backendConfig,
Secret: secretValue,
}
return backend, nil
}
func (b *AwsSsmParameterStoreBackend) GetSecretOutput(secretKey string) secret.SecretOutput {
if val, ok := b.Secret[secretKey]; ok {
return secret.SecretOutput{Value: &val, Error: nil}
}
es := errors.New("backend does not provide secret key").Error()
log.Error().
Str("backend_id", b.BackendId).
Str("backend_type", b.Config.BackendType).
Strs("parameters", b.Config.Parameters).
Str("parameter_path", b.Config.ParameterPath).
Str("secret_key", secretKey).
Msg("failed to retrieve parameters")
return secret.SecretOutput{Value: nil, Error: &es}
}