diffcrypt 0.3.2 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2009b6cc9a7318e8f6624d6fbde27562799a4ccd44d7aa1263d6c1ff6dbea2a8
4
- data.tar.gz: 9f3aacfbd55710037b3bbadc56d6513b66775da721e4120b20ab5e95f320837e
3
+ metadata.gz: 5914065f605f66fa0b4bd189b3ffd3f1f837cc4ab3d417215fb9366fea723668
4
+ data.tar.gz: 18485d4613dbf5503a481cd74bd659cb572c24f0e1a7378348d38f8bb4cfedca
5
5
  SHA512:
6
- metadata.gz: 5412dc78d1e840f0b8d58eb60f13b3e761945c6a76235ad9eb32fd737eaba8df027892c8ad836a56f7e154a60ecb5085608db448021d1c4cd6aad0e8a87ba696
7
- data.tar.gz: 2c3002f8783d0c92f13f3efc13e8e8a23a3d5d80aaa9ea1c20cf7148e8bad6b3ad1a840389412c138f70a8c494c465fc592beea2774f616ca63b8406370d7797
6
+ metadata.gz: c3de8085e6c26e338ff1cf5239bd66761497bcf98caa2234faf13aefa83e7b559fb6162ca07626fd315ba8ee40fb372043277176456b83fefa2ccded4060f7d8
7
+ data.tar.gz: d6d2a864d9a845234080d81a986ef6a7859000838558c639dce1c0e1175d6ed6dab836d182e40723eadc57534b8058ae162b53102ded1e17302ae1b24d6fd8a5
data/.circleci/config.yml CHANGED
@@ -1,12 +1,39 @@
1
1
  version: 2.1
2
2
 
3
3
  jobs:
4
- build:
4
+ bundle:
5
5
  docker:
6
- - image: circleci/ruby:2.6.6
6
+ - image: circleci/ruby:2.7.1
7
+ working_directory: /mnt/ramdisk
7
8
  steps:
8
9
  - checkout
9
- - run: bundle install
10
+ - restore_cache:
11
+ keys:
12
+ - bundler-{{ checksum "diffcrypt.gemspec" }}-{{ .Environment.CACHE_VERSION }}
13
+ - run:
14
+ name: bundle install
15
+ command: |
16
+ gem install bundler -v '2.1.4'
17
+ bundle install --path=vendor/bundle --jobs=4 --retry=3
18
+ - save_cache:
19
+ key: bundler-{{ checksum "diffcrypt.gemspec" }}-{{ .Environment.CACHE_VERSION }}
20
+ paths:
21
+ - vendor/bundle
22
+
23
+ test:
24
+ docker:
25
+ - image: circleci/ruby:2.7.1
26
+ working_directory: /mnt/ramdisk
27
+ steps:
28
+ - checkout
29
+ - restore_cache:
30
+ keys:
31
+ - bundler-{{ checksum "diffcrypt.gemspec" }}-{{ .Environment.CACHE_VERSION }}
32
+ - run:
33
+ name: bundle install
34
+ command: |
35
+ gem install bundler -v '2.1.4'
36
+ bundle install --path=vendor/bundle --jobs=4 --retry=3
10
37
  - run:
11
38
  name: Setup Code Climate test-reporter
12
39
  command: |
@@ -19,7 +46,33 @@ jobs:
19
46
  ./cc-test-reporter before-build
20
47
  bundle exec rake test
21
48
  ./cc-test-reporter after-build --coverage-input-type lcov --exit-code $?
49
+ rubocop:
50
+ docker:
51
+ - image: circleci/ruby:2.7.1
52
+ working_directory: /mnt/ramdisk
53
+ steps:
54
+ - checkout
55
+ - restore_cache:
56
+ keys:
57
+ - bundler-{{ checksum "diffcrypt.gemspec" }}-{{ .Environment.CACHE_VERSION }}
58
+ - run:
59
+ name: bundle install
60
+ command: |
61
+ gem install bundler -v '2.1.4'
62
+ bundle install --path=vendor/bundle --jobs=4 --retry=3
22
63
  - run:
