secure_credentials 0.1.1 → 0.2.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: 67f34834484a909ed1ca0cdb4da8d09a57f9c1f2381237c6a22f95081827d4c9
4
- data.tar.gz: 2da212d3f2e4941c269937cbb40484b2e27d5d38609c224ca92a3b4d1af8d258
3
+ metadata.gz: 3f105345f86816004375c9c6aec5e6d48330f14768e4da243f0f0edf0894341b
4
+ data.tar.gz: c0a64940f0b7d72c8f338797dc4d35dd1493c88f8fdb2abd733ba6d7bb152947
5
5
  SHA512:
6
- metadata.gz: b0bbf47d6d142af404268bbfe991c40e9f502dc065e780fdcf2d6fa003c7bc6eaf374ee7c2a2d9aa2d4795266e2c561641d115425ee539afce23b803b9542577
7
- data.tar.gz: a6284aa14dd2998ca6cb6ca5fdd0bab26f5274a978704cf4339fc961ddca7df780352057b612a3f12786f782f659f4d247ad748de2ede16aaf951cd1eee7146d
6
+ metadata.gz: 36475092d3f12f08d1ab749694318bafe52c88a84b873149ab51fe3e13eaddd8dea317d1c05d541ec58a692a9c984d63a33cfe01c6094f64bc1484f71f265760
7
+ data.tar.gz: 6234c6c383e3ceff2c6db4f502e11a2325d7d61c8b1511588205d50f5750bbd90ebc26da5f0d631d7b67bc7aca246914abce0a0cecf0e9dc7a0873676fcecd74
data/.gitignore CHANGED
@@ -6,6 +6,8 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /gemfiles/.bundle
10
+ /gemfiles/*.lock
9
11
  Gemfile.lock
10
12
 
11
13
  # rspec failure tracking
data/.travis.yml CHANGED
@@ -4,13 +4,9 @@ cache: bundler
4
4
  rvm:
5
5
  - 2.5
6
6
  - 2.4
7
+ gemfile:
8
+ - gemfiles/rails_5.2.gemfile
9
+ - gemfiles/rails_5.1.gemfile
7
10
 
8
11
  notifications:
9
12
  email: false
10
-
11
- # for 2.5.0 until 2.5.1 is released:
12
- # https://github.com/travis-ci/travis-ci/issues/8978
13
- # https://github.com/travis-ci/travis-ci/issues/8969#issuecomment-354135622
14
- before_install:
15
- - gem update --system
16
- - gem install bundler
data/Appraisals ADDED
@@ -0,0 +1,7 @@
1
+ appraise 'rails_5.2' do
2
+ gem 'activesupport', '~> 5.2.0'
3
+ end
4
+
5
+ appraise 'rails_5.1' do
6
+ gem 'activesupport', '~> 5.1.0'
7
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # 0.2.1
2
+ - Rails 5.1 support.
3
+
4
+ # 0.1.1
5
+ - Initial release
data/Gemfile CHANGED
@@ -5,6 +5,8 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
5
5
  # Specify your gem's dependencies in gemspec file
6
6
  gemspec
7
7
 
8
+ gem 'appraisal'
9
+
8
10
  gem 'rspec', '~> 3.7'
9
11
  gem 'rspec-its', '~> 1.2'
10
12
 
data/README.md CHANGED
@@ -4,30 +4,29 @@
4
4
  [![Code Climate](https://codeclimate.com/github/printercu/secure_credentials/badges/gpa.svg)](https://codeclimate.com/github/printercu/secure_credentials)
5
5
  [![Build Status](https://travis-ci.org/printercu/secure_credentials.svg)](https://travis-ci.org/printercu/secure_credentials)
6
6
 
7
- Makes it possible to use best of encrypted credentials
8
- and environment-dependent secrets. Sharing encryption keys with
9
- every developer in a team is a security issue, and purpose of this gem
10
- is to help you to avoid it.
11
-
12
7
  ## Rationale
13
8
 
14
9
  Rails 5.2 brings good idea of storing encrypted credentials in the repo:
15
- credentials are securely tracked in version control, less chances to face an issue
10
+ credentials are securely tracked in version control, less chance to face an issue
16
11
  during deployment, etc. However there are several drawbacks in current implementation:
17
12
 
18
13
  - It's hard to manage environment-specific credentials.
19
- For example, use some different browser api keys in development and production,
14
+ For example, to use different browser api keys in development and production,
20
15
  one is whitelisted for `locahost` and other one for app's domain.
21
16
  - In most cases it's required to share `master.key` with every developer.
22
17
  This is not acceptable for a lot of teams, and framework must serve their needs too.
23
18
 
24
19
  There are a couple ways to workaround this issues, but all of them brings
25
- unnecessary complexity. This gem takes best from new encrypted `credentials.yml.enc`
26
- and multi-environmental `secrets.yml`. It allows to use combination
20
+ unnecessary complexity. This gem takes best from new encrypted credentials (`credentials.yml.enc`)
21
+ and multi-environmental secrets (`secrets.yml`). It allows to use combination
27
22
  of encrypted and plain files for same configuration in different environments.
28
23
  For example, having encrypted `credentials.production.yml.enc` for production
29
24
  and multi-environmental `credentials.yml` for all other environments.
30
25
 
26
+ There are some other issues caused by storing `master.key` in local repo.
27
+ See this wiki page for details:<br>
28
+ [Rails 5.2 credentials are not secure](https://github.com/printercu/secure_credentials/wiki/Rails-5.2-credentials-are-not-secure).
29
+
31
30
  ## Installation
32
31
 
33
32
  Add this line to your application's Gemfile:
@@ -45,7 +44,7 @@ And then execute:
45
44
  By default this gem patches Rails::Application to make `#credentials`, `#secrets` and `#encrypted`
46
45
  use Rails-compatible wrapper around SecureCredentials::Store.
47
46
 
48
- SecureCredentials::Store provides read-write interface for YAML configuration files. It supports:
47
+ SecureCredentials::Store provides read-write access to YAML configuration files. It supports:
49
48
 
50
49
  - both encrypted and plain files,
51
50
  - both file-per-environment and multi-environment files.
@@ -65,26 +64,28 @@ Otherwise `env` is used to fetch appropriate section.
65
64
  Key for decoding encoded files can be passed:
66
65
 
67
66
  - in `key` argument;
68
- - envvar identified by `env_key`, default is to upcased basename appended with `_KEY`
67
+ - in envvar identified by `env_key`, default is to upcased basename appended with `_KEY`
69
68
  (ex., `SECRETS_KEY`);
70
69
  - in file found at `key_path`,
71
70
  by default it uses filename and replaces `.yml.enc` with `.key`
72
71
  (`secrets.production.key` for `secrets.production.yml.enc`);
73
72
  - `SecureCredentials.master_key` which is read from `config/master.key` in Rails apps.
74
73
 
75
- Use `rails encrypted path/to/file.yml.enc -k path/to/key.key` to edit encrypted files.
74
+ To edit encrypted files use `rails encrypted:edit path/to/file.yml.enc -k path/to/key.key`.
76
75
  Missing `.key` and `.yml` files are automatically created when you edit them for the first time.
77
76
 
78
77
  ## Best practices
79
78
 
80
- - __Don't keep master.key in local repo!__
79
+ - __Don't keep master.key in local working directory!__
81
80
 
82
- It's the as PIN-code written on backside of credit card.
81
+ It's like a PIN-code written on backside of credit card.
83
82
  Keep it in secure place and use it when you need to modify credentials.
84
83
 
85
- - Don't share production credentials with those who must not access them.
84
+ - Don't share production credentials with those team members who don't need to access them.
86
85
 
87
86
  Secrets get less secret every time they are shared.
87
+ It's better to share some particular keys to selected developers,
88
+ instead of giving everybody access to all keys.
88
89
 
89
90
  ## Development
90
91
 
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "rspec", "~> 3.7"
7
+ gem "rspec-its", "~> 1.2"
8
+ gem "rubocop", "~> 0.56"
9
+ gem "pry", "~> 0.11"
10
+ gem "pry-byebug", "~> 3.6"
11
+ gem "activesupport", "~> 5.1.0"
12
+
13
+ gemspec path: "../"
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "rspec", "~> 3.7"
7
+ gem "rspec-its", "~> 1.2"
8
+ gem "rubocop", "~> 0.56"
9
+ gem "pry", "~> 0.11"
10
+ gem "pry-byebug", "~> 3.6"
11
+ gem "activesupport", "~> 5.2.0"
12
+
13
+ gemspec path: "../"
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copied from activesupport 5.2
4
+ # rubocop:disable all
5
+
6
+ require "pathname"
7
+ require "active_support/message_encryptor"
8
+
9
+ module ActiveSupport
10
+ class EncryptedFile
11
+ class MissingContentError < RuntimeError
12
+ def initialize(content_path)
13
+ super "Missing encrypted content file in #{content_path}."
14
+ end
15
+ end
16
+
17
+ class MissingKeyError < RuntimeError
18
+ def initialize(key_path:, env_key:)
19
+ super \
20
+ "Missing encryption key to decrypt file with. " +
21
+ "Ask your team for your master key and write it to #{key_path} or put it in the ENV['#{env_key}']."
22
+ end
23
+ end
24
+
25
+ CIPHER = "aes-128-gcm"
26
+
27
+ def self.generate_key
28
+ SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(CIPHER))
29
+ end
30
+
31
+
32
+ attr_reader :content_path, :key_path, :env_key, :raise_if_missing_key
33
+
34
+ def initialize(content_path:, key_path:, env_key:, raise_if_missing_key:)
35
+ @content_path, @key_path = Pathname.new(content_path), Pathname.new(key_path)
36
+ @env_key, @raise_if_missing_key = env_key, raise_if_missing_key
37
+ end
38
+
39
+ def key
40
+ read_env_key || read_key_file || handle_missing_key
41
+ end
42
+
43
+ def read
44
+ if !key.nil? && content_path.exist?
45
+ decrypt content_path.binread
46
+ else
47
+ raise MissingContentError, content_path
48
+ end
49
+ end
50
+
51
+ def write(contents)
52
+ IO.binwrite "#{content_path}.tmp", encrypt(contents)
53
+ FileUtils.mv "#{content_path}.tmp", content_path
54
+ end
55
+
56
+ def change(&block)
57
+ writing read, &block
58
+ end
59
+
60
+
61
+ private
62
+ def writing(contents)
63
+ tmp_file = "#{Process.pid}.#{content_path.basename.to_s.chomp('.enc')}"
64
+ tmp_path = Pathname.new File.join(Dir.tmpdir, tmp_file)
65
+ tmp_path.binwrite contents
66
+
67
+ yield tmp_path
68
+
69
+ updated_contents = tmp_path.binread
70
+
71
+ write(updated_contents) if updated_contents != contents
72
+ ensure
73
+ FileUtils.rm(tmp_path) if tmp_path.exist?
74
+ end
75
+
76
+
77
+ def encrypt(contents)
78
+ encryptor.encrypt_and_sign contents
79
+ end
80
+
81
+ def decrypt(contents)
82
+ encryptor.decrypt_and_verify contents
83
+ end
84
+
85
+ def encryptor
86
+ @encryptor ||= ActiveSupport::MessageEncryptor.new([ key ].pack("H*"), cipher: CIPHER)
87
+ end
88
+
89
+
90
+ def read_env_key
91
+ ENV[env_key]
92
+ end
93
+
94
+ def read_key_file
95
+ key_path.binread.strip if key_path.exist?
96
+ end
97
+
98
+ def handle_missing_key
99
+ raise MissingKeyError, key_path: key_path, env_key: env_key if raise_if_missing_key
100
+ end
101
+ end
102
+ end
103
+
104
+ # rubocop:enable all
@@ -1,5 +1,9 @@
1
1
  require 'securerandom'
2
- require 'active_support/encrypted_file'
2
+ begin
3
+ require 'active_support/encrypted_file'
4
+ rescue LoadError
5
+ require 'secure_credentials/active_support/encrypted_file'
6
+ end
3
7
 
4
8
  module SecureCredentials
5
9
  # Wraps ActiveSupport::EncryptedFile and provides passing key as an argument.
@@ -1,3 +1,3 @@
1
1
  module SecureCredentials
2
- VERSION = '0.1.1'.freeze
2
+ VERSION = '0.2.1'.freeze
3
3
  end
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ['lib']
21
21
 
22
- spec.add_dependency 'activesupport', '~> 5.2'
22
+ spec.add_dependency 'activesupport', '~> 5.1'
23
23
 
24
- spec.add_development_dependency 'bundler', '~> 1.16'
24
+ spec.add_development_dependency 'bundler', '> 1.16'
25
25
  spec.add_development_dependency 'rake', '~> 10.0'
26
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: secure_credentials
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Melentiev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-01 00:00:00.000000000 Z
11
+ date: 2019-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,26 +16,26 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '5.2'
19
+ version: '5.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '5.2'
26
+ version: '5.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.16'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.16'
41
41
  - !ruby/object:Gem::Dependency
@@ -64,6 +64,8 @@ files:
64
64
  - ".rspec"
65
65
  - ".rubocop.yml"
66
66
  - ".travis.yml"
67
+ - Appraisals
68
+ - CHANGELOG.md
67
69
  - Gemfile
68
70
  - README.md
69
71
  - Rakefile
@@ -71,7 +73,10 @@ files:
71
73
  - bin/git-hooks/pre-commit
72
74
  - bin/install_git_hooks
73
75
  - bin/setup
76
+ - gemfiles/rails_5.1.gemfile
77
+ - gemfiles/rails_5.2.gemfile
74
78
  - lib/secure_credentials.rb
79
+ - lib/secure_credentials/active_support/encrypted_file.rb
75
80
  - lib/secure_credentials/credentials.rb
76
81
  - lib/secure_credentials/encrypted_file.rb
77
82
  - lib/secure_credentials/no_rails_patch.rb
@@ -98,8 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
103
  - !ruby/object:Gem::Version
99
104
  version: '0'
100
105
  requirements: []
101
- rubyforge_project:
102
- rubygems_version: 2.7.6
106
+ rubygems_version: 3.0.3
103
107
  signing_key:
104
108
  specification_version: 4
105
109
  summary: Rails credentials without security issues. With environments support.