stack_master 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c6272dd327e82ec747c26129191c4c8e262a4350d6634941f14035746399cb77
4
- data.tar.gz: 6dc8058810bee48a3aed457669ffdda94e9d88fdc2ab1e1c12b9a689a3799c46
3
+ metadata.gz: 1acbc281b89ec3188892fac6692c4e885780efd8ba83f746a774557c0e1194ca
4
+ data.tar.gz: e18cb99eb7f3e99ac0b8fee4b952cb1d21b9f1467a4bbe8dac9250695649f543
5
5
  SHA512:
6
- metadata.gz: 6dad4bcffbc40f9a45377625ef7769f122b5880bbcc61bead8a9ffdd75ee063001f322f9e62079aa00b370f791afd2f76c7acb9b668f6d4f7f41128c63954b65
7
- data.tar.gz: a12c14c9024e187a5b734020cda2adc1c40d7983f58450022ea5f2301412968a167f4ebd6233f02097b8341541dc5ae50b213b6b59730f540594df90b327fd5f
6
+ metadata.gz: bcc6882c647189f6f758896da7cd8084638b707af26faeb234435b99a1e5cd466c0ca90e2f30a67b4414f21f38d899414d7935e49d2a7355ccd84ad700c87ba9
7
+ data.tar.gz: b48a690acadd00aa426084cc3b3b7aeb100b6fbfeaad738cb645df77ca6bd3edce347acf71d2b28ec3ff80833f15e4c55f95f5719922f0d061b2102c0ae1760c
data/README.md CHANGED
@@ -175,7 +175,7 @@ key_name: myapp-us-east-1
175
175
 
176
176
  ### Compile Time Parameters
177
177
 
178
- Compile time parameters can be used for [SparkleFormation](http://www.sparkleformation.io) templates. It conforms and
178
+ Compile time parameters can be used for [SparkleFormation](http://www.sparkleformation.io) templates. It conforms and
179
179
  allows you to use the [Compile Time Parameters](http://www.sparkleformation.io/docs/sparkle_formation/compile-time-parameters.html) feature.
180
180
 
181
181
  A simple example looks like this
@@ -268,6 +268,7 @@ you will likely want to set the parameter to NoEcho in your template.
268
268
  db_password:
269
269
  parameter_store: ssm_parameter_name
270
270
  ```
271
+
271
272
  ### 1Password Lookup
272
273
  An Alternative to the alternative secret store is accessing 1password secrets using the 1password cli (`op`).
273
274
  You declare a 1password lookup with the following parameters in your parameters file:
@@ -286,6 +287,44 @@ Currently we support two types of secrets, `password`s and `secureNote`s. All va
286
287
 
287
288
  For more information on 1password cli please see [here](https://support.1password.com/command-line-getting-started/)
288
289
 
290
+ ### EJSON Store
291
+
292
+ [ejson](https://github.com/Shopify/ejson) is a tool to manage asymmetrically encrypted values in JSON format.
293
+ This allows you to keep secrets securely in git/Github and gives anyone the ability the capability to add new
294
+ secrets without requiring access to the private key. [ejson_wrapper](https://github.com/envato/ejson_wrapper)
295
+ encrypts the underlying EJSON private key with KMS and stores it in the ejson file as `_private_key_enc`. Each
296
+ time an ejson secret is required, the underlying EJSON private key is first decrypted before passing it onto
297
+ ejson to decrypt the file.
298
+
299
+ First, generate an ejson file with ejson_wrapper, specifying the KMS key ID to be used:
300
+
301
+ ```shell
302
+ gem install ejson_wrapper
303
+ ejson_wrapper generate --region us-east-1 --kms-key-id [key_id] --file secrets/production.ejson
304
+ ```
305
+
306
+ Then, add the `ejson_file` argument to your stack in stack_master.yml:
307
+
308
+ ```yaml
309
+ stacks:
310
+ us-east-1:
311
+ my_app:
312
+ template: my_app.json
313
+ ejson_file: production.ejson
314
+ ```
315
+
316
+ finally refer to the secret key in the parameter file, i.e. parameters/my_app.yml:
317
+
318
+ ```yaml
319
+ my_param:
320
+ ejson: "my_secret"
321
+ ```
322
+
323
+ Additional configuration options:
324
+
325
+ - `ejson_file_region` The AWS region to attempt to decrypt private key with
326
+ - `ejson_file_kms` Default: true. Set to false to use ejson without KMS.
327
+
289
328
  ### Security Group
290
329
 
291
330
  Looks up a security group by name and returns the ARN.
data/lib/stack_master.rb CHANGED
@@ -68,6 +68,7 @@ module StackMaster
68
68
  autoload :AcmCertificate, 'stack_master/parameter_resolvers/acm_certificate'
69
69
  autoload :AmiFinder, 'stack_master/parameter_resolvers/ami_finder'
70
70
  autoload :StackOutput, 'stack_master/parameter_resolvers/stack_output'
71
+ autoload :Ejson, 'stack_master/parameter_resolvers/ejson'
71
72
  autoload :Secret, 'stack_master/parameter_resolvers/secret'
72
73
  autoload :SnsTopicName, 'stack_master/parameter_resolvers/sns_topic_name'
73
74
  autoload :SecurityGroup, 'stack_master/parameter_resolvers/security_group'
@@ -0,0 +1,48 @@
1
+ require 'ejson_wrapper'
2
+
3
+ module StackMaster
4
+ module ParameterResolvers
5
+ class Ejson < Resolver
6
+ SecretNotFound = Class.new(StandardError)
7
+
8
+ def initialize(config, stack_definition)
9
+ @config = config
10
+ @stack_definition = stack_definition
11
+ end
12
+
13
+ def resolve(secret_key)
14
+ validate_ejson_file_specified
15
+ secrets = decrypt_ejson_file
16
+ secrets.fetch(secret_key.to_sym) do
17
+ raise SecretNotFound, "Unable to find key #{secret_key} in file #{ejson_file}"
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def validate_ejson_file_specified
24
+ if @stack_definition.ejson_file.nil?
25
+ raise ArgumentError, "No ejson_file defined for stack definition #{@stack_definition.stack_name} in #{@stack_definition.region}"
26
+ end
27
+ end
28
+
29
+ def decrypt_ejson_file
30
+ @decrypt_ejson_file ||= EJSONWrapper.decrypt(ejson_file_path,
31
+ use_kms: @stack_definition.ejson_file_kms,
32
+ region: ejson_file_region)
33
+ end
34
+
35
+ def ejson_file_region
36
+ @stack_definition.ejson_file_region || StackMaster.cloud_formation_driver.region
37
+ end
38
+
39
+ def ejson_file_path
40
+ @ejson_file_path ||= File.join(@config.base_dir, secret_path_relative_to_base)
41
+ end
42
+
43
+ def secret_path_relative_to_base
44
+ @secret_path_relative_to_base ||= File.join('secrets', @stack_definition.ejson_file)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -10,6 +10,9 @@ module StackMaster
10
10
  :base_dir,
11
11
  :template_dir,
12
12
  :secret_file,
13
+ :ejson_file,
14
+ :ejson_file_region,
15
+ :ejson_file_kms,
13
16
  :stack_policy_file,
14
17
  :additional_parameter_lookup_dirs,
15
18
  :s3,
@@ -25,6 +28,7 @@ module StackMaster
25
28
  @s3 = {}
26
29
  @files = []
27
30
  @allowed_accounts = nil
31
+ @ejson_file_kms = true
28
32
  super
29
33
  @template_dir ||= File.join(@base_dir, 'templates')
30
34
  @allowed_accounts = Array(@allowed_accounts)
@@ -41,6 +45,9 @@ module StackMaster
41
45
  @notification_arns == other.notification_arns &&
42
46
  @base_dir == other.base_dir &&
43
47
  @secret_file == other.secret_file &&
48
+ @ejson_file == other.ejson_file &&
49
+ @ejson_file_region == other.ejson_file_region &&
50
+ @ejson_file_kms == other.ejson_file_kms &&
44
51
  @stack_policy_file == other.stack_policy_file &&
45
52
  @additional_parameter_lookup_dirs == other.additional_parameter_lookup_dirs &&
46
53
  @s3 == other.s3 &&
@@ -75,7 +75,7 @@ module StackMaster
75
75
 
76
76
  def single_param_update?(param_name)
77
77
  return false if param_name.blank? || @current_stack.blank? || body_different?
78
- differences = HashDiff.diff(@current_stack.parameters_with_defaults, @proposed_stack.parameters_with_defaults)
78
+ differences = Hashdiff.diff(@current_stack.parameters_with_defaults, @proposed_stack.parameters_with_defaults)
79
79
  return false if differences.count != 1
80
80
  diff = differences[0]
81
81
  diff[0] == "~" && diff[1] == param_name
@@ -1,3 +1,3 @@
1
1
  module StackMaster
2
- VERSION = "1.14.0"
2
+ VERSION = "1.15.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stack_master
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.0
4
+ version: 1.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Hodgkiss
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-07-03 00:00:00.000000000 Z
12
+ date: 2019-08-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -377,6 +377,20 @@ dependencies:
377
377
  version: '0'
378
378
  - !ruby/object:Gem::Dependency
379
379
  name: hashdiff
380
+ requirement: !ruby/object:Gem::Requirement
381
+ requirements:
382
+ - - "~>"
383
+ - !ruby/object:Gem::Version
384
+ version: '1'
385
+ type: :runtime
386
+ prerelease: false
387
+ version_requirements: !ruby/object:Gem::Requirement
388
+ requirements:
389
+ - - "~>"
390
+ - !ruby/object:Gem::Version
391
+ version: '1'
392
+ - !ruby/object:Gem::Dependency
393
+ name: ejson_wrapper
380
394
  requirement: !ruby/object:Gem::Requirement
381
395
  requirements:
382
396
  - - ">="
@@ -441,6 +455,7 @@ files:
441
455
  - lib/stack_master/parameter_resolver.rb
442
456
  - lib/stack_master/parameter_resolvers/acm_certificate.rb
443
457
  - lib/stack_master/parameter_resolvers/ami_finder.rb
458
+ - lib/stack_master/parameter_resolvers/ejson.rb
444
459
  - lib/stack_master/parameter_resolvers/env.rb
445
460
  - lib/stack_master/parameter_resolvers/latest_ami.rb
446
461
  - lib/stack_master/parameter_resolvers/latest_ami_by_tags.rb
@@ -514,8 +529,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
514
529
  - !ruby/object:Gem::Version
515
530
  version: '0'
516
531
  requirements: []
517
- rubyforge_project:
518
- rubygems_version: 2.7.6
532
+ rubygems_version: 3.0.3
519
533
  signing_key:
520
534
  specification_version: 4
521
535
  summary: StackMaster is a sure-footed way of creating, updating and keeping track