team-secrets 0.1.0

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.
@@ -0,0 +1,122 @@
1
+ require 'team-secrets/secret_manager'
2
+ require 'team-secrets/master_key'
3
+ require 'fileutils'
4
+
5
+ describe SecretManager do
6
+
7
+ context 'secret management' do
8
+ master_key = MasterKey.generate
9
+ secrets = SecretManager.new master_key
10
+
11
+ it 'can add a secret' do
12
+ # add(secret_name, secret, account = nil, category = nil, notes = nil)
13
+ secrets.add('SMTP_PASS', 'sMith_bArney!', 'mailer@example.com', [:PROD], 'Production SMTP password')
14
+ secrets.add('SMTP_PASS', 'jAmes_fRanke1', 'dev@example.com', [:DEV], 'Development SMTP password')
15
+ secrets.add('SMS_API_KEY', '843jds83jd82jd', nil, [:PROD, :DEV])
16
+ secrets.add('DEPLOY_KEY', '84dk84ujd83jeallmxcjrujdjjfjkhkjhakjshdfjk')
17
+
18
+ expect(secrets.data).to be_a(Array)
19
+ expect(secrets.data.size).to eq(4)
20
+ expect(secrets.data[0].keys).to eq([:name, :tags, :account, :secret, :notes, :added])
21
+ expect(secrets.data[0][:name]).to eq('SMTP_PASS')
22
+ expect(secrets.data[0][:secret]).to_not eq('sMith_bArney!')
23
+ end
24
+
25
+ it 'find a secret with data' do
26
+ # No tag
27
+ res = secrets.find('SMTP_PASS')
28
+ expect(res.length).to eq(2)
29
+
30
+ # With tags
31
+ res = secrets.find('SMTP_PASS', [:DEV], false)
32
+ expect(res.length).to eq(1)
33
+
34
+ expect(res[0][:name]).to eq('SMTP_PASS')
35
+ expect(res[0][:secret]).to_not eq('jAmes_fRanke1')
36
+ expect(res[0][:account]).to eq('dev@example.com')
37
+ expect(res[0][:tags]).to eq([:DEV])
38
+ expect(res[0][:notes]).to eq('Development SMTP password')
39
+ expect(res[0][:added]).to be
40
+ end
41
+
42
+ it 'can get a secret' do
43
+ # No tags
44
+ res = secrets.getSecret('SMTP_PASS')
45
+ expect(res.length).to eq(2)
46
+ expect(res).to include('jAmes_fRanke1')
47
+ expect(res).to include('sMith_bArney!')
48
+
49
+ # With tag
50
+ res = secrets.getSecret('SMTP_PASS', :DEV)
51
+ expect(res).to eq('jAmes_fRanke1')
52
+
53
+ # Can we get it twice?
54
+ res = secrets.getSecret('SMTP_PASS', [:DEV])
55
+ expect(res).to eq('jAmes_fRanke1')
56
+
57
+ # With the other tags
58
+ res = secrets.getSecret('SMTP_PASS', [:PROD])
59
+ expect(res).to eq('sMith_bArney!')
60
+
61
+ # With both tags, no matches
62
+ res = secrets.getSecret('SMTP_PASS', [:DEV, :PROD])
63
+ expect(res).to be_nil
64
+
65
+ # A longer string, matches both tags
66
+ res = secrets.getSecret('SMS_API_KEY', [:DEV, :PROD])
67
+ expect(res).to eq('843jds83jd82jd')
68
+
69
+ # No match, wrong tags
70
+ res = secrets.getSecret('SMS_API_KEY', [:DEV, :QA])
71
+ expect(res).to be_nil
72
+
73
+ # No category
74
+ res = secrets.getSecret('DEPLOY_KEY')
75
+ expect(res).to eq('84dk84ujd83jeallmxcjrujdjjfjkhkjhakjshdfjk')
76
+ end
77
+
78
+ it 'can return all secrets' do
79
+ res = secrets.getAll
80
+ expect(res.length).to eq(4)
81
+
82
+ res = secrets.getAll(:DEV)
83
+ expect(res.length).to eq(2)
84
+ end
85
+
86
+ it 'can remove a secret' do
87
+ res = secrets.getAll
88
+ expect(res.length).to eq(4)
89
+
90
+ # Remove nothing, tag doesn't match
91
+ secrets.remove('SMS_API_KEY', :NOPE)
92
+ res = secrets.getAll
93
+ expect(res.length).to eq(4)
94
+
95
+ secrets.remove('SMS_API_KEY', [:PROD, :DEV])
96
+ res = secrets.getAll
97
+ expect(res.length).to eq(3)
98
+
99
+ secrets.remove('SMTP_PASS')
100
+ res = secrets.getAll
101
+ expect(res.length).to eq(1)
102
+ end
103
+
104
+ it 'can rotate encryption keys' do
105
+ secrets.add('ROTATE_TEST_1', 'alskdfjalskjdf3984')
106
+ secrets.add('ROTATE_TEST_2', '2o341-llakdsjfjfdk')
107
+
108
+ secret_ref = []
109
+ for i in 0..2
110
+ secret_ref.push secrets.data[i][:secret]
111
+ end
112
+
113
+ secrets.rotateMasterKey(MasterKey.generate)
114
+
115
+ for i in 0..2
116
+ expect(secret_ref).not_to include(secrets.data[i][:secret])
117
+ end
118
+ end
119
+
120
+ end
121
+
122
+ end
@@ -0,0 +1,30 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ Proc-Type: 4,ENCRYPTED
3
+ DEK-Info: AES-128-CBC,976BA65B445F48E06F6486493B76E3ED
4
+
5
+ 6Y+inTC0bI9bPKYuz9+zZjyST5h/iAxApDSjIZzntp7j8oM6XxVb4DeLyG1L/Don
6
+ VMbjx3NCnsGNSTw51MrV9Kwhsq0CvtgIOW6CdP3oQT3D4wA8516r6qjNm6NF0ePz
7
+ /e7CxzFIOcX1TUbwBYc7/rTQg27Ll77tcoCSO3P6Pn1U/QSIHQO8U7LKNVPt5JFo
8
+ TUM7m50dWUuqgcQLqicfyZoG2EB3T0a/YsmDiBG49gepCjmiPAaTC8O0YqaeMREZ
9
+ UuxWHB22LuNc689FFrf4WNajw+DVgpGHdRRotILZcT6JftpHvHe+7I3TbRxglUsm
10
+ 30XHGnn+yQntHmQ0JFaMoZeBn3C0KGg0e213Nb35OHWkMO/NBRXQpYFAECCx26wz
11
+ GP71+oYe8xysatUC7t9eBaFhQuFU9vKCW5Vw0nkpwIaUAuWVExMtSiaV909BfQ/G
12
+ TZcwqeFi2U7TNGaGQN0Bky1bAIHDHPrmJ3DVs0Ql1TNRszIkyjiFUFBK27k3Yn4K
13
+ Xs4WUihzYuPgzh7pZ40vldhbVHMTSQtLRX9TptiRMEqtTXl6hVb701w+zDcE0sDQ
14
+ G2mNOihE12CRMLBo9TMWDyAeXxSNu4JRJnXMzLCIwCl6McE+0TW8nFf5wQ1gJ85Z
15
+ TCDXpVM9U3MQcpLoPsBoLBiJRGqi3dcuimjDNuZAoIbTk6yQ4c6frLUWG4+kfuCI
16
+ moK23uCdFVY3F6KrNFv4YnWlO5lSnWOFA21RKraGhvwIId+LK126cIDuwlL/TEI8
17
+ FviFBYCkwVsxv8EhcF/hllGIHfVi45ONjzECLLJGH7bplURaDB+tcXUtdJ6orUjI
18
+ k9ZONkIO8AlYJ0VMv2O/qjXKbNFOoch/LUC2J6DDcKKcNj8KX2Q803K+mcFOgzLz
19
+ FkWru6CBQVdSo3vR0gX47BBMJWWksEMuxLq7dh1KZ+LLZQtsjU3bAlYpl2gcEhTC
20
+ W0L+OE8J5C1ER/SniJ84hgF2kkTQjBHSHQOlrc+b/FbxgCMphdUekP1hTfr74CfV
21
+ Su13SFxnvNVxjyuHMRVI6iICsAbpicKAbakqqCzEChT5jaNDQpATevdhiAMZsJAO
22
+ 7YxozipZu6j8Uxgvwwv+hHKE0JHATJ223alBHPrFZLd8Kj0yGpx3b4yT8psfHZHb
23
+ ptEPosz9EcdF6zO4FH6dV6kX1JLBu+jwYQqrlgmk3KraYNlWpPKbB0/eQD9GLpds
24
+ JnqHD5lAunYyEQwmnm5S+sojT7nxM7WmOhwHxJNtFAZevMMJ7EPKwuaFhFq5B1qt
25
+ 2rZIERYWF4EYn3V2AGh37HAyJQGc2pQRacVdzwC9oiqo7wdu7TaqEks5+iKMspK7
26
+ lpFAnXfa0GFnJHHyCyC0qxuzU/kSaWxrTIzxirl8wABndoqZfWjh9f+eMVMrr6CR
27
+ IFll1vwPhqUe2SniRBPDfIsSVCLxtQnFXnJ3zxj2VQRODJP/FICItHqy5R2S2qTW
28
+ 9J7KGpaC3elDKcpuUULeoLwzqEu7Gl8sRq8zSzcP9QOuRo6a2iFeRMgtthSbL1xe
29
+ jiYehLZWZoh+TlHqe2ED8uR9inTFtddS85Z4i1eXoKBxHN7kP46ENtkC8jp+g80S
30
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1 @@
1
+ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKyRjeNjDigBgFdRl9BkAaWMuZZJ6hRm4UaDOdScZxeahgdpKh0YnceFF5CBTBcKfotfAHh13yKqCZNDOXQOAycZFF6NiRnqSHemIkPNtwUP27Cuh/emHsCyvElBr6Gh3Hlr0kcnPwe6xKfRG+kSoTFt8sqQ/ZiOCs6fguZXTEMpsWCEt6QyLKcSV8N/ow4TcJ39DhanIm+nm4wsGafvgAsuGTuzTus4EuOmQg3CxCsxxri2EcnqewLXyqzHiQUQneO9oLq6i1rmL0XiM0h9mmojqj4m1WPWGYGnz6oWRqm3P9ReyJhnLqmTCenoouCo5y/OO7Rc9Fm/brf8Wxn7Ib example@example.local
@@ -0,0 +1,8 @@
1
+ -----BEGIN RSA PUBLIC KEY-----
2
+ MIIBCgKCAQEAyskY3jYw4oAYBXUZfQZAGljLmWSeoUZuFGgznUnGcXmoYHaSodGJ
3
+ 3HhReQgUwXCn6LXwB4dd8iqgmTQzl0DgMnGRRejYkZ6kh3piJDzbcFD9uwrof3ph
4
+ 7AsrxJQa+hodx5a9JHJz8HusSn0RvpEqExbfLKkP2YjgrOn4LmV0xDKbFghLekMi
5
+ ynElfDf6MOE3Cd/Q4WpyJvp5uMLBmn74ALLhk7s07rOBLjpkINwsQrMca4thHJ6n
6
+ sC18qsx4kFEJ3jvaC6uota5i9F4jNIfZpqI6o+JtVj1hmBp8+qFkaptz/UXsiYZy
7
+ 6pkwnp6KLgqOcvzju0XPRZv263/FsZ+yGwIDAQAB
8
+ -----END RSA PUBLIC KEY-----
@@ -0,0 +1,67 @@
1
+ require 'team-secrets/user_manager'
2
+ require 'fileutils'
3
+
4
+ describe UserManager do
5
+
6
+ context 'user management' do
7
+ temp_folder = File.dirname(File.dirname(__FILE__)) +'/tmp'
8
+
9
+ before(:all) do
10
+ Dir.mkdir(temp_folder) unless File.exists?(temp_folder)
11
+ end
12
+
13
+ after(:all) do
14
+ FileUtils.rm_rf(temp_folder+'/users') if File.exists?(temp_folder+'/users')
15
+ end
16
+
17
+ it 'can add a user' do
18
+ users = UserManager.new
19
+
20
+ users.working_dir = temp_folder
21
+ users.user_dir = temp_folder+'/users'
22
+
23
+ users.add('new_guy', File.dirname(__FILE__) +'/support/test_key.pub.pem')
24
+ users.add('new_gal', File.dirname(__FILE__) +'/support/test_key.pub.pem')
25
+
26
+ expect(users.data).to be_a(Array)
27
+ expect(users.data.size).to eq(2)
28
+ expect(users.data[0].keys).to eq([:user, :public_key, :added, :lock_box, :sha256])
29
+ expect(users.all).to eq(['new_guy', 'new_gal'])
30
+ end
31
+
32
+ it 'can find a user' do
33
+ users = UserManager.new
34
+
35
+ users.working_dir = temp_folder
36
+ users.user_dir = temp_folder+'/users'
37
+
38
+ users.add('new_guy', File.dirname(__FILE__) +'/support/test_key.pub.pem')
39
+ users.add('new_gal', File.dirname(__FILE__) +'/support/test_key.pub.pem')
40
+
41
+ expect(users.find('fake_bud')).to be_nil
42
+ expect(users.find('new_guy')).to be
43
+ expect(users.find('new_gal')).to have_key(:public_key)
44
+ expect(users.find('new_gal')[:user]).to eq('new_gal')
45
+ end
46
+
47
+ it 'can remove a user' do
48
+ users = UserManager.new
49
+
50
+ users.working_dir = temp_folder
51
+ users.user_dir = temp_folder+'/users'
52
+
53
+ users.add('good_gal', File.dirname(__FILE__) +'/support/test_key.pub.pem')
54
+ users.add('bad_guy', File.dirname(__FILE__) +'/support/test_key.pub.pem')
55
+
56
+ expect(users.data).to be_a(Array)
57
+ expect(users.data.size).to eq(2)
58
+ expect(users.all).to eq(['good_gal', 'bad_guy'])
59
+
60
+ users.remove('bad_guy')
61
+
62
+ expect(users.data.size).to eq(1)
63
+ expect(users.all).to eq(['good_gal'])
64
+ end
65
+ end
66
+
67
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = 'team-secrets'
6
+ gem.version = '0.1.0'
7
+ gem.platform = Gem::Platform::RUBY
8
+ gem.authors = ['Eric Bigoness']
9
+ gem.email = ['design@firelit.com']
10
+ gem.homepage = 'https://github.com/firelit/secrets'
11
+
12
+ gem.summary = 'A utility for securely managing team secrets'
13
+ gem.description = 'Encyrpt and store team secrets, passwords and API keys in a repository with built-in user management'
14
+
15
+ gem.files = `git ls-files`.split("\n")
16
+ gem.test_files = `git ls-files -- {test,spec,features}/*.rb`.split("\n")
17
+ gem.require_paths = ["lib"]
18
+
19
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: team-secrets
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Eric Bigoness
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Encyrpt and store team secrets, passwords and API keys in a repository
14
+ with built-in user management
15
+ email:
16
+ - design@firelit.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".gitignore"
22
+ - ".rspec"
23
+ - ".travis.yml"
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - README.md
27
+ - Rakefile
28
+ - lib/team-secrets.rb
29
+ - lib/team-secrets/file_manager.rb
30
+ - lib/team-secrets/key_helper.rb
31
+ - lib/team-secrets/manifest_manager.rb
32
+ - lib/team-secrets/master_key.rb
33
+ - lib/team-secrets/secret_manager.rb
34
+ - lib/team-secrets/user_manager.rb
35
+ - spec/file_manager_spec.rb
36
+ - spec/manifest_manager_spec.rb
37
+ - spec/master_key_spec.rb
38
+ - spec/secret_manager_spec.rb
39
+ - spec/support/test_key
40
+ - spec/support/test_key.pub
41
+ - spec/support/test_key.pub.pem
42
+ - spec/user_manager_spec.rb
43
+ - team-secrets.gemspec
44
+ homepage: https://github.com/firelit/secrets
45
+ licenses: []
46
+ metadata: {}
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 2.6.8
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: A utility for securely managing team secrets
67
+ test_files:
68
+ - spec/file_manager_spec.rb
69
+ - spec/manifest_manager_spec.rb
70
+ - spec/master_key_spec.rb
71
+ - spec/secret_manager_spec.rb
72
+ - spec/user_manager_spec.rb