chef-vault 3.4.2 → 4.0.11

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae942cd10e48bec9d688f5c91e12853ebd257a2664768444d3f9f472e391dcc3
4
- data.tar.gz: 04dc8c57516c24949b014cbb7e2e259dea2f9e7458505bccb87b6ab0698db1f4
3
+ metadata.gz: a31b1dc1d2889fdab403f6f55a662c744529586f116d4d3f87196595fedc245c
4
+ data.tar.gz: '079f1cabc8c809b0a98b30b0e19181e88ea205317387ec1eef8a396c43476d56'
5
5
  SHA512:
6
- metadata.gz: 6dad5ce4503b40fe2866c9c89d34ab45e56c8cbbac9bc98a4a2716584b1898277e4d2b177ff133b4959b7fee722d9a6b22fcd318c39d0703eb54bd657fa0f637
7
- data.tar.gz: 18706d51d76afd1929e09a79a618b9a174604b37b22e778bed552620061f8826919d239ecf47a63b03ef729495b558fc0002640dac19e37d8d74c2cbd4d3c4b3
6
+ metadata.gz: 50b6f9f0261bfd2f98aecdb0f84ec2c7b9aa775d31982ab2985a758cf423bf2af128e10f69de353129d3e74ce92d5f0579fafcdb3764abd6344a5de7b1e8ac84
7
+ data.tar.gz: b6a488022c267e9c9709ec16ac835b45a833a11445c20af6b833f50e2d650bc5f6d9949baabce01f3502168b16c7ad1b676856d683e63914122e3a380a18fe99
data/Gemfile CHANGED
@@ -1,14 +1,25 @@
1
- source "https://rubygems.org/"
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
5
  group :development do
6
- gem "chefstyle", git: "https://github.com/chef/chefstyle.git"
6
+ gem "chefstyle"
7
7
  gem "chef-zero"
8
8
  gem "rake"
9
9
  gem "rspec", "~> 3.4"
10
10
  gem "aruba", "~> 0.6"
11
- gem "simplecov", "~> 0.9"
12
- gem "simplecov-console", "~> 0.2"
13
- gem "chef"
11
+ gem "chef", "~> 14.0" # avoids test failures on license acceptance
12
+ end
13
+
14
+ group :docs do
15
+ gem "yard"
16
+ gem "redcarpet"
17
+ gem "github-markup"
18
+ end
19
+
20
+ group :debug do
21
+ gem "pry"
22
+ gem "pry-byebug"
23
+ gem "pry-stack_explorer", "~> 0.4.0" # pin until we drop ruby < 2.6
24
+ gem "rb-readline"
14
25
  end
@@ -18,7 +18,7 @@
18
18
  # See the License for the specific language governing permissions and
19
19
  # limitations under the License.
20
20
 
21
- require "optparse"
21
+ require "optparse" unless defined?(OptionParser)
22
22
 
