CubicLouve

Spring_MTの技術ブログ

Railsのcredentialの実装を追う + 自由にpathを指定してeditできるtaskを作る

スタートはここから

rails/credentials_command.rb at 0f5c8c5bc61b7e382e64cad4846406021bc8cd35 · rails/rails · GitHub

keyの生成

Rails::Generators::EncryptionKeyFileGenerator を使う これは

rails/encryption_key_file_generator.rb at 0f5c8c5bc61b7e382e64cad4846406021bc8cd35 · rails/rails · GitHub

中で ActiveSupport::EncryptedFile.generate_key を読んでいて

github.com

SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(CIPHER)) となっている。

ActiveSupport::MessageEncryptor.key_lenOpenSSL::Cipher.new(cipher).key_len をラップしているだけ。

ファイルの暗号化

rails/application.rb at 0f5c8c5bc61b7e382e64cad4846406021bc8cd35 · rails/rails · GitHub

ActiveSupport::EncryptedConfiguration が使われる

最終的に ActiveSupport::EncryptedFile に行き着く。

rails/encrypted_file.rb at 0f5c8c5bc61b7e382e64cad4846406021bc8cd35 · rails/rails · GitHub

taskの例

require "active_support/encrypted_file"

namespace :credentials do
  desc 'keyの生成'
  task generate_key: :environment do
    puts ActiveSupport::EncryptedFile.generate_key
  end

  desc 'ファイルの編集'
  task :edit_credential_file, ['path'] => :environment do |task, args|
    path = args.path
    credentials = ActiveSupport::EncryptedConfiguration.new(
      config_path: path,
      env_key: "RAILS_MASTER_KEY",
      key_path: "",
      raise_if_missing_key: true
    )
    credentials.change { |tmp_path| system(*Shellwords.split(ENV["EDITOR"]), tmp_path.to_s) }
    begin
      credentials.validate!
    rescue ActiveSupport::EncryptedConfiguration::InvalidContentError => error
      puts "WARNING: #{error.message}"
      puts "Your application will not be able to load '#{path}' until the error has been fixed."
    end
  end
end