one_secret 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +88 -0
- data/Rakefile +6 -0
- data/lib/one_secret/key_resolution.rb +49 -0
- data/lib/one_secret/railtie.rb +15 -0
- data/lib/one_secret/secret.rb +28 -0
- data/lib/one_secret/secrets_yaml.rb +21 -0
- data/lib/one_secret/tasks.rake +31 -0
- data/lib/one_secret/version.rb +3 -0
- data/lib/one_secret.rb +30 -0
- data/one-secret.gemspec +27 -0
- data/spec/one_secret/key_resolution_spec.rb +71 -0
- data/spec/one_secret/secret_spec.rb +66 -0
- data/spec/one_secret/secrets_yaml_spec.rb +49 -0
- data/spec/spec_helper.rb +27 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0c8a5942cb4fc9c9d963c5c864bd010f99654383
|
4
|
+
data.tar.gz: b6de107225f64c0352e8021c36b95a994ee72f86
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1e47321d197d53553fc6a6341275acc0501d2aab999e5364a773852e157c7219ea7dcb4abb68f16a9535631177ed7131b45aa1c5a501555b44779d9821d6b584
|
7
|
+
data.tar.gz: 73d9e80006eedbebc63cda314ec99e870d5d4239e4d4e17d433d12888b249692c7f339679b657621e58ed7b10d6540e2a206aa6178a0547af66f49b3f5acb905
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Omer Rauchwerger
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# OneSecret
|
2
|
+
|
3
|
+
If you're storing your application keys, passwords and other secrets apart
|
4
|
+
from your main git repository and you are working in a team, you
|
5
|
+
probably know that managing those secrets across the team is a pain in
|
6
|
+
the ass.
|
7
|
+
|
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.
|
11
|
+
|
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).
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
gem 'one_secret'
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install one_secret
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
### Setting a new secret
|
32
|
+
|
33
|
+
To set a new secret, simply call the `one_secret:set` task:
|
34
|
+
|
35
|
+
$ rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
|
36
|
+
|
37
|
+
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.
|
40
|
+
|
41
|
+
### Accessing secrets
|
42
|
+
|
43
|
+
Inside your app, secrets are decrypted automatically, so you can use them freely:
|
44
|
+
|
45
|
+
Rails.application.secrets.aws_secret_key # => aba41f7bea276da49ef50aa33474fee4
|
46
|
+
|
47
|
+
Also, all secrets are copied to `ENV`, so you can also use this:
|
48
|
+
|
49
|
+
ENV['aws_secret_key'] # => aba41f7bea276da49ef50aa33474fee4
|
50
|
+
|
51
|
+
If you want to access secrets outside Rails, use the `one_secret:get`
|
52
|
+
task:
|
53
|
+
|
54
|
+
$ rake one_secret:get aws_secret_key
|
55
|
+
> aba41f7bea276da49ef50aa33474fee4
|
56
|
+
|
57
|
+
### Setting secrets for the Production environment
|
58
|
+
|
59
|
+
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
|
+
|
61
|
+
#### Pass `secret_key_base` In
|
62
|
+
|
63
|
+
If your app is on Heroku, you can wire `heroku config:get`:
|
64
|
+
|
65
|
+
$ RAILS_ENV=production SECRET_KEY_BASE=`heroku config:get SECRET_KEY_BASE` rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
|
66
|
+
|
67
|
+
If you're not on Heroku, you can pass your Production `secret_key_base` to Rake:
|
68
|
+
|
69
|
+
$ RAILS_ENV=production SECRET_KEY_BASE=<your production secret> rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
|
70
|
+
|
71
|
+
**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
|
+
|
73
|
+
#### Type `secret_key_base` In
|
74
|
+
|
75
|
+
If your running environment doesn't have a `secret_key_base`, OneSecret will simply prompt for it.
|
76
|
+
|
77
|
+
$ RAILS_ENV=production rake one_secret:set aws_secret_key aba41f7bea276da49ef50aa33474fee4
|
78
|
+
> <OneSecret> Please enter your secret key: <paste your production secret here>
|
79
|
+
|
80
|
+
Accessing secrets is the same for Production, as your Production machines would typically have `ENV['secret_key_base']` present.
|
81
|
+
|
82
|
+
## Contributing
|
83
|
+
|
84
|
+
1. Fork it ( https://github.com/rauchy/one_secret/fork )
|
85
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
86
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
87
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
88
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require "active_support/core_ext"
|
2
|
+
|
3
|
+
module OneSecret
|
4
|
+
module KeyResolution
|
5
|
+
def self.try(*strategies)
|
6
|
+
strategies.each do |strategy|
|
7
|
+
klass_name = "OneSecret::KeyResolution::#{strategy.to_s.capitalize}"
|
8
|
+
klass = klass_name.constantize
|
9
|
+
instance = klass.new
|
10
|
+
key = instance.key
|
11
|
+
return key if key
|
12
|
+
end
|
13
|
+
|
14
|
+
raise OneSecret.message("Cannot resolve key.")
|
15
|
+
end
|
16
|
+
|
17
|
+
class Env
|
18
|
+
def initialize(env = ENV)
|
19
|
+
@env = env
|
20
|
+
end
|
21
|
+
|
22
|
+
def key
|
23
|
+
@env["secret_key_base"] || @env["SECRET_KEY_BASE"]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Rails
|
28
|
+
def key
|
29
|
+
::Rails.application.secrets.secret_key_base
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Stdin
|
34
|
+
require 'io/console'
|
35
|
+
|
36
|
+
def initialize(output = STDOUT, input = STDIN)
|
37
|
+
@output = output
|
38
|
+
@input = input
|
39
|
+
end
|
40
|
+
|
41
|
+
def key
|
42
|
+
@output.print OneSecret.message("Please enter your secret key: ")
|
43
|
+
key = @input.noecho(&:gets).chomp
|
44
|
+
@output.puts
|
45
|
+
key unless key.blank?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module OneSecret
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
config.before_initialize do
|
4
|
+
Secret.key = KeyResolution.try(:env, :rails, :stdin)
|
5
|
+
|
6
|
+
Rails.application.secrets.each_pair do |key, value|
|
7
|
+
Rails.application.secrets[key] = ENV[key.to_s] = Secret.load(value)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
rake_tasks do
|
12
|
+
load "one_secret/tasks.rake"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end if defined?(Rails)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module OneSecret
|
2
|
+
class Secret
|
3
|
+
class << self
|
4
|
+
def key=(key)
|
5
|
+
Encryptor.default_options.merge!({key: key})
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(value)
|
10
|
+
@iv = SecureRandom.hex(16)
|
11
|
+
@salt = Time.now.to_i.to_s
|
12
|
+
@value = Encryptor.encrypt(to_hash.merge(value: value))
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_hash
|
16
|
+
{
|
17
|
+
value: @value,
|
18
|
+
iv: @iv,
|
19
|
+
salt: @salt,
|
20
|
+
algorithm: Encryptor.default_options[:algorithm]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.load(encrypted_value)
|
25
|
+
Encryptor.decrypt(encrypted_value) rescue encrypted_value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module OneSecret
|
5
|
+
class SecretsYAML
|
6
|
+
attr_reader :values
|
7
|
+
|
8
|
+
def initialize(path)
|
9
|
+
@path = path
|
10
|
+
@values = YAML.load(IO.read(path))
|
11
|
+
end
|
12
|
+
|
13
|
+
def set(environment, key, value)
|
14
|
+
@values[environment][key] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def save
|
18
|
+
File.write(@path, @values.to_yaml)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
namespace :one_secret do
|
2
|
+
desc "Encrypts and sets a new secret in config/secrets.yml under the current environment"
|
3
|
+
task :set => :environment do
|
4
|
+
key, value = *ARGV[1..2]
|
5
|
+
OneSecret.set(Rails.env, key, value)
|
6
|
+
|
7
|
+
disable_tasks(key, value)
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Encrypts and displays a new secret, but does not store it in config/secrets.yml"
|
11
|
+
task :build => :environment do
|
12
|
+
value = ARGV[1]
|
13
|
+
puts OneSecret.build(value).to_hash
|
14
|
+
|
15
|
+
disable_tasks(value)
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Decrypts and gets a secret from the current environment in config/secrets.yml"
|
19
|
+
task :get => :environment do
|
20
|
+
key = ARGV[1]
|
21
|
+
puts OneSecret.get(Rails.env, key)
|
22
|
+
|
23
|
+
disable_tasks(key)
|
24
|
+
end
|
25
|
+
|
26
|
+
def disable_tasks(*tasks)
|
27
|
+
tasks.each do |task_name|
|
28
|
+
task task_name.to_sym do ; end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/one_secret.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "one_secret/version"
|
2
|
+
require "one_secret/key_resolution"
|
3
|
+
require "one_secret/secret"
|
4
|
+
require "one_secret/secrets_yaml"
|
5
|
+
require "encryptor"
|
6
|
+
require "one_secret/railtie"
|
7
|
+
|
8
|
+
module OneSecret
|
9
|
+
def self.build(value)
|
10
|
+
Secret.new(value)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.set(environment, key, value)
|
14
|
+
secrets = SecretsYAML.new("config/secrets.yml")
|
15
|
+
build(value).tap do |secret|
|
16
|
+
secrets.set(Rails.env, key, secret.to_hash)
|
17
|
+
secrets.save
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.get(environment, key)
|
22
|
+
secrets = SecretsYAML.new("config/secrets.yml")
|
23
|
+
secret = secrets.values[Rails.env][key]
|
24
|
+
Secret.load(secret)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.message(text)
|
28
|
+
"\e[33m<OneSecret>\e[0m #{text}"
|
29
|
+
end
|
30
|
+
end
|
data/one-secret.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'one_secret/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "one_secret"
|
8
|
+
spec.version = OneSecret::VERSION
|
9
|
+
spec.authors = ["Omer Lachish-Rauchwerger"]
|
10
|
+
spec.email = ["omer@rauchy.net"]
|
11
|
+
spec.summary = %q{Keep application secrets easily and securely as part of your Rails app.}
|
12
|
+
spec.description = %q{}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "pry"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec-mocks", "~> 3.0.2"
|
25
|
+
spec.add_dependency "activesupport"
|
26
|
+
spec.add_dependency "encryptor"
|
27
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
module OneSecret
|
4
|
+
describe KeyResolution do
|
5
|
+
it "instantiates strategies" do
|
6
|
+
KeyResolution::Foo = double("FooKeyResolution")
|
7
|
+
expect(KeyResolution::Foo).to receive(:new).and_return(double(key: true))
|
8
|
+
KeyResolution.try(:foo)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "uses strategies" do
|
12
|
+
KeyResolution::Bar = double(new: double(key: 5))
|
13
|
+
KeyResolution.try(:bar).must_equal 5
|
14
|
+
end
|
15
|
+
|
16
|
+
it "tries all strategies until some key is returned" do
|
17
|
+
KeyResolution::Bar = double(new: double(key: nil))
|
18
|
+
KeyResolution::Baz = double(new: double(key: 5))
|
19
|
+
KeyResolution::Qux = double(new: double(key: 6))
|
20
|
+
|
21
|
+
KeyResolution.try(:bar, :baz, :qux).must_equal 5
|
22
|
+
end
|
23
|
+
|
24
|
+
it "raises an error if no key was found using all strategies" do
|
25
|
+
KeyResolution::Bar = double(new: double(key: nil))
|
26
|
+
-> { KeyResolution.try(:bar) }.must_raise RuntimeError
|
27
|
+
end
|
28
|
+
|
29
|
+
describe KeyResolution::Env do
|
30
|
+
it "resolves a key using an environment variable called 'secret_key_base'" do
|
31
|
+
KeyResolution::Env.new({"secret_key_base" => "hola"}).key.must_equal "hola"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "resolves a key using an environment variable called 'SECRET_KEY_BASE'" do
|
35
|
+
KeyResolution::Env.new({"SECRET_KEY_BASE" => "amigo"}).key.must_equal "amigo"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "fails to resolve a key otherwise" do
|
39
|
+
KeyResolution::Env.new({}).key.must_be_nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe KeyResolution::Rails do
|
44
|
+
it "resolves a key using Rails' application secrets" do
|
45
|
+
::Rails = double
|
46
|
+
::Rails.stub_chain(:application, :secrets, :secret_key_base).and_return("hola")
|
47
|
+
KeyResolution::Rails.new.key.must_equal "hola"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "fails to resolve a key otherwise" do
|
51
|
+
::Rails = double
|
52
|
+
::Rails.stub_chain(:application, :secrets, :secret_key_base)
|
53
|
+
KeyResolution::Rails.new.key.must_be_nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe KeyResolution::Stdin do
|
58
|
+
it "asks the user to type in the secret key" do
|
59
|
+
output = double(print: true, puts: true)
|
60
|
+
input = double(noecho: "hola")
|
61
|
+
KeyResolution::Stdin.new(output, input).key.must_equal "hola"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "fails to resolve a secret key if entered empty" do
|
65
|
+
output = double(print: true, puts: true)
|
66
|
+
input = double(noecho: "")
|
67
|
+
KeyResolution::Stdin.new(output, input).key.must_be_nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
module OneSecret
|
4
|
+
describe Secret do
|
5
|
+
def with_iv(iv)
|
6
|
+
SecureRandom.stub(:hex, iv) { yield }
|
7
|
+
end
|
8
|
+
|
9
|
+
def with_salt(salt)
|
10
|
+
Time.stub(:now, salt) { yield }
|
11
|
+
end
|
12
|
+
|
13
|
+
before do
|
14
|
+
Secret.key = "f3bbdba9485ac1ee1412d2c839be0a0f"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "encrypts a string" do
|
18
|
+
with_iv "I am a random iv" do
|
19
|
+
with_salt Time.at(0) do
|
20
|
+
secret = Secret.new("Encrypt me!")
|
21
|
+
secret.to_hash.keys.must_include :value
|
22
|
+
secret.to_hash[:value].must_be :!=, "Encrypt me!"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "uses a random iv" do
|
28
|
+
with_iv "I am a random iv" do
|
29
|
+
secret = Secret.new("Encrypt me!")
|
30
|
+
secret.to_hash.keys.must_include :iv
|
31
|
+
secret.to_hash[:iv].must_equal "I am a random iv"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "uses now as a salt" do
|
36
|
+
with_salt Time.at(0) do
|
37
|
+
secret = Secret.new("Encrypt me!")
|
38
|
+
secret.to_hash.keys.must_include :salt
|
39
|
+
secret.to_hash[:salt].must_equal "0"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it "specifies the algorithm being used" do
|
44
|
+
secret = Secret.new("Encrypt me!")
|
45
|
+
secret.to_hash.keys.must_include :algorithm
|
46
|
+
secret.to_hash[:algorithm].must_equal "aes-256-cbc"
|
47
|
+
end
|
48
|
+
|
49
|
+
describe ".load" do
|
50
|
+
it "returns the same value when a non-encrypted hash is provided" do
|
51
|
+
Secret.load("I am not encrypted").must_equal "I am not encrypted"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "decrypts encrypted hashes" do
|
55
|
+
encrypted_hash = {
|
56
|
+
value: "\xE6N\x9DF\xDA%\xC2nR\n\x1D\x9F\xE0l\xB1\x1F",
|
57
|
+
iv: "b511f7ffa666467c1c55f466886277b8",
|
58
|
+
salt: "12be65aafdd78c0540146f2f995c95c7",
|
59
|
+
algorithm: "aes-256-cbc"
|
60
|
+
}
|
61
|
+
|
62
|
+
Secret.load(encrypted_hash).must_equal "I am encrypted"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module OneSecret
|
5
|
+
describe SecretsYAML do
|
6
|
+
def temp_file(content)
|
7
|
+
file = Tempfile.new('foo')
|
8
|
+
file.write(content)
|
9
|
+
file.flush
|
10
|
+
file.path
|
11
|
+
end
|
12
|
+
|
13
|
+
it "sets new values in the correct environment" do
|
14
|
+
path = temp_file """---
|
15
|
+
|
16
|
+
development:
|
17
|
+
|
18
|
+
foo: bar
|
19
|
+
|
20
|
+
test:
|
21
|
+
|
22
|
+
bar: baz
|
23
|
+
|
24
|
+
production:
|
25
|
+
|
26
|
+
baz: qux
|
27
|
+
"""
|
28
|
+
secrets = SecretsYAML.new(path)
|
29
|
+
secrets.set("test", "bar", "barness")
|
30
|
+
secrets.save
|
31
|
+
|
32
|
+
File.readlines(path).join("\n").must_equal """---
|
33
|
+
|
34
|
+
development:
|
35
|
+
|
36
|
+
foo: bar
|
37
|
+
|
38
|
+
test:
|
39
|
+
|
40
|
+
bar: barness
|
41
|
+
|
42
|
+
production:
|
43
|
+
|
44
|
+
baz: qux
|
45
|
+
"""
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require './lib/one_secret'
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'minitest/spec'
|
5
|
+
require 'minitest/pride'
|
6
|
+
|
7
|
+
require 'rspec/mocks'
|
8
|
+
require 'minitest/autorun'
|
9
|
+
require 'rspec/mocks'
|
10
|
+
|
11
|
+
module MinitestRSpecMocksIntegration
|
12
|
+
include ::RSpec::Mocks::ExampleMethods
|
13
|
+
|
14
|
+
def before_setup
|
15
|
+
::RSpec::Mocks.setup
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def after_teardown
|
20
|
+
super
|
21
|
+
::RSpec::Mocks.verify
|
22
|
+
ensure
|
23
|
+
::RSpec::Mocks.teardown
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Minitest::Spec.send(:include, MinitestRSpecMocksIntegration)
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: one_secret
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Omer Lachish-Rauchwerger
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-mocks
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.0.2
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.0.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activesupport
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: encryptor
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: ''
|
98
|
+
email:
|
99
|
+
- omer@rauchy.net
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- Gemfile
|
106
|
+
- LICENSE.txt
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- lib/one_secret.rb
|
110
|
+
- lib/one_secret/key_resolution.rb
|
111
|
+
- lib/one_secret/railtie.rb
|
112
|
+
- lib/one_secret/secret.rb
|
113
|
+
- lib/one_secret/secrets_yaml.rb
|
114
|
+
- lib/one_secret/tasks.rake
|
115
|
+
- lib/one_secret/version.rb
|
116
|
+
- one-secret.gemspec
|
117
|
+
- spec/one_secret/key_resolution_spec.rb
|
118
|
+
- spec/one_secret/secret_spec.rb
|
119
|
+
- spec/one_secret/secrets_yaml_spec.rb
|
120
|
+
- spec/spec_helper.rb
|
121
|
+
homepage: ''
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
metadata: {}
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
requirements: []
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 2.1.11
|
142
|
+
signing_key:
|
143
|
+
specification_version: 4
|
144
|
+
summary: Keep application secrets easily and securely as part of your Rails app.
|
145
|
+
test_files:
|
146
|
+
- spec/one_secret/key_resolution_spec.rb
|
147
|
+
- spec/one_secret/secret_spec.rb
|
148
|
+
- spec/one_secret/secrets_yaml_spec.rb
|
149
|
+
- spec/spec_helper.rb
|