diff --git a/.rubocop.yml b/.rubocop.yml
index 8eebde6..ab4aa20 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -16,7 +16,6 @@ AllCops:
- LICENSE.txt
- README.md
- Rakefile
- - bridgetown.automation.rb
- script/**/*
- vendor/**/*
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8ffc7f1..92b0ed0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
## Main
-Nothing so far
+### Breaking Changes
+* Switch from ActiveSupport to dry-credentials (see README)
## 0.2.0
diff --git a/README.md b/README.md
index 4622d96..ba2c448 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
This plugin adds Rails-like encrypted credentials to Bridgetown.
-Credentials like passwords, access tokens and other secrets are often passed to sites each by it's own ENV variable. This is both uncool, non-atomic and therefore unreliable. Use this plugin to store your credentials in encrypted YAML files which you can safely commit to your source code repository. In order to use all of them in Bridgetown, you have to set or pass exactly one ENV variable holding the key to decrypt.
+Credentials like passwords, access tokens and other secrets are often passed to sites each by its own ENV variable. This is both uncool, non-atomic and therefore unreliable. Use this plugin to store your credentials in encrypted YAML files which you can safely commit to your source code repository. In order to use all of them in Bridgetown, you have to set or pass exactly one ENV variable holding the key to decrypt.
* [Homepage](https://github.com/svoop/bridgetown_credentials)
* [API](https://www.rubydoc.info/gems/bridgetown_credentials)
@@ -34,12 +34,6 @@ Bundler.setup(:default, Bridgetown.env)
require "bridgetown_credentials"
```
-For safety, you should exclude key files from the source code repository:
-
-```shell
-bin/bridgetown apply "$(bundle info --path bridgetown_credentials)/bridgetown.automation.rb"
-```
-
### Secure Installation
This gem is [cryptographically signed](https://guides.rubygems.org/security/#using-gems) in order to assure it hasn't been tampered with.
@@ -51,6 +45,32 @@ gem cert --add <(curl -Ls https://raw.github.com/svoop/bridgetown_credentials/ma
bundle install --trust-policy MediumSecurity
```
+## Update from 0.1.x to 1.x.x
+
+As of version 1, this gem uses [Dry::Credentials](https://rubygems.org/gems/dry-credentials) instead of ActiveSupport (which is planned to be ditched from Bridgetown at some point in the future). This requires you to take some additional steps:
+
+1. Backup the decrypted credentials for every environment:
`bin/bridgetown credentials edit -e ENVIRONMENT`
+2. Delete (or move elsewhere) your old encrypted credentials files:
`rm config/credentials/*`
+3. Update this gem to a version >= 1:
`bundle update bridgetown_credentials`
+4. Create new encrypted credentials files for every environment:
`bin/bridgetown credentials edit -e ENVIRONMENT`
+5. Step 4 prints the new ENV variable which contains the private key required whenever you edit or query credentials. Example: For the development environment, the new ENV variable `DEVELOPMENT_CREDENTIALS_KEY` replaces the old ENV variable `BRIDGETOWN_DEVELOPMENT_KEY`.
+
+Please note that Dry::Credentials does not support unified environments (one `config/credentials.yml.enc` for both development and production) anymore!
+
+Also, nested credentials have to be queried differently now and thus you might have to update your Bridgetown site accordingly. Given the example credentials from the [Usage section](#usage) below:
+
+```ruby
+# Queries up to version 0.1.x
+Bridgetown.credentials.foo # => "bar"
+Bridgetown.credentials.aws[:access_key_id] # => "awsXid"
+Bridgetown.credentials.google.dig((:maps, :api_key) # => "goomXkey"
+
+# Queries as of version 1.x.x
+Bridgetown.credentials.foo # => "bar"
+Bridgetown.credentials.aws.access_key_id # => "awsXid"
+Bridgetown.credentials.google.maps.api_key # => "goomXkey"
+```
+
## Usage
### First Time
@@ -76,18 +96,9 @@ google:
api_key: goopXkey
```
-After saving the file, the following new files have been created:
-
-```
-config/
- └─ credentials/
- ├─ development.key
- └─ development.yml.enc
-```
-
-⚠️ Move the `*.key` files to a safe place such as a password manager now! Never check them into the source code repository!
+After saving, the private key required to encrypt/decrypt the credentials is printed this first time only. Make sure you store this information in a safe place, you will need it in the future.
-The credentials you've edited above have been written to `development.yml.enc` and will be available when Bridgetown is in `development` mode.
+The credentials you've edited above has been written to `config/credentials/development.yml.enc` and will be loaded when Bridgetown is in `development` mode.
To edit the credentials for `production` mode:
@@ -95,54 +106,32 @@ To edit the credentials for `production` mode:
bin/bridgetown credentials edit -e production
```
-To edit or use a credentials file from now on, you have to set the corresponding key as an ENV variable. The actual key is the content of the `*.key` file you should have tucked away above.
+To edit or query credentials from now on, the corresponding ENV variable with the private key has to be set:
```shell
-export BRIDGETOWN_DEVELOPMENT_KEY="10aabbccddeeff00112233445566778899"
-export BRIDGETOWN_PRODUCTION_KEY="20aabbccddeeff00112233445566778899"
+export DEVELOPMENT_CREDENTIALS_KEY="4c87...af93"
+export PRODUCTION_CREDENTIALS_KEY="92bb...820f"
```
-#### Unified Environments
-
-If you prefer not to separate credentials between different environments:
-
-```shell
-rm config/credentials/production.*
-mv config/credentials/development.yml config/credentials.yml
-rmdir config/credentials
-```
+### Edit
-This simplifies the files to:
+The command is the same as the first time:
```
-config/
- └─ credentials.yml.enc
-```
-
-To edit or use this from now on, you have to set:
-
-
-```shell
-export BRIDGETOWN_CREDENTIALS_KEY="30aabbccddeeff00112233445566778899"
+bin/bridgetown credentials edit
+bin/bridgetown credentials edit -e production
```
-⚠️ If `config/credentials.yml` is present, any other credentials files are ignored.
-
-### Read
+### Query
Throughout the Bridgetown stack, you can now use the credentials as follows:
```ruby
-Bridgetown.credentials.foo # => "bar"
-Bridgetown.credentials.aws[:access_key_id] # => "awsXid"
-Bridgetown.credentials.google.dig((:maps, :api_key) # => "goomXkey"
+Bridgetown.credentials.foo # => "bar"
+Bridgetown.credentials.aws.access_key_id # => "awsXid"
+Bridgetown.credentials.google.maps.api_key # => "goomXkey"
```
-### Commands
-
-* `bin/bridgetown credentials edit` – edit the credentials
-* `bin/bridgetown credentials show` – dump the decrypted credentials to STDOUT
-
## Tests
* `bundle exec rake test` to run the test suite
diff --git a/bridgetown.automation.rb b/bridgetown.automation.rb
deleted file mode 100644
index 83525ef..0000000
--- a/bridgetown.automation.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# Make sure key files are not committed to the source code repository
-append_to_file ".gitignore" do
- <<~END
- config/credentials.key
- config/credentials/*.key
- END
-end
diff --git a/bridgetown_credentials.gemspec b/bridgetown_credentials.gemspec
index 297e2c4..ef6452c 100644
--- a/bridgetown_credentials.gemspec
+++ b/bridgetown_credentials.gemspec
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
'bug_tracker_uri' => 'https://github.com/svoop/bridgetown_credentials/issues'
}
- spec.files = Dir['lib/**/*', '*.automation.rb']
+ spec.files = Dir['lib/**/*']
spec.test_files = Dir['spec/**/*']
spec.require_paths = %w(lib)
@@ -46,7 +46,7 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 3.0.0"
spec.add_runtime_dependency "bridgetown", ">= 1.2.0", "< 2.0"
- spec.add_runtime_dependency "activesupport", "~> 7"
+ spec.add_runtime_dependency "dry-credentials", "~> 0", ">= 0.2.1"
spec.add_development_dependency 'debug'
spec.add_development_dependency 'rake'
@@ -56,4 +56,6 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'guard'
spec.add_development_dependency 'guard-minitest'
spec.add_development_dependency 'yard'
+
+ spec.post_install_message = "⚠️ Breaking change: bridgetown_credentials >= 1.0.0 no longer depends on ActiveSupport. Please read the update section in the README for how to migrate your Bridgetown site. Don't worry, it's a piece of cake!"
end
diff --git a/lib/bridgetown_credentials.rb b/lib/bridgetown_credentials.rb
index 7362e47..4bded75 100644
--- a/lib/bridgetown_credentials.rb
+++ b/lib/bridgetown_credentials.rb
@@ -1,17 +1,12 @@
# frozen_string_literal: true
+require "dry/credentials"
require "bridgetown"
-require 'tempfile'
-require 'yaml'
-require "active_support/encrypted_configuration"
-
require_relative "bridgetown_credentials/version"
-require_relative "bridgetown_credentials/credentials"
-require_relative "bridgetown_credentials/commands"
+require_relative "bridgetown_credentials/initializer"
require_relative "bridgetown_credentials/commands/credentials"
-require_relative "bridgetown_credentials/bridgetown"
Bridgetown.initializer :bridgetown_credentials do
- Bridgetown.extend BridgetownCredentials::Bridgetown
+ BridgetownCredentials.initializer
end
diff --git a/lib/bridgetown_credentials/bridgetown.rb b/lib/bridgetown_credentials/bridgetown.rb
deleted file mode 100644
index ef6f78c..0000000
--- a/lib/bridgetown_credentials/bridgetown.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-module BridgetownCredentials
- module Bridgetown
-
- def credentials
- BridgetownCredentials::Credentials.new(
- root_dir: ::Bridgetown.configuration.root_dir,
- env: ::Bridgetown.env
- ).credentials
- end
-
- end
-end
diff --git a/lib/bridgetown_credentials/commands.rb b/lib/bridgetown_credentials/commands.rb
deleted file mode 100644
index 3d75c77..0000000
--- a/lib/bridgetown_credentials/commands.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module BridgetownCredentials
- class Commands
-
- def initialize(root_dir: ::Bridgetown.configuration.root_dir, env: ::Bridgetown.env)
- @credentials = BridgetownCredentials::Credentials.new(root_dir: root_dir, env: env)
- end
-
- def edit
- tempfile = Tempfile.new('btcs')
- tempfile.write @credentials.credentials.read
- tempfile.close
- system "#{ENV['EDITOR']} #{tempfile.path}"
- @credentials.credentials.write File.read(tempfile.path)
- ensure
- tempfile.unlink
- end
-
- def show
- puts @credentials.credentials.read
- end
- end
-end
diff --git a/lib/bridgetown_credentials/commands/credentials.rb b/lib/bridgetown_credentials/commands/credentials.rb
index 24a5873..c3c0b00 100644
--- a/lib/bridgetown_credentials/commands/credentials.rb
+++ b/lib/bridgetown_credentials/commands/credentials.rb
@@ -6,22 +6,15 @@ module BridgetownCredentials
class Commands
class Credentials < Thor
Bridgetown::Commands::Registrations.register do
- desc "credentials ", "Work with Rails-like encrypted credentials"
+ desc "credentials ", "Work with encrypted credentials"
subcommand "credentials", Credentials
end
- desc "edit", "Edit the credentials"
+ desc "edit", "Edit (or create) encrypted credentials"
option :environment, aliases: '-e'
def edit
- ENV['BRIDGETOWN_ENV'] = options['environment'] if options['environment']
- BridgetownCredentials::Commands.new.edit
- end
-
- desc "show", "Dump the decrypted credentials to STDOUT"
- option :environment, aliases: '-e'
- def show
- ENV['BRIDGETOWN_ENV'] = options['environment'] if options['environment']
- BridgetownCredentials::Commands.new.show
+ BridgetownCredentials.initializer
+ Bridgetown.credentials.edit! options['environment']
end
end
end
diff --git a/lib/bridgetown_credentials/credentials.rb b/lib/bridgetown_credentials/credentials.rb
deleted file mode 100644
index 636d0f2..0000000
--- a/lib/bridgetown_credentials/credentials.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-module BridgetownCredentials
- class Credentials
-
- attr_reader :credentials
-
- def initialize(root_dir:, env:)
- @config_path = Pathname(root_dir).join('config') # NOTE: config dir is hardcoded as of bridgetown-1.2
- @env = env
- @credentials = credentials_path ? load : create
- end
-
- private
-
- def credentials_path
- [
- @config_path.join("credentials.yml.enc"),
- default_credentials_path
- ].find do |path|
- path.file?
- end
- end
-
- def credentials_env
- ['BRIDGETOWN', credentials_path.basename('.yml.enc'), 'KEY']
- .join('_')
- .upcase
- end
-
- def default_credentials_path
- @config_path.join('credentials', "#{@env}.yml.enc")
- end
-
- def default_key_path
- @config_path.join('credentials', "#{@env}.key")
- end
-
- def load
- ActiveSupport::EncryptedConfiguration.new(
- config_path: credentials_path,
- env_key: credentials_env,
- key_path: '---',
- raise_if_missing_key: true
- )
- end
-
- def create
- default_key_path.dirname.mkpath
- default_key_path.write(ActiveSupport::EncryptedConfiguration.generate_key)
- ActiveSupport::EncryptedConfiguration.new(
- config_path: default_credentials_path,
- env_key: '---',
- key_path: default_key_path,
- raise_if_missing_key: false
- )
- end
-
- end
-end
diff --git a/lib/bridgetown_credentials/initializer.rb b/lib/bridgetown_credentials/initializer.rb
new file mode 100644
index 0000000..d5af605
--- /dev/null
+++ b/lib/bridgetown_credentials/initializer.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module BridgetownCredentials
+ class << self
+ def initializer
+ Dry::Credentials::Extension.new.then do |credentials|
+ credentials[:env] = Bridgetown.env
+ credentials[:dir] = Bridgetown.configuration.root_dir + '/config/credentials'
+ credentials.load!
+ Bridgetown.define_singleton_method(:credentials) { credentials }
+ end
+ end
+ end
+end
diff --git a/lib/bridgetown_credentials/version.rb b/lib/bridgetown_credentials/version.rb
index 131abac..ef9fd59 100644
--- a/lib/bridgetown_credentials/version.rb
+++ b/lib/bridgetown_credentials/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module BridgetownCredentials
- VERSION = "0.2.0"
+ VERSION = "0.2.1"
end
diff --git a/spec/fixtures/separated/config/credentials/development.yml.enc b/spec/fixtures/separated/config/credentials/development.yml.enc
deleted file mode 100644
index 498f164..0000000
--- a/spec/fixtures/separated/config/credentials/development.yml.enc
+++ /dev/null
@@ -1 +0,0 @@
-9i/EtUJt1efCi00JI8zjhF0NLObmkgZYdz1AybNHLKc4Hr8=--TpvEzWdBo9BDIehP--58KgR6zZPV7ji2Ej4LKwtg==
\ No newline at end of file
diff --git a/spec/fixtures/separated/config/credentials/production.yml.enc b/spec/fixtures/separated/config/credentials/production.yml.enc
deleted file mode 100644
index 723dadd..0000000
--- a/spec/fixtures/separated/config/credentials/production.yml.enc
+++ /dev/null
@@ -1 +0,0 @@
-S5RzJRMyPJ+0/yqQnDxSZ3ZZ6TVM21Uzt5rtj+77Tnkd--vny3NxIG5530Q2Cc--vqccEZ/3Jga3Jbc9G1knSA==
\ No newline at end of file
diff --git a/spec/fixtures/unified/config/credentials.yml.enc b/spec/fixtures/unified/config/credentials.yml.enc
deleted file mode 100644
index e0d5572..0000000
--- a/spec/fixtures/unified/config/credentials.yml.enc
+++ /dev/null
@@ -1 +0,0 @@
-iEiDBqdV97GT29DWsyuuiHSdPDOZjwwat5mn--Kw4OaG2ueY51rkD7--hwUIAa4Llvp2GoUaz+NPww==
\ No newline at end of file
diff --git a/spec/fixtures/unified/config/credentials/development.yml.enc b/spec/fixtures/unified/config/credentials/development.yml.enc
deleted file mode 100644
index 498f164..0000000
--- a/spec/fixtures/unified/config/credentials/development.yml.enc
+++ /dev/null
@@ -1 +0,0 @@
-9i/EtUJt1efCi00JI8zjhF0NLObmkgZYdz1AybNHLKc4Hr8=--TpvEzWdBo9BDIehP--58KgR6zZPV7ji2Ej4LKwtg==
\ No newline at end of file
diff --git a/spec/fixtures/unified/config/credentials/production.yml.enc b/spec/fixtures/unified/config/credentials/production.yml.enc
deleted file mode 100644
index 723dadd..0000000
--- a/spec/fixtures/unified/config/credentials/production.yml.enc
+++ /dev/null
@@ -1 +0,0 @@
-S5RzJRMyPJ+0/yqQnDxSZ3ZZ6TVM21Uzt5rtj+77Tnkd--vny3NxIG5530Q2Cc--vqccEZ/3Jga3Jbc9G1knSA==
\ No newline at end of file
diff --git a/spec/lib/bridgetown_credentials/commands_spec.rb b/spec/lib/bridgetown_credentials/commands_spec.rb
deleted file mode 100644
index 5daa677..0000000
--- a/spec/lib/bridgetown_credentials/commands_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-require_relative '../../spec_helper'
-
-describe BridgetownCredentials::Commands do
-
- describe :edit do
- it "generates the necessary files and writes the credentials via EDITOR" do
- ENV['EDITOR'] = 'echo "foo: bar" >'
- Dir.mktmpdir do |root_dir|
- root_dir = Pathname(root_dir)
- subject = BridgetownCredentials::Commands.new(root_dir: root_dir, env: 'staging')
- subject.edit
- ENV['BRIDGETOWN_STAGING_KEY'] = File.read(root_dir.join('config', 'credentials', 'staging.key'))
- subject = BridgetownCredentials::Commands.new(root_dir: root_dir, env: 'staging')
- _{ subject.show }.must_output "foo: bar\n"
- end
- end
- end
-
- describe :show do
- let :root_dir do
- fixtures_path.join('separated')
- end
-
- subject do
- ENV['BRIDGETOWN_PRODUCTION_KEY'] = KEYS[:production]
- BridgetownCredentials::Commands.new(root_dir: root_dir, env: 'production')
- end
-
- it "prints the decrypted credentials without leading three dashes line" do
- _{ subject.show }.must_output "production: PRODUCTION\n"
- end
- end
-
-end
diff --git a/spec/lib/bridgetown_credentials/credentials_spec.rb b/spec/lib/bridgetown_credentials/credentials_spec.rb
deleted file mode 100644
index 0133034..0000000
--- a/spec/lib/bridgetown_credentials/credentials_spec.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-require_relative '../../spec_helper'
-
-describe BridgetownCredentials::Credentials do
- context "unified credentials" do
- let :root_dir do
- fixtures_path.join('unified')
- end
-
- subject do
- BridgetownCredentials::Credentials.new(root_dir: root_dir, env: 'development')
- end
-
- describe :credentials_path do
- it "always discovers credentials.yml.enc" do
- _(subject.send(:credentials_path)).must_equal root_dir.join('config', 'credentials.yml.enc')
- end
- end
-
- describe :credentials_env do
- it "always returns BRIDGETOWN_CREDENTIALS_KEY" do
- _(subject.send(:credentials_env)).must_equal 'BRIDGETOWN_CREDENTIALS_KEY'
- end
- end
-
- describe :credentials do
- it "always decodes credentials.yml.enc" do
- ENV['BRIDGETOWN_CREDENTIALS_KEY'] = KEYS[:unified]
- _(subject.credentials).must_be_instance_of ActiveSupport::EncryptedConfiguration
- end
-
- it "fails if no key env var is set" do
- ENV['BRIDGETOWN_CREDENTIALS_KEY'] = nil
- _{ subject.credentials.config }.must_raise RuntimeError
- end
- end
- end
-
- context "separated credentials" do
- let :root_dir do
- fixtures_path.join('separated')
- end
-
- subject do
- BridgetownCredentials::Credentials.new(root_dir: root_dir, env: 'production')
- end
-
- describe :credentials_path do
- it "discovers .yml.enc for the current environment" do
- _(subject.send(:credentials_path)).must_equal root_dir.join('config', 'credentials', 'production.yml.enc')
- end
- end
-
- describe :credentials_env do
- it "returns the env var key for the current environment" do
- _(subject.send(:credentials_env)).must_equal 'BRIDGETOWN_PRODUCTION_KEY'
- end
- end
-
- describe :credentials do
- it "decodes .yml.enc for the current environment" do
- ENV['BRIDGETOWN_PRODUCTION_KEY'] = KEYS[:production]
- _(subject.credentials).must_be_instance_of ActiveSupport::EncryptedConfiguration
- end
-
- it "fails if no key env var is set" do
- ENV['BRIDGETOWN_PRODUCTION_KEY'] = nil
- _{ subject.credentials.config }.must_raise RuntimeError
- end
- end
- end
-
- context "new credentials" do
- describe :initializer do
- it "generate a key" do
- Dir.mktmpdir do |root_dir|
- root_dir = Pathname(root_dir)
- BridgetownCredentials::Credentials.new(root_dir: root_dir, env: 'foobar')
- _(root_dir.join('config', 'credentials', 'foobar.key')).path_must_exist
- end
- end
- end
- end
-end
diff --git a/spec/lib/bridgetown_credentials/initializer_spec.rb b/spec/lib/bridgetown_credentials/initializer_spec.rb
new file mode 100644
index 0000000..7319f48
--- /dev/null
+++ b/spec/lib/bridgetown_credentials/initializer_spec.rb
@@ -0,0 +1,12 @@
+require_relative '../../spec_helper'
+
+describe BridgetownCredentials do
+ describe :initializer do
+ it "sets env, dir and defines credentials on Bridgetown" do
+ BridgetownCredentials.initializer
+ _(Bridgetown).must_respond_to :credentials
+ _(Bridgetown.credentials[:env]).must_equal Bridgetown.env
+ _(Bridgetown.credentials[:dir]).must_equal Bridgetown.configuration.root_dir + '/config/credentials'
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c2e4187..6baf90d 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -13,19 +13,3 @@
require 'minitest/flash'
require 'minitest/focus'
-
-class Minitest::Spec
- class << self
- alias_method :context, :describe
- end
-end
-
-def fixtures_path
- Pathname(__dir__).join('fixtures')
-end
-
-KEYS = {
- unified: '4f9ab3ef4bddd3ad6d01886b6ffff49c',
- development: 'e4af0afc87c885a430afa3c9691d8bf4',
- production: '5f1380543df0a4c839324619e0acf0bf'
-}