23
23
  options_config = {
24
24
  chef: {
@@ -82,7 +82,7 @@ options_config.each do |option, config|
82
82
  options[option] = options[option] ? options[option] : config[:default]
83
83
  end
84
84
 
85
- require "rubygems"
85
+ require "rubygems" unless defined?(Gem)
86
86
  $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
87
87
  require "chef-vault"
88
88
 
@@ -1,6 +1,6 @@
1
- # -*- encoding: utf-8 -*-
2
1
  # Chef-Vault Gemspec file
3
- # Copyright 2013-15, Nordstrom, Inc.
2
+ # Copyright 2013-2015, Nordstrom, Inc.
3
+ # Copyright 2017-2019, Chef Software, Inc.
4
4
 
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
6
6
  # you may not use this file except in compliance with the License.
@@ -17,24 +17,19 @@
17
17
  $:.push File.expand_path("../lib", __FILE__)
18
18
  require "chef-vault/version"
19
19
 
20
- def self.prerelease?
21
- !ENV["TRAVIS_TAG"] || ENV["TRAVIS_TAG"].empty?
22
- end
23
-
24
20
  Gem::Specification.new do |s|
25
21
  s.name = "chef-vault"
26
22
  s.version = ChefVault::VERSION
27
- s.version = "#{s.version}-pre#{ENV['TRAVIS_BUILD_NUMBER']}" if ENV["TRAVIS"]
28
23
  s.authors = ["Thom May"]
29
24
  s.email = ["thom@chef.io"]
30
- s.summary = "Data encryption support for Chef using data bags"
25
+ s.summary = "Data encryption support for Chef Infra using data bags"
31
26
  s.description = s.summary
32
27
  s.homepage = "https://github.com/chef/chef-vault"
33
28
  s.license = "Apache-2.0"
34
- s.files = %w{LICENSE README.md Gemfile} + Dir.glob("*.gemspec") + `git ls-files`.split("\n").select { |f| f =~ %r{^(?:bin/|lib/)}i }
29
+ s.files = %w{LICENSE Gemfile} + Dir.glob("*.gemspec") + `git ls-files`.split("\n").select { |f| f =~ %r{^(?:bin/|lib/)}i }
35
30
  s.require_paths = ["lib"]
36
31
  s.bindir = "bin"
37
32
  s.executables = %w{ chef-vault }
38
33
 
39
- s.required_ruby_version = ">= 2.2.0"
34
+ s.required_ruby_version = ">= 2.4"
40
35
  end
@@ -23,14 +23,14 @@ require "chef/api_client"
23
23
  require "chef/data_bag_item"
24
24
  require "chef/encrypted_data_bag_item"
25
25
  require "chef/user"
26
- require "chef-vault/version"
27
- require "chef-vault/exceptions"
28
- require "chef-vault/item"
29
- require "chef-vault/item_keys"
30
- require "chef-vault/user"
31
- require "chef-vault/certificate"
32
- require "chef-vault/chef_api"
33
- require "chef-vault/actor"
26
+ require_relative "chef-vault/version"
27
+ require_relative "chef-vault/exceptions"
28
+ require_relative "chef-vault/item"
29
+ require_relative "chef-vault/item_keys"
30
+ require_relative "chef-vault/user"
31
+ require_relative "chef-vault/certificate"
32
+ require_relative "chef-vault/chef_api"
33
+ require_relative "chef-vault/actor"
34
34
 
35
35
  require "mixlib/log"
36
36
 
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require "json"
17
+ require "json" unless defined?(JSON)
18
18
 
19
19
  class ChefVault
20
20
  class Actor
@@ -27,6 +27,7 @@ class ChefVault
27
27
  if actor_type != "clients" && actor_type != "admins"
28
28
  raise "You must pass either 'clients' or 'admins' as the first argument to ChefVault::Actor.new."
29
29
  end
30
+
30
31
  @type = actor_type
31
32
  @name = actor_name
32
33
  end
@@ -52,7 +53,7 @@ class ChefVault
52
53
  case http_error.response.code
53
54
  when "404"
54
55
  raise ChefVault::Exceptions::AdminNotFound,
55
- "FATAL: Could not find default key for #{name} in users or clients!"
56
+ "FATAL: Could not find default key for #{name} in users or clients!"
56
57
  when "403"
57
58
  print_forbidden_error
58
59
  raise http_error
@@ -73,7 +74,7 @@ class ChefVault
73
74
  raise http_error
74
75
  elsif http_error.response.code.eql?("404")
75
76
  raise ChefVault::Exceptions::ClientNotFound,
76
- "#{name} is not a valid chef client and/or node"
77
+ "#{name} is not a valid chef client and/or node"
77
78
  else
78
79
  raise http_error
79
80
  end
@@ -115,6 +116,7 @@ class ChefVault
115
116
  # If the keys endpoint doesn't exist, try getting it directly from the V0 chef object.
116
117
  rescue Net::HTTPServerException => http_error
117
118
  raise http_error unless http_error.response.code.eql?("404")
119
+
118
120
  if request_actor_type.eql?("clients")
119
121
  chef_api_client.load(name).public_key
120
122
  else
@@ -15,8 +15,8 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- require "securerandom"
19
- require "chef-vault/mixins"
18
+ require "securerandom" unless defined?(SecureRandom)
19
+ require_relative "mixins"
20
20
 
21
21
  class ChefVault
22
22
  class Item < Chef::DataBagItem
@@ -131,6 +131,10 @@ class ChefVault
131
131
  end
132
132
  end
133
133
 
134
+ def mode(mode)
135
+ keys.mode(mode) if mode
136
+ end
137
+
134
138
  def admins(admin_string, action = :add)
135
139
  admin_string.split(",").each do |admin|
136
140
  admin.strip!
@@ -142,7 +146,7 @@ class ChefVault
142
146
  keys.delete(admin_key)
143
147
  else
144
148
  raise ChefVault::Exceptions::KeysActionNotValid,
145
- "#{action} is not a valid action"
149
+ "#{action} is not a valid action"
146
150
  end
147
151
  end
148
152
  end
@@ -157,7 +161,7 @@ class ChefVault
157
161
 
158
162
  def secret
159
163
  if @keys.include?(@node_name) && !@keys[@node_name].nil?
160
- private_key = OpenSSL::PKey::RSA.new(File.open(@client_key_path).read())
164
+ private_key = OpenSSL::PKey::RSA.new(File.open(@client_key_path).read)
161
165
  begin
162
166
  private_key.private_decrypt(Base64.decode64(@keys[@node_name]))
163
167
  rescue OpenSSL::PKey::RSAError
@@ -268,7 +272,7 @@ class ChefVault
268
272
 
269
273
  if Chef::Config[:solo_legacy_mode]
270
274
  data_bag_path = File.join(Chef::Config[:data_bag_path],
271
- data_bag)
275
+ data_bag)
272
276
  data_bag_item_path = File.join(data_bag_path, @raw_data["id"])
273
277
 
274
278
  FileUtils.rm("#{data_bag_item_path}.json")
@@ -336,7 +340,16 @@ class ChefVault
336
340
  def self.data_bag_item_type(vault, name)
337
341
  # adapted from https://github.com/opscode-cookbooks/chef-vault/blob/v1.3.0/libraries/chef_vault_item.rb
338
342
  # and https://github.com/sensu/sensu-chef/blob/2.9.0/libraries/sensu_helpers.rb
339
- dbi = Chef::DataBagItem.load(vault, name)
343
+ begin
344
+ dbi = Chef::DataBagItem.load(vault, name)
345
+ rescue Net::HTTPServerException => http_error
346
+ if http_error.response.code == "404"
347
+ raise ChefVault::Exceptions::ItemNotFound,
348
+ "#{vault}/#{name} not found"
349
+ else
350
+ raise http_error
351
+ end
352
+ end
340
353
  encrypted = dbi.detect do |_, v|
341
354
  v.is_a?(Hash) && v.key?("encrypted_data")
342
355
  end
@@ -358,12 +371,12 @@ class ChefVault
358
371
  # no longer be found
359
372
  # @return [void]
360
373
  def refresh(clean_unknown_clients = false)
361
- unless search
374
+ if search.empty?
362
375
  raise ChefVault::Exceptions::SearchNotFound,
363
- "#{vault}/#{item} does not have a stored search_query, "\
364
- "probably because it was created with an older version "\
365
- "of chef-vault. Use 'knife vault update' to update the "\
366
- "databag with the search query."
376
+ "#{@data_bag}/#{@raw_data["id"]} does not have a stored "\
377
+ "search_query, probably because it was created with an "\
378
+ "older version of chef-vault. Use 'knife vault update' "\
379
+ "to update the databag with the search query."
367
380
  end
368
381
 
369
382
  # a bit of a misnomer; this doesn't remove unknown
@@ -434,11 +447,12 @@ class ChefVault
434
447
  true
435
448
  rescue Net::HTTPServerException => http_error
436
449
  return false if http_error.response.code == "404"
450
+
437
451
  raise http_error
438
452
  end
439
453
 
440
454
  # adds or deletes an API client from the vault item keys
441
- # @param client [Chef::ApiClient] the API client to operate on
455
+ # @param api_client [Chef::ApiClient] the API client to operate on
442
456
  # @param action [Symbol] :add or :delete
443
457
  # @return [void]
444
458
  def handle_client_action(api_client, action)
@@ -460,7 +474,7 @@ class ChefVault
460
474
  end
461
475
 
462
476
  # removes a client to the vault item keys
463
- # @param client_or_node [String] the name of the API client or node to remove
477
+ # @param name [String] the name of the API client or node to remove
464
478
  # @return [void]
465
479
  def delete_client_or_node(name)
466
480
  client = load_actor(name, "clients")
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require "chef-vault/mixins"
17
+ require_relative "mixins"
18
18
 
19
19
  class ChefVault
20
20
  class ItemKeys < Chef::DataBagItem
@@ -39,9 +39,11 @@ class ChefVault
39
39
  def [](key)
40
40
  # return options immediately
41
41
  return @raw_data[key] if %w{id admins clients search_query mode}.include?(key)
42
+
42
43
  # check if the key is in the write-back cache
43
44
  ckey = @cache[key]
44
45
  return ckey unless ckey.nil?
46
+
45
47
  # check if the key is saved in sparse mode
46
48
  skey = sparse_key(sparse_id(key)) if sparse?
47
49
  if skey
@@ -58,6 +60,7 @@ class ChefVault
58
60
  return (ckey ? true : false) unless ckey.nil?
59
61
  # check if the key is saved in sparse mode
60
62
  return true if sparse? && sparse_key(sparse_id(key))
63
+
61
64
  # fallback to non-sparse mode if sparse key is not found
62
65
  @raw_data.keys.include?(key)
63
66
  end
@@ -66,10 +69,14 @@ class ChefVault
66
69
  type = chef_key.type
67
70
  unless @raw_data.key?(type)
68
71
  raise ChefVault::Exceptions::V1Format,
69
- "cannot manage a v1 vault. See UPGRADE.md for help"
72
+ "cannot manage a v1 vault. See UPGRADE.md for help"
70
73
  end
71
74
  @cache[chef_key.name] = skip_reencryption ? self[chef_key.name] : nil
72
- @cache[chef_key.name] ||= ChefVault::ItemKeys.encode_key(chef_key.key, data_bag_shared_secret)
75
+ begin
76
+ @cache[chef_key.name] ||= ChefVault::ItemKeys.encode_key(chef_key.key, data_bag_shared_secret)
77
+ rescue OpenSSL::PKey::RSAError
78
+ raise OpenSSL::PKey::RSAError, "While adding #{chef_key.type} an invalid or old (pre chef-server 12) format public key was found for #{chef_key.name}"
79
+ end
73
80
  @raw_data[type] << chef_key.name unless @raw_data[type].include?(chef_key.name)
74
81
  @raw_data[type]
75
82
  end
@@ -135,7 +142,7 @@ class ChefVault
135
142
  begin
136
143
  Chef::DataBagItem.from_hash("data_bag" => data_bag,
137
144
  "id" => sparse_id(key))
138
- .destroy(data_bag, sparse_id(key))
145
+ .destroy(data_bag, sparse_id(key))
139
146
  rescue Net::HTTPServerException => http_error
140
147
  raise http_error unless http_error.response.code == "404"
141
148
  end
@@ -161,6 +168,25 @@ class ChefVault
161
168
  end
162
169
  end
163
170
  end
171
+
172
+ if @raw_data["mode"] == "sparse"
173
+ @raw_data.each do |key, val|
174
+ next if %w{ id clients admins search_query mode }.include?(key)
175
+
176
+ skey = Chef::DataBagItem.from_hash(
177
+ "data_bag" => data_bag,
178
+ "id" => sparse_id(key),
179
+ key => val
180
+ )
181
+ @raw_data.delete(key)
182
+ if Chef::Config[:solo_legacy_mode]
183
+ save_solo(skey.id, skey.raw_data)
184
+ else
185
+ skey.save
186
+ end
187
+ end
188
+ end
189
+
164
190
  # save raw data
165
191
  if Chef::Config[:solo_legacy_mode]
166
192
  save_solo(item_id)
@@ -187,7 +213,7 @@ class ChefVault
187
213
  items = Chef::DataBag.load(data_bag).keys.select { |item| item =~ rgx }
188
214
  items.each do |id|
189
215
  Chef::DataBagItem.from_hash("data_bag" => data_bag, "id" => id)
190
- .destroy(data_bag, id)
216
+ .destroy(data_bag, id)
191
217
  end
192
218
  # destroy this metadata
193
219
  super(data_bag, id)
@@ -6,7 +6,7 @@ class ChefVault
6
6
  # paths and use that by preference
7
7
  # 1. Otherwise, just use the first location in the array
8
8
  def find_solo_path(item_id)
9
- if Chef::Config[:data_bag_path].kind_of?(Array)
9
+ if Chef::Config[:data_bag_path].is_a?(Array)
10
10
  path = Chef::Config[:data_bag_path].find do |dir|
11
11
  File.exist?(File.join(dir, data_bag, "#{item_id}.json"))
12
12
  end
@@ -15,7 +15,7 @@ class ChefVault
15
15
  data_bag_path = File.join(path, data_bag)
16
16
  else
17
17
  data_bag_path = File.join(Chef::Config[:data_bag_path],
18
- data_bag)
18
+ data_bag)
19
19
  end
