class CICI::Encrypt
Public Class Methods
new(ui, decrypter, config)
click to toggle source
# File lib/cici/encrypt.rb, line 17 def initialize(ui, decrypter, config) @ui = ui @config = config @util = CICI::Util.new(@ui) @decrypter = decrypter # Default key/iv that's generated for you. We can change these values later before encryption. aes = OpenSSL::Cipher.new('AES-256-CBC') aes.encrypt @encryption_key = aes.random_key @encryption_iv = aes.random_iv @first_time_encrypting = false end
Public Instance Methods
start()
click to toggle source
# File lib/cici/encrypt.rb, line 31 def start assert_secret_files_exist # We want to reuse key/iv values for encryption. So, let's get those values before moving forward. prompt_for_keys compress assert_files_in_gitignore encrypt end
Private Instance Methods
assert_files_in_gitignore()
click to toggle source
# File lib/cici/encrypt.rb, line 113 def assert_files_in_gitignore ignore_file_name = '.gitignore' if @config.skip_gitignore? || !File.exist?(ignore_file_name) @ui.verbose('Skipping adding entries to .gitignore file') return end @ui.verbose("Adding entries to #{ignore_file_name} file") current_gitignore_file_contents = Set[] File.foreach(ignore_file_name).with_index do |line, _line_num| line = line.strip current_gitignore_file_contents = current_gitignore_file_contents.add(line) end @ui.debug("current contents of #{ignore_file_name}: #{current_gitignore_file_contents}") new_gitignore_additions = current_gitignore_file_contents.clone add_to_gitignore = lambda { |file| new_gitignore_additions = new_gitignore_additions.add(file) } # Add all but the encrypted output file as that is required for decryption add_to_gitignore.call(@config.output_file) add_to_gitignore.call(@config.base_path) @config.all_secrets_original_paths.each do |secret_file| add_to_gitignore.call(secret_file) end new_gitignore_additions -= current_gitignore_file_contents @ui.debug("additions to #{ignore_file_name}: #{new_gitignore_additions}") new_gitignore_additions = new_gitignore_additions.to_a unless new_gitignore_additions.empty? # only write if something to add @ui.debug("writing new #{ignore_file_name} additions: #{new_gitignore_additions}") gitignore_file_prepended_additions = new_gitignore_additions.join("\n") + "\n\n" + File.read(ignore_file_name) File.write(ignore_file_name, gitignore_file_prepended_additions) end @ui.verbose("Done adding entries to #{ignore_file_name}") end
assert_secret_files_exist()
click to toggle source
# File lib/cici/encrypt.rb, line 42 def assert_secret_files_exist @ui.verbose('Asserting secret files exist') assert_file_exists = lambda { |file| @ui.debug("Checking #{file} exists...") @ui.fail("File or directory at path #{file} does not exist. Can't encrypt your secrets with missing secrets.") unless File.exist?(file) } @ui.verbose("Checking secrets exist in #{@config.base_path} directory.") @config.all_secrets.each do |file| assert_file_exists.call(file) end end
compress()
click to toggle source
# File lib/cici/encrypt.rb, line 82 def compress @ui.verbose('Compressing secrets...') @util.run_command("tar cvf #{@config.output_file} #{@config.base_path}") end
encrypt()
click to toggle source
# File lib/cici/encrypt.rb, line 88 def encrypt @ui.verbose("Encrypting #{@config.output_file} to file #{@config.output_file_encrypted}") aes = OpenSSL::Cipher.new('AES-256-CBC') data = File.binread(@config.output_file) aes.encrypt aes.key = @encryption_key aes.iv = @encryption_iv File.write(@config.output_file_encrypted, aes.update(data) + aes.final) if @first_time_encrypting @ui.success('Success! Now, you need to follow these last few steps:') @ui.success("1. Make sure to add #{@config.output_file_encrypted} to your version control") @ui.success('Below you will find secret keys used to encrypt and decrypt your secrets in the future.') @ui.success('**These will not be revealed ever again!** Store these in a safe and secure place.') @ui.success('') @ui.success('2. Share these secret keys with your team. They must provide the same keys to encrypt again. Keep secrets up-to-date with a git hook.') @ui.success('3. Set these *secret* environment variables in your CI server for decryption.') @ui.success("Key: #{CICI::DECRYPT_KEY_ENV_VAR} and value: #{Base64.encode64(@encryption_key).strip}") @ui.success("Key: #{CICI::DECRYPT_IV_ENV_VAR} and value: #{Base64.encode64(@encryption_iv).strip}") else @ui.success('Success!') end end
prompt_for_keys()
click to toggle source
# File lib/cici/encrypt.rb, line 58 def prompt_for_keys has_encrypted_before = File.exist?(@config.output_file) if has_encrypted_before @ui.message('It looks like you have encrypted your secrets before.') @ui.message('Enter the key you use to encrypt:') key = Base64.decode64(STDIN.gets.chomp) @ui.message('Enter the IV you use to encrypt:') iv = Base64.decode64(STDIN.gets.chomp) plain = @decrypter.decrypt(key, iv) @ui.fail('Key or IV value does not match the key/IV pair used when previously encrypting') if plain.empty? @encryption_key = key @encryption_iv = iv else @ui.debug("Encrypted output file, #{@config.output_file}, does not exist. Therefore, let's assume this is the first time encrypting secrets.") @ui.message('It looks like this is the first time that you are encrypting secrets.') @ui.message('Generating secure keys for you...') @first_time_encrypting = true end end