one_secret 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/README.md +70 -26
- data/Rakefile +2 -0
- data/lib/one_secret.rb +28 -6
- data/lib/one_secret/configuration.rb +11 -0
- data/lib/one_secret/railtie.rb +20 -9
- data/lib/one_secret/secret.rb +6 -0
- data/lib/one_secret/secrets_yaml.rb +0 -1
- data/lib/one_secret/store.rb +29 -0
- data/lib/one_secret/tasks.rake +5 -0
- data/lib/one_secret/version.rb +1 -1
- data/spec/one_secret/store_spec.rb +31 -0
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d92e86e4a1e7f67523a826c713580a6a9e2f897c
|
4
|
+
data.tar.gz: feacc094ab2ff27e542041c468bf37108a0fae94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ef3b84b365791adf3438ab3fff989f41c760c1657d0b06c2836158dc45d898005c91b5f66dceb2cca6433c03c1bb01b78793d71e7b5ef9214cd95b5baaa009e
|
7
|
+
data.tar.gz: 28bc13b6226b169ace616c81b58ca2fe44f28de3fceaeba74b964d4bebcbf9b87e3af780438329b2d40fb9615b4ae80fe3a6236fab0680d58845ab6db5ac6fcc
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# OneSecret
|
1
|
+
# OneSecret [![Build Status](https://travis-ci.org/rauchy/one-secret.svg)](https://travis-ci.org/rauchy/one-secret)
|
2
2
|
|
3
3
|
If you're storing your application keys, passwords and other secrets apart
|
4
4
|
from your main git repository and you are working in a team, you
|
@@ -6,67 +6,109 @@ probably know that managing those secrets across the team is a pain in
|
|
6
6
|
the ass.
|
7
7
|
|
8
8
|
OneSecret aims to remedy that by encrypting all your secrets
|
9
|
-
inside Rails' secrets.yml and decrypting them on the fly so that they are freely
|
10
|
-
available
|
9
|
+
inside Rails' `config/secrets.yml` and decrypting them on the fly so that they are freely
|
10
|
+
available in your application.
|
11
11
|
|
12
12
|
OneSecret uses Rails' `secret_key_base` as a key for encrypting your
|
13
|
-
secrets, so the only thing you need to set in your Production servers is the `secret_key_base` (you should be doing
|
13
|
+
secrets, so the only thing you need to set in your Production servers is the `secret_key_base` (you should be doing this even if you don't use OneSecret).
|
14
14
|
|
15
15
|
## Installation
|
16
16
|
|
17
17
|
Add this line to your application's Gemfile:
|
18
18
|
|
19
|
-
|
19
|
+
```ruby
|
20
|
+
gem 'one_secret'
|
21
|
+
```
|
20
22
|
|
21
23
|
And then execute:
|
22
24
|
|
23
|
-
|
25
|
+
```sh
|
26
|
+
$ bundle
|
27
|
+
```
|
24
28
|
|
25
|
-
|
29
|
+
## Requirements
|
26
30
|
|
27
|
-
|
31
|
+
This gem only works with Rails >= 4.1, since it tightly integrates with the `secrets.yml` which was added by Rails 4.1
|
28
32
|
|
29
33
|
## Usage
|
30
34
|
|
31
35
|
### Setting a new secret
|
32
36
|
|
33
|
-
To set a new secret, simply call the `one_secret:set` task:
|
37
|
+
To set a new secret, simply call the `one_secret:set` task with a key and value to encrypt:
|
34
38
|
|
35
|
-
|
39
|
+
```sh
|
40
|
+
rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
|
41
|
+
```
|
36
42
|
|
37
43
|
That's it! This will encrypt the value and keep it inside
|
38
|
-
`config/secrets.yml`. Feel free to commit
|
39
|
-
repository
|
44
|
+
`config/secrets.yml`. **Feel free to commit this file to your git
|
45
|
+
repository.**
|
40
46
|
|
41
47
|
### Accessing secrets
|
42
48
|
|
43
|
-
|
49
|
+
There are 3 ways to access your secrets:
|
44
50
|
|
45
|
-
|
51
|
+
1. Inside your app, secrets are decrypted automatically, so you can use them freely:
|
46
52
|
|
47
|
-
|
53
|
+
```ruby
|
54
|
+
Rails.application.secrets.aws_secret_key # => aba41f7bea276da49ef50aa33474fee4
|
55
|
+
```
|
48
56
|
|
49
|
-
|
57
|
+
2. If you wish to, you can access all secrets through `ENV`:
|
50
58
|
|
51
|
-
|
59
|
+
```ruby
|
60
|
+
ENV['aws_secret_key'] # => aba41f7bea276da49ef50aa33474fee4
|
61
|
+
```
|
62
|
+
|
63
|
+
To enable access through `ENV`, add this configuration block to
|
64
|
+
`application.rb`:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
# application.rb
|
68
|
+
OneSecret.configure do
|
69
|
+
decrypt_into_env!
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
3. If you want to access secrets outside Rails, use the `one_secret:get`
|
52
74
|
task:
|
53
75
|
|
54
|
-
|
55
|
-
|
56
|
-
|
76
|
+
```sh
|
77
|
+
rake one_secret:get aws_secret_key
|
78
|
+
> aba41f7bea276da49ef50aa33474fee4
|
79
|
+
```
|
80
|
+
|
81
|
+
or you could use the `one_secret:get_all` task to get a hash of all
|
82
|
+
decrypted values.
|
83
|
+
|
84
|
+
### Determining the secret_key_base
|
85
|
+
|
86
|
+
The above commands work in development since you have the `secret_key_base` set in `config/secrets.yml`. OneSecret
|
87
|
+
will use the following strategy to determine what the value of `secret_key_base` should be:
|
88
|
+
|
89
|
+
* ENV['SECRET_KEY_BASE']
|
90
|
+
* Rails.application.secrets.secret_key_base
|
91
|
+
* STDIN prompt
|
92
|
+
|
57
93
|
### Setting secrets for the Production environment
|
58
94
|
|
59
95
|
Since the Production `secret_key_base` is only available in your Production servers, you should provide the `secret_key_base` to the `one_secret:set` Rake task when setting Production secrets. This could be done in one of the following ways:
|
60
96
|
|
61
97
|
#### Pass `secret_key_base` In
|
62
98
|
|
63
|
-
If your app is on Heroku, you can wire `heroku config:get`:
|
99
|
+
If your app is hosted on Heroku, you can wire `heroku config:get`:
|
100
|
+
:a
|
101
|
+
|
64
102
|
|
65
|
-
|
103
|
+
```sh
|
104
|
+
$ RAILS_ENV=production SECRET_KEY_BASE=`heroku config:get SECRET_KEY_BASE` rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
|
105
|
+
```
|
66
106
|
|
67
|
-
If you're not on Heroku, you can pass your Production `secret_key_base` to Rake:
|
107
|
+
If you're not hosted on Heroku, you can pass your Production `secret_key_base` to Rake:
|
68
108
|
|
69
|
-
|
109
|
+
```sh
|
110
|
+
RAILS_ENV=production SECRET_KEY_BASE=<your production secret> rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
|
111
|
+
```
|
70
112
|
|
71
113
|
**Important** - note that there is an extra space at the beginning of this command. Make sure you prefix your command with that extra space so it doesn't get saved in your shell history.
|
72
114
|
|
@@ -74,8 +116,10 @@ If you're not on Heroku, you can pass your Production `secret_key_base` to Rake:
|
|
74
116
|
|
75
117
|
If your running environment doesn't have a `secret_key_base`, OneSecret will simply prompt for it.
|
76
118
|
|
77
|
-
|
78
|
-
|
119
|
+
```sh
|
120
|
+
$ RAILS_ENV=production rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
|
121
|
+
> <OneSecret> Please enter your secret key: <paste your production secret here>
|
122
|
+
```
|
79
123
|
|
80
124
|
Accessing secrets is the same for Production, as your Production machines would typically have `ENV['secret_key_base']` present.
|
81
125
|
|
data/Rakefile
CHANGED
data/lib/one_secret.rb
CHANGED
@@ -2,26 +2,48 @@ require "one_secret/version"
|
|
2
2
|
require "one_secret/key_resolution"
|
3
3
|
require "one_secret/secret"
|
4
4
|
require "one_secret/secrets_yaml"
|
5
|
+
require "one_secret/configuration"
|
6
|
+
require "one_secret/store"
|
5
7
|
require "encryptor"
|
6
8
|
require "one_secret/railtie"
|
7
9
|
|
8
10
|
module OneSecret
|
11
|
+
def self.configure(&block)
|
12
|
+
configuration.instance_eval(&block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configuration
|
16
|
+
@configuration ||= Configuration.new
|
17
|
+
end
|
18
|
+
|
9
19
|
def self.build(value)
|
10
|
-
Secret.
|
20
|
+
Secret.unlocked {
|
21
|
+
return Secret.new(value)
|
22
|
+
}
|
11
23
|
end
|
12
24
|
|
13
25
|
def self.set(environment, key, value)
|
14
|
-
secrets = SecretsYAML.new("config/secrets.
|
26
|
+
secrets = SecretsYAML.new(Rails.application.paths["config/secrets"].first)
|
15
27
|
build(value).tap do |secret|
|
16
|
-
secrets.set(
|
28
|
+
secrets.set(environment, key, secret.to_hash)
|
17
29
|
secrets.save
|
18
30
|
end
|
19
31
|
end
|
20
32
|
|
21
33
|
def self.get(environment, key)
|
22
|
-
secrets = SecretsYAML.new("config/secrets.
|
23
|
-
secret = secrets.values[
|
24
|
-
|
34
|
+
secrets = SecretsYAML.new(Rails.application.paths["config/secrets"].first)
|
35
|
+
secret = secrets.values[environment][key]
|
36
|
+
|
37
|
+
Secret.unlocked {
|
38
|
+
return Secret.load(secret)
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.get_all(environment)
|
43
|
+
secrets = SecretsYAML.new(Rails.application.paths["config/secrets"].first)
|
44
|
+
Secret.unlocked {
|
45
|
+
return Hash[secrets.values[environment].map { |k, v| [k, Secret.load(v)] }]
|
46
|
+
}
|
25
47
|
end
|
26
48
|
|
27
49
|
def self.message(text)
|
data/lib/one_secret/railtie.rb
CHANGED
@@ -2,10 +2,10 @@ module OneSecret
|
|
2
2
|
class Railtie < Rails::Railtie
|
3
3
|
config.before_initialize do
|
4
4
|
if should_run?
|
5
|
-
Secret.
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
Secret.unlocked do
|
6
|
+
each_secret do |name, secret|
|
7
|
+
put_in_stores(name, secret)
|
8
|
+
end
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -16,11 +16,22 @@ module OneSecret
|
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
class << self
|
20
|
+
|
21
|
+
def each_secret(&block)
|
22
|
+
Rails.application.secrets.each_pair(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def put_in_stores(name, secret)
|
26
|
+
[ApplicationSecretsStore, EnvStore].each { |s| s.new.put(name, secret) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def should_run?
|
30
|
+
if defined?(Rake)
|
31
|
+
!Rake.application.top_level_tasks.include?("assets:precompile")
|
32
|
+
else
|
33
|
+
true
|
34
|
+
end
|
24
35
|
end
|
25
36
|
end
|
26
37
|
end
|
data/lib/one_secret/secret.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
module OneSecret
|
2
|
+
class Store
|
3
|
+
def initialize(hash)
|
4
|
+
@hash = hash
|
5
|
+
end
|
6
|
+
|
7
|
+
def put(key, value)
|
8
|
+
decrypted_value = Secret.load(value)
|
9
|
+
@hash[key.to_s] = decrypted_value
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ApplicationSecretsStore < Store
|
14
|
+
def initialize
|
15
|
+
super(Rails.application.secrets)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class EnvStore < Store
|
20
|
+
def initialize
|
21
|
+
@decrypt_into_env = OneSecret.configuration.decrypt_into_env?
|
22
|
+
super(ENV)
|
23
|
+
end
|
24
|
+
|
25
|
+
def put(key, value)
|
26
|
+
super(key, value) if @decrypt_into_env
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/one_secret/tasks.rake
CHANGED
@@ -23,6 +23,11 @@ namespace :one_secret do
|
|
23
23
|
disable_tasks(key)
|
24
24
|
end
|
25
25
|
|
26
|
+
desc "Decrypts and gets all secrets from the current environment in config/secrets.yml"
|
27
|
+
task :get_all => :environment do
|
28
|
+
puts OneSecret.get_all(Rails.env)
|
29
|
+
end
|
30
|
+
|
26
31
|
def disable_tasks(*tasks)
|
27
32
|
tasks.each do |task_name|
|
28
33
|
task task_name.to_sym do ; end
|
data/lib/one_secret/version.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
module OneSecret
|
4
|
+
describe ApplicationSecretsStore do
|
5
|
+
describe "#put" do
|
6
|
+
it "puts values in Rails.application.secrets" do
|
7
|
+
::Rails = double
|
8
|
+
::Rails.stub_chain(:application, :secrets).and_return(OpenStruct.new)
|
9
|
+
|
10
|
+
ApplicationSecretsStore.new.put(:foo, "bar")
|
11
|
+
Rails.application.secrets.foo.must_equal "bar"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe EnvStore do
|
17
|
+
describe "#put" do
|
18
|
+
it "puts values in ENV when configured to do so" do
|
19
|
+
OneSecret.configure { decrypt_into_env! }
|
20
|
+
EnvStore.new.put(:foo, "bar")
|
21
|
+
ENV["foo"].must_equal "bar"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "doesn't put values in ENV when not configured to do so" do
|
25
|
+
OneSecret.configure { decrypt_into_env!(false) }
|
26
|
+
EnvStore.new.put(:baz, "qux")
|
27
|
+
ENV["baz"].must_be_nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: one_secret
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Omer Lachish-Rauchwerger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -102,21 +102,25 @@ extensions: []
|
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
104
|
- ".gitignore"
|
105
|
+
- ".travis.yml"
|
105
106
|
- Gemfile
|
106
107
|
- LICENSE.txt
|
107
108
|
- README.md
|
108
109
|
- Rakefile
|
109
110
|
- lib/one_secret.rb
|
111
|
+
- lib/one_secret/configuration.rb
|
110
112
|
- lib/one_secret/key_resolution.rb
|
111
113
|
- lib/one_secret/railtie.rb
|
112
114
|
- lib/one_secret/secret.rb
|
113
115
|
- lib/one_secret/secrets_yaml.rb
|
116
|
+
- lib/one_secret/store.rb
|
114
117
|
- lib/one_secret/tasks.rake
|
115
118
|
- lib/one_secret/version.rb
|
116
119
|
- one-secret.gemspec
|
117
120
|
- spec/one_secret/key_resolution_spec.rb
|
118
121
|
- spec/one_secret/secret_spec.rb
|
119
122
|
- spec/one_secret/secrets_yaml_spec.rb
|
123
|
+
- spec/one_secret/store_spec.rb
|
120
124
|
- spec/spec_helper.rb
|
121
125
|
homepage: ''
|
122
126
|
licenses:
|
@@ -138,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
142
|
version: '0'
|
139
143
|
requirements: []
|
140
144
|
rubyforge_project:
|
141
|
-
rubygems_version: 2.
|
145
|
+
rubygems_version: 2.2.2
|
142
146
|
signing_key:
|
143
147
|
specification_version: 4
|
144
148
|
summary: Keep application secrets easily and securely as part of your Rails app.
|
@@ -146,4 +150,5 @@ test_files:
|
|
146
150
|
- spec/one_secret/key_resolution_spec.rb
|
147
151
|
- spec/one_secret/secret_spec.rb
|
148
152
|
- spec/one_secret/secrets_yaml_spec.rb
|
153
|
+
- spec/one_secret/store_spec.rb
|
149
154
|
- spec/spec_helper.rb
|