20
20
  data_bag_item_path = File.join(data_bag_path, item_id) + ".json"
21
21
 
@@ -15,6 +15,6 @@
15
15
  # limitations under the License.
16
16
 
17
17
  class ChefVault
18
- VERSION = "3.4.2"
18
+ VERSION = "4.0.11"
19
19
  MAJOR, MINOR, TINY = VERSION.split(".")
20
20
  end
@@ -33,7 +33,7 @@ class ChefVault
33
33
  end
34
34
 
35
35
  def values_from_file(file)
36
- json = File.open(file) { |fh| fh.read() }
36
+ json = File.open(file, &:read)
37
37
 
38
38
  values_from_json(json)
39
39
  end
@@ -14,7 +14,7 @@
14
14
  # limitations under the License.
15
15
 
16
16
  require "chef/knife"
17
- require "chef-vault"
17
+ require_relative "../../chef-vault"
18
18
 
19
19
  class Chef
20
20
  class Knife
@@ -26,6 +26,10 @@ class Chef
26
26
  vault_admins = Chef::Config[:knife][:vault_admins]
27
27
  admin_array = [Chef::Config[:node_name]]
28
28
 
29
+ if !vault_admins.kind_of?(Array)
30
+ ui.warn("Vault admin must be an array")
31
+ end
32
+
29
33
  if config_admins
