secret_store 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +9 -5
- data/lib/secret_store/version.rb +1 -1
- data/lib/secret_store.rb +31 -16
- data/spec/secret_store_spec.rb +12 -11
- metadata +9 -9
data/README.md
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
SecretStore
|
2
2
|
===========
|
3
3
|
|
4
|
-
Store secrets for your app
|
4
|
+
Store secrets for your app AES encrypted in a yaml file.
|
5
5
|
|
6
6
|
Often when working on a web application, you have the need for storing a
|
7
7
|
variety of API keys or secrets to 3rd party services. However, it's not
|
8
8
|
desireable to check those secrets in as plain text to the code respository.
|
9
|
+
This means that any 3rd party access to your repository provides that info.
|
10
|
+
With SecretStore, parties without knowledge of the master password (this can
|
11
|
+
include your own team members!) will not have direct access to such secrets.
|
9
12
|
|
10
13
|
One common way around this is to set such keys in the environment. This is,
|
11
14
|
for example, what [Heroku recommends](https://devcenter.heroku.com/articles/config-vars)
|
@@ -41,11 +44,12 @@ require "secret_store"
|
|
41
44
|
secret_store = SecretStore.new("master_password", "/path/to/data.yml")
|
42
45
|
secret_store.store("some_api_key", "c7dd199")
|
43
46
|
secret_store.get("some_api_key") # => "c7dd199"
|
44
|
-
secret_store.get("unknown_key") # =>
|
47
|
+
secret_store.get("unknown_key") # => nil
|
48
|
+
secret_store.get!("unknown_key") # => raises IndexError
|
45
49
|
|
46
|
-
secret_store.store("
|
47
|
-
secret_store.store("
|
48
|
-
secret_store.store("
|
50
|
+
secret_store.store("secret", "b123fa") # => stores
|
51
|
+
secret_store.store("secret", "new_val") # => raises error
|
52
|
+
secret_store.store!("secret", "new_val") # => overwrites stored
|
49
53
|
```
|
50
54
|
|
51
55
|
For a typical application, it could be desirable to define a
|
data/lib/secret_store/version.rb
CHANGED
data/lib/secret_store.rb
CHANGED
@@ -10,10 +10,10 @@ class SecretStore
|
|
10
10
|
self.file_path = file_path
|
11
11
|
end
|
12
12
|
|
13
|
-
def store(key, secret,
|
14
|
-
load_data
|
13
|
+
def store(key, secret, reload_data = true)
|
14
|
+
load_data if reload_data
|
15
15
|
|
16
|
-
if
|
16
|
+
if @data[key.to_s]
|
17
17
|
raise "Key #{key} already stored"
|
18
18
|
end
|
19
19
|
|
@@ -22,9 +22,20 @@ class SecretStore
|
|
22
22
|
load_data[key]
|
23
23
|
end
|
24
24
|
|
25
|
+
def store!(key, secret)
|
26
|
+
load_data
|
27
|
+
@data.delete(key.to_s)
|
28
|
+
store(key, secret, false)
|
29
|
+
end
|
30
|
+
|
25
31
|
def get(key)
|
26
|
-
ciphertext = @data
|
27
|
-
|
32
|
+
if ciphertext = @data[key.to_s]
|
33
|
+
cipher.decrypt(ciphertext)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def get!(key)
|
38
|
+
get(key) or raise IndexError.new(%Q[key not found: "#{key}"])
|
28
39
|
end
|
29
40
|
|
30
41
|
def encrypt(secret)
|
@@ -32,18 +43,9 @@ class SecretStore
|
|
32
43
|
end
|
33
44
|
|
34
45
|
def change_password(new_password)
|
35
|
-
|
36
|
-
|
37
|
-
@data.each_key do |key|
|
38
|
-
new_data[key] = get(key)
|
39
|
-
end
|
40
|
-
|
46
|
+
decrypted = decrypted_data
|
41
47
|
self.password = new_password
|
42
|
-
|
43
|
-
new_data.each do |key, plaintext|
|
44
|
-
@data[key] = encrypt(plaintext)
|
45
|
-
end
|
46
|
-
|
48
|
+
replace_with_decrypted(decrypted)
|
47
49
|
store_data
|
48
50
|
end
|
49
51
|
|
@@ -77,4 +79,17 @@ class SecretStore
|
|
77
79
|
f.puts YAML.dump @data
|
78
80
|
end
|
79
81
|
end
|
82
|
+
|
83
|
+
def decrypted_data
|
84
|
+
@data.each_key.inject({}) do |decrypted_data, key|
|
85
|
+
decrypted_data[key] = get(key)
|
86
|
+
decrypted_data
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def replace_with_decrypted(decrypted)
|
91
|
+
decrypted.each do |key, plaintext|
|
92
|
+
@data[key] = encrypt(plaintext)
|
93
|
+
end
|
94
|
+
end
|
80
95
|
end
|
data/spec/secret_store_spec.rb
CHANGED
@@ -36,18 +36,17 @@ describe SecretStore, "storing a secret" do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
context "when the key is already stored" do
|
39
|
-
it "raises
|
39
|
+
it "raises" do
|
40
40
|
subject.store("foobar", "fizzbuzz")
|
41
41
|
lambda {
|
42
42
|
subject.store("foobar", "fizzbuzz")
|
43
43
|
}.should raise_error
|
44
44
|
end
|
45
45
|
|
46
|
-
it "
|
46
|
+
it "can be overwritten with #store!" do
|
47
47
|
subject.store("foobar", "fizzbuzz")
|
48
|
-
|
49
|
-
|
50
|
-
}.should_not raise_error
|
48
|
+
subject.store!("foobar", "buzzfizz")
|
49
|
+
subject.get("foobar").should == "buzzfizz"
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
@@ -61,12 +60,6 @@ describe SecretStore, "getting a secret" do
|
|
61
60
|
subject.get("foobar").should == "fizzbuzz"
|
62
61
|
end
|
63
62
|
|
64
|
-
it "raises IndexError if the key is not found" do
|
65
|
-
lambda{
|
66
|
-
subject.get("not_found")
|
67
|
-
}.should raise_error(IndexError)
|
68
|
-
end
|
69
|
-
|
70
63
|
it "raises OpenSSL::Cipher::CipherError if the password for the store is wrong" do
|
71
64
|
subject.store("foobar", "fizzbuzz")
|
72
65
|
with_wrong_pass = SecretStore.new("wrong_pass", tmpfile.path)
|
@@ -74,6 +67,14 @@ describe SecretStore, "getting a secret" do
|
|
74
67
|
with_wrong_pass.get("foobar")
|
75
68
|
}.should raise_error(OpenSSL::Cipher::CipherError)
|
76
69
|
end
|
70
|
+
|
71
|
+
context "when called via #get!" do
|
72
|
+
it "raises IndexError if the key is not found" do
|
73
|
+
lambda{
|
74
|
+
subject.get!("not_found")
|
75
|
+
}.should raise_error(IndexError)
|
76
|
+
end
|
77
|
+
end
|
77
78
|
end
|
78
79
|
|
79
80
|
describe SecretStore, "changing the password" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: secret_store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-08-11 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gibberish
|
16
|
-
requirement: &
|
16
|
+
requirement: &2152744720 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2152744720
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &2152744200 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2152744200
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &2152743740 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2152743740
|
47
47
|
description: Store secrets for your app in a encrypted in a yaml file.
|
48
48
|
email:
|
49
49
|
- xternal1+github@gmail.com
|
@@ -74,7 +74,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
74
|
version: '0'
|
75
75
|
segments:
|
76
76
|
- 0
|
77
|
-
hash:
|
77
|
+
hash: 2805007848849734124
|
78
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
79
|
none: false
|
80
80
|
requirements:
|
@@ -83,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
83
|
version: '0'
|
84
84
|
segments:
|
85
85
|
- 0
|
86
|
-
hash:
|
86
|
+
hash: 2805007848849734124
|
87
87
|
requirements: []
|
88
88
|
rubyforge_project: secret_store
|
89
89
|
rubygems_version: 1.8.15
|