secure_data_bag 2.2.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,3 @@
1
-
2
1
  module SecureDataBag
3
- VERSION = "2.2.0"
2
+ VERSION = '3.0.0'.freeze
4
3
  end
5
-
@@ -4,23 +4,24 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'secure_data_bag/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "secure_data_bag"
7
+ spec.name = 'secure_data_bag'
8
8
  spec.version = SecureDataBag::VERSION
9
- spec.authors = ["Jonathan Serafini"]
10
- spec.email = ["jonathan@lightspeedretail.com"]
11
- spec.summary = "Per-field data bag item encryption"
12
- spec.description = "Provides a mechanism to partially encrypt data bag items and therefore ensure that they are searchable"
13
- spec.license = "MIT"
14
- spec.homepage =
15
- "https://github.com/JonathanSerafini/chef-secure_data_bag"
9
+ spec.authors = ['Jonathan Serafini']
10
+ spec.email = ['jonathan@lightspeedretail.com']
11
+ spec.summary = 'Mechanism to partially encryot data bag items'
12
+ spec.description = IO.read(File.join(File.dirname(__FILE__), 'README.md'))
13
+ spec.license = 'MIT'
14
+ spec.homepage =
15
+ 'https://github.com/JonathanSerafini/chef-secure_data_bag'
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
19
+ spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency "chef"
21
+ spec.add_dependency 'chef'
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.6"
24
- spec.add_development_dependency "rake"
25
- spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency 'bundler', '~> 1.6'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'cookstyle'
26
27
  end
@@ -4,14 +4,14 @@ require 'chef/data_bag_item'
4
4
  require 'chef/encrypted_data_bag_item'
5
5
 
6
6
  describe SecureDataBag::Item do
7
- let(:key) { "password" }
8
- let(:secret) { "data/secret.pem" }
9
- let(:fields) { ["encoded"] }
7
+ let(:key) { 'password' }
8
+ let(:secret) { 'data/secret.pem' }
9
+ let(:fields) { ['encoded'] }
10
10
 
11
- let(:simple_data) { { "id"=>"test", decoded:"decoded", encoded:"encoded" } }
12
- let(:nested_data) { simple_data.merge({ nested:simple_data }) }
11
+ let(:simple_data) { { 'id' => 'test', decoded: 'decoded', encoded: 'encoded' } }
12
+ let(:nested_data) { simple_data.merge(nested: simple_data) }
13
13
 
14
- let(:item) { SecureDataBag::Item.new(key:key, fields:fields) }
14
+ let(:item) { SecureDataBag::Item.new(key: key, fields: fields) }
15
15
 
16
16
  let(:dbag_item) do
17
17
  dbag_item = Chef::DataBagItem.new
@@ -31,29 +31,28 @@ describe SecureDataBag::Item do
31
31
  nested_item
32
32
  end
33
33
 
34
- it "encodes simple data" do
34
+ it 'encodes simple data' do
35
35
  dbag = simple_item
36
36
  data = dbag.encoded_data
37
- expect(data[:decoded]).to eq("decoded")
38
- expect(data[:encoded]).not_to eq("encoded")
37
+ expect(data[:decoded]).to eq('decoded')
38
+ expect(data[:encoded]).not_to eq('encoded')
39
39
  expect(data[:encoded][:encrypted_data]).not_to eq(nil)
40
40
  end
41
41
 
42
- it "encodes nested data" do
42
+ it 'encodes nested data' do
43
43
  dbag = nested_item
44
44
  data = dbag.encoded_data
45
- expect(data[:nested][:decoded]).to eq("decoded")
46
- expect(data[:nested][:encoded]).not_to eq("encoded")
45
+ expect(data[:nested][:decoded]).to eq('decoded')
46
+ expect(data[:nested][:encoded]).not_to eq('encoded')
47
47
  expect(data[:nested][:encoded][:encrypted_data]).not_to eq(nil)
48
48
  end
49
49
 
50
- it "decodes encrypted_data_bag_item" do
50
+ it 'decodes encrypted_data_bag_item' do
51
51
  edbag = Chef::EncryptedDataBagItem.encrypt_data_bag_item(dbag_item, key)
52
52
  dbag = item
53
53
  dbag.raw_data = edbag
54
54
  data = dbag.raw_data
55
- expect(data[:decoded]).to eq("decoded")
56
- expect(data[:encoded]).to eq("encoded")
55
+ expect(data[:decoded]).to eq('decoded')
56
+ expect(data[:encoded]).to eq('encoded')
57
57
  end