30
34
  admin_array += [config_admins]
31
35
  elsif vault_admins
@@ -14,7 +14,7 @@
14
14
  # limitations under the License.
15
15
 
16
16
  require "chef/knife"
17
- require "chef-vault"
17
+ require_relative "../../chef-vault"
18
18
 
19
19
  class Chef
20
20
  class Knife
@@ -55,13 +55,16 @@ class Chef
55
55
  # - item_keys has zero or more keys in sparse mode
56
56
  # vaults have a number of keys >= 2
57
57
  return false unless bag.keys.size >= 2
58
+
58
59
  # partition into those that end in _keys
59
60
  keylike, notkeylike = split_vault_keys(bag)
60
61
  # there must be an equal number of keyline and not-keylike items
61
62
  return false unless keylike.size == notkeylike.size
63
+
62
64
  # strip the _keys suffix and check if the sets match
63
65
  keylike.map! { |k| k.gsub(/_keys$/, "") }
64
66
  return false unless keylike.sort == notkeylike.sort
67
+
65
68
  # it's (probably) a vault
66
69
  true
67
70
  end
@@ -70,7 +73,7 @@ class Chef
70
73
  # get all item keys
71
74
  keys = bag.keys.select { |k| k =~ /_keys$/ }
72
75
  # get all sparse keys
