chef-vault 3.4.2 → 4.0.11

Sign up to get free protection for your applications and to get access to all the features.
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
- ```