diff --git a/README.md b/README.md index 51ebd42..057ef42 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,9 @@ Instead of needing a private key locally, you can provide it to EYAML by setting If you put your rails master key encrypted in the eyaml file, make sure you don't have another `master.key` file somewhere, since that can interfere. +When setting the SECRET_KEY_BASE_DUMMY environment variable, the secrets/credentials loading will be skipped. +This can be handy to for example do an asset precompilation step in production where you don't need any secrets/credentials. + ### Example setup To add encryption + credentials to a rails project do the following things: diff --git a/lib/eyaml/railtie.rb b/lib/eyaml/railtie.rb index eede2a2..0b5c362 100644 --- a/lib/eyaml/railtie.rb +++ b/lib/eyaml/railtie.rb @@ -12,34 +12,37 @@ class ConflictError < StandardError end config.before_configuration do - if File.exist?(Rails.root.join("config", "master.key")) - raise ConflictError, "A config/master.key has been found. The rails credentials lookup conflicts with eyaml. Please remove rails credentials management by removing the master.key file to keep using eyaml." - end - secret_files_present = Dir.glob(auth_files(:secrets)).any? - credential_files_present = Dir.glob(auth_files(:credentials)).any? + unless ENV.fetch("SECRET_KEY_BASE_DUMMY", false) + # Allow rails to run without loading the credentials + if File.exist?(Rails.root.join("config", "master.key")) + raise ConflictError, "A config/master.key has been found. The rails credentials lookup conflicts with eyaml. Please remove rails credentials management by removing the master.key file to keep using eyaml." + end + secret_files_present = Dir.glob(auth_files(:secrets)).any? + credential_files_present = Dir.glob(auth_files(:credentials)).any? - secrets_or_credentials = if Rails.version >= "7.2" - :credentials - else - if credential_files_present + secrets_or_credentials = if Rails.version >= "7.2" :credentials - elsif secret_files_present - :secrets + else + if credential_files_present + :credentials + elsif secret_files_present + :secrets + end end - end - auth_files(secrets_or_credentials).each do |file| - next unless valid?(file) + auth_files(secrets_or_credentials).each do |file| + next unless valid?(file) - # If private_key is nil (i.e. when $EJSON_PRIVATE_KEY is not set), EYAML will search - # for a public/private key in the key directory (either $EJSON_KEYDIR, if set, or /opt/ejson/keys) - cipherdata = YAML.load_file(file) - secrets = EYAML.decrypt(cipherdata, private_key: ENV[PRIVATE_KEY_ENV_VAR]) - .except("_public_key") - secrets = EYAML::Util.with_deep_deundescored_keys(secrets) - .deep_symbolize_keys + # If private_key is nil (i.e. when $EJSON_PRIVATE_KEY is not set), EYAML will search + # for a public/private key in the key directory (either $EJSON_KEYDIR, if set, or /opt/ejson/keys) + cipherdata = YAML.load_file(file) + secrets = EYAML.decrypt(cipherdata, private_key: ENV[PRIVATE_KEY_ENV_VAR]) + .except("_public_key") + secrets = EYAML::Util.with_deep_deundescored_keys(secrets) + .deep_symbolize_keys - break Rails.application.send(secrets_or_credentials).deep_merge!(secrets) + break Rails.application.send(secrets_or_credentials).deep_merge!(secrets) + end end end diff --git a/lib/eyaml/version.rb b/lib/eyaml/version.rb index 27dfbf0..99e399a 100644 --- a/lib/eyaml/version.rb +++ b/lib/eyaml/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module EYAML - VERSION = "0.4.3" + VERSION = "0.4.4" end diff --git a/spec/eyaml/railtie_spec.rb b/spec/eyaml/railtie_spec.rb index 213bd78..69fa165 100644 --- a/spec/eyaml/railtie_spec.rb +++ b/spec/eyaml/railtie_spec.rb @@ -16,6 +16,8 @@ let(:credentials) { credentials_class.new } before(:each) do + ENV.delete("SECRET_KEY_BASE_DUMMY") + FakeFS::FileSystem.clone(fixtures_root) supported_extensions.each do |ext| @@ -43,6 +45,12 @@ end end + it "does not try to load credentials when SECRET_KEY_BASE_DUMMY env var is set" do + ENV["SECRET_KEY_BASE_DUMMY"] = "1" + expect { run_load_hooks }.not_to raise_error + expect(credentials).to(be_empty) + end + it "raises when a master.key file is present" do run_load_hooks expect(credentials).to(include(:secret)) @@ -147,6 +155,8 @@ let(:secrets) { secrets_class.new } before(:each) do + ENV.delete("SECRET_KEY_BASE_DUMMY") + FakeFS::FileSystem.clone(fixtures_root) supported_extensions.each do |ext| @@ -168,6 +178,12 @@ allow_rails.to(receive_message_chain("application.secrets").and_return(secrets)) end + it "does not try to load secrets when SECRET_KEY_BASE_DUMMY env var is set" do + ENV["SECRET_KEY_BASE_DUMMY"] = "1" + expect { run_load_hooks }.not_to raise_error + expect(secrets).to(be_empty) + end + it "merges secrets into application secrets" do run_load_hooks expect(secrets).to(include(:secret))