73
- r = Regexp.union(keys.map { |k| Regexp.new("^#{k.chomp('_keys')}_key_.*") })
76
+ r = Regexp.union(keys.map { |k| Regexp.new("^#{k.chomp("_keys")}_key_.*") })
74
77
  sparse = bag.keys.select { |k| k =~ r }
75
78
  # the rest
76
79
  items = bag.keys - keys - sparse
@@ -13,9 +13,9 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
17
- require "chef/knife/vault_admins"
18
- require "chef/knife/vault_clients"
16
+ require_relative "vault_base"
17
+ require_relative "vault_admins"
18
+ require_relative "vault_clients"
19
19
 
20
20
  class Chef
21
21
  class Knife
@@ -84,7 +84,7 @@ class Chef
84
84
 
85
85
  if file
86
86
  vault_item["file-name"] = File.basename(file)
87
- vault_item["file-content"] = File.open(file) { |f| f.read() }
87
+ vault_item["file-content"] = File.open(file, &:read)
88
88
  end
89
89
  else
90
90
  vault_json = edit_hash({})
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
16
+ require_relative "vault_base"
17
17
 
18
18
  class Chef
19
19
  class Knife
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
16
+ require_relative "vault_base"
17
17
 
18
18
  class Chef
19
19
  class Knife
@@ -34,7 +34,7 @@ class Chef
34
34
  File.open(path, "w") do |file|
35
35
  file.write(vault_item["file-content"])
36
36
  end
37
- ui.info("Saved #{vault_item['file-name']} as #{path}")
37
+ ui.info("Saved #{vault_item["file-name"]} as #{path}")
38
38
  else
39
39
  show_usage
40
40
  end
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
16
+ require_relative "vault_base"
17
17
 
18
18
  class Chef
19
19
  class Knife
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
16
+ require_relative "vault_base"
17
17
 
18
18
  class Chef
19
19
  class Knife
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
16
+ require_relative "vault_base"
17
17
 
18
18
  class Chef
19
19
  class Knife
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
16
+ require_relative "vault_base"
17
17
 
18
18
  class Chef
19
19
  class Knife
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
16
+ require_relative "vault_base"
17
17
 
18
18
  class Chef
19
19
  class Knife
@@ -47,8 +47,8 @@ class Chef
47
47
  ChefVault::Exceptions::ItemNotFound
48
48
 
49
49
  raise ChefVault::Exceptions::ItemNotFound,
50
- "#{vault}/#{item} does not exist, "\
51
- "use 'knife vault create' to create."
50
+ "#{vault}/#{item} does not exist, "\
51
+ "use 'knife vault create' to create."
52
52
  end
53
53
  else
54
54
  show_usage
@@ -13,8 +13,8 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
17
- require "chef/knife/vault_clients"
16
+ require_relative "vault_base"
17
+ require_relative "vault_clients"
18
18
 
19
19
  class Chef
20
20
  class Knife
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
16
+ require_relative "vault_base"
17
17
 
18
18
  class Chef
19
19
  class Knife
@@ -45,9 +45,10 @@ class Chef
45
45
  end
46
46
  end
47
47
 
48
+ # Permalink for regex of replacing '_keys' with '': https://rubular.com/r/5cA5JNSyLfPSfY
48
49
  def vault_items(vault)
49
50
  Chef::DataBag.load(vault).keys.each_with_object([]) do |key, array|
50
- array << key.sub("_keys", "") if key =~ /.+_keys$/
51
+ array << key.sub(/_keys(?=[^_keys]*$)/, "") if key =~ /.+_keys$/
51
52
  end
52
53
  end
53
54
 
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
16
+ require_relative "vault_base"
17
17
 
18
18
  class Chef
19
19
  class Knife
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
16
+ require_relative "vault_base"
17
17
 
18
18
  class Chef
19
19
  class Knife
@@ -13,9 +13,9 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "chef/knife/vault_base"
17
- require "chef/knife/vault_admins"
18
- require "chef/knife/vault_clients"
16
+ require_relative "vault_base"
17
+ require_relative "vault_admins"
18
+ require_relative "vault_clients"
19
19
 
20
20
  class Chef
21
21
  class Knife
@@ -54,6 +54,11 @@ class Chef
54
54
  long: "--clean",
55
55
  description: "Clean clients before performing search"
56
56
 
57
+ option :keys_mode,
58
+ short: "-K KEYS_MODE",
59
+ long: "--keys-mode KEYS_MODE",
60
+ description: "Mode in which to save vault keys"
61
+
57
62
  def run
58
63
  vault = @name_args[0]
59
64
  item = @name_args[1]
@@ -62,16 +67,17 @@ class Chef
62
67
  json_file = config[:json]
63
68
  file = config[:file]
64
69
  clean = config[:clean]
70
+ keys_mode = config[:keys_mode]
65
71
 
66
72
  set_mode(config[:vault_mode])
67
73
 
