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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3e6ecced2b2fd28691b954df6e31da6a1725ecab
4
- data.tar.gz: e9d53b25fe331ce481a88274d376e18ee5ca27b5
3
+ metadata.gz: d92e86e4a1e7f67523a826c713580a6a9e2f897c
4
+ data.tar.gz: feacc094ab2ff27e542041c468bf37108a0fae94
5
5
  SHA512:
6
- metadata.gz: 00fcfd0525e727279170cac1263b213869bb0897cc2fc0e53518463b1b88e9dce7b67720b64014bc889be38d6301243e87e77c27225dacf21f70164d6c0c429a
7
- data.tar.gz: d7596da0e82404965fb5f003886efc2e3c147577b0396f3382d791ff8143eb6e80f682d296ba9f1aa129eaba9d6866f06b12b22cb9c610a4aca993d7f578293e
6
+ metadata.gz: 3ef3b84b365791adf3438ab3fff989f41c760c1657d0b06c2836158dc45d898005c91b5f66dceb2cca6433c03c1bb01b78793d71e7b5ef9214cd95b5baaa009e
7
+ data.tar.gz: 28bc13b6226b169ace616c81b58ca2fe44f28de3fceaeba74b964d4bebcbf9b87e3af780438329b2d40fb9615b4ae80fe3a6236fab0680d58845ab6db5ac6fcc
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
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 to your application.
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 that even if you don't use OneSecret).
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
- gem 'one_secret'
19
+ ```ruby
20
+ gem 'one_secret'
21
+ ```
20
22
 
21
23
  And then execute:
22
24
 
23
- $ bundle
25
+ ```sh
26
+ $ bundle
27
+ ```
24
28
 
25
- Or install it yourself as:
29
+ ## Requirements
26
30
 
27
- $ gem install one_secret
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
- $ rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
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 that file to your git
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
- Inside your app, secrets are decrypted automatically, so you can use them freely:
49
+ There are 3 ways to access your secrets:
44
50
 
45
- Rails.application.secrets.aws_secret_key # => aba41f7bea276da49ef50aa33474fee4
51
+ 1. Inside your app, secrets are decrypted automatically, so you can use them freely:
46
52
 
47
- Also, all secrets are copied to `ENV`, so you can also use this:
53
+ ```ruby
54
+ Rails.application.secrets.aws_secret_key # => aba41f7bea276da49ef50aa33474fee4
55
+ ```
48
56
 
49
- ENV['aws_secret_key'] # => aba41f7bea276da49ef50aa33474fee4
57
+ 2. If you wish to, you can access all secrets through `ENV`:
50
58
 
51
- If you want to access secrets outside Rails, use the `one_secret:get`
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
- $ rake one_secret:get aws_secret_key
55
- > aba41f7bea276da49ef50aa33474fee4
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
- $ RAILS_ENV=production SECRET_KEY_BASE=`heroku config:get SECRET_KEY_BASE` rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
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
- $ RAILS_ENV=production SECRET_KEY_BASE=<your production secret> rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
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
- $ RAILS_ENV=production rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
78
- > <OneSecret> Please enter your secret key: <paste your production secret here>
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
@@ -4,3 +4,5 @@ require 'rake/testtask'
4
4
  Rake::TestTask.new do |t|
5
5
  t.pattern = "spec/**/*_spec.rb"
6
6
  end
7
+
8
+ task :default => :test
@@ -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.new(value)
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.yml")
26
+ secrets = SecretsYAML.new(Rails.application.paths["config/secrets"].first)
15
27
  build(value).tap do |secret|
16
- secrets.set(Rails.env, key, secret.to_hash)
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.yml")
23
- secret = secrets.values[Rails.env][key]
24
- Secret.load(secret)
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)
@@ -0,0 +1,11 @@
1
+ module OneSecret
2
+ class Configuration
3
+ def decrypt_into_env!(should_decrypt=true)
4
+ @decrypt_into_env = should_decrypt
5
+ end
6
+
7
+ def decrypt_into_env?
8
+ !!@decrypt_into_env
9
+ end
10
+ end
11
+ end
@@ -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.key = KeyResolution.try(:env, :rails, :stdin)
6
-
7
- Rails.application.secrets.each_pair do |key, value|
8
- Rails.application.secrets[key] = ENV[key.to_s] = Secret.load(value)
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
- def self.should_run?
20
- if defined?(Rake)
21
- !Rake.application.top_level_tasks.include?("assets:precompile")
22
- else
23
- true
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
@@ -1,6 +1,12 @@
1
1
  module OneSecret
2
2
  class Secret
3
3
  class << self
4
+ def unlocked
5
+ self.key = KeyResolution.try(:env, :rails, :stdin)
6
+ yield
7
+ self.key = nil
8
+ end
9
+
4
10
  def key=(key)
5
11
  Encryptor.default_options.merge!({key: key})
6
12
  end
@@ -1,5 +1,4 @@
1
1
  require 'yaml'
2
- require 'erb'
3
2
 
4
3
  module OneSecret
5
4
  class SecretsYAML
@@ -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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module OneSecret
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
@@ -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.1
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-07-28 00:00:00.000000000 Z
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.1.11
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