Skip to content

Commit a6a9fed

Browse files
authored
Merge pull request rails#42106 from ghiculescu/secrets-nested-keys
Allow access to nested secrets by method calls
2 parents e0d2459 + 94d1d52 commit a6a9fed

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

activesupport/CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
* Allow nested access to keys on `Rails.application.credentials`
2+
3+
Previously only top level keys in `credentials.yml.enc` could be accessed with method calls. Now any key can.
4+
5+
For example, given these secrets:
6+
7+
```yml
8+
aws:
9+
access_key_id: 123
10+
secret_access_key: 345
11+
```
12+
13+
`Rails.application.credentials.aws.access_key_id` will now return the same thing as `Rails.application.credentials.aws[:access_key_id]`
14+
15+
*Alex Ghiculescu*
16+
117
* Added a faster and more compact `ActiveSupport::Cache` serialization format.
218

319
It can be enabled with `config.active_support.cache_format_version = 7.0` or

activesupport/lib/active_support/encrypted_configuration.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ def config
3434
end
3535

3636
private
37+
def deep_transform(hash)
38+
hash.transform_values { |value| value.is_a?(Hash) ? ActiveSupport::InheritableOptions.new(deep_transform(value)) : value }
39+
end
40+
3741
def options
38-
@options ||= ActiveSupport::InheritableOptions.new(config)
42+
@options ||= ActiveSupport::InheritableOptions.new(deep_transform(config))
3943
end
4044

4145
def deserialize(config)

activesupport/test/encrypted_configuration_test.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,14 @@ class EncryptedConfigurationTest < ActiveSupport::TestCase
3737
end
3838

3939
test "reading configuration by key file" do
40-
@credentials.write({ something: { good: true } }.to_yaml)
40+
@credentials.write({ something: { good: true, bad: false, nested: { foo: "bar" } } }.to_yaml)
4141

4242
assert @credentials.something[:good]
43+
assert_not @credentials.something[:bad]
44+
assert @credentials.something.good
45+
assert_not @credentials.something.bad
46+
assert_equal "bar", @credentials.dig(:something, :nested, :foo)
47+
assert_equal "bar", @credentials.something.nested.foo
4348
end
4449

4550
test "reading comment-only configuration" do

guides/source/security.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1163,9 +1163,11 @@ For example, with the following decrypted `config/credentials.yml.enc`:
11631163
```yaml
11641164
secret_key_base: 3b7cd72...
11651165
some_api_key: SOMEKEY
1166+
system:
1167+
access_key_id: 1234AB
11661168
```
11671169
1168-
`Rails.application.credentials.some_api_key` returns `"SOMEKEY"`.
1170+
`Rails.application.credentials.some_api_key` returns `"SOMEKEY"`. `Rails.application.credentials.system.access_key_id` returns `"1234AB"`.
11691171

11701172
If you want an exception to be raised when some key is blank, you can use the bang
11711173
version:

0 commit comments

Comments
 (0)