68
- if vault && item && ((values || json_file || file) || (search || clients || admins))
74
+ if vault && item && ((values || json_file || file) || (search || clients || admins) || (keys_mode))
69
75
  begin
70
76
  vault_item = ChefVault::Item.load(vault, item)
71
77
 
72
78
  # Keys management first
73
79
  if clean
74
- vault_clients = vault_item.get_clients.clone().sort()
80
+ vault_clients = vault_item.get_clients.clone.sort
75
81
  vault_clients.each do |client|
76
82
  ui.info "Deleting #{client}"
77
83
  vault_item.delete_client(client)
@@ -91,7 +97,7 @@ class Chef
91
97
 
92
98
  if file
93
99
  vault_item["file-name"] = File.basename(file)
94
- vault_item["file-content"] = File.open(file) { |f| f.read() }
100
+ vault_item["file-content"] = File.open(file, &:read)
95
101
  end
96
102
 
97
103
  vault_item.save
@@ -105,6 +111,11 @@ class Chef
105
111
  "#{vault}/#{item} does not exist, "\
106
112
  "use 'knife vault create' to create."
107
113
  end
114
+
115
+ if keys_mode
116
+ vault_item.mode(keys_mode)
117
+ vault_item.save_keys
118
+ end
108
119
  else
109
120
  show_usage
110
121
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-vault
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.2
4
+ version: 4.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thom May
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-22 00:00:00.000000000 Z
11
+ date: 2020-08-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Data encryption support for Chef using data bags
13
+ description: Data encryption support for Chef Infra using data bags
14
14
  email:
15
15
  - thom@chef.io
16
16
  executables:
@@ -20,7 +20,6 @@ extra_rdoc_files: []
20
20
  files:
21
21
  - Gemfile
22
22
  - LICENSE
23
- - README.md
24
23
  - bin/chef-vault
25
24
  - chef-vault.gemspec
26
25
  - lib/chef-vault.rb
@@ -62,16 +61,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
62
61
  requirements:
63
62
  - - ">="
64
63
  - !ruby/object:Gem::Version
65
- version: 2.2.0
64
+ version: '2.4'
66
65
  required_rubygems_version: !ruby/object:Gem::Requirement
67
66
  requirements:
68
67
  - - ">="
69
68
  - !ruby/object:Gem::Version
70
69
  version: '0'
71
70
  requirements: []
72
- rubyforge_project:
73
- rubygems_version: 2.7.6
71
+ rubygems_version: 3.0.3
74
72
  signing_key:
75
73
  specification_version: 4
76
- summary: Data encryption support for Chef using data bags
74
+ summary: Data encryption support for Chef Infra using data bags
77
75
  test_files: []