58
58
  end
59
-
@@ -14,4 +14,3 @@ RSpec.configure do |config|
14
14
  mocks.verify_partial_doubles = true
15
15
  end
16
16
  end
17
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: secure_data_bag
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Serafini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-26 00:00:00.000000000 Z
11
+ date: 2016-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -66,8 +66,103 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: Provides a mechanism to partially encrypt data bag items and therefore
70
- ensure that they are searchable
69
+ - !ruby/object:Gem::Dependency
70
+ name: cookstyle
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
+ description: "# SecureDataBag / Knife Secure Bag\n\nKnife Secure Bag provides a consistent
84
+ interface to DataBagItem, EncryptedDataBagItem as well as the custom created SecureDataBagItem
85
+ while also providing a few extra handy features to help in your DataBag workflows.
86
+ \n\nSecureDataBagItem, can not only manage your existing DataBagItems and EncryptedDataBagItems,
87
+ but it also provides you with a DataBag type which enables you to selectively encrypt
88
+ only some of the fields in your DataBag thus allowing you to be able to search for
89
+ the remaining fields. \n\n## Installation\n\nTo build and install the plugin add
90
+ it your Gemfile or run: \n\n```shell\ngem install secure_data_bag\n```\n\n## Configuration\n\n####
91
+ Knife Secure Bag\n\nDefaults for the Knife command may be provided in your _knife.rb_
92
+ file.\n\n```ruby\nknife[:secure_data_bag][:encrypted_keys] = %w(\n password\n ssh_keys\n
93
+ \ ssh_ids\n public_keys\n private_keys\n keys\n secret\n)\nknife[:secure_data_bag][:secret_file]
94
+ = \"#{local_dir}/secret.pem\"\nknife[:secure_data_bag][:export_root] = \"#{kitchen_dir}/data_bags\"\nknife[:secure_data_bag][:export_on_upload]
95
+ = true\nknife[:secure_data_bag][:defaults][:secrets][:export_format] = 'plain'\n```\n\nTo
96
+ break this up:\n\n`knife[:secure_data_bag][:encrypted_keys] = []`\n\nWhen Knife
97
+ Secure Bag encrypts a hash with an _encryption format_ of *nested*, it will recursively
98
+ walk through the hash from the bottom up and encrypt any key found within this array.\n\n`knife[:secure_data_bag][:secret_file]`\n\nWhen
99
+ encryption is required, the shared secret found at this location will be loaded.
100
+ \n\n`knife[:secure_data_bag][:export_root]`\n\nWhen exporting a data\\_bag\\_item,
101
+ files will be created in below this root directory. Typically this would be the
102
+ data\\_bag folder located within your kitchen.\n\n`knife[:secure_data_bag][:export_on_upload]`\n\nWhen
103
+ a data\\_bag\\_item is edited using `knife secure bag edit`, it may be automatically
104
+ exported to the _export\\_root_.\n\n`knife[:secure_data_bag][:defaults][:secrets][:export_format]`\n\nThe
105
+ configuration file additionally supports the _defaults_ hash which provides default
106
+ values for all _command line arguments_ that one might use. Of all of them only
107
+ the _export\\_format_ key is likely to be of much use.\n\n## Examples\n\n#### Chef
108
+ cookbook recipe\n\n```ruby\nmetadata = {}\n\n# Define the keys we wish to encrypt\nmetadata[:encrypted_keys]
109
+ = %w(encoded)\n\n# Optionally load a specific shared secret. Otherwise, the global
110
+ \n# encrypted\\_data\\_bag\\_secret will be automatically used.\nsecret_key = SecureDataBagItem.load_key(\"/path/to/secret\")\n\n#
111
+ Create a hash of data to use as an exampe\nraw_data = {\n\tid: \"item\", \n data_bag:
112
+ \"data_bag\",\n\tencoded: \"my string\", \n\tunencoded: \"other string\"\n}\n\n#
113
+ Instantiate a SecureDataBagItem from a hash\nitem = SecureDataBagItem.from_hash(data,
114
+ metadata)\n\n# Or more explicitely\nitem = SecureDataBagItem.from_hash(data, encrypted_keys:
115
+ %w(encoded))\n\n# Or load from server\nitem = SecureDataBagItem.load(\"data_bag\",
116
+ \"item\")\n\n# Print the un-encrypted raw data\npp item.raw_data\n\n# Print the
117
+ un-encrypted `encoded` key\npp item['encoded']\n\n# Print the encrypted hash as
118
+ a data_bag_item hash\npp item.to_hash\n\n=begin\n{ \n id: \"item\", \n
119
+ \ data_bag: \"data_bag\",\n encoded: {\n encrypted_data: \"encoded\",\n
120
+ \ cipher: aes-256-cbc,\n iv: 13453453dkgfefg==\n version: 1\n }\n unencoded:
121
+ \ \"other string\",\n}\n=end\n```\n\n## Usage\n\n#### Knife commands\n\nPrint an
122
+ DataBagItem, EncryptedDataBagItem or SecureDataBagItem, auto-detecting the encryption
123
+ method used as plain text.\n\n```shell\nknife secure bag show -F js secrets secret_item\n```\n\nPrint
124
+ an DataBagItem, EncryptedDataBagItem or SecureDataBagItem, auto-detecting the encryption
125
+ method used as a SecureDataBagItem in encrypted format.\n\n```shell\nknife secure
126
+ bag show -F js secrets secret_item --enc-format nested\n```\n\nEdit an EncryptedDataBagItem,
127
+ preserve it's encryption type, and export a copy to the _data\\_bag_ folder in your
128
+ kitchen.\n\n```shell\nknife secure bag edit secrets secret_item --export\n```\n\n##
129
+ Knife SubCommands\n\nMost of the SubCommands support the following command-line
130
+ options:\n\n`--enc-format [plain,encrypted,nested]`\n\nEnsure that, when displaying
131
+ or uploading the data\\_bag\\_item, we forcibly encrypt the data\\_bag\\_item using
132
+ the specified format instead of preserving the existing format. \n\nIn this case:
133
+ \n- plain: refers to a DataBagItem\n- encrypted: refers to an EnrytpedDataBagItem\n-
134
+ nested: refers to a SecureDataBagItem\n\n`--dec-format [plain,encrypted,nested]`\n\nAttempt
135
+ to decrypt the data\\_bag\\_item using the given format rather than the auto-detected
136
+ one. The only real reason to use this is when you wish to specifically select _plain_
137
+ as the format so as to not decrypt the item.\n\n`--enc-keys key1,key2,key3`\n\nProvide
138
+ a comma delimited list of hash keys which should be encrypted when encrypting the
139
+ data\\_bag\\_item. This list will be concatenated with any key names listed in the
140
+ configuration file or which were previously encrypted. \n\n`--export`\n\nExport
141
+ the data\\_bag\\_item to json file in either of _export-format_ or _enc-format_.\n\n`--export-format`\n\nOverrides
142
+ the encryption format only for the _export_ feature.\n\n`--export-root`\n\nRoot
143
+ directly under which a folder should exist for each _data_bag_ into which to export
144
+ _data_bag_items_ as json files.\n\nWhen displaying the content of the _data\\_bag\\_item_,
145
+ an additional key of *_secure_metadata* will be added to the output which contains
146
+ gem specific metadata such as the encryption formats and any encrypted keys found.
147
+ This key will _not_ be saved with the item, however it may be manipulated to alter
148
+ the behavior of the _edit_ or _export_ commands.\n\n#### knife secure bag show DATA_BAG
149
+ ITEM\n\nThis command functions just like `knife data bag show` and is used to print
150
+ out the content of either a DataBagItem, EncryptedDataBagItem or SecureDataBagItem.\n\nBy
151
+ default, it will auto-detect the Item type, and print it's unencrypted version to
152
+ the terminal. This behavior, however, may be altered using the previously mentioned
153
+ command line options.\n\n#### knife secure bag open PATH\n\nThis commands functions
154
+ much like `knife secure bag show`, however it is designed to load a _data\\_bag\\_item_
155
+ from disk as opposed to loading it from Chef server. This may be of use when view
156
+ the content of an exported encrypted file.\n\n#### knife secure bag edit DATA_BAG
157
+ DATA_BAG_ITEM\n\nThis command functions just like `knife data bag edit` and is used
158
+ to edit either a DataBagItem, EncryptedDataBagItem or a SecureDataBagItem. It supports
159
+ all of the same options as `knife secure bag show`. \n\n#### knife secure bag from
160
+ file DATA_BAG PATH\n\nThis command functions just like `knife data bag from file`
161
+ and is used to upload either a DataBagItem, EncryptedDataBagItem or a SecureDataBagItem.
162
+ It supports all of the same options as `knife secure bag show`. \n\n## Recipe DSL\n\nThe
163
+ gem additionally provides a few Recipe DSL methods which may be useful.\n\n```ruby\nload_secure_item
164
+ = secure_data_bag_item(\n data_bag_name, \n data_bag_item, \n cache: false\n)\n\nload_plain_item
165
+ = data_bag_item(data_bag_name, data_bag_item)\nconvert_plain_to_secure = secure_data_bag_item!(load_plain_item)\n```\n\n"
71
166
  email:
