kms-tools 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module KmsTools
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,37 @@
1
+ RSpec.shared_context "aws mocks" do
2
+ before do
3
+ mock_kms = Aws::KMS::Client.new(stub_responses: true)
4
+
5
+ mock_kms.stub_responses(:list_aliases,
6
+ aliases:[
7
+ {alias_name: "alias/aws/ec2"},
8
+ {alias_name: "alias/aws/rds"},
9
+ {alias_name: "alias/test/test1"},
10
+ {alias_name: "alias/test/test2"}
11
+ ])
12
+
13
+ mock_kms.stub_responses(:describe_key,
14
+ key_metadata:{
15
+ aws_account_id: "123456789012",
16
+ key_id: "12345678-1234-1234-1234-123456789012",
17
+ arn: "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
18
+ })
19
+
20
+ mock_kms.stub_responses(:encrypt,
21
+ {ciphertext_blob: KmsTools::TestData.encrypted_string,
22
+ key_id: 'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012'
23
+ })
24
+
25
+ mock_kms.stub_responses(:decrypt,
26
+ {plaintext: "some super secret test data for testing",
27
+ key_id: 'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012'
28
+ })
29
+
30
+ mock_kms.stub_responses(:generate_data_key,
31
+ {ciphertext_blob: '\n \xF5\xA5\xB4\x96\x98?{=y\x92\"-\xE1~\x13\x9EA\xF6*\x8C\x94\xE5\t',
32
+ key_id: 'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012'
33
+ })
34
+
35
+ allow(Aws::KMS::Client).to receive(:new).and_return(mock_kms)
36
+ end
37
+ end
@@ -0,0 +1,83 @@
1
+ require "spec_helper"
2
+ require "kms-tools"
3
+ require "kms-tools/test_data"
4
+
5
+ module KmsTools
6
+ describe "With mocked AWS response" do
7
+ include_context "aws mocks"
8
+
9
+ describe Base do
10
+ subject(:base_without_params) { Base.new }
11
+ subject(:base_with_params) { Base.new({:region => 'us-west-1', :master_key => "alias/test/test1", :profile => 'test'}) }
12
+ context "#available_aliases" do
13
+ it "should return all custom key aliases" do
14
+ expect(base_without_params.available_aliases).to include("alias/test/test1", "alias/test/test2")
15
+ end
16
+ it "should filter out built-in AWS key aliases" do
17
+ expect(base_without_params.available_aliases).not_to include("alias/aws/ec2", "alias/aws/rds")
18
+ end
19
+ end
20
+
21
+ context " #use_key_alias=" do
22
+ it "should not allow assignment of a key that's not available" do
23
+ expect{ base_without_params.use_key_alias = "alias/not/allowed" }.to raise_error(RuntimeError, "Requested key alias not available with current credentials!")
24
+ end
25
+ it "should set the master_key for the object when a valid alias is provided" do
26
+ base_without_params.use_key_alias = "alias/test/test1"
27
+ expect(base_without_params.master_key).to eql("alias/test/test1")
28
+ end
29
+ end
30
+
31
+ context "#master_key" do
32
+ it "should return nil when no key has been set" do
33
+ expect(base_without_params.master_key).to eql(nil)
34
+ end
35
+ it "should return the current key after being explicitly set" do
36
+ base_without_params.use_key_alias = "alias/test/test1"
37
+ expect(base_without_params.master_key).to eql("alias/test/test1")
38
+ end
39
+ it "should return the current key without being set if present at initialize" do
40
+ expect(base_with_params.master_key).to eql("alias/test/test1")
41
+ end
42
+ end
43
+
44
+ context "#master_key_arn" do
45
+ it "should return nil when no key has been set" do
46
+ expect(base_without_params.master_key_arn).to eql(nil)
47
+ end
48
+ it "should return the ARN of the current master_key after master key is explicitly set" do
49
+ base_without_params.use_key_alias = "alias/test/test1"
50
+ expect(base_without_params.master_key_arn).to eql("arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012")
51
+ end
52
+ it "should return the ARN of the current master_key without master_key being set if present at initialize" do
53
+ expect(base_with_params.master_key_arn).to eql("arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012")
54
+ end
55
+ end
56
+
57
+ context "#master_key_id" do
58
+ it "should return nil when no key has been set" do
59
+ expect(base_without_params.master_key_id).to eql(nil)
60
+ end
61
+ it "should return the ID of the current master_key when a master key is set" do
62
+ base_without_params.use_key_alias = "alias/test/test1"
63
+ expect(base_without_params.master_key_id).to eql("12345678-1234-1234-1234-123456789012")
64
+ end
65
+ it "should return the ID of the current master_key without master_key being set if present at initialize" do
66
+ expect(base_with_params.master_key_id).to eql("12345678-1234-1234-1234-123456789012")
67
+ end
68
+ end
69
+
70
+ context "#region" do
71
+ it "should return the default region when no other region is set" do
72
+ expect(base_without_params.region).to eq(KmsTools::Base::DEFAULT_REGION)
73
+ end
74
+ it "should return the region set in the options if present at initialize" do
75
+ expect(base_with_params.region).to eq('us-west-1')
76
+ end
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+
83
+
@@ -0,0 +1,95 @@
1
+ require "spec_helper"
2
+ require "kms-tools"
3
+ require "kms-tools/test_data"
4
+
5
+ module KmsTools
6
+ describe "With mocked AWS response" do
7
+ include_context "aws mocks"
8
+
9
+ describe Decrypter do
10
+ subject(:dec) { Decrypter.new }
11
+ context "#decrypt_string" do
12
+ it "should return an plaintext string when called with a base64 encoded string" do
13
+ expect(dec.decrypt_string("base64encodedciphertext")).to eql("some super secret test data for testing")
14
+ end
15
+ it "should fail when called with a non-string" do
16
+ expect{ dec.decrypt_string(Object.new) }.to raise_error(NoMethodError)
17
+ expect{ dec.decrypt_string([1,2,3]) }.to raise_error(NoMethodError)
18
+ expect{ dec.decrypt_string(something: "wrong", something_else: "wrong") }.to raise_error(NoMethodError)
19
+ end
20
+ end
21
+
22
+ context "#decrypt_with_data_key" do
23
+ it "should properly decrypt data when all required params are present" do
24
+ decrypted_test = dec.decrypt_with_data_key({
25
+ cipher: KmsTools::EncryptedFile::DEFAULT_CIPHER,
26
+ encrypted_key: "Encrypted Key",
27
+ encrypted_iv: "Encrypted IV",
28
+ encrypted_data: KmsTools::TestData.encrypted_local_data,
29
+ checksum: "0028efdfd0b942ab64bb0ab40d49ec62c6a0d83f"
30
+ })
31
+ expect(decrypted_test).to eql(KmsTools::TestData.plaintext_local_data)
32
+ end
33
+ it "should fail to decrypt when checksum verification fails" do
34
+ expect{ dec.decrypt_with_data_key({
35
+ cipher: KmsTools::EncryptedFile::DEFAULT_CIPHER,
36
+ encrypted_key: "Encrypted Key",
37
+ encrypted_iv: "Encrypted IV",
38
+ encrypted_data: KmsTools::TestData.encrypted_local_data,
39
+ checksum: "badchecksum"
40
+ }) }.to raise_error(RuntimeError, "File integrity check failed!")
41
+ end
42
+ end
43
+
44
+ context "#stream_encrypt_with_data_key" do
45
+ before do
46
+ require 'stringio'
47
+ allow(File).to receive(:open).with('some/in/file', 'rb').and_return(StringIO.new KmsTools::TestData.encrypted_local_data, "r")
48
+ allow(File).to receive(:open).with('some/padded/in/file', 'rb').and_return(StringIO.new "0000" + KmsTools::TestData.encrypted_local_data, "r")
49
+ allow(File).to receive(:open).with('some/out/file', 'wb+').and_return(StringIO.new)
50
+ end
51
+ it "should properly decrypt streaming data when all required params are present" do
52
+ infile = File.open('some/in/file', 'rb')
53
+ outfile = File.open('some/out/file', 'wb+')
54
+ dec.stream_decrypt_with_data_key({
55
+ in: infile,
56
+ out: outfile,
57
+ cipher: KmsTools::EncryptedFile::DEFAULT_CIPHER,
58
+ encrypted_key: "Encrypted Key",
59
+ encrypted_iv: "Encrypted IV",
60
+ checksum: "0028efdfd0b942ab64bb0ab40d49ec62c6a0d83f"
61
+ })
62
+ expect(outfile.string).to eql(KmsTools::TestData.plaintext_local_data)
63
+ end
64
+ it "should fail to decrypt when checksum verification fails" do
65
+ infile = File.open('some/in/file', 'rb')
66
+ outfile = File.open('some/out/file', 'wb+')
67
+ expect{ dec.stream_decrypt_with_data_key({in: infile,
68
+ out: outfile,
69
+ cipher: KmsTools::EncryptedFile::DEFAULT_CIPHER,
70
+ encrypted_key: "Encrypted Key",
71
+ encrypted_iv: "Encrypted IV",
72
+ checksum: "badchecksum"
73
+ }) }.to raise_error(RuntimeError, "Decrypted data stream failed checksum verification!")
74
+ end
75
+ it "should properly decrypt streaming data when given a padded stream and a seek position is provided" do
76
+ infile = File.open('some/padded/in/file', 'rb')
77
+ outfile = File.open('some/out/file', 'wb+')
78
+ dec.stream_decrypt_with_data_key({
79
+ in: infile,
80
+ out: outfile,
81
+ position: 4,
82
+ cipher: KmsTools::EncryptedFile::DEFAULT_CIPHER,
83
+ encrypted_key: "Encrypted Key",
84
+ encrypted_iv: "Encrypted IV",
85
+ checksum: "0028efdfd0b942ab64bb0ab40d49ec62c6a0d83f"
86
+ })
87
+ expect(outfile.string).to eql(KmsTools::TestData.plaintext_local_data)
88
+ end
89
+ end
90
+
91
+ end
92
+ end
93
+ end
94
+
95
+
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+ require "kms-tools"
3
+
4
+ module KmsTools
5
+ describe "With mocked AWS response" do
6
+ include_context "aws mocks"
7
+
8
+ before do
9
+
10
+ end
11
+
12
+ end
13
+ end
14
+
@@ -0,0 +1,91 @@
1
+ require "spec_helper"
2
+ require "kms-tools"
3
+ require "kms-tools/test_data"
4
+
5
+ module KmsTools
6
+ describe "With mocked AWS response" do
7
+ include_context "aws mocks"
8
+
9
+ describe Encrypter do
10
+ subject(:enc) { Encrypter.new }
11
+ context "#encrypt_string" do
12
+ it "should fail if called before a key has been set" do
13
+ expect{ enc.encrypt_string("something") }.to raise_error(ArgumentError)
14
+ end
15
+ it "should return a base64 encoded encrypted string when called after a key has been set" do
16
+ enc.use_key_alias = "alias/test/test1"
17
+ expect(enc.encrypt_string("some test data")).to eql(Base64.strict_encode64(KmsTools::TestData.encrypted_string))
18
+ end
19
+ end
20
+
21
+ context "#kms_encrypt" do
22
+ it "should fail if called before a key has been set" do
23
+ expect{ enc.kms_encrypt("something") }.to raise_error(ArgumentError)
24
+ end
25
+ it "should return an Aws::KMS::Types::EncryptResponse when called after a key has been set" do
26
+ enc.use_key_alias = "alias/test/test1"
27
+ expect(enc.kms_encrypt("something").ciphertext_blob).to be_a(String)
28
+ expect(enc.kms_encrypt("something").key_id).to be_a(String)
29
+ end
30
+ end
31
+
32
+ context "#encrypt_with_data_key" do
33
+ it "should properly encrypt data when all required params are present" do
34
+ encrypted_test = enc.encrypt_with_data_key({
35
+ :cipher => KmsTools::EncryptedFile::DEFAULT_CIPHER,
36
+ :encrypted_key => "Encrypted Key",
37
+ :encrypted_iv => "Encrypted IV",
38
+ :data => KmsTools::TestData.plaintext_local_data
39
+ })
40
+ expect(encrypted_test).to eql(KmsTools::TestData.encrypted_local_data)
41
+ end
42
+ end
43
+
44
+ context "#stream_encrypt_with_data_key" do
45
+ before do
46
+ require 'stringio'
47
+ allow(File).to receive(:open).with('some/in/file', 'rb').and_return(StringIO.new KmsTools::TestData.plaintext_local_data, "r")
48
+ allow(File).to receive(:open).with('some/out/file', 'wb+').and_return(StringIO.new)
49
+ end
50
+ it "should properly encrypt streaming data when all required params are present" do
51
+ infile = File.open('some/in/file', 'rb')
52
+ outfile = File.open('some/out/file', 'wb+')
53
+ enc.stream_encrypt_with_data_key({
54
+ :in => infile,
55
+ :out => outfile,
56
+ :cipher => KmsTools::EncryptedFile::DEFAULT_CIPHER,
57
+ :encrypted_key => "Encrypted Key",
58
+ :encrypted_iv => "Encrypted IV",
59
+ })
60
+ # The raw binary can actually be different for this and still be valid so we have to compare Base64, sigh
61
+ expect(Base64.strict_encode64(outfile.string)).to eql(Base64.strict_encode64(KmsTools::TestData.encrypted_local_data))
62
+ end
63
+ end
64
+
65
+ context "#new_key" do
66
+ it "should fail if called before a key has been set" do
67
+ expect{ enc.new_key }.to raise_error(ArgumentError)
68
+ end
69
+ it "should return an Aws::KMS::Types::GenerateDataKeyResponse when called after a key has been set" do
70
+ enc.use_key_alias = "alias/test/test1"
71
+ expect(enc.new_key.ciphertext_blob).to be_a(String)
72
+ expect(enc.new_key.key_id).to be_a(String)
73
+ end
74
+ end
75
+
76
+ context "#new_encrypted_key" do
77
+ it "should fail if called before a key has been set" do
78
+ expect{ enc.new_encrypted_key }.to raise_error(ArgumentError)
79
+ end
80
+ it "should return a base64 encoded encrypted data key string" do
81
+ enc.use_key_alias = "alias/test/test1"
82
+ expect(enc.new_encrypted_key).to be_a(String)
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+ end
89
+ end
90
+
91
+
@@ -0,0 +1,11 @@
1
+ require 'base64'
2
+ require 'ostruct'
3
+
4
+ module KmsTools
5
+ TestData = OpenStruct.new(
6
+ :plaintext_string => "some super secret test data for testing",
7
+ :encrypted_string => Base64.decode64("CiD1pbSWmD97PXmSIi3hfhOeQfYqjJTlCY0K73RygjvymxKVAQEBAgB49aW0lpg/ez15kiIt4X4TnkH2KoyU5QmNCu90coI78psAAABsMGoGCSqGSIb3DQEHBqBdMFsCAQAwVgYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAzCOoe4Fw9k62RTPfUCARCAKczfxQvZLoSYcTLgubrWTc9JPXy972PusseX0D1G1apF4HH1fWeRDhwW"),
8
+ :plaintext_local_data => "some super secret test data to locally encrypt",
9
+ :encrypted_local_data => Base64.decode64("9nqpUQ63ALqOOAD8/HdVhg5z0dT+m4fDkEu93LDk3G5Vzuc73FVxtvZulxkQuENJ"),
10
+ )
11
+ end
@@ -0,0 +1,26 @@
1
+ RSpec.configure do |config|
2
+ config.expect_with :rspec do |expectations|
3
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
4
+ end
5
+
6
+ config.mock_with :rspec do |mocks|
7
+ mocks.verify_partial_doubles = true
8
+ end
9
+
10
+ config.filter_run :focus
11
+ config.run_all_when_everything_filtered = true
12
+ config.example_status_persistence_file_path = "spec/examples.txt"
13
+ config.disable_monkey_patching!
14
+ #config.profile_examples = 10
15
+ config.order = :random
16
+ Kernel.srand config.seed
17
+ config.expose_dsl_globally = true
18
+ if config.files_to_run.one?
19
+ config.default_formatter = 'doc'
20
+ end
21
+
22
+ #load mocked AWS responses since this whole gem relies on AWS
23
+ require File.dirname(__FILE__) + '/kms-tools/aws_mocks.rb'
24
+
25
+ end
26
+
metadata ADDED
@@ -0,0 +1,202 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kms-tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Matt Krieger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: highline
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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: hashdiff
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
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: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
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: rspec-core
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-expectations
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec-mocks
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: gli
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 2.13.4
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 2.13.4
139
+ description:
140
+ email: matt.krieger@sportngin.com
141
+ executables:
142
+ - kms-tools
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".gitignore"
147
+ - ".octopolo.yml"
148
+ - ".soyuz.yml"
149
+ - ".travis.yml"
150
+ - CHANGELOG.markdown
151
+ - Gemfile
152
+ - README.md
153
+ - Rakefile
154
+ - bin/kms-tools
155
+ - kms-tools.gemspec
156
+ - lib/kms-cli.rb
157
+ - lib/kms-tools.rb
158
+ - lib/kms-tools/base.rb
159
+ - lib/kms-tools/cli/commands/decrypt.rb
160
+ - lib/kms-tools/cli/commands/encrypt.rb
161
+ - lib/kms-tools/cli/commands/list_aliases.rb
162
+ - lib/kms-tools/cli/decrypt.rb
163
+ - lib/kms-tools/cli/encrypt.rb
164
+ - lib/kms-tools/cli/helpers.rb
165
+ - lib/kms-tools/cli/output.rb
166
+ - lib/kms-tools/decrypter.rb
167
+ - lib/kms-tools/encrypted_file.rb
168
+ - lib/kms-tools/encrypter.rb
169
+ - lib/kms-tools/version.rb
170
+ - spec/kms-tools/aws_mocks.rb
171
+ - spec/kms-tools/base_spec.rb
172
+ - spec/kms-tools/decrypter_spec.rb
173
+ - spec/kms-tools/encrypted_file_spec.rb
174
+ - spec/kms-tools/encrypter_spec.rb
175
+ - spec/kms-tools/test_data.rb
176
+ - spec/spec_helper.rb
177
+ homepage: http://www.sportngin.com
178
+ licenses: []
179
+ metadata: {}
180
+ post_install_message:
181
+ rdoc_options: []
182
+ require_paths:
183
+ - lib
184
+ - lib
185
+ required_ruby_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ required_rubygems_version: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ requirements: []
196
+ rubyforge_project:
197
+ rubygems_version: 2.4.8
198
+ signing_key:
199
+ specification_version: 4
200
+ summary: CLI for encrypting and decrypting data using Amazon KMS
201
+ test_files: []
202
+ has_rdoc: yard