data/README.md DELETED
@@ -1,307 +0,0 @@
1
- # Chef-Vault
2
-
3
- [![Gem Version](https://badge.fury.io/rb/chef-vault.svg)](http://badge.fury.io/rb/chef-vault)
4
-
5
- [![Build Status](https://travis-ci.org/chef/chef-vault.svg?branch=master)](https://travis-ci.org/chef/chef-vault)
6
-
7
- [![Inline docs](http://inch-ci.org/github/chef/chef-vault.svg?branch=master)](http://inch-ci.org/github/chef/chef-vault)
8
-
9
- [![Code Climate](https://codeclimate.com/github/chef/chef-vault/badges/gpa.svg)](https://codeclimate.com/github/chef/chef-vault)
10
-
11
- ## DESCRIPTION:
12
-
13
- Gem that allows you to encrypt a Chef Data Bag Item using the public keys of
14
- a list of chef nodes. This allows only those chef nodes to decrypt the
15
- encrypted values.
16
-
17
- For a more detailed explanation of how chef-vault works, please refer to this blog post [Chef Vault – what is it and what can it do for you?](https://www.chef.io/blog/2016/01/21/chef-vault-what-is-it-and-what-can-it-do-for-you/) by Nell Shamrell-Harrington.
18
-
19
- ## INSTALLATION:
20
-
21
- Be sure you are running the latest version Chef. Versions earlier than
22
- 0.10.0 don't support plugins:
23
-
24
- gem install chef
25
-
26
- This plugin is distributed as a Ruby Gem. To install it, run:
27
-
28
- gem install chef-vault
29
-
30
- Depending on your system's configuration, you may need to run this command
31
- with root privileges.
32
-
33
- ## DEVELOPMENT:
34
-
35
- ### Git Hooks
36
-
37
- There is a git pre-commit hook to help you keep your chefstyle up to date.
38
- If you wish to use it, simply:
39
-
40
- ```
41
- mv hooks/pre-commit .git/hooks/
42
- chmod +x .git/hooks/pre-commit
43
- ```
44
-
45
- ### Running Your Changes
46
-
47
- To run your changes locally:
48
-
49
- ```
50
- bundle install
51
- bundle exec knife vault
52
- ```
53
-
54
- ### Testing
55
-
56
- #### Rspec Tests
57
-
58
- There are some unit tests that can be run with:
59
-
60
- ```
61
- bundle exec rspec spec/
62
- ```
63
-
64
- #### Cucumber Testing
65
-
66
- There are cucumber tests. Run the whole suite with:
67
-
68
- ```
69
- bundle exec rake features
70
- ```
71
-
72
- If you get any failures, you can run the specific feature that failed with:
73
-
74
- ```
75
- bundle exec cucumber features/<failed>.feature
76
- ```
77
-
78
- If you want to test things out directly, after a failure you can go into the test
79
- directory and try out the commands that failed:
80
-
81
- ```
82
- cd tmp/aruba
83
- bundle exec knife <your command that failed from test with -c knife.rb>
84
- ```
85
-
86
- Optionally add `-VV` to the above to get a full stacktrace.
87
-
88
- ### Rubocop Errors
89
-
90
- If you are seeing rubocop errors in travis for your pull request, run:
91
-
92
- `bundle exec chefstyle -a`
93
-
94
- This will fix up your rubocop errors automatically, and warn you about any it can't.
95
-
96
- ## KNIFE COMMANDS:
97
-
98
- See KNIFE_EXAMPLES.md for examples of commands
99
-
100
- ### knife.rb
101
-
102
- To set 'client' as the default mode, add the following line to the knife.rb file.
103
-
104
- knife[:vault_mode] = 'client'
105
-
106
- To set the default list of admins for creating and updating vaults, add the
107
- following line to the knife.rb file.
108
-
109
- knife[:vault_admins] = [ 'example-alice', 'example-bob', 'example-carol' ]
110
-
111
- (These values can be overridden on the command line by using -A)
112
-
113
- NOTE: chef-vault 1.0 knife commands are not supported! Please use chef-vault
114
- 2.0 commands.
115
-
116
- ### Vault
117
-
118
- knife vault create VAULT ITEM VALUES
119
- knife vault edit VAULT ITEM
120
- knife vault refresh VAULT ITEM
121
- knife vault update VAULT ITEM VALUES [--clean]
122
- knife vault remove VAULT ITEM VALUES
123
- knife vault delete VAULT ITEM
124
- knife vault rotate keys VAULT ITEM
125
- knife vault rotate all keys
126
- knife vault show VAULT [ITEM] [VALUES]
127
- knife vault download VAULT ITEM PATH
128
- knife vault isvault VAULT ITEM
129
- knife vault itemtype VAULT ITEM
130
-
131
- #### Global Options
132
-
133
- Short | Long | Description | Default | Valid Values | Sub-Commands
134
- ------|------|-------------|---------|--------------|-------------
135
- -M MODE | --mode MODE | Chef mode to run in. Can be set in knife.rb | solo | solo, client | all
136
- -S SEARCH | --search SEARCH | Chef Server SOLR Search Of Nodes | | | create, remove , update
137
- -C CLIENTS | --clients CLIENTS | Chef clients to be added as clients, can be comma list | | | create, remove , update
138
- -A ADMINS | --admins ADMINS | Chef clients or users to be vault admins, can be comma list | | | create, remove, update
139
- -J FILE | --json FILE | JSON file to be used for values, will be merged with VALUES if VALUES is passed | | | create, update
140
- | --file FILE | File that chef-vault should encrypt. It adds "file-content" & "file-name" keys to the vault item | | | create, update
141
- -p DATA | --print DATA | Print extra vault data | | search, clients, admins, all | show
142
- -F FORMAT | --format FORMAT | Format for decrypted output | summary | summary, json, yaml, pp | show
143
- | --clean-unknown-clients | Remove unknown clients during key rotation | | | refresh, remove, rotate
144
- | --clean | Clean clients list before performing search | | | refresh, update
145
-
146
- ## USAGE IN RECIPES
147
-
148
- To use this gem in a recipe to decrypt data you must first install the gem
149
- via a chef_gem resource. Once the gem is installed require the gem and then
150
- you can create a new instance of ChefVault.
151
-
152
- NOTE: chef-vault 1.0 style decryption is supported, however it has been
153
- deprecated and chef-vault 2.0 decryption should be used instead
154
-
155
- ### Example Code
156
-
157
- chef_gem 'chef-vault' do
158
- compile_time true if respond_to?(:compile_time)
159
- end
160
-
161
- require 'chef-vault'
162
-
163
- item = ChefVault::Item.load("passwords", "root")
164
- item["password"]
165
-
166
- Note that in this case, the gem needs to be installed at compile time
167
- because the require statement is at the top-level of the recipe. If
168
- you move the require of chef-vault and the call to `::load` to
169
- library or provider code, you can install the gem in the converge phase
170
- instead.
171
-
172
- ### Specifying an alternate node name or client key path
173
-
174
- Normally, the value of `Chef::Config[:node_name]` is used to find the
175
- per-node encrypted secret in the keys data bag item, and the value of
176
- `Chef::Config[:client_key]` is used to locate the private key to decrypt
177
- this secret.
178
-
179
- These can be overridden by passing a hash with the keys `:node_name` or
180
- `:client_key_path` to `ChefVault::Item.load`:
181
-
182
- item = ChefVault::Item.load(
183
- 'passwords', 'root',
184
- node_name: 'service_foo',
185
- client_key_path: '/secure/place/service_foo.pem'
186
- )
187
- item['password']
188
-
189
- The above example assumes that you have transferred
190
- `/secure/place/service_foo.pem` to your system via a secure channel.
191
-
192
- This usage allows you to decrypt a vault using a key shared among several
193
- nodes, which can be helpful when working in cloud environments or other
194
- configurations where nodes are created dynamically.
195
-
196
- ### chef_vault_item helper
197
-
198
- The [chef-vault cookbook](https://supermarket.chef.io/cookbooks/chef-vault)
199
- contains a recipe to install the chef-vault gem and a helper method
200
- `chef_vault_helper` which makes it easier to test cookbooks that use
201
- chef-vault using Test Kitchen.
202
-
203
- ## DETERMINING IF AN ITEM IS A VAULT
204
-
205
- ChefVault provides a helper method to determine if a data bag item is a vault,
206
- which can be helpful if you produce a recipe for community consumption and want
207
- to support both normal data bags and vaults:
208
-
209
- if ChefVault::Item.vault?('passwords', 'root')
210
- item = ChefVault::Item.load('passwords', 'root')
211
- else
212
- item = Chef::DataBagItem.load('passwords', 'root')
213
- end
214
-
215
- This functionality is also available from the command line as `knife vault isvault VAULT ITEM`.
216
-
217
- ## DETERMINING THE TYPE OF A DATA BAG ITEM
218
-
219
- ChefVault provides a helper method to determine the type of a data bag item.
220
- It returns one of the symbols :normal, :encrypted or :vault
221
-
222
- case ChefVault::Item.data_bag_item_type('passwords', 'root')
223
- when :normal
224
- ...
225
- when :encrypted
226
- ...
227
- when :vault
228
- ...
229
- end
230
-
231
- This functionality is also available from the command line as `knife vault itemtype VAULT ITEM`.
232
-
233
- ## USAGE STAND ALONE
234
-
235
- `chef-vault` can be used as a stand alone binary to decrypt values stored in
236
- Chef. It requires that Chef is installed on the system and that you have a
237
- valid knife.rb. This is useful if you want to mix `chef-vault` into non-Chef
238
- recipe code, for example some other script where you want to protect a
239
- password.
240
-
241
- It does still require that the data bag has been encrypted for the user's or
242
- client's pem and pushed to the Chef server. It mixes Chef into the gem and
243
- uses it to go grab the data bag.
244
-
245
- Use `chef-vault --help` to see all all available options
246
-
247
- ### Example usage (password)
248
-
249
- chef-vault -v passwords -i root -a password -k /etc/chef/knife.rb
250
-
251
- ## TESTING
252
-
253
- To use Chef Vault in Test Kitchen, ensure that the `chef-vault` recipe
254
- is in your `run_list`, and then add the following to your
255
- suite in `.kitchen.yml`:
256
-
257
- ```yaml
258
- data_bags_path: 'path/to/data_bags'
259
- attributes:
260
- chef_vault:
261
- databags_fallback: true
262
- ```
263
-
264
- You can then use the `chef_vault_item` helper in the aforementioned chef-vault cookbook.
265
-
266
- To stub vault items in ChefSpec, use the
267
- [chef-vault-testfixtures](https://rubygems.org/gems/chef-vault-testfixtures)
268
- gem.
269
-
270
- ## Contributing
271
-
272
- For information on contributing to this project see <https://github.com/chef/chef/blob/master/CONTRIBUTING.md>
273
-
274
- ## Authors
275
-
276
- Author:: Kevin Moser - @moserke<br>
277
- Author:: Eli Klein - @eliklein<br>
278
- Author:: Joey Geiger - @jgeiger<br>
279
- Author:: Joshua Timberman - @jtimberman<br>
280
- Author:: James FitzGibbon - @jf647<br>
281
- Author:: Thom May - @thommay<br>
282
-
283
- ## Contributors
284
-
285
- Contributor:: Matt Brimstone - @brimstone<br>
286
- Contributor:: Thomas Gschwind - @thg65<br>
287
- Contributor:: Reto Hermann<br>
288
-
289
- ## License
290
-
291
- Copyright:: Copyright (c) 2013-15 Nordstrom, Inc.<br>
292
- Copyright:: Copyright (c) 2016 Chef Software, Inc.<br>
293
- License:: Apache License, Version 2.0
294
-
295
- ```text
296
- Licensed under the Apache License, Version 2.0 (the "License");
297
- you may not use this file except in compliance with the License.
298
- You may obtain a copy of the License at
299
-
300
- http://www.apache.org/licenses/LICENSE-2.0
301
-
302
- Unless required by applicable law or agreed to in writing, software
303
- distributed under the License is distributed on an "AS IS" BASIS,
304
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
305
- See the License for the specific language governing permissions and
306
- limitations under the License.
307
- ```