72
167
  - jonathan@lightspeedretail.com
73
168
  executables: []
@@ -76,18 +171,28 @@ extra_rdoc_files: []
76
171
  files:
77
172
  - ".gitignore"
78
173
  - ".rspec"
174
+ - CHANGELOG.md
79
175
  - Gemfile
80
176
  - LICENSE.txt
81
177
  - README.md
82
178
  - Rakefile
83
179
  - lib/chef/config.rb
84
180
  - lib/chef/dsl/data_query.rb
85
- - lib/chef/knife/secure_bag_base.rb
86
181
  - lib/chef/knife/secure_bag_edit.rb
87
182
  - lib/chef/knife/secure_bag_from_file.rb
183
+ - lib/chef/knife/secure_bag_open.rb
88
184
  - lib/chef/knife/secure_bag_show.rb
185
+ - lib/chef/knife/secure_data_bag/base_mixin.rb
186
+ - lib/chef/knife/secure_data_bag/defaults_mixin.rb
187
+ - lib/chef/knife/secure_data_bag/export_mixin.rb
188
+ - lib/chef/knife/secure_data_bag/secrets_mixin.rb
89
189
  - lib/secure_data_bag.rb
190
+ - lib/secure_data_bag/check_encrypted.rb
191
+ - lib/secure_data_bag/constants.rb
192
+ - lib/secure_data_bag/decryptor.rb
90
193
  - lib/secure_data_bag/dsl/data_query.rb
194
+ - lib/secure_data_bag/encryptor.rb
195
+ - lib/secure_data_bag/exceptions.rb
91
196
  - lib/secure_data_bag/item.rb
92
197
  - lib/secure_data_bag/version.rb
93
198
  - secure_data_bag.gemspec
@@ -113,10 +218,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
218
  version: '0'
114
219
  requirements: []
115
220
  rubyforge_project:
116
- rubygems_version: 2.4.5.1
221
+ rubygems_version: 2.2.3
117
222
  signing_key:
118
223
  specification_version: 4
119
- summary: Per-field data bag item encryption
224
+ summary: Mechanism to partially encryot data bag items
120
225
  test_files:
121
226
  - spec/item_spec.rb
122
227
  - spec/spec_helper.rb
@@ -1,74 +0,0 @@
1
-
2
- require 'chef/knife'
3
-
4
- class Chef
5
- class Knife
6
- module SecureBagBase
7
- def self.included(includer)
8
- includer.class_eval do
9
- deps do
10
- require 'secure_data_bag'
11
- end
12
-
13
- option :secret,
14
- short: "-s SECRET",
15
- long: "--secret",
16
- description: "The secret key to use to encrypt data bag item values"
17
-
18
- option :secret_file,
19
- long: "--secret-file SECRET_FILE",
20
- description: "A file containing a secret key to use to encrypt data bag item values"
21
-
22
- option :encoded_fields,
23
- long: "--encoded-fields FIELD1,FIELD2,FIELD3",
24
- description: "List of attribute keys for which to encode values",
25
- proc: Proc.new { |s| s.split(',') }
26
- end
27
- end
28
-
29
- def encoded_fields
30
- config[:encoded_fields] ||
31
- Chef::Config[:knife][:secure_data_bag][:fields]
32
- end
33
-
34
- def secret_file
35
- config[:secret_file] ||
36
- SecureDataBag::Item.secret_path
37
- end
38
-
39
- def secret
40
- @secret ||= read_secret
41
- end
42
-
43
- def use_encryption
44
- true
45
- end
46
-
47
- def read_secret
48
- if config[:secret] then config[:secret]
49
- else SecureDataBag::Item.load_secret(secret_file)
50
- end
51
- end
52
-
53
- def require_secret
54
- if not secret
55
- show_usage
56
- ui.fatal("A secret or secret_file must be specified")
57
- exit 1
58
- end
59
- end
60
-
61
- def data_for_create(hash={})
62
- hash[:id] = @data_bag_item_name
63
- hash
64
- end
65
-
66
- def data_for_save(hash)
67
- @encoded_fields = hash.delete(:_encoded_fields)
68
- hash
69
- end
70
-
71
- end
72
- end
73
- end
74
-