Skip to content

Commit d9c2553

Browse files
authored
Merge pull request #1292 from nickhammond/aws-secrets-manager-simple
Aws secrets manager simple strings and error checking
2 parents d5ec0e6 + 725da6a commit d9c2553

File tree

2 files changed

+82
-3
lines changed

2 files changed

+82
-3
lines changed

lib/kamal/secrets/adapters/aws_secrets_manager.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,28 @@ def login(_account)
66

77
def fetch_secrets(secrets, account:, session:)
88
{}.tap do |results|
9-
JSON.parse(get_from_secrets_manager(secrets, account: account))["SecretValues"].each do |secret|
9+
get_from_secrets_manager(secrets, account: account).each do |secret|
1010
secret_name = secret["Name"]
1111
secret_string = JSON.parse(secret["SecretString"])
1212

1313
secret_string.each do |key, value|
1414
results["#{secret_name}/#{key}"] = value
1515
end
16+
rescue JSON::ParserError
17+
results["#{secret_name}"] = secret["SecretString"]
1618
end
1719
end
1820
end
1921

2022
def get_from_secrets_manager(secrets, account:)
21-
`aws secretsmanager batch-get-secret-value --secret-id-list #{secrets.map(&:shellescape).join(" ")} --profile #{account.shellescape}`.tap do
22-
raise RuntimeError, "Could not read #{secret} from AWS Secrets Manager" unless $?.success?
23+
`aws secretsmanager batch-get-secret-value --secret-id-list #{secrets.map(&:shellescape).join(" ")} --profile #{account.shellescape}`.tap do |secrets|
24+
raise RuntimeError, "Could not read #{secrets} from AWS Secrets Manager" unless $?.success?
25+
26+
secrets = JSON.parse(secrets)
27+
28+
return secrets["SecretValues"] unless secrets["Errors"].present?
29+
30+
raise RuntimeError, secrets["Errors"].map { |error| "#{error['SecretId']}: #{error['Message']}" }.join(" ")
2331
end
2432
end
2533

test/secrets/aws_secrets_manager_adapter_test.rb

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,35 @@
11
require "test_helper"
22

33
class AwsSecretsManagerAdapterTest < SecretAdapterTestCase
4+
test "fails when errors are present" do
5+
stub_ticks.with("aws --version 2> /dev/null")
6+
stub_ticks
7+
.with("aws secretsmanager batch-get-secret-value --secret-id-list unknown1 unknown2 --profile default")
8+
.returns(<<~JSON)
9+
{
10+
"SecretValues": [],
11+
"Errors": [
12+
{
13+
"SecretId": "unknown1",
14+
"ErrorCode": "ResourceNotFoundException",
15+
"Message": "Secrets Manager can't find the specified secret."
16+
},
17+
{
18+
"SecretId": "unknown2",
19+
"ErrorCode": "ResourceNotFoundException",
20+
"Message": "Secrets Manager can't find the specified secret."
21+
}
22+
]
23+
}
24+
JSON
25+
26+
error = assert_raises RuntimeError do
27+
JSON.parse(shellunescape(run_command("fetch", "unknown1", "unknown2")))
28+
end
29+
30+
assert_equal [ "unknown1: Secrets Manager can't find the specified secret.", "unknown2: Secrets Manager can't find the specified secret." ].join(" "), error.message
31+
end
32+
433
test "fetch" do
534
stub_ticks.with("aws --version 2> /dev/null")
635
stub_ticks
@@ -44,6 +73,48 @@ class AwsSecretsManagerAdapterTest < SecretAdapterTestCase
4473
assert_equal expected_json, json
4574
end
4675

76+
test "fetch with string value" do
77+
stub_ticks.with("aws --version 2> /dev/null")
78+
stub_ticks
79+
.with("aws secretsmanager batch-get-secret-value --secret-id-list secret secret2/KEY1 --profile default")
80+
.returns(<<~JSON)
81+
{
82+
"SecretValues": [
83+
{
84+
"ARN": "arn:aws:secretsmanager:us-east-1:aaaaaaaaaaaa:secret:secret",
85+
"Name": "secret",
86+
"VersionId": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv",
87+
"SecretString": "a-string-secret",
88+
"VersionStages": [
89+
"AWSCURRENT"
90+
],
91+
"CreatedDate": "2024-01-01T00:00:00.000000"
92+
},
93+
{
94+
"ARN": "arn:aws:secretsmanager:us-east-1:aaaaaaaaaaaa:secret:secret2",
95+
"Name": "secret2",
96+
"VersionId": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv",
97+
"SecretString": "{\\"KEY2\\":\\"VALUE2\\"}",
98+
"VersionStages": [
99+
"AWSCURRENT"
100+
],
101+
"CreatedDate": "2024-01-01T00:00:00.000000"
102+
}
103+
],
104+
"Errors": []
105+
}
106+
JSON
107+
108+
json = JSON.parse(shellunescape(run_command("fetch", "secret", "secret2/KEY1")))
109+
110+
expected_json = {
111+
"secret"=>"a-string-secret",
112+
"secret2/KEY2"=>"VALUE2"
113+
}
114+
115+
assert_equal expected_json, json
116+
end
117+
47118
test "fetch with secret names" do
48119
stub_ticks.with("aws --version 2> /dev/null")
49120
stub_ticks

0 commit comments

Comments
 (0)