moonshot 1.1.0.beta1 → 1.1.0.beta2

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
  SHA1:
3
- metadata.gz: 2940b0c43a48274eb8368400726fc3269ff6fdf9
4
- data.tar.gz: fb6dfbf21127e8c55533bf848361f81c07f2b0d7
3
+ metadata.gz: 47ebc9ac74a51f7c8b474a1947508d4f32d16e9d
4
+ data.tar.gz: 84c3812ddc48bb7308027d442306a85288be1c94
5
5
  SHA512:
6
- metadata.gz: 146242a237abcccc8229257e0c73310ff539ba1483a57695cc1d6ccbc534778ac015354a9b91fa7ee09e83a8c2e921c3e61946dfd7a5ce0169b04ef005b37376
7
- data.tar.gz: aaf546412e380adc74bc823e7e2a7aef2e1ae31eafb35c2fe284e075b714940eb3d88b7c72dfa53a890f1bf9a62b0fb2108691f52eca510aa205bc1eccf67af2
6
+ metadata.gz: 2bd8244804aa2441c7f95434f68ae5f39c8e0c9fa305d986a66e5477e0285d244a6cb196a77036d22080fe62cf4897b8438f932fba53638fe71120c1b2bc065a
7
+ data.tar.gz: fb7bba6e3ae5e84e2a8f4f9c70953f1578425770fe37ea9ce2a2f2bc7f920757a31f311c7cacc3834488a3355b828871ca22a271fb385620fbb4e0a2c4935a54
@@ -0,0 +1,111 @@
1
+ # This plugin encrypts parameters of the stack using a KMS Key,
2
+ # storing and passing the key used to the stack as a parameter as
3
+ # well. The resources in the stack can then use that KMS Key to
4
+ # decrypt those values.
5
+ #
6
+ # Example:
7
+ #
8
+ # Moonshot.config do |s|
9
+ # # .. mechanism config, etc. ..
10
+ #
11
+ # # The user will be prompted for values for SecretParameter1 and
12
+ # # SecretParameter2, which will then be encrypted by this plugins
13
+ # # pre_create and pre_update hooks.
14
+ # c.plugins << Moonshot::Plugins::EncryptedParameters.new(
15
+ # 'KMSKey1', %w(SecretParameter1 SecretParameter2)
16
+ #
17
+ # # Don't prompt the user for a KMS Key, since the default of 'Auto'
18
+ # # will generate a new key. They can override it with an answer
19
+ # # file or command line parameter if needed.
20
+ # c.parameter_sources['KMSKey1'] = Moonshot::AlwaysUseDefaultSource.new
21
+ # end
22
+ module Moonshot
23
+ class EncryptedParameters
24
+ # @param [String] kms_key_parameter_name
25
+ # The parameter name to store the KMS Key ARN as.
26
+ # @param [Array<String>] parameters
27
+ # Names of parameters to encrypt, if they are not already set.
28
+ def initialize(kms_key_parameter_name, parameters)
29
+ @kms_key_parameter_name = kms_key_parameter_name
30
+ @parameters = parameters
31
+ @delete_key = true
32
+ end
33
+
34
+ def pre_create(res)
35
+ @ilog = res.ilog
36
+
37
+ key_arn = find_or_create_kms_key
38
+ pe = ParameterEncrypter.new(key_arn)
39
+
40
+ @parameters.each do |parameter_name|
41
+ sp = Moonshot.config.parameters[parameter_name]
42
+ raise "No such parameter #{parameter_name}" unless sp
43
+
44
+ @ilog.start_threaded "Handling encrypted parameter #{parameter_name.blue}..." do |s|
45
+ if sp.use_previous?
46
+ # TODO: Remove this and the one below when the upstream race is fixed.
47
+ # See https://github.com/askreet/interactive-logger/issues/7
48
+ sleep 0.05
49
+ s.success "Using previous encrypted value for #{parameter_name.blue}."
50
+ elsif !sp.set? && !sp.default?
51
+ # If the parameter isn't set, we can't encrypt it. Doing
52
+ # nothing means we will give the user a friendly error message
53
+ # about unset parameters when the controller resumes.
54
+ sleep 0.05
55
+ s.failure "No value to encrypt for #{parameter_name.blue}!"
56
+ else
57
+ s.continue "Encrypting new value for parameter #{parameter_name.blue}..."
58
+ Moonshot.config.parameters[sp.name].set(pe.encrypt(sp.value))
59
+ s.success "Encrypted new value for parameter #{parameter_name.blue}!"
60
+ end
61
+ end
62
+ end
63
+ end
64
+ alias pre_update pre_create
65
+
66
+ def post_delete(res)
67
+ key_arn = Moonshot.config.parameters[@kms_key_parameter_name].value
68
+
69
+ res.ilog.start_threaded "Cleaning up KMS Key #{@kms_key_parameter_name.blue}..." do |s|
70
+ if @delete_key
71
+ KmsKey.new(key_arn).delete
72
+ s.success "Deleted KMS Key #{@kms_key_parameter_name.blue}!"
73
+ else
74
+ # TODO: See above.
75
+ sleep 0.05
76
+ s.success "Retained KMS Key #{@kms_key_parameter_name.blue}."
77
+ end
78
+ end
79
+ end
80
+
81
+ def delete_cli_hook(parser)
82
+ parser.on('--retain-kms-key', TrueClass, 'Do not delete the KMS Key for this environment.') do
83
+ @delete_key = false
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def find_or_create_kms_key
90
+ key_arn = nil
91
+
92
+ @ilog.start_threaded "Checking for KMS Key #{@kms_key_parameter_name}" do |s|
93
+ if Moonshot.config.parameters.key?(@kms_key_parameter_name)
94
+ if 'Auto' == Moonshot.config.parameters[@kms_key_parameter_name].value
95
+ s.continue "Auto-generating KMS Key for #{@kms_key_parameter_name.blue}... "
96
+ key_arn = KmsKey.create.arn
97
+ Moonshot.config.parameters[@kms_key_parameter_name].set(key_arn)
98
+ s.success "Created a new KMS Key for #{@kms_key_parameter_name.blue}!"
99
+ else
100
+ key_arn = KmsKey.new(Moonshot.config.parameters[@kms_key_parameter_name].value).arn
101
+ s.success "Using existing KMS Key for #{@kms_key_parameter_name.blue}!"
102
+ end
103
+ end
104
+ end
105
+
106
+ raise "No such Stack Parameter #{@kms_key_parameter_name}!" unless key_arn
107
+
108
+ key_arn
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,22 @@
1
+ class EncryptedParameters
2
+ # Class that manages KMS keys in AWS.
3
+ class KmsKey
4
+ attr_reader :arn
5
+
6
+ def initialize(arn)
7
+ @arn = arn
8
+ @kms_client = Aws::KMS::Client.new
9
+ end
10
+
11
+ def self.create
12
+ resp = Aws::KMS::Client.new.create_key
13
+ arn = resp.key_metadata.arn
14
+
15
+ new(arn)
16
+ end
17
+
18
+ def delete
19
+ @kms_client.schedule_key_deletion(key_id: @arn, pending_window_in_days: 7)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ require 'base64'
2
+
3
+ class EncryptedParameters
4
+ # Class that can encrypt and decrypt parameters using KMS.
5
+ class ParameterEncrypter
6
+ # @param [String] key_arn The ARN for the KMS key.
7
+ def initialize(key_arn)
8
+ @kms_client = Aws::KMS::Client.new
9
+ @key_arn = key_arn
10
+ end
11
+
12
+ # Encrypt and base64 encode the parameter value.
13
+ #
14
+ # @param [String] param_value The parameter to encrypt.
15
+ # @return [String] base64 encoded encrypted ciphertext.
16
+ def encrypt(param_value)
17
+ resp = @kms_client.encrypt(key_id: @key_arn, plaintext: param_value)
18
+
19
+ # Use strict here to avoid newlines which cause issues with parameters.
20
+ Base64.strict_encode64(resp.ciphertext_blob)
21
+ end
22
+ end
23
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moonshot
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0.beta1
4
+ version: 1.1.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cloud Engineering <engineering@acquia.com>
@@ -317,6 +317,9 @@ files:
317
317
  - lib/moonshot/unicode_table.rb
318
318
  - lib/moonshot/yaml_stack_template.rb
319
319
  - lib/plugins/backup.rb
320
+ - lib/plugins/encrypted_parameters.rb
321
+ - lib/plugins/encrypted_parameters/kms_key.rb
322
+ - lib/plugins/encrypted_parameters/parameter_encrypter.rb
320
323
  homepage: https://github.com/acquia/moonshot
321
324
  licenses:
322
325
  - Apache-2.0