• D
    Add credentials using a generic EncryptedConfiguration class (#30067) · 69f976b8
    David Heinemeier Hansson 提交于
    * WIP: Add credentials using a generic EncryptedConfiguration class
    
    This is sketch code so far.
    
    * Flesh out EncryptedConfiguration and test it
    
    * Better name
    
    * Add command and generator for credentials
    
    * Use the Pathnames
    
    * Extract EncryptedFile from EncryptedConfiguration and add serializers
    
    * Test EncryptedFile
    
    * Extract serializer validation
    
    * Stress the point about losing comments
    
    * Allow encrypted configuration to be read without parsing for display
    
    * Use credentials by default and base them on the master key
    
    * Derive secret_key_base in test/dev, source it from credentials in other envs
    
    And document the usage.
    
    * Document the new credentials setup
    
    * Stop generating the secrets.yml file now that we have credentials
    
    * Document what we should have instead
    
    Still need to make it happen, tho.
    
    * [ci skip] Keep wording to `key base`; prefer defaults.
    
    Usually we say we change defaults, not "spec" out a release.
    
    Can't use backticks in our sdoc generated documentation either.
    
    * Abstract away OpenSSL; prefer MessageEncryptor.
    
    * Spare needless new when raising.
    
    * Encrypted file test shouldn't depend on subclass.
    
    * [ci skip] Some woordings.
    
    * Ditch serializer future coding.
    
    * I said flip it. Flip it good.
    
    * [ci skip] Move require_master_key to the real production.rb.
    
    * Add require_master_key to abort the boot process.
    
    In case the master key is required in a certain environment
    we should inspect that the key is there and abort if it isn't.
    
    * Print missing key message and exit immediately.
    
    Spares us a lengthy backtrace and prevents further execution.
    
    I've verified the behavior in a test app, but couldn't figure the
    test out as loading the app just exits immediately with:
    
    ```
    /Users/kasperhansen/Documents/code/rails/activesupport/lib/active_support/testing/isolation.rb:23:in `load': marshal data too short (ArgumentError)
    	from /Users/kasperhansen/Documents/code/rails/activesupport/lib/active_support/testing/isolation.rb:23:in `run'
    	from /Users/kasperhansen/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/minitest-5.10.2/lib/minitest.rb:830:in `run_one_method'
    	from /Users/kasperhansen/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/minitest-5.10.2/lib/minitest/parallel.rb:32:in `block (2 levels) in start'
    ```
    
    It's likely we need to capture and prevent the exit somehow.
    Kernel.stub(:exit) didn't work. Leaving it for tomorrow.
    
    * Fix require_master_key config test.
    
    Loading the app would trigger the `exit 1` per require_master_key's
    semantics, which then aborted the test.
    
    Fork and wait for the child process to finish, then inspect the
    exit status.
    
    Also check we aborted because of a missing master key, so something
    else didn't just abort the boot.
    
    Much <3 to @tenderlove for the tip.
    
    * Support reading/writing configs via methods.
    
    * Skip needless deep symbolizing.
    
    * Remove save; test config reader elsewhere.
    
    * Move secret_key_base check to when we're reading it.
    
    Otherwise we'll abort too soon since we don't assign the secret_key_base
    to secrets anymore.
    
    * Add missing string literal comments; require unneeded yaml require.
    
    * ya ya ya, rubocop.
    
    * Add master_key/credentials after bundle.
    
    Then we can reuse the existing message on `rails new bc4`.
    
    It'll look like:
    
    ```
    Using web-console 3.5.1 from https://github.com/rails/web-console.git (at master@ce985eb)
    Using rails 5.2.0.alpha from source at `/Users/kasperhansen/Documents/code/rails`
    Using sass-rails 5.0.6
    Bundle complete! 16 Gemfile dependencies, 72 gems now installed.
    Use `bundle info [gemname]` to see where a bundled gem is installed.
    Adding config/master.key to store the master encryption key: 97070158c44b4675b876373a6bc9d5a0
    
    Save this in a password manager your team can access.
    
    If you lose the key, no one, including you, can access anything encrypted with it.
    
          create  config/master.key
    ```
    
    And that'll be executed even if `--skip-bundle` was passed.
    
    * Ensure test app has secret_key_base.
    
    * Assign secret_key_base to app or omit.
    
    * Merge noise
    
    * Split options for dynamic delegation into its own method and use deep symbols to make it work
    
    * Update error to point to credentials instead
    
    * Appease Rubocop
    
    * Validate secret_key_base when reading it.
    
    Instead of relying on the validation in key_generator move that into
    secret_key_base itself.
    
    * Fix generator and secrets test.
    
    Manually add config.read_encrypted_secrets since it's not there by default
    anymore.
    
    Move mentions of config/secrets.yml to config/credentials.yml.enc.
    
    * Remove files I have no idea how they got here.
    
    * [ci skip] swap secrets for credentials.
    
    * [ci skip] And now, changelogs are coming.
    69f976b8
app_generator_test.rb 24.3 KB