require 'gpgme' # Note: to encrypt the file after a change use the command line: # gpg -a -c -o config/overrides/#{stage}/filename.yml.asc config/overrides/#{stage}/filename.yml
namespace :deploy do
desc "update encrypted files in `stage` overrides, if necessary, and link" task :copy_secure_overrides do on roles(:all) do stage = fetch(:stage) Dir.glob(deploy_config_path.expand_path.dirname.join('overrides',stage.to_s,'*.asc')).each do |local_encrypted_file| filename = File.split(local_encrypted_file).last.chomp('.asc') remote_encrypted_file = "#{shared_path}/config/#{filename}.asc" remote_plaintext_file = "#{shared_path}/config/#{filename}" remote_override_file = "#{release_path}/config/overrides/#{stage}/#{filename}" if chksums_differ?(local_encrypted_file, remote_encrypted_file) plaintext = decrypt(local_encrypted_file) execute "mkdir -p '#{shared_path}/config'" upload! local_encrypted_file, remote_encrypted_file upload! StringIO.new(plaintext), remote_plaintext_file execute "chmod 600 #{remote_plaintext_file}" end execute "mkdir -p '#{release_path}/config/overrides/#{stage}'" execute "/bin/ln -nsf #{remote_plaintext_file} #{remote_override_file}" execute "rm -f #{remote_override_file}.asc" end end end
end
def decrypt(local_encrypted_file)
got_it = false while not got_it begin print "\nPlease enter the passphrase to decrypt %s: " % File.split(local_encrypted_file).last password = $stdin.noecho(&:gets).chomp crypto = GPGME::Crypto.new(:password => password) data = crypto.decrypt File.read(local_encrypted_file) plaintext = data.read got_it = true rescue GPGME::Error::DecryptFailed puts "\nInvalid Password, decryption failed" puts end end plaintext
end
def chksums_differ?(local,remote)
local_hasher = system('which','sha1sum') ? 'sha1sum' : 'shasum' local_chksum = `#{local_hasher} "#{local}"`.split(' ').first remote_chksum = capture("[ -f #{remote} ] && sha1sum #{remote} || true").split(' ').first || 'file_not_found' local_chksum != remote_chksum
end