diffcrypt 0.3.2 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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