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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddb4e09c2998f196711cd698067557e0ba49e66c315a8bb77cabdf75cc4d309b
4
- data.tar.gz: bc5fab11b745e1d8b42054a652f9bc0a704642d84fae56c2fe59b77f10265d5a
3
+ metadata.gz: c62c6220168593608f0c75ea45f2c6669cfeab3394d3a00ea8471e9df634b6df
4
+ data.tar.gz: 0ff04f5c3f5def5bb5251017d475c30217ac9e1f338ccfd3be76efa1c8e773b3
5
5
  SHA512:
6
- metadata.gz: 61f468931ae0cc0ec27c9b312c511b95f607d994bd4ddd2489feb9db7ab7968861e0c4dd402b063d25c02043d76cf6a07ddb1ae30df3876e8e5720b20356fa6c
7
- data.tar.gz: 1c4fac048ab6cc8083bc28d97f7f0e0b712b8b4e06767f82fa01b0d64a69469afa4f56bc4ec3301dfa4fbf263bd13f2fefd61e7de9c9b54dbb541e0d0a9974b7
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
- @client = Aws::SecretsManager::Client.new(
7
- region: Config[:secrets_manager][:region]
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.key?('environment')
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
- region: @region_object[:region],
12
- environments:
13
- {
14
- 'env1' => 'production',
15
- 'env2' => 'staging',
16
- 'env3' => 'development'
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 = { 'environment' => 'env1' }
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 = { 'environment' => 'some_env_not_in_config' }
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 = { 'environment' => 'some_env' }
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 = { 'no_environment_key' => 'some_value' }
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
- @backend.lookup('secret_name', scope, nil, nil)
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.0
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-21 00:00:00.000000000 Z
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