From 827bfe4f41c39eade078e26ad5653979891d89c7 Mon Sep 17 00:00:00 2001
From: "yuuji.yaginuma" <yuuji.yaginuma@gmail.com>
Date: Sat, 1 Apr 2017 13:22:25 +0900
Subject: Use the config value directly when call `secrets`

Currently, `read_encrypted_secrets` is set with initializer.
Therefore if refer to `secrets` in config, `read_encrypted_secrets` is false,
so can not get the value of `secrets.yml.enc`.

In order to be able to refer to secrets in config, modified to refer to
`config.read_encrypted_secrets` when calling `secrets`.

Fixes #28618.
---
 railties/lib/rails/application.rb           |  4 +++-
 railties/lib/rails/application/bootstrap.rb |  1 -
 railties/lib/rails/secrets.rb               | 10 ++-------
 railties/test/secrets_test.rb               | 34 ++++++++++++++++++++++-------
 4 files changed, 31 insertions(+), 18 deletions(-)

(limited to 'railties')

diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 89f7b5991f..f8a923141d 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -386,7 +386,9 @@ module Rails
     def secrets
       @secrets ||= begin
         secrets = ActiveSupport::OrderedOptions.new
-        secrets.merge! Rails::Secrets.parse(config.paths["config/secrets"].existent, env: Rails.env)
+        files = config.paths["config/secrets"].existent
+        files = files.reject { |path| path.end_with?(".enc") } unless config.read_encrypted_secrets
+        secrets.merge! Rails::Secrets.parse(files, env: Rails.env)
 
         # Fallback to config.secret_key_base if secrets.secret_key_base isn't set
         secrets.secret_key_base ||= config.secret_key_base
diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb
index 4223c38146..dc0491035d 100644
--- a/railties/lib/rails/application/bootstrap.rb
+++ b/railties/lib/rails/application/bootstrap.rb
@@ -81,7 +81,6 @@ INFO
 
       initializer :set_secrets_root, group: :all do
         Rails::Secrets.root = root
-        Rails::Secrets.read_encrypted_secrets = config.read_encrypted_secrets
       end
     end
   end
diff --git a/railties/lib/rails/secrets.rb b/railties/lib/rails/secrets.rb
index 2a95712cd9..8b644f212c 100644
--- a/railties/lib/rails/secrets.rb
+++ b/railties/lib/rails/secrets.rb
@@ -14,12 +14,10 @@ module Rails
     end
 
     @cipher = "aes-128-gcm"
-    @read_encrypted_secrets = false
     @root = File # Wonky, but ensures `join` uses the current directory.
 
     class << self
-      attr_writer   :root
-      attr_accessor :read_encrypted_secrets
+      attr_writer :root
 
       def parse(paths, env:)
         paths.each_with_object(Hash.new) do |path, all_secrets|
@@ -88,11 +86,7 @@ module Rails
 
         def preprocess(path)
           if path.end_with?(".enc")
-            if @read_encrypted_secrets
-              decrypt(IO.binread(path))
-            else
-              ""
-            end
+            decrypt(IO.binread(path))
           else
             IO.read(path)
           end
diff --git a/railties/test/secrets_test.rb b/railties/test/secrets_test.rb
index 953408f0b4..73b6cb7a66 100644
--- a/railties/test/secrets_test.rb
+++ b/railties/test/secrets_test.rb
@@ -9,22 +9,22 @@ class Rails::SecretsTest < ActiveSupport::TestCase
 
   def setup
     build_app
-
-    @old_read_encrypted_secrets, Rails::Secrets.read_encrypted_secrets =
-      Rails::Secrets.read_encrypted_secrets, true
   end
 
   def teardown
-    Rails::Secrets.read_encrypted_secrets = @old_read_encrypted_secrets
-
     teardown_app
   end
 
   test "setting read to false skips parsing" do
-    Rails::Secrets.read_encrypted_secrets = false
+    run_secrets_generator do
+      Rails::Secrets.write(<<-end_of_secrets)
+        test:
+          yeah_yeah: lets-walk-in-the-cool-evening-light
+      end_of_secrets
 
-    Dir.chdir(app_path) do
-      assert_equal Hash.new, Rails::Secrets.parse(%w( config/secrets.yml.enc ), env: "production")
+      Rails.application.config.read_encrypted_secrets = false
+      Rails.application.instance_variable_set(:@secrets, nil) # Dance around caching 💃🕺
+      assert_not Rails.application.secrets.yeah_yeah
     end
   end
 
@@ -90,11 +90,29 @@ class Rails::SecretsTest < ActiveSupport::TestCase
       end_of_secrets
 
       Rails.application.config.root = app_path
+      Rails.application.config.read_encrypted_secrets = true
       Rails.application.instance_variable_set(:@secrets, nil) # Dance around caching 💃🕺
       assert_equal "lets-walk-in-the-cool-evening-light", Rails.application.secrets.yeah_yeah
     end
   end
 
+  test "refer secrets inside env config" do
+    run_secrets_generator do
+      Rails::Secrets.write(<<-end_of_yaml)
+        production:
+          some_secret: yeah yeah
+      end_of_yaml
+
+      add_to_env_config "production", <<-end_of_config
+        config.dereferenced_secret = Rails.application.secrets.some_secret
+      end_of_config
+
+      Dir.chdir(app_path) do
+        assert_equal "yeah yeah\n", `bin/rails runner -e production "puts Rails.application.config.dereferenced_secret"`
+      end
+    end
+  end
+
   private
     def run_secrets_generator
       Dir.chdir(app_path) do
-- 
cgit v1.2.3