README.md in ejson-rails-0.1.1 vs README.md in ejson-rails-0.2.0

- old
+ new

@@ -1,10 +1,10 @@ # EJSON::Rails -[![Build Status](https://travis-ci.com/Shopify/ejson-rails.svg?token=ShuwwQhmf65yNstgcUSy&branch=master)](https://travis-ci.com/Shopify/ejson-rails) +[![Build Status](https://github.com/Shopify/ejson-rails/workflows/CI/badge.svg?branch=main)](https://github.com/Shopify/ejson-rails/actions?query=branch%3Amain) -Automatically injects `ejson` decrypted secrets into your `Rails.application.secrets`. +Automatically injects [`ejson`](https://github.com/Shopify/ejson) decrypted secrets into your `Rails.application.secrets`. ## Installation Add this line to your application's Gemfile: @@ -28,9 +28,98 @@ // project/config/secrets.json { "some_secret": "key" } ``` will be accessible via `Rails.application.secrets.some_secret` or `Rails.application.secrets[:some_secret]` on boot. JSON files are loaded once and contents are `deep_merge`'d into your app's existing rails secrets. + +Secrets will also be accessible via `Rails.application.credentials`, e.g. `Rails.application.credentials.some_secret` or `Rails.application.credentials[:some_secret]`. To avoid subtle compatibility issues, if a credential already exists, an error will occur. + +NOTE: This gem does not decrypt ejson for you. You will need to configure this as part of your deployment pipeline. + +## Migrating to credentials + +Rails 7.1 has deprecated application secrets in favor of credentials. ejson-rails can migrate secrets to application credentials. + +Even before running Rails 7.1, you can migrate your secrets in a few steps. + +First, move the development and test secrets to JSON secrets: + +```sh-session +bin/rails runner 'Rails.root.join("config/secrets.#{Rails.env}.json").write(JSON.pretty_generate(Rails.application.secrets.to_h.without(:secret_key_base)))' +bin/rails runner -e test 'Rails.root.join("config/secrets.#{Rails.env}.json").write(JSON.pretty_generate(Rails.application.secrets.to_h.without(:secret_key_base)))' +``` + +Secrets support ERB while EJSON secrets don't, so if your secrets contain ERB, you will need to move that logic to the environment configurations: + +**Before**: + +`config/secrets.yml` +```yaml +development: + some_external_service: + api_token: <%= ENV.fetch(SOME_EXTERNAL_SERVICE_API_TOKEN, "12345") %> +``` + +**After**: + +`config/secrets.development.json` as generated by the command above. +```json +{ + "some_external_service": { + "api_token": "12345" + }, + "something_else_entirely": "abc" +} +``` + +`config/environments/development.rb` +```ruby +Rails.application.configure do + # elided + + # credential should be set using []=, not the dynamic accessors + credentials[:some_external_service][:api_token] = ENV.fetch("SOME_EXTERNAL_SERVICE_API_TOKEN", "12345") + + # top-level values must be set through `credentials.config` + credentials.config[:something_else_entirely] = ENV.fetch("SOMETHING_ELSE_ENTIRELY", "abc") +end +``` + +Note that the code accesses the credentials as a Hash with `[]` and `[]=`. This is important because the dynamic accessor methods will set values in a different object, and credentials will behave inconsistently after that: + +```ruby +Rails.application.credentials.some_external_service.api_token = "foo" +Rails.application.credentials[:some_external_service][:api_token] # => "12345" +``` + +Also note the code sets top-level values through `credentials.config`, because `credentials#[]=(key, value)` sets values in a different object. + +```ruby +Rails.application.credentials[:something_else_entirely] = "foo" +Rails.application.credentials[:something_else_entirely] # => "abc" +``` + +Make sure there's no code using the dynamic accessors before setting the configuration in the Hash, or the values won't be accessible from the dynamic accessor: + +```ruby +Rails.application.credentials.something_else_entirely # just accessing is enough to cause the issue +Rails.application.credentials[:some_external_service][:api_token] = "foo" +Rails.application.credentials.some_external_service.api_token # => "12345" +``` + +You're now ready to use credentials instead of secrets: + +```sh-session +git ls-files | xargs ruby -pi -e 'gsub("Rails.application.secrets", "Rails.application.credentials")' -- +``` + +To avoid the deprecation warning from the use of secrets in `ejson-rails` once you're running Rails 7.1, require another file from your Gemfile: + +```ruby +gem 'ejson-rails', require: 'ejson/rails/skip_secrets' +``` + +This will no longer merge secrets from JSON in `Rails.application.secrets`. This will be the default in the next major version. ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.