hiera-secrets-manager 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hiera/backend/secrets_manager_backend.rb +52 -6
- data/spec/secrets_manager_backend_spec.rb +96 -21
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c62c6220168593608f0c75ea45f2c6669cfeab3394d3a00ea8471e9df634b6df
|
4
|
+
data.tar.gz: 0ff04f5c3f5def5bb5251017d475c30217ac9e1f338ccfd3be76efa1c8e773b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 296c97802ac92301ae42ae581edb461bc570e63564a5732bd14b1acd0453c68eec7ece9461be07573f6ac145c2ea51fcf50f4a29f687eb2cf28e8f0dedee6b6d
|
7
|
+
data.tar.gz: 317abde2b8f974939dd5282f5dd4e42d3c86cfbc947826b0a24c074dab95cb80002520cb0584e9104be84492a1454925b32ca8eef786ba37665c5d188f201c29
|
@@ -3,16 +3,23 @@ class Hiera
|
|
3
3
|
class Secrets_manager_backend
|
4
4
|
def initialize
|
5
5
|
require 'aws-sdk-secretsmanager'
|
6
|
-
@
|
7
|
-
|
8
|
-
)
|
9
|
-
|
10
|
-
Hiera.debug('AWS Secrets Manager backend starting')
|
6
|
+
@config = Config
|
7
|
+
@client = create_client
|
11
8
|
end
|
12
9
|
|
13
10
|
def lookup(key, scope, order_override, resolution_type)
|
14
11
|
answer = nil
|
15
12
|
|
13
|
+
if @client.nil?
|
14
|
+
Hiera.debug('Key lookup failed. AWS Secrets Manager backend is in a bad state.')
|
15
|
+
return answer
|
16
|
+
end
|
17
|
+
|
18
|
+
if contains_illegal_characters?(key)
|
19
|
+
Hiera.debug("#{key} contains illegal characters. Skipping lookup.")
|
20
|
+
return answer
|
21
|
+
end
|
22
|
+
|
16
23
|
key_to_query = format_key(key, scope, Config[:secrets_manager])
|
17
24
|
|
18
25
|
begin
|
@@ -26,6 +33,12 @@ class Hiera
|
|
26
33
|
|
27
34
|
private
|
28
35
|
|
36
|
+
# AWS Secrets Manager only allows alphanumeric characters or (/_+=.@-) in key names
|
37
|
+
# GetSecret requests will fail for keys which have illegal characters
|
38
|
+
def contains_illegal_characters?(key)
|
39
|
+
%r{^[a-zA-Z0-9\/_+=.@\-]+$}.match(key).nil?
|
40
|
+
end
|
41
|
+
|
29
42
|
def get_prefix(environments, scope)
|
30
43
|
if environments && environments.key?(scope['environment'])
|
31
44
|
environments[scope['environment']]
|
@@ -35,7 +48,7 @@ class Hiera
|
|
35
48
|
end
|
36
49
|
|
37
50
|
def format_key(key, scope, config)
|
38
|
-
if scope.
|
51
|
+
if scope.include?('environment') && scope['environment']
|
39
52
|
environments = config[:environments]
|
40
53
|
prefix = get_prefix(environments, scope)
|
41
54
|
"#{prefix}/#{key}"
|
@@ -43,6 +56,39 @@ class Hiera
|
|
43
56
|
key
|
44
57
|
end
|
45
58
|
end
|
59
|
+
|
60
|
+
def create_client
|
61
|
+
if missing_config?
|
62
|
+
Hiera.debug('Warning! Config is empty. Starting in a bad state.')
|
63
|
+
return nil
|
64
|
+
end
|
65
|
+
|
66
|
+
if missing_keys?
|
67
|
+
Hiera.debug("Warning! Missing key(s) #{missing_keys} in Config. Starting in a bad state.")
|
68
|
+
return nil
|
69
|
+
end
|
70
|
+
|
71
|
+
Hiera.debug('AWS Secrets Manager backend starting')
|
72
|
+
Aws::SecretsManager::Client.new(
|
73
|
+
region: @config[:secrets_manager][:region],
|
74
|
+
access_key_id: @config[:secrets_manager][:access_key_id],
|
75
|
+
secret_access_key: @config[:secrets_manager][:secret_access_key]
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
def missing_config?
|
80
|
+
@config[:secrets_manager].nil?
|
81
|
+
end
|
82
|
+
|
83
|
+
def missing_keys?
|
84
|
+
!missing_keys.empty?
|
85
|
+
end
|
86
|
+
|
87
|
+
def missing_keys
|
88
|
+
%i[region access_key_id secret_access_key].reject do |key|
|
89
|
+
@config[:secrets_manager].include?(key)
|
90
|
+
end
|
91
|
+
end
|
46
92
|
end
|
47
93
|
end
|
48
94
|
end
|
@@ -4,23 +4,38 @@ require 'hiera/backend/secrets_manager_backend'
|
|
4
4
|
class Hiera
|
5
5
|
module Backend
|
6
6
|
describe Secrets_manager_backend do
|
7
|
-
before do
|
7
|
+
before(:each) do
|
8
8
|
@region_object = { region: 'some_region' }
|
9
|
+
@credentials = { access_key_id: 'some_id',
|
10
|
+
secret_access_key: 'some_access_key' }
|
9
11
|
@config_object = { secrets_manager:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
{
|
13
|
+
region: @region_object[:region],
|
14
|
+
access_key_id: @credentials[:access_key_id],
|
15
|
+
secret_access_key: @credentials[:secret_access_key],
|
16
|
+
environments:
|
17
|
+
{
|
18
|
+
'env1' => 'production',
|
19
|
+
'env2' => 'staging',
|
20
|
+
'env3' => 'development'
|
21
|
+
}
|
22
|
+
} }
|
23
|
+
|
19
24
|
Config.load(@config_object)
|
20
25
|
Hiera.stubs(:debug)
|
26
|
+
@mock_client = mock('client')
|
21
27
|
Aws::SecretsManager::Client
|
22
28
|
.stubs(:new)
|
23
|
-
.with(@region_object
|
29
|
+
.with(region: @region_object[:region],
|
30
|
+
access_key_id: @credentials[:access_key_id],
|
31
|
+
secret_access_key: @credentials[:secret_access_key])
|
32
|
+
.returns(@mock_client)
|
33
|
+
end
|
34
|
+
|
35
|
+
def mock_scope_with_environment(environment)
|
36
|
+
mock_scope = mock
|
37
|
+
mock_scope.stubs(:lookupvar).with('environment').returns(environment)
|
38
|
+
Hiera::Scope.new(mock_scope)
|
24
39
|
end
|
25
40
|
|
26
41
|
describe '#initialize' do
|
@@ -34,19 +49,59 @@ class Hiera
|
|
34
49
|
it 'should set up a connection to AWS Secrets Manager' do
|
35
50
|
Aws::SecretsManager::Client
|
36
51
|
.expects(:new)
|
37
|
-
.with(@region_object
|
52
|
+
.with(region: @region_object[:region],
|
53
|
+
access_key_id: @credentials[:access_key_id],
|
54
|
+
secret_access_key: @credentials[:secret_access_key])
|
38
55
|
Secrets_manager_backend.new
|
39
56
|
end
|
57
|
+
|
58
|
+
context 'with bad config' do
|
59
|
+
after do
|
60
|
+
Secrets_manager_backend.new
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'with empty config, should announce that it has no config' do
|
64
|
+
config_object = {}
|
65
|
+
Config.load(config_object)
|
66
|
+
Hiera
|
67
|
+
.expects(:debug)
|
68
|
+
.with('Warning! Config is empty. Starting in a bad state.')
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'with no params, should announce that it is in a bad state' do
|
72
|
+
config_object = { secrets_manager: {} }
|
73
|
+
Config.load(config_object)
|
74
|
+
Hiera
|
75
|
+
.expects(:debug)
|
76
|
+
.with('Warning! Missing key(s) [:region, :access_key_id, :secret_access_key] in Config. Starting in a bad state.')
|
77
|
+
end
|
78
|
+
|
79
|
+
[:region, :access_key_id, :secret_access_key].each do |key|
|
80
|
+
it "debug should announce when key [#{key}] is missing in config" do
|
81
|
+
@config_object[:secrets_manager].delete(key)
|
82
|
+
Config.load(@config_object)
|
83
|
+
Hiera
|
84
|
+
.expects(:debug)
|
85
|
+
.with("Warning! Missing key(s) [:#{key}] in Config. Starting in a bad state.")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
40
89
|
end
|
41
90
|
|
42
91
|
describe '#lookup' do
|
43
92
|
before do
|
44
|
-
@mock_client = mock('client')
|
45
|
-
Aws::SecretsManager::Client
|
46
|
-
.stubs(:new)
|
47
|
-
.with(@region_object).returns(@mock_client)
|
48
93
|
@backend = Secrets_manager_backend.new
|
49
|
-
@scope =
|
94
|
+
@scope = mock_scope_with_environment('env1')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should announce if it is in a bad state' do
|
98
|
+
config_object = { secrets_manager: {} }
|
99
|
+
Config.load(config_object)
|
100
|
+
Hiera
|
101
|
+
.expects(:debug)
|
102
|
+
.with('Key lookup failed. AWS Secrets Manager backend is in a bad state.')
|
103
|
+
backend = Secrets_manager_backend.new
|
104
|
+
backend.lookup('some_secret', {}, nil, nil)
|
50
105
|
end
|
51
106
|
|
52
107
|
it 'should return a secret that exists' do
|
@@ -85,7 +140,8 @@ class Hiera
|
|
85
140
|
end
|
86
141
|
|
87
142
|
it 'falls back to provided scope environment when Hiera config does not include environment as a key / value pair' do
|
88
|
-
scope =
|
143
|
+
scope = mock_scope_with_environment('some_env_not_in_config')
|
144
|
+
|
89
145
|
prefixed_secret_name = 'some_env_not_in_config/secret_name'
|
90
146
|
|
91
147
|
@mock_client
|
@@ -99,7 +155,8 @@ class Hiera
|
|
99
155
|
incomplete_config = { secrets_manager: { region: @region_object[:region] } }
|
100
156
|
Config.load(incomplete_config)
|
101
157
|
|
102
|
-
scope =
|
158
|
+
scope = mock_scope_with_environment('some_env')
|
159
|
+
|
103
160
|
prefixed_secret_name = 'some_env/secret_name'
|
104
161
|
|
105
162
|
@mock_client
|
@@ -110,14 +167,32 @@ class Hiera
|
|
110
167
|
end
|
111
168
|
|
112
169
|
it 'does not use prefix if no environment is provided in scope' do
|
113
|
-
scope =
|
170
|
+
scope = mock_scope_with_environment(nil)
|
171
|
+
|
114
172
|
secret_name = 'secret_name'
|
115
173
|
|
116
174
|
@mock_client
|
117
175
|
.expects(:get_secret_value)
|
118
176
|
.with(secret_id: secret_name)
|
119
177
|
.returns('secret_string' => 'the_secret')
|
120
|
-
|
178
|
+
|
179
|
+
@backend.lookup(secret_name, scope, nil, nil)
|
180
|
+
end
|
181
|
+
|
182
|
+
%w[: ~ # \\].each do |character|
|
183
|
+
it "returns nil if key has illegal character [#{character}] (according to AWS)" do
|
184
|
+
@mock_client
|
185
|
+
.expects(:get_secret_value)
|
186
|
+
.never
|
187
|
+
|
188
|
+
secret_name = "secret#{character}name"
|
189
|
+
|
190
|
+
Hiera
|
191
|
+
.expects(:debug)
|
192
|
+
.with("#{secret_name} contains illegal characters. Skipping lookup.")
|
193
|
+
|
194
|
+
@backend.lookup(secret_name, @scope, nil, nil)
|
195
|
+
end
|
121
196
|
end
|
122
197
|
end
|
123
198
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hiera-secrets-manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Unruly
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-secretsmanager
|