Skip to content

Commit

Permalink
EncryptedParameters plugin should be in the Moonshot::Plugins module (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
janost authored and askreet committed Jan 27, 2017
1 parent a4708c9 commit a6ee79b
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 97 deletions.
138 changes: 72 additions & 66 deletions lib/plugins/encrypted_parameters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,92 +20,98 @@
# c.parameter_sources['KMSKey1'] = Moonshot::AlwaysUseDefaultSource.new
# end
module Moonshot
class EncryptedParameters
# @param [String] kms_key_parameter_name
# The parameter name to store the KMS Key ARN as.
# @param [Array<String>] parameters
# Names of parameters to encrypt, if they are not already set.
def initialize(kms_key_parameter_name, parameters)
@kms_key_parameter_name = kms_key_parameter_name
@parameters = parameters
@delete_key = true
end
module Plugins
class EncryptedParameters
# @param [String] kms_key_parameter_name
# The parameter name to store the KMS Key ARN as.
# @param [Array<String>] parameters
# Names of parameters to encrypt, if they are not already set.
def initialize(kms_key_parameter_name, parameters)
@kms_key_parameter_name = kms_key_parameter_name
@parameters = parameters
@delete_key = true
end

def pre_create(res)
@ilog = res.ilog
def pre_create(res)
@ilog = res.ilog

key_arn = find_or_create_kms_key
pe = ParameterEncrypter.new(key_arn)
key_arn = find_or_create_kms_key
pe = ParameterEncrypter.new(key_arn)

@parameters.each do |parameter_name|
sp = Moonshot.config.parameters[parameter_name]
raise "No such parameter #{parameter_name}" unless sp
@parameters.each do |parameter_name|
sp = Moonshot.config.parameters[parameter_name]
raise "No such parameter #{parameter_name}" unless sp

@ilog.start_threaded "Handling encrypted parameter #{parameter_name.blue}..." do |s|
if sp.use_previous?
# TODO: Remove this and the one below when the upstream race is fixed.
# See https://github.com/askreet/interactive-logger/issues/7
sleep 0.05
s.success "Using previous encrypted value for #{parameter_name.blue}."
elsif !sp.set? && !sp.default?
# If the parameter isn't set, we can't encrypt it. Doing
# nothing means we will give the user a friendly error message
# about unset parameters when the controller resumes.
sleep 0.05
s.failure "No value to encrypt for #{parameter_name.blue}!"
else
s.continue "Encrypting new value for parameter #{parameter_name.blue}..."
Moonshot.config.parameters[sp.name].set(pe.encrypt(sp.value))
s.success "Encrypted new value for parameter #{parameter_name.blue}!"
@ilog.start_threaded "Handling encrypted parameter #{parameter_name.blue}..." do |s|
if sp.use_previous?
# TODO: Remove this and the one below when the upstream race is fixed.
# See https://github.com/askreet/interactive-logger/issues/7
sleep 0.05
s.success "Using previous encrypted value for #{parameter_name.blue}."
elsif !sp.set? && !sp.default?
# If the parameter isn't set, we can't encrypt it. Doing
# nothing means we will give the user a friendly error message
# about unset parameters when the controller resumes.
sleep 0.05
s.failure "No value to encrypt for #{parameter_name.blue}!"
else
s.continue "Encrypting new value for parameter #{parameter_name.blue}..."
Moonshot.config.parameters[sp.name].set(pe.encrypt(sp.value))
s.success "Encrypted new value for parameter #{parameter_name.blue}!"
end
end
end
end
end
alias pre_update pre_create
alias pre_update pre_create

def post_delete(res)
key_arn = Moonshot.config.parameters[@kms_key_parameter_name].value
def post_delete(res)
key_arn = Moonshot.config.parameters[@kms_key_parameter_name].value

res.ilog.start_threaded "Cleaning up KMS Key #{@kms_key_parameter_name.blue}..." do |s|
if @delete_key
KmsKey.new(key_arn).delete
s.success "Deleted KMS Key #{@kms_key_parameter_name.blue}!"
else
# TODO: See above.
sleep 0.05
s.success "Retained KMS Key #{@kms_key_parameter_name.blue}."
res.ilog.start_threaded "Cleaning up KMS Key #{@kms_key_parameter_name.blue}..." do |s|
if @delete_key
KmsKey.new(key_arn).delete
s.success "Deleted KMS Key #{@kms_key_parameter_name.blue}!"
else
# TODO: See above.
sleep 0.05
s.success "Retained KMS Key #{@kms_key_parameter_name.blue}."
end
end
end
end

def delete_cli_hook(parser)
parser.on('--retain-kms-key', TrueClass, 'Do not delete the KMS Key for this environment.') do
@delete_key = false
def delete_cli_hook(parser)
parser.on(
'--retain-kms-key',
TrueClass,
'Do not delete the KMS Key for this environment.'
) do
@delete_key = false
end
end
end

private
private

def find_or_create_kms_key
key_arn = nil
def find_or_create_kms_key
key_arn = nil

@ilog.start_threaded "Checking for KMS Key #{@kms_key_parameter_name}" do |s|
if Moonshot.config.parameters.key?(@kms_key_parameter_name)
if 'Auto' == Moonshot.config.parameters[@kms_key_parameter_name].value
s.continue "Auto-generating KMS Key for #{@kms_key_parameter_name.blue}... "
key_arn = KmsKey.create.arn
Moonshot.config.parameters[@kms_key_parameter_name].set(key_arn)
s.success "Created a new KMS Key for #{@kms_key_parameter_name.blue}!"
else
key_arn = KmsKey.new(Moonshot.config.parameters[@kms_key_parameter_name].value).arn
s.success "Using existing KMS Key for #{@kms_key_parameter_name.blue}!"
@ilog.start_threaded "Checking for KMS Key #{@kms_key_parameter_name}" do |s|
if Moonshot.config.parameters.key?(@kms_key_parameter_name)
if 'Auto' == Moonshot.config.parameters[@kms_key_parameter_name].value
s.continue "Auto-generating KMS Key for #{@kms_key_parameter_name.blue}... "
key_arn = KmsKey.create.arn
Moonshot.config.parameters[@kms_key_parameter_name].set(key_arn)
s.success "Created a new KMS Key for #{@kms_key_parameter_name.blue}!"
else
key_arn = KmsKey.new(Moonshot.config.parameters[@kms_key_parameter_name].value).arn
s.success "Using existing KMS Key for #{@kms_key_parameter_name.blue}!"
end
end
end
end

raise "No such Stack Parameter #{@kms_key_parameter_name}!" unless key_arn
raise "No such Stack Parameter #{@kms_key_parameter_name}!" unless key_arn

key_arn
key_arn
end
end
end
end
32 changes: 17 additions & 15 deletions lib/plugins/encrypted_parameters/kms_key.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
module Moonshot
class EncryptedParameters
# Class that manages KMS keys in AWS.
class KmsKey
attr_reader :arn
module Plugins
class EncryptedParameters
# Class that manages KMS keys in AWS.
class KmsKey
attr_reader :arn

def initialize(arn)
@arn = arn
@kms_client = Aws::KMS::Client.new
end
def initialize(arn)
@arn = arn
@kms_client = Aws::KMS::Client.new
end

def self.create
resp = Aws::KMS::Client.new.create_key
arn = resp.key_metadata.arn
def self.create
resp = Aws::KMS::Client.new.create_key
arn = resp.key_metadata.arn

new(arn)
end
new(arn)
end

def delete
@kms_client.schedule_key_deletion(key_id: @arn, pending_window_in_days: 7)
def delete
@kms_client.schedule_key_deletion(key_id: @arn, pending_window_in_days: 7)
end
end
end
end
Expand Down
34 changes: 18 additions & 16 deletions lib/plugins/encrypted_parameters/parameter_encrypter.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
require 'base64'
module Moonshot
class EncryptedParameters
# Class that can encrypt and decrypt parameters using KMS.
class ParameterEncrypter
# @param [String] key_arn The ARN for the KMS key.
def initialize(key_arn)
@kms_client = Aws::KMS::Client.new
@key_arn = key_arn
end
module Plugins
class EncryptedParameters
# Class that can encrypt and decrypt parameters using KMS.
class ParameterEncrypter
# @param [String] key_arn The ARN for the KMS key.
def initialize(key_arn)
@kms_client = Aws::KMS::Client.new
@key_arn = key_arn
end

# Encrypt and base64 encode the parameter value.
#
# @param [String] param_value The parameter to encrypt.
# @return [String] base64 encoded encrypted ciphertext.
def encrypt(param_value)
resp = @kms_client.encrypt(key_id: @key_arn, plaintext: param_value)
# Encrypt and base64 encode the parameter value.
#
# @param [String] param_value The parameter to encrypt.
# @return [String] base64 encoded encrypted ciphertext.
def encrypt(param_value)
resp = @kms_client.encrypt(key_id: @key_arn, plaintext: param_value)

# Use strict here to avoid newlines which cause issues with parameters.
Base64.strict_encode64(resp.ciphertext_blob)
# Use strict here to avoid newlines which cause issues with parameters.
Base64.strict_encode64(resp.ciphertext_blob)
end
end
end
end
Expand Down

0 comments on commit a6ee79b

Please sign in to comment.