23
64
  name: rubocop
24
65
  command: bundle exec rubocop
25
66
  when: always
67
+
68
+ workflows:
69
+ version: 2
70
+ all:
71
+ jobs:
72
+ - bundle
73
+ - test:
74
+ requires:
75
+ - bundle
76
+ - rubocop:
77
+ requires:
78
+ - bundle
data/.rubocop.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
+ TargetRubyVersion: 2.6
3
4
 
4
5
  Style/ClassAndModuleChildren:
5
6
  Exclude:
@@ -9,10 +10,12 @@ Style/Documentation:
9
10
  Metrics/MethodLength:
10
11
  Exclude:
11
12
  - test/**/*_test.rb
12
- TrailingCommaInArrayLiteral:
13
+ Style/TrailingCommaInArrayLiteral:
13
14
  EnforcedStyleForMultiline: consistent_comma
14
15
  Style/TrailingCommaInArguments:
15
16
  EnforcedStyleForMultiline: consistent_comma
17
+ Style/TrailingCommaInHashLiteral:
18
+ EnforcedStyleForMultiline: consistent_comma
16
19
  Style/AccessorGrouping:
17
20
  EnforcedStyle: separated
18
21
 
data/CHANGELOG.md CHANGED
@@ -7,6 +7,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
 
9
9
 
10
+ ## [0.5.1] - 2021-03-29
11
+
12
+ ### Added
13
+
14
+ - Support for Rails 6.1
15
+
16
+
17
+
18
+ ## [0.5.0] - 2020-12-06
19
+
20
+ ### Added
21
+
22
+ - `Diffcrypt::Rails::ApplicationHelper` to simplify integration
23
+ - `rake diffcrypt:init` command to help setup credentials
24
+
25
+ ### Changed
26
+
27
+ - Default cipher is now `aes-265-gcm`
28
+ - YAML keys are now sorted
29
+ - Improved support for rails native `aes-128-gcm` cipher
30
+ - Improved test coverage for differing ciphers
31
+
32
+
33
+
34
+ ## [0.4.1] - 2020-10-06
35
+
36
+ ### Fixed
37
+
38
+ - Could not initialize a new file or modify existing rails format file (Thanks @swiknaba #31)
39
+
40
+
41
+
42
+ ## [0.4.0] - 2020-10-01
43
+
44
+ ### Changed
45
+
46
+ - Encryptor can now use other ciphers than the default
47
+
48
+ ### Dependencies
49
+
50
+ - simplecov: 0.17.0 -> 0.18.0 (#20)
51
+ - rubocop: 0.88.0 -> 0.92.0 (#24)
52
+
53
+
54
+
55
+ ## [0.3.3] - 2020-07-25
56
+
57
+ ### Fixed
58
+
59
+ - Explicit FileUtils require to avoid potentially warning logs
60
+
61
+
62
+
10
63
  ## [0.3.2] - 2020-07-20
11
64
 
12
65
  ### Added
data/Gemfile CHANGED
@@ -7,6 +7,6 @@ gemspec
7
7
 
8
8
  gem 'minitest', '~> 5.0'
9
9
  gem 'rake', '~> 13.0'
10
- gem 'rubocop', '~> 0.88.0'
11
- gem 'simplecov', '~> 0.17.0', require: false # CodeClimate not compatible with 0.18+ yet - https://github.com/codeclimate/test-reporter/issues/413
10
+ gem 'rubocop', '~> 1.11.0'
11
+ gem 'simplecov', '~> 0.21.2', require: false # CodeClimate not compatible with 0.18+ yet - https://github.com/codeclimate/test-reporter/issues/413
12
12
  gem 'simplecov-lcov', '< 0.8'
data/README.md CHANGED
@@ -36,8 +36,8 @@ There are a few ways to use the library, depending on how advanced your use case
36
36
  The easiest way to get started is to use the CLI.
37
37
 
38
38
  ```shell
39
- diffcrypt decrypt -k $(cat test/fixtures/master.key) test/fixtures/example.yml.enc
40
- diffcrypt encrypt -k $(cat test/fixtures/master.key) test/fixtures/example.yml
39
+ diffcrypt decrypt -k $(cat test/fixtures/aes-128-gcm.key) test/fixtures/example.yml.enc
40
+ diffcrypt encrypt -k $(cat test/fixtures/aes-128-gcm.key) test/fixtures/example.yml
41
41
  ```
42
42
 
43
43
 
@@ -66,23 +66,27 @@ Currently there is not native support for rails, but ActiveSupport can be monkey
66
66
  the built in encrypter. All existing `rails credentials:edit` also work with this method.
67
67
 
68
68
  ```ruby
69
- require 'diffcrypt/rails/encrypted_configuration'
69
+ # config/application.rb
70
70
  module Rails
71
71
  class Application
72
- def encrypted(path, key_path: 'config/master.key', env_key: 'RAILS_MASTER_KEY')
73
- Diffcrypt::Rails::EncryptedConfiguration.new(
74
- config_path: Rails.root.join(path),
75
- key_path: Rails.root.join(key_path),
76
- env_key: env_key,
77
- raise_if_missing_key: config.require_master_key,
78
- )
79
- end
72
+ include Diffcrypt::Rails::ApplicationHelper
80
73
  end
81
74
  end
82
75
  ```
83
76
 
84
77
 
85
78
 
79
+ ## Converting between ciphers
80
+
81
+ Sometimes you may want to rotate the cipher used on a file. You can do this programmatically using the ruby code above, or you can also chain the CLI commands like so:
82
+
83
+ ```shell
84
+ diffcrypt decrypt -k $(cat test/fixtures/aes-128-gcm.key) test/fixtures/example.yml.enc > test/fixtures/example.128.yml \
85
+ && diffcrypt encrypt --cipher aes-256-gcm -k $(cat test/fixtures/aes-256-gcm.key) test/fixtures/example.128.yml > test/fixtures/example.256.yml.enc && rm test/fixtures/example.128.yml
86
+ ```
87
+
88
+
89
+
86
90
  ## Development
87
91
 
88
92
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/Rakefile CHANGED
@@ -8,5 +8,7 @@ Rake::TestTask.new(:test) do |t|
8
8
  t.libs << 'lib'
9
9
  t.test_files = FileList['test/**/*_test.rb']
10
10
  end
11
-
12
11
  task default: :test
12
+
13
+ path = File.expand_path(__dir__)
14
+ Dir.glob("#{path}/lib/diffcrypt/tasks/**/*.rake").sort.each { |f| load f }
data/diffcrypt.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = 'Diffable encrypted configuration files that can be safely committed into a git repository'
13
13
  spec.homepage = 'https://github.com/marcqualie/diffcrypt'
14
14
  spec.license = 'MIT'
15
- spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0')
16
16
 
17
17
  # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
18
18
 
@@ -22,13 +22,13 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  # Specify which files should be added to the gem when it is released.
24
24
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ spec.files = Dir.chdir(::File.expand_path(__dir__)) do
26
26
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
27
  end
28
28
  spec.bindir = 'bin'
29
29
  spec.executables = %w[diffcrypt]
30
30
  spec.require_paths = ['lib']
31
31
 
32
- spec.add_runtime_dependency 'activesupport', '~> 6.0.0'
32
+ spec.add_runtime_dependency 'activesupport', '>= 6.0', '< 6.2'
33
33
  spec.add_runtime_dependency 'thor', '>= 0.20', '< 2'
34
34
  end
data/lib/diffcrypt.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'diffcrypt/encryptor'
4
4
  require 'diffcrypt/version'
5
+ require 'diffcrypt/railtie' if defined?(Rails)
5
6
 
6
7
  module Diffcrypt
7
8
  class Error < StandardError; end
data/lib/diffcrypt/cli.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative './encryptor'
4
+ require_relative './file'
4
5
  require_relative './version'
5
6
 
6
7
  module Diffcrypt
@@ -8,21 +9,22 @@ module Diffcrypt
8
9
  desc 'decrypt <path>', 'Decrypt a file'
9
10
  method_option :key, aliases: %i[k], required: true
10
11
  def decrypt(path)
11
- ensure_file_exists(path)
12
- contents = File.read(path)
13
- puts encryptor.decrypt(contents)
12
+ file = File.new(path)
13
+ ensure_file_exists(file)
14
+ say file.decrypt(key)
14
15
  end
15
16
 
16
17
  desc 'encrypt <path>', 'Encrypt a file'
17
18
  method_option :key, aliases: %i[k], required: true
19
+ method_option :cipher, default: Encryptor::DEFAULT_CIPHER
18
20
  def encrypt(path)
19
- ensure_file_exists(path)
20
- contents = File.read(path)
21
- puts encryptor.encrypt(contents)
21
+ file = File.new(path)
22
+ ensure_file_exists(file)
23
+ say file.encrypt(key, cipher: options[:cipher])
22
24
  end
23
25
 
24
26
  desc 'generate-key', 'Generate a 32 bit key'
25
- method_option :cipher, default: Encryptor::CIPHER
27
+ method_option :cipher, default: Encryptor::DEFAULT_CIPHER
26
28
  def generate_key
27
29
  say Encryptor.generate_key(options[:cipher])
28
30
  end
@@ -41,8 +43,9 @@ module Diffcrypt
41
43
  @encryptor ||= Encryptor.new(key)
42
44
  end
43
45
 
44
- def ensure_file_exists(path)
45
- abort('[ERROR] File does not exist') unless File.exist?(path)
46
+ # @param [Diffcrypt::File] path
47
+ def ensure_file_exists(file)
48
+ abort('[ERROR] File does not exist') unless file.exists?
46
49
  end
47
50
 
48
51
  def self.exit_on_failure?
@@ -12,15 +12,16 @@ require_relative './version'
12
12
 
13
13
  module Diffcrypt
14
14
  class Encryptor
15
- CIPHER = 'aes-128-gcm'
15
+ DEFAULT_CIPHER = 'aes-256-gcm'
16
16
 
17
- def self.generate_key(cipher = CIPHER)
17
+ def self.generate_key(cipher = DEFAULT_CIPHER)
18
18
  SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(cipher))
19
19
  end
20
20
 
21
- def initialize(key)
21
+ def initialize(key, cipher: DEFAULT_CIPHER)
22
22
  @key = key
23
- @encryptor ||= ActiveSupport::MessageEncryptor.new([key].pack('H*'), cipher: CIPHER)
23
+ @cipher = cipher
24
+ @encryptor ||= ActiveSupport::MessageEncryptor.new([key].pack('H*'), cipher: cipher)
24
25
  end
25
26
 
26
27
  # @param [String] contents The raw YAML string to be encrypted
@@ -46,11 +47,11 @@ module Diffcrypt
46
47
  # @param [String] contents The raw YAML string to be encrypted
47
48
  # @param [String, nil] original_encrypted_contents The original (encrypted) content to determine which keys have changed
48
49
  # @return [String]
49
- def encrypt(contents, original_encrypted_contents = nil)
50
+ def encrypt(contents, original_encrypted_contents = nil, cipher: nil)
50
51
  data = encrypt_data contents, original_encrypted_contents
51
52
  YAML.dump(
52
53
  'client' => "diffcrypt-#{Diffcrypt::VERSION}",
53
- 'cipher' => CIPHER,
54
+ 'cipher' => cipher || @cipher,
54
55
  'data' => data,
55
56
  )
56
57
  end
@@ -85,7 +86,7 @@ module Diffcrypt
85
86
  key_changed ? encrypt_string(value) : original_encrypted_value
86
87
  end
87
88
  end
88
- data
89
+ data.sort.to_h
89
90
  end
90
91
  # rubocop:enable Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity
91
92
 
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './encryptor'
4
+
5
+ module Diffcrypt
6
+ class File
7
+ attr_reader :file
8
+
9
+ def initialize(path)
10
+ @path = ::File.absolute_path path
11
+ end
12
+
13
+ def encrypted?
14
+ to_yaml['cipher']
15
+ end
16
+
17
+ # Determines the cipher to use for encryption/decryption
18
+ def cipher
19
+ return 'aes-128-gcm' if format == 'activesupport'
20
+
21
+ to_yaml['cipher'] || Encryptor::DEFAULT_CIPHER
22
+ end
23
+
24
+ # @return [Boolean]
25
+ def exists?
26
+ ::File.exist?(@path)
27
+ end
28
+
29
+ # Determines the format to be used for encryption
30
+ # @return [String] diffcrypt|activesupport
31
+ def format
32
+ return 'diffcrypt' if read == ''
33
+ return 'diffcrypt' if read.index('---')&.zero?
34
+
35
+ 'activesupport'
36
+ end
37
+
38
+ # @return [String] Raw contents of the file
39
+ def read
40
+ return '' unless ::File.exist?(@path)
41
+
42
+ @read ||= ::File.read(@path)
43
+ @read
44
+ end
45
+
46
+ # Save the encrypted contents back to disk
47
+ # @return [Boolean] True is file save was successful
48
+ def write(key, data, cipher: nil)
49
+ cipher ||= self.cipher
50
+ yaml = ::YAML.dump(data)
51
+ contents = Encryptor.new(key, cipher: cipher).encrypt(yaml)
52
+ ::File.write(@path, contents)
53
+ end
54
+
55
+ # TODO: This seems useless, figure out what's up
56
+ def encrypt(key, cipher: DEFAULT_CIPHER)
57
+ return read if encrypted?
58
+
59
+ Encryptor.new(key, cipher: cipher).encrypt(read)
60
+ end
61
+
62
+ # TODO: Add a test to verify this does descrypt properly
63
+ def decrypt(key)
64
+ return read unless encrypted?
65
+
66
+ Encryptor.new(key, cipher: cipher).decrypt(read)
67
+ end
68
+
69
+ def to_yaml
70
+ @to_yaml ||= YAML.safe_load(read) || {}
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './encrypted_configuration'
4
+
5
+ module Diffcrypt
6
+ module Rails
7
+ module ApplicationHelper
8
+ def encrypted(path, key_path: 'config/master.key', env_key: 'RAILS_MASTER_KEY')
9
+ config_path, key_path = resolve_encrypted_paths(path, key_path)
10
+
11
+ Diffcrypt::Rails::EncryptedConfiguration.new(
12
+ config_path: config_path,
13
+ key_path: key_path,
14
+ env_key: env_key,
15
+ raise_if_missing_key: config.require_master_key,
16
+ )
17
+ end
18
+
19
+ protected
20
+
21
+ def resolve_encrypted_paths(config_path, key_path)
22
+ config_path_abs = ::Rails.root.join(config_path)
23
+ key_path_abs = ::Rails.root.join(key_path)
24
+
25
+ # We always want to use `config/credentials/[environment]` for consistency
26
+ # If the master credentials do not exist, and a user has not specificed an environment, default to development
27
+ if config_path == 'config/credentials.yml.enc' && ::File.exist?(config_path_abs.to_s) == false
28
+ config_path_abs = ::Rails.root.join('config/credentials/development.yml.enc')
29
+ key_path_abs = ::Rails.root.join('config/credentials/development.key')
30
+ end
31
+
32
+ [
33
+ config_path_abs,
34
+ key_path_abs,
35
+ ]
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'fileutils'
3
4
  require 'pathname'
4
5
  require 'tmpdir'
5
6
 
@@ -8,6 +9,8 @@ require 'active_support/core_ext/hash'
8
9
  require 'active_support/core_ext/module/delegation'
9
10
  require 'active_support/core_ext/object/inclusion'
10
11
 
12
+ require 'diffcrypt/file'
13
+
11
14
  module Diffcrypt
12
15
  module Rails
13
16
  class EncryptedConfiguration
@@ -20,13 +23,13 @@ module Diffcrypt
20
23
  delegate_missing_to :options
21
24
 
22
25
  def initialize(config_path:, key_path:, env_key:, raise_if_missing_key:)
23
- @content_path = Pathname.new(File.absolute_path(config_path)).yield_self do |path|
26
+ @content_path = Pathname.new(::File.absolute_path(config_path)).yield_self do |path|
24
27
  path.symlink? ? path.realpath : path
25
28
  end
29
+ @diffcrypt_file = Diffcrypt::File.new(@content_path)
26
30
  @key_path = Pathname.new(key_path)
27
31
  @env_key = env_key
28
32
  @raise_if_missing_key = raise_if_missing_key
29
- @active_support_encryptor = ActiveSupport::MessageEncryptor.new([key].pack('H*'), cipher: Encryptor::CIPHER)
30
33
  end
31
34
 
32
35
  # Determines if file is using the diffable format, or still
@@ -50,7 +53,7 @@ module Diffcrypt
50
53
  deserialize(contents)
51
54
 
52
55
  IO.binwrite "#{content_path}.tmp", encrypt(contents, original_encrypted_contents)
53
- FileUtils.mv "#{content_path}.tmp", content_path
56
+ ::FileUtils.mv "#{content_path}.tmp", content_path
54
57
  end
55
58
 
56
59
  def config
@@ -72,7 +75,7 @@ module Diffcrypt
72
75
  # rubocop:disable Metrics/AbcSize
73
76
  def writing(contents)
74
77
  tmp_file = "#{Process.pid}.#{content_path.basename.to_s.chomp('.enc')}"
75
- tmp_path = Pathname.new File.join(Dir.tmpdir, tmp_file)
78
+ tmp_path = Pathname.new ::File.join(Dir.tmpdir, tmp_file)
76
79
  tmp_path.binwrite contents
77
80
 
78
81
  yield tmp_path
@@ -81,10 +84,17 @@ module Diffcrypt
81
84
 
82
85
  write(updated_contents, content_path_diffable? && content_path.binread)
83
86
  ensure
84
- FileUtils.rm(tmp_path) if tmp_path&.exist?
87
+ ::FileUtils.rm(tmp_path) if tmp_path&.exist?
85
88
  end
86
89
  # rubocop:enable Metrics/AbcSize
87
90
 
91
+ # Standard rails credentials encrypt the entire file. We need to detect this to use the correct
92
+ # data interface
93
+ # @return [Boolean]
94
+ def rails_native_credentials?(contents)
95
+ contents.index('---').nil?
96
+ end
97
+
88
98
  # @param [String] contents The new content to be encrypted
89
99
  # @param [String] diff_against The original (encrypted) content to determine which keys have changed
90
100
  # @return [String] Encrypted content to commit
@@ -95,16 +105,25 @@ module Diffcrypt
95
105
  # @param [String] contents
96
106
  # @return [String]
97
107
  def decrypt(contents)
98
- if contents.index('---').nil?
99
- @active_support_encryptor.decrypt_and_verify contents
108
+ if rails_native_credentials?(contents)
109
+ active_support_encryptor.decrypt_and_verify contents
100
110
  else
101
111
  encryptor.decrypt contents
102
112
  end
103
113
  end
104
114
 
115
+ # Rails applications with an existing credentials file, the inbuilt active support encryptor should be used
116
+ # @return [ActiveSupport::MessageEncryptor]
117
+ def active_support_encryptor
118
+ @active_support_encryptor ||= ActiveSupport::MessageEncryptor.new(
119
+ [key].pack('H*'),
120
+ cipher: 'aes-128-gcm',
121
+ )
122
+ end
123
+
105
124
  # @return [Encryptor]
106
125
  def encryptor
107
- @encryptor ||= Encryptor.new key
126
+ @encryptor ||= Encryptor.new key, cipher: @diffcrypt_file.cipher
108
127
  end
109
128
 
110
129
  def read_env_key
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'diffcrypt/rails/application_helper'
4
+
5
+ module Diffcrypt
6
+ class Railtie < ::Rails::Railtie
7
+ railtie_name :diffcrypt
8
+
9
+ rake_tasks do
10
+ path = ::File.expand_path(__dir__)
11
+ ::Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :diffcrypt do
4
+ desc 'Initialize credentials for all environments'
5
+ task :init, %i[environments] do |_t, args|
6
+ args.with_defaults(
7
+ environments: 'development,test,staging,production',
8
+ )
9
+ environments = args.environments.split(',')
10
+
11
+ environments.each do |environment|
12
+ key_path = Rails.root.join('config', 'credentials', "#{environment}.key")
13
+ file_path = Rails.root.join('config', 'credentials', "#{environment}.yml.enc")
14
+ gitignore_path = Rails.root.join('.gitignore')
15
+ next if File.exist?(file_path) || File.exist?(key_path)
16
+
17
+ # Generate a new key
18
+ key = Diffcrypt::Encryptor.generate_key
19
+ key_dir = File.dirname(key_path)
20
+ Dir.mkdir(key_dir) unless Dir.exist?(key_dir)
21
+ ::File.write(key_path, key)
22
+
23
+ # Encrypt default contents
24
+ file = Diffcrypt::File.new(file_path)
25
+ data = {
26
+ 'secret_key_base' => SecureRandom.hex(32),
27
+ }
28
+ file.write(key, data)
29
+
30
+ # Ensure .key files are always ignored
31
+ ::File.open(gitignore_path, 'a') do |f|
32
+ f.write("\nconfig/credentials/*.key")
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Diffcrypt
4
- VERSION = '0.3.2'
4
+ VERSION = '0.5.1'
5
5
  end
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diffcrypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc Qualie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-20 00:00:00.000000000 Z
11
+ date: 2021-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ - - "<"
18
21
  - !ruby/object:Gem::Version
19
- version: 6.0.0
22
+ version: '6.2'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '6.0'
30
+ - - "<"
25
31
  - !ruby/object:Gem::Version
26
- version: 6.0.0
32
+ version: '6.2'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: thor
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -70,8 +76,13 @@ files:
70
76
  - lib/diffcrypt.rb
71
77
  - lib/diffcrypt/cli.rb
72
78
  - lib/diffcrypt/encryptor.rb
79
+ - lib/diffcrypt/file.rb
80
+ - lib/diffcrypt/rails/application_helper.rb
73
81
  - lib/diffcrypt/rails/encrypted_configuration.rb
82
+ - lib/diffcrypt/railtie.rb
83
+ - lib/diffcrypt/tasks/rails.rake
74
84
  - lib/diffcrypt/version.rb
85
+ - tmp/.keep
75
86
  homepage: https://github.com/marcqualie/diffcrypt
76
87
  licenses:
77
88
  - MIT
@@ -86,14 +97,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
97
  requirements:
87
98
  - - ">="
88
99
  - !ruby/object:Gem::Version
89
- version: 2.5.0
100
+ version: 2.6.0
90
101
  required_rubygems_version: !ruby/object:Gem::Requirement
91
102
  requirements:
92
103
  - - ">="
93
104
  - !ruby/object:Gem::Version
94
105
  version: '0'
95
106
  requirements: []
96
- rubygems_version: 3.1.2
107
+ rubygems_version: 3.1.4
97
108
  signing_key:
98
109
  specification_version: 4
99
110
  summary: Diffable encrypted configuration files