cheffish 15.0.0 → 15.0.3
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 +4 -4
- data/Gemfile +2 -2
- data/Rakefile +1 -1
- data/lib/chef/resource/chef_acl.rb +13 -10
- data/lib/chef/resource/chef_client.rb +2 -2
- data/lib/chef/resource/chef_container.rb +2 -2
- data/lib/chef/resource/chef_data_bag.rb +2 -2
- data/lib/chef/resource/chef_data_bag_item.rb +11 -10
- data/lib/chef/resource/chef_environment.rb +1 -1
- data/lib/chef/resource/chef_group.rb +1 -1
- data/lib/chef/resource/chef_mirror.rb +6 -5
- data/lib/chef/resource/chef_node.rb +1 -1
- data/lib/chef/resource/chef_organization.rb +2 -2
- data/lib/chef/resource/chef_resolved_cookbooks.rb +5 -3
- data/lib/chef/resource/chef_role.rb +5 -1
- data/lib/chef/resource/chef_user.rb +2 -2
- data/lib/chef/resource/private_key.rb +10 -10
- data/lib/chef/resource/public_key.rb +4 -3
- data/lib/cheffish.rb +1 -0
- data/lib/cheffish/base_resource.rb +13 -11
- data/lib/cheffish/basic_chef_client.rb +2 -2
- data/lib/cheffish/chef_actor_base.rb +2 -1
- data/lib/cheffish/chef_run.rb +5 -6
- data/lib/cheffish/chef_run_listener.rb +1 -3
- data/lib/cheffish/key_formatter.rb +1 -9
- data/lib/cheffish/merged_config.rb +2 -2
- data/lib/cheffish/node_properties.rb +7 -3
- data/lib/cheffish/recipe_dsl.rb +2 -2
- data/lib/cheffish/rspec/chef_run_support.rb +1 -1
- data/lib/cheffish/rspec/matchers/have_updated.rb +5 -5
- data/lib/cheffish/rspec/recipe_run_wrapper.rb +1 -1
- data/lib/cheffish/rspec/repository_support.rb +1 -0
- data/lib/cheffish/version.rb +1 -1
- data/spec/functional/fingerprint_spec.rb +8 -6
- data/spec/integration/chef_acl_spec.rb +27 -19
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 547830e01071a34cc583bbf5217ae5f55270c014c393e9a69301023a88717279
|
4
|
+
data.tar.gz: a29005438abb411a4b59bc7b1cf1782e36219e2bd951ec49c64273f9a7de6144
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6db5d7117bb249b37d894d3b3e776f7d3b5e8c87cb2895e156fbe4393031dbfdfdcff8a9133b4bb7e578f85440905a5acbd30426e7a8d81171ac3fd44f583936
|
7
|
+
data.tar.gz: 2216df827dc0635fdf0e3a340a80dbf267c8c51f58d7bde7c2a7deb28f0b3eeb24975bc88e3c44809c12189c05751a8624285d90a7472ace2bbb6b69dd99542d
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -7,7 +7,7 @@ require "uri"
|
|
7
7
|
class Chef
|
8
8
|
class Resource
|
9
9
|
class ChefAcl < Cheffish::BaseResource
|
10
|
-
|
10
|
+
provides :chef_acl
|
11
11
|
|
12
12
|
# Path of the thing being secured, e.g. nodes, nodes/*, nodes/mynode,
|
13
13
|
# */*, **, roles/base, data/secrets, cookbooks/apache2, /users/*,
|
@@ -99,6 +99,7 @@ class Chef
|
|
99
99
|
# NOTE: if superusers exist, this should turn into a warning.
|
100
100
|
raise "chef_acl attempted to remove all actors from GRANT! I'm sorry Dave, I can't let you remove access to an object with no hope of recovery."
|
101
101
|
end
|
102
|
+
|
102
103
|
modify[differences] ||= {}
|
103
104
|
modify[differences][permission] = desired_json
|
104
105
|
end
|
@@ -107,7 +108,7 @@ class Chef
|
|
107
108
|
if modify.size > 0
|
108
109
|
changed = true
|
109
110
|
description = [ "update acl #{path} at #{rest_url(path)}" ] + modify.flat_map do |diffs, permissions|
|
110
|
-
diffs.map { |diff| " #{permissions.keys.join(
|
111
|
+
diffs.map { |diff| " #{permissions.keys.join(", ")}:#{diff}" }
|
111
112
|
end
|
112
113
|
converge_by description do
|
113
114
|
modify.values.each do |permissions|
|
@@ -127,11 +128,13 @@ class Chef
|
|
127
128
|
children, _error = list(path, "*")
|
128
129
|
Chef::ChefFS::Parallelizer.parallel_do(children) do |child|
|
129
130
|
next if child.split("/")[-1] == "containers"
|
131
|
+
|
130
132
|
create_acl(child)
|
131
133
|
end
|
132
134
|
# containers mess up our descent, so we do them last
|
133
135
|
Chef::ChefFS::Parallelizer.parallel_do(children) do |child|
|
134
136
|
next if child.split("/")[-1] != "containers"
|
137
|
+
|
135
138
|
create_acl(child)
|
136
139
|
end
|
137
140
|
|
@@ -141,7 +144,7 @@ class Chef
|
|
141
144
|
# Get the current ACL for the given path
|
142
145
|
def current_acl(acl_path)
|
143
146
|
@current_acls ||= {}
|
144
|
-
|
147
|
+
unless @current_acls.key?(acl_path)
|
145
148
|
@current_acls[acl_path] = begin
|
146
149
|
rest.get(rest_url(acl_path))
|
147
150
|
rescue Net::HTTPServerException => e
|
@@ -252,8 +255,7 @@ class Chef
|
|
252
255
|
end
|
253
256
|
end
|
254
257
|
|
255
|
-
def load_current_resource
|
256
|
-
end
|
258
|
+
def load_current_resource; end
|
257
259
|
|
258
260
|
#
|
259
261
|
# Matches chef_acl paths like nodes, nodes/*.
|
@@ -270,7 +272,7 @@ class Chef
|
|
270
272
|
def match_paths(path)
|
271
273
|
# Turn multiple slashes into one
|
272
274
|
# nodes//x -> nodes/x
|
273
|
-
path = path.gsub(/
|
275
|
+
path = path.gsub(%r{[/]+}, "/")
|
274
276
|
# If it's absolute, start the matching with /. If it's relative, start with '' (relative root).
|
275
277
|
if path[0] == "/"
|
276
278
|
matches = [ "/" ]
|
@@ -305,6 +307,7 @@ class Chef
|
|
305
307
|
if parts[0..index - 1].all? { |p| p != "*" }
|
306
308
|
raise error
|
307
309
|
end
|
310
|
+
|
308
311
|
[]
|
309
312
|
else
|
310
313
|
found
|
@@ -421,21 +424,21 @@ class Chef
|
|
421
424
|
when 1
|
422
425
|
# /organizations/*, /users/*, roles/*, nodes/*, etc.
|
423
426
|
results, error = rest_list(path)
|
424
|
-
|
427
|
+
unless error
|
425
428
|
results = results.map { |result| ::File.join(path, result) }
|
426
429
|
end
|
427
430
|
|
428
431
|
when 2
|
429
432
|
# /organizations/NAME/*
|
430
433
|
results, error = rest_list(::File.join(path, "containers"))
|
431
|
-
|
434
|
+
unless error
|
432
435
|
results = results.map { |result| ::File.join(path, result) }
|
433
436
|
end
|
434
437
|
|
435
438
|
when 3
|
436
439
|
# /organizations/NAME/TYPE/*
|
437
440
|
results, error = rest_list(path)
|
438
|
-
|
441
|
+
unless error
|
439
442
|
results = results.map { |result| ::File.join(path, result) }
|
440
443
|
end
|
441
444
|
end
|
@@ -466,7 +469,7 @@ class Chef
|
|
466
469
|
end
|
467
470
|
|
468
471
|
def rest_list(path)
|
469
|
-
|
472
|
+
# All our rest lists are hashes where the keys are the names
|
470
473
|
[ rest.get(rest_url(path)).keys, nil ]
|
471
474
|
rescue Net::HTTPServerException => e
|
472
475
|
if e.response.code == "405" || e.response.code == "404"
|
@@ -4,7 +4,7 @@ require_relative "../../cheffish/chef_actor_base"
|
|
4
4
|
class Chef
|
5
5
|
class Resource
|
6
6
|
class ChefClient < Cheffish::ChefActorBase
|
7
|
-
|
7
|
+
provides :chef_client
|
8
8
|
|
9
9
|
# Client attributes
|
10
10
|
property :chef_client_name, Cheffish::NAME_REGEX, name_property: true
|
@@ -18,7 +18,7 @@ class Chef
|
|
18
18
|
|
19
19
|
# Output public key (if so desired)
|
20
20
|
property :output_key_path, String
|
21
|
-
property :output_key_format, Symbol, default: :openssh, equal_to:
|
21
|
+
property :output_key_format, Symbol, default: :openssh, equal_to: %i{pem der openssh}
|
22
22
|
|
23
23
|
# Proc that runs just before the resource executes. Called with (resource)
|
24
24
|
def before(&block)
|
@@ -5,12 +5,12 @@ require "chef/chef_fs/data_handler/container_data_handler"
|
|
5
5
|
class Chef
|
6
6
|
class Resource
|
7
7
|
class ChefContainer < Cheffish::BaseResource
|
8
|
-
|
8
|
+
provides :chef_container
|
9
9
|
|
10
10
|
property :chef_container_name, Cheffish::NAME_REGEX, name_property: true
|
11
11
|
|
12
12
|
action :create do
|
13
|
-
|
13
|
+
unless @current_exists
|
14
14
|
converge_by "create container #{new_resource.chef_container_name} at #{rest.url}" do
|
15
15
|
rest.post("containers", normalize_for_post(new_json))
|
16
16
|
end
|
@@ -4,12 +4,12 @@ require_relative "../../cheffish/base_resource"
|
|
4
4
|
class Chef
|
5
5
|
class Resource
|
6
6
|
class ChefDataBag < Cheffish::BaseResource
|
7
|
-
|
7
|
+
provides :chef_data_bag
|
8
8
|
|
9
9
|
property :data_bag_name, Cheffish::NAME_REGEX, name_property: true
|
10
10
|
|
11
11
|
action :create do
|
12
|
-
|
12
|
+
unless current_resource_exists?
|
13
13
|
converge_by "create data bag #{new_resource.data_bag_name} at #{rest.url}" do
|
14
14
|
rest.post("data", { "name" => new_resource.data_bag_name })
|
15
15
|
end
|
@@ -7,7 +7,7 @@ require "chef/encrypted_data_bag_item"
|
|
7
7
|
class Chef
|
8
8
|
class Resource
|
9
9
|
class ChefDataBagItem < Cheffish::BaseResource
|
10
|
-
|
10
|
+
provides :chef_data_bag_item
|
11
11
|
|
12
12
|
def initialize(*args)
|
13
13
|
super
|
@@ -137,7 +137,7 @@ class Chef
|
|
137
137
|
|
138
138
|
# If the current secret doesn't work, look through the specified old secrets
|
139
139
|
|
140
|
-
|
140
|
+
unless current_resource.secret
|
141
141
|
old_secrets = []
|
142
142
|
if new_resource.old_secret
|
143
143
|
old_secrets += Array(new_resource.old_secret)
|
@@ -148,17 +148,17 @@ class Chef
|
|
148
148
|
end
|
149
149
|
end
|
150
150
|
old_secrets.each do |secret|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
151
|
+
|
152
|
+
Chef::EncryptedDataBagItem::Decryptor.for(first_real_value, secret).for_decrypted_item
|
153
|
+
current_resource.secret secret
|
154
|
+
rescue Chef::EncryptedDataBagItem::DecryptionFailure
|
155
|
+
decrypt_error = $!
|
156
|
+
|
157
157
|
end
|
158
158
|
|
159
159
|
# If we couldn't figure out the secret, emit a warning (this isn't a fatal flaw unless we
|
160
160
|
# need to reuse one of the values from the data bag)
|
161
|
-
|
161
|
+
unless current_resource.secret
|
162
162
|
if decrypt_error
|
163
163
|
Chef::Log.warn "Existing data bag is encrypted, but could not decrypt: #{decrypt_error.message}."
|
164
164
|
else
|
@@ -280,9 +280,10 @@ class Chef
|
|
280
280
|
elsif current_resource.encrypt
|
281
281
|
# Encryption is different and we can't read the old values. Only allow the change
|
282
282
|
# if we're overwriting the data bag item
|
283
|
-
|
283
|
+
unless new_resource.complete
|
284
284
|
raise "Cannot encrypt #{new_resource.name} due to failure to decrypt existing resource. Set 'complete true' to overwrite or add the old secret as old_secret / old_secret_path."
|
285
285
|
end
|
286
|
+
|
286
287
|
_differences = [ "overwrite data bag item (cannot decrypt old data bag item)"]
|
287
288
|
differences = (new_resource.raw_data.keys & current_resource.raw_data.keys).map { |key| "overwrite #{key}" }
|
288
289
|
differences += (new_resource.raw_data.keys - current_resource.raw_data.keys).map { |key| "add #{key}" }
|
@@ -6,7 +6,7 @@ require "chef/chef_fs/data_handler/environment_data_handler"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class ChefEnvironment < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :chef_environment
|
10
10
|
|
11
11
|
property :environment_name, Cheffish::NAME_REGEX, name_property: true
|
12
12
|
property :description, String
|
@@ -6,7 +6,7 @@ require "chef/chef_fs/data_handler/group_data_handler"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class ChefGroup < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :chef_group
|
10
10
|
|
11
11
|
property :group_name, Cheffish::NAME_REGEX, name_property: true
|
12
12
|
property :users, ArrayType
|
@@ -9,7 +9,7 @@ require "chef/chef_fs/file_system/repository/chef_repository_file_system_root_di
|
|
9
9
|
class Chef
|
10
10
|
class Resource
|
11
11
|
class ChefMirror < Cheffish::BaseResource
|
12
|
-
|
12
|
+
provides :chef_mirror
|
13
13
|
|
14
14
|
# Path of the data to mirror, e.g. nodes, nodes/*, nodes/mynode,
|
15
15
|
# */*, **, roles/base, data/secrets, cookbooks/apache2, etc.
|
@@ -95,6 +95,7 @@ class Chef
|
|
95
95
|
if new_resource.concurrency <= 0
|
96
96
|
raise "chef_mirror.concurrency must be above 0! Was set to #{new_resource.concurrency}"
|
97
97
|
end
|
98
|
+
|
98
99
|
# Honor concurrency
|
99
100
|
Chef::ChefFS::Parallelizer.threads = new_resource.concurrency - 1
|
100
101
|
|
@@ -103,13 +104,14 @@ class Chef
|
|
103
104
|
if new_resource.path[0] == "/"
|
104
105
|
raise "Absolute paths in chef_mirror not yet supported."
|
105
106
|
end
|
107
|
+
|
106
108
|
# Copy!
|
107
109
|
path = Chef::ChefFS::FilePattern.new("/#{new_resource.path}")
|
108
110
|
ui = CopyListener.new(self)
|
109
111
|
error = Chef::ChefFS::FileSystem.copy_to(path, src_root, dest_root, nil, options, ui, proc { |p| p.path })
|
110
112
|
|
111
113
|
if error
|
112
|
-
raise "Errors while copying:#{ui.errors.map { |e| "#{e}\n" }.join(
|
114
|
+
raise "Errors while copying:#{ui.errors.map { |e| "#{e}\n" }.join("")}"
|
113
115
|
end
|
114
116
|
end
|
115
117
|
|
@@ -163,7 +165,7 @@ class Chef
|
|
163
165
|
end
|
164
166
|
|
165
167
|
def repo_mode
|
166
|
-
new_resource.chef_server[:chef_server_url] =~
|
168
|
+
new_resource.chef_server[:chef_server_url] =~ %r{/organizations/} ? "hosted_everything" : "everything"
|
167
169
|
end
|
168
170
|
|
169
171
|
def options
|
@@ -179,8 +181,7 @@ class Chef
|
|
179
181
|
result
|
180
182
|
end
|
181
183
|
|
182
|
-
def load_current_resource
|
183
|
-
end
|
184
|
+
def load_current_resource; end
|
184
185
|
|
185
186
|
class CopyListener
|
186
187
|
def initialize(mirror)
|
@@ -6,7 +6,7 @@ require "chef/chef_fs/data_handler/data_handler_base"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class ChefOrganization < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :chef_organization
|
10
10
|
|
11
11
|
property :organization_name, Cheffish::NAME_REGEX, name_property: true
|
12
12
|
property :full_name, String
|
@@ -68,7 +68,7 @@ class Chef
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
new_resource.members.each do |user|
|
71
|
-
|
71
|
+
unless existing_members.include?(user)
|
72
72
|
converge_by "Add #{user} to organization #{new_resource.organization_name}" do
|
73
73
|
rest.post("#{rest.root_url}/organizations/#{new_resource.organization_name}/users/", { "username" => user })
|
74
74
|
end
|
@@ -4,7 +4,7 @@ require "chef_zero"
|
|
4
4
|
class Chef
|
5
5
|
class Resource
|
6
6
|
class ChefResolvedCookbooks < Cheffish::BaseResource
|
7
|
-
|
7
|
+
provides :chef_resolved_cookbooks
|
8
8
|
|
9
9
|
def initialize(*args)
|
10
10
|
super
|
@@ -43,7 +43,8 @@ class Chef
|
|
43
43
|
new_resource.berksfile.upload(
|
44
44
|
server_url: new_resource.chef_server[:chef_server_url],
|
45
45
|
client_name: new_resource.chef_server[:options][:client_name],
|
46
|
-
client_key: new_resource.chef_server[:options][:signing_key_filename]
|
46
|
+
client_key: new_resource.chef_server[:options][:signing_key_filename]
|
47
|
+
)
|
47
48
|
else
|
48
49
|
file = Tempfile.new("privatekey")
|
49
50
|
begin
|
@@ -53,7 +54,8 @@ class Chef
|
|
53
54
|
new_resource.berksfile.upload(
|
54
55
|
server_url: new_resource.chef_server[:chef_server_url],
|
55
56
|
client_name: new_resource.chef_server[:options][:client_name] || "me",
|
56
|
-
client_key: file.path
|
57
|
+
client_key: file.path
|
58
|
+
)
|
57
59
|
|
58
60
|
ensure
|
59
61
|
file.close
|
@@ -6,7 +6,7 @@ require "chef/chef_fs/data_handler/role_data_handler"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class ChefRole < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :chef_role
|
10
10
|
|
11
11
|
property :role_name, Cheffish::NAME_REGEX, name_property: true
|
12
12
|
property :description, String
|
@@ -62,6 +62,7 @@ class Chef
|
|
62
62
|
if recipes.size == 0
|
63
63
|
raise ArgumentError, "At least one recipe must be specified"
|
64
64
|
end
|
65
|
+
|
65
66
|
@run_list_modifiers ||= []
|
66
67
|
@run_list_modifiers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") }
|
67
68
|
end
|
@@ -70,6 +71,7 @@ class Chef
|
|
70
71
|
if roles.size == 0
|
71
72
|
raise ArgumentError, "At least one role must be specified"
|
72
73
|
end
|
74
|
+
|
73
75
|
@run_list_modifiers ||= []
|
74
76
|
@run_list_modifiers += roles.map { |role| Chef::RunList::RunListItem.new("role[#{role}]") }
|
75
77
|
end
|
@@ -78,6 +80,7 @@ class Chef
|
|
78
80
|
if recipes.size == 0
|
79
81
|
raise ArgumentError, "At least one recipe must be specified"
|
80
82
|
end
|
83
|
+
|
81
84
|
@run_list_removers ||= []
|
82
85
|
@run_list_removers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") }
|
83
86
|
end
|
@@ -86,6 +89,7 @@ class Chef
|
|
86
89
|
if roles.size == 0
|
87
90
|
raise ArgumentError, "At least one role must be specified"
|
88
91
|
end
|
92
|
+
|
89
93
|
@run_list_removers ||= []
|
90
94
|
@run_list_removers += roles.map { |recipe| Chef::RunList::RunListItem.new("role[#{role}]") }
|
91
95
|
end
|
@@ -4,7 +4,7 @@ require_relative "../../cheffish/chef_actor_base"
|
|
4
4
|
class Chef
|
5
5
|
class Resource
|
6
6
|
class ChefUser < Cheffish::ChefActorBase
|
7
|
-
|
7
|
+
provides :chef_user
|
8
8
|
|
9
9
|
# Client attributes
|
10
10
|
property :user_name, Cheffish::NAME_REGEX, name_property: true
|
@@ -25,7 +25,7 @@ class Chef
|
|
25
25
|
|
26
26
|
# Output public key (if so desired)
|
27
27
|
property :output_key_path, String
|
28
|
-
property :output_key_format,
|
28
|
+
property :output_key_format, %i{pem der openssh}, default: :openssh
|
29
29
|
|
30
30
|
# Proc that runs just before the resource executes. Called with (resource)
|
31
31
|
def before(&block)
|
@@ -6,18 +6,18 @@ require_relative "../../cheffish/key_formatter"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class PrivateKey < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :private_key
|
10
10
|
|
11
11
|
allowed_actions :create, :delete, :regenerate, :nothing
|
12
12
|
default_action :create
|
13
13
|
|
14
14
|
# Path to private key. Set to :none to create the key in memory and not on disk.
|
15
15
|
property :path, [ String, :none ], name_property: true
|
16
|
-
property :format,
|
17
|
-
property :type,
|
16
|
+
property :format, %i{pem der}, default: :pem
|
17
|
+
property :type, %i{rsa dsa}, default: :rsa # TODO support :ec
|
18
18
|
# These specify an optional public_key you can spit out if you want.
|
19
19
|
property :public_key_path, String
|
20
|
-
property :public_key_format,
|
20
|
+
property :public_key_format, %i{openssh pem der}, default: :openssh
|
21
21
|
# Specify this if you want to copy another private key but give it a different format / password
|
22
22
|
property :source_key
|
23
23
|
property :source_key_path, String
|
@@ -31,7 +31,7 @@ class Chef
|
|
31
31
|
|
32
32
|
# PEM-only
|
33
33
|
property :pass_phrase, String
|
34
|
-
property :cipher, String, equal_to: OpenSSL::Cipher.ciphers.map
|
34
|
+
property :cipher, String, equal_to: OpenSSL::Cipher.ciphers.map(&:downcase), default: "des-ede3-cbc", coerce: proc { |x| x.downcase }
|
35
35
|
|
36
36
|
# Set this to regenerate the key if it does not have the desired characteristics (like size, type, etc.)
|
37
37
|
property :regenerate_if_different, [TrueClass, FalseClass]
|
@@ -202,22 +202,22 @@ class Chef
|
|
202
202
|
def new_key_with_path
|
203
203
|
path = new_resource.path
|
204
204
|
if path.is_a?(Symbol)
|
205
|
-
|
205
|
+
[ nil, path ]
|
206
206
|
elsif Pathname.new(path).relative?
|
207
207
|
private_key, private_key_path = Cheffish.get_private_key_with_path(path, run_context.config)
|
208
208
|
if private_key
|
209
|
-
|
209
|
+
[ private_key, (private_key_path || :none) ]
|
210
210
|
elsif run_context.config[:private_key_write_path]
|
211
211
|
@should_create_directory = true
|
212
212
|
path = ::File.join(run_context.config[:private_key_write_path], path)
|
213
|
-
|
213
|
+
[ nil, path ]
|
214
214
|
else
|
215
215
|
raise "Could not find key #{path} and Chef::Config.private_key_write_path is not set."
|
216
216
|
end
|
217
217
|
elsif ::File.exist?(path)
|
218
|
-
|
218
|
+
[ IO.read(path), path ]
|
219
219
|
else
|
220
|
-
|
220
|
+
[ nil, path ]
|
221
221
|
end
|
222
222
|
end
|
223
223
|
|
@@ -6,13 +6,13 @@ require_relative "../../cheffish/key_formatter"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class PublicKey < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :public_key
|
10
10
|
|
11
11
|
allowed_actions :create, :delete, :nothing
|
12
12
|
default_action :create
|
13
13
|
|
14
14
|
property :path, String, name_property: true
|
15
|
-
property :format,
|
15
|
+
property :format, %i{pem der openssh}, default: :openssh
|
16
16
|
|
17
17
|
property :source_key
|
18
18
|
property :source_key_path, String
|
@@ -24,9 +24,10 @@ class Chef
|
|
24
24
|
end
|
25
25
|
|
26
26
|
action :create do
|
27
|
-
|
27
|
+
unless new_source_key
|
28
28
|
raise "No source key specified"
|
29
29
|
end
|
30
|
+
|
30
31
|
desired_output = encode_public_key(new_source_key)
|
31
32
|
if Array(current_resource.action) == [ :delete ] || desired_output != IO.read(new_resource.path)
|
32
33
|
converge_by "write #{new_resource.format} public key #{new_resource.path} from #{new_source_key_publicity} key #{new_resource.source_key_path}" do
|
data/lib/cheffish.rb
CHANGED
@@ -98,6 +98,7 @@ module Cheffish
|
|
98
98
|
elsif config[:private_key_paths]
|
99
99
|
config[:private_key_paths].each do |private_key_path|
|
100
100
|
next unless File.exist?(private_key_path)
|
101
|
+
|
101
102
|
Dir.entries(private_key_path).sort.each do |key|
|
102
103
|
ext = File.extname(key)
|
103
104
|
if key == name || ext == "" || ext == ".pem"
|
@@ -91,7 +91,7 @@ module Cheffish
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def json_differences_internal(old_json, new_json, print_values, name, result)
|
94
|
-
if old_json.
|
94
|
+
if old_json.is_a?(Hash) && new_json.is_a?(Hash)
|
95
95
|
removed_keys = old_json.keys.inject({}) { |hash, key| hash[key] = true; hash }
|
96
96
|
new_json.each_pair do |new_key, new_value|
|
97
97
|
if old_json.key?(new_key)
|
@@ -101,18 +101,18 @@ module Cheffish
|
|
101
101
|
end
|
102
102
|
else
|
103
103
|
if print_values
|
104
|
-
result << " add #{name ==
|
104
|
+
result << " add #{name == "" ? new_key : "#{name}.#{new_key}"} = #{new_value.inspect}"
|
105
105
|
else
|
106
|
-
result << " add #{name ==
|
106
|
+
result << " add #{name == "" ? new_key : "#{name}.#{new_key}"}"
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
110
110
|
removed_keys.keys.each do |removed_key|
|
111
|
-
result << " remove #{name ==
|
111
|
+
result << " remove #{name == "" ? removed_key : "#{name}.#{removed_key}"}"
|
112
112
|
end
|
113
113
|
else
|
114
|
-
old_json = old_json.to_s if old_json.
|
115
|
-
new_json = new_json.to_s if new_json.
|
114
|
+
old_json = old_json.to_s if old_json.is_a?(Symbol)
|
115
|
+
new_json = new_json.to_s if new_json.is_a?(Symbol)
|
116
116
|
if old_json != new_json
|
117
117
|
if print_values
|
118
118
|
result << " update #{name} from #{old_json.inspect} to #{new_json.inspect}"
|
@@ -134,8 +134,8 @@ module Cheffish
|
|
134
134
|
end
|
135
135
|
|
136
136
|
modifiers.each do |path, value|
|
137
|
-
path = [path]
|
138
|
-
path = path.map
|
137
|
+
path = [path] unless path.is_a?(Array)
|
138
|
+
path = path.map(&:to_s)
|
139
139
|
parent = 0.upto(path.size - 2).inject(json) do |hash, index|
|
140
140
|
if hash.nil?
|
141
141
|
nil
|
@@ -148,6 +148,7 @@ module Cheffish
|
|
148
148
|
if !parent.nil? && !parent.is_a?(Hash)
|
149
149
|
raise "Attempt to set #{path} to #{value} when #{path[0..-2]} is not a hash"
|
150
150
|
end
|
151
|
+
|
151
152
|
existing_value = parent ? parent[path[-1]] : nil
|
152
153
|
|
153
154
|
if value.is_a?(Proc)
|
@@ -158,7 +159,7 @@ module Cheffish
|
|
158
159
|
else
|
159
160
|
# Create parent if necessary, overwriting values
|
160
161
|
parent = path[0..-2].inject(json) do |hash, path_part|
|
161
|
-
hash[path_part] = {}
|
162
|
+
hash[path_part] = {} unless hash[path_part]
|
162
163
|
hash[path_part]
|
163
164
|
end
|
164
165
|
if path.size > 0
|
@@ -173,6 +174,7 @@ module Cheffish
|
|
173
174
|
|
174
175
|
def apply_run_list_modifiers(add_to_run_list, delete_from_run_list, run_list)
|
175
176
|
return run_list if (!add_to_run_list || add_to_run_list.size == 0) && (!delete_from_run_list || !delete_from_run_list.size)
|
177
|
+
|
176
178
|
delete_from_run_list ||= []
|
177
179
|
add_to_run_list ||= []
|
178
180
|
|
@@ -191,7 +193,7 @@ module Cheffish
|
|
191
193
|
# because found_desired will be less than add_to_run_list_index. The result will
|
192
194
|
# be X, A, B, Y, Z.
|
193
195
|
if found_desired >= add_to_run_list_index
|
194
|
-
result += add_to_run_list[add_to_run_list_index..found_desired].map
|
196
|
+
result += add_to_run_list[add_to_run_list_index..found_desired].map(&:to_s)
|
195
197
|
add_to_run_list_index = found_desired + 1
|
196
198
|
end
|
197
199
|
else
|
@@ -204,7 +206,7 @@ module Cheffish
|
|
204
206
|
end
|
205
207
|
|
206
208
|
# Copy any remaining desired items at the end
|
207
|
-
result += add_to_run_list[add_to_run_list_index..-1].map
|
209
|
+
result += add_to_run_list[add_to_run_list_index..-1].map(&:to_s)
|
208
210
|
result
|
209
211
|
end
|
210
212
|
|
@@ -14,7 +14,7 @@ module Cheffish
|
|
14
14
|
include Chef::DSL::Recipe
|
15
15
|
|
16
16
|
def initialize(node = nil, events = nil, **chef_config)
|
17
|
-
|
17
|
+
unless node
|
18
18
|
node = Chef::Node.new
|
19
19
|
node.name "basic_chef_client"
|
20
20
|
node.automatic[:platform] = "basic_chef_client"
|
@@ -31,7 +31,7 @@ module Cheffish
|
|
31
31
|
case events
|
32
32
|
when Array
|
33
33
|
events.each { |e| dispatcher.register(e) } if events
|
34
|
-
when !nil
|
34
|
+
when !nil # rubocop: disable Lint/LiteralAsCondition
|
35
35
|
dispatcher.register(events)
|
36
36
|
end
|
37
37
|
@run_context = Chef::RunContext.new(node, {}, dispatcher)
|
@@ -24,9 +24,10 @@ module Cheffish
|
|
24
24
|
end
|
25
25
|
else
|
26
26
|
# Create the actor if it's missing
|
27
|
-
|
27
|
+
unless new_public_key
|
28
28
|
raise "You must specify a public key to create a #{actor_type}! Use the private_key resource to create a key, and pass it in with source_key_path."
|
29
29
|
end
|
30
|
+
|
30
31
|
description = [ "create #{actor_type} #{new_resource.name} at #{actor_path}" ] + differences
|
31
32
|
converge_by description do
|
32
33
|
result = rest.post((actor_path).to_s, normalize_for_post(new_json))
|
data/lib/cheffish/chef_run.rb
CHANGED
@@ -34,15 +34,14 @@ module Cheffish
|
|
34
34
|
def client
|
35
35
|
@client ||= begin
|
36
36
|
chef_config = self.chef_config.dup
|
37
|
-
chef_config[:log_level] ||= :debug
|
38
|
-
chef_config[:verbose_logging] = false
|
37
|
+
chef_config[:log_level] ||= :debug unless chef_config.key?(:log_level)
|
38
|
+
chef_config[:verbose_logging] = false unless chef_config.key?(:verbose_logging)
|
39
39
|
chef_config[:stdout] = StringIOTee.new(chef_config[:stdout])
|
40
40
|
chef_config[:stderr] = StringIOTee.new(chef_config[:stderr])
|
41
41
|
chef_config[:log_location] = StringIOTee.new(chef_config[:log_location])
|
42
42
|
@client = ::Cheffish::BasicChefClient.new(nil,
|
43
43
|
[ event_sink, Chef::Formatters.new(:doc, chef_config[:stdout], chef_config[:stderr]) ],
|
44
|
-
chef_config
|
45
|
-
)
|
44
|
+
chef_config)
|
46
45
|
end
|
47
46
|
end
|
48
47
|
|
@@ -125,14 +124,14 @@ module Cheffish
|
|
125
124
|
message << "--- Chef Client Output ---\n"
|
126
125
|
message << "--- ---\n"
|
127
126
|
message << stdout
|
128
|
-
message << "\n"
|
127
|
+
message << "\n" unless stdout.end_with?("\n")
|
129
128
|
end
|
130
129
|
if stderr && !stderr.empty?
|
131
130
|
message << "--- ---\n"
|
132
131
|
message << "--- Chef Client Error Output ---\n"
|
133
132
|
message << "--- ---\n"
|
134
133
|
message << stderr
|
135
|
-
message << "\n"
|
134
|
+
message << "\n" unless stderr.end_with?("\n")
|
136
135
|
end
|
137
136
|
if logs && !logs.empty?
|
138
137
|
message << "--- ---\n"
|
@@ -55,15 +55,7 @@ module Cheffish
|
|
55
55
|
hexes = Digest::MD5.hexdigest(data)
|
56
56
|
hexes.scan(/../).join(":")
|
57
57
|
when :pkcs8sha1fingerprint
|
58
|
-
|
59
|
-
raise "PKCS8 SHA1 not supported in Ruby #{RUBY_VERSION}"
|
60
|
-
end
|
61
|
-
require "openssl_pkcs8"
|
62
|
-
pkcs8_pem = key.to_pem_pkcs8
|
63
|
-
pkcs8_base64 = pkcs8_pem.split("\n").reject { |l| l =~ /^-----/ }
|
64
|
-
pkcs8_data = Base64.decode64(pkcs8_base64.join)
|
65
|
-
hexes = Digest::SHA1.hexdigest(pkcs8_data)
|
66
|
-
hexes.scan(/../).join(":")
|
58
|
+
raise "PKCS8 SHA1 not supported by Ruby 2.0 and later"
|
67
59
|
else
|
68
60
|
raise "Unrecognized key format #{format}"
|
69
61
|
end
|
@@ -27,7 +27,7 @@ module Cheffish
|
|
27
27
|
result_configs = []
|
28
28
|
configs.each do |config|
|
29
29
|
value = config[name]
|
30
|
-
|
30
|
+
unless value.nil?
|
31
31
|
if value.respond_to?(:keys)
|
32
32
|
result_configs << value
|
33
33
|
elsif result_configs.size > 0
|
@@ -63,7 +63,7 @@ module Cheffish
|
|
63
63
|
alias_method :has_key?, :key?
|
64
64
|
|
65
65
|
def keys
|
66
|
-
configs.flat_map
|
66
|
+
configs.flat_map(&:keys).uniq
|
67
67
|
end
|
68
68
|
|
69
69
|
def values
|
@@ -39,7 +39,7 @@ module Cheffish
|
|
39
39
|
attribute "tags" do |existing_tags|
|
40
40
|
existing_tags ||= []
|
41
41
|
tags.each do |tag|
|
42
|
-
|
42
|
+
unless existing_tags.include?(tag.to_s)
|
43
43
|
existing_tags << tag.to_s
|
44
44
|
end
|
45
45
|
end
|
@@ -64,8 +64,8 @@ module Cheffish
|
|
64
64
|
if tags.size == 0
|
65
65
|
attribute("tags")
|
66
66
|
else
|
67
|
-
tags = tags[0] if tags.size == 1 && tags[0].
|
68
|
-
attribute("tags", tags.map
|
67
|
+
tags = tags[0] if tags.size == 1 && tags[0].is_a?(Array)
|
68
|
+
attribute("tags", tags.map(&:to_s))
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -80,6 +80,7 @@ module Cheffish
|
|
80
80
|
if recipes.size == 0
|
81
81
|
raise ArgumentError, "At least one recipe must be specified"
|
82
82
|
end
|
83
|
+
|
83
84
|
@run_list_modifiers ||= []
|
84
85
|
@run_list_modifiers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") }
|
85
86
|
end
|
@@ -88,6 +89,7 @@ module Cheffish
|
|
88
89
|
if roles.size == 0
|
89
90
|
raise ArgumentError, "At least one role must be specified"
|
90
91
|
end
|
92
|
+
|
91
93
|
@run_list_modifiers ||= []
|
92
94
|
@run_list_modifiers += roles.map { |role| Chef::RunList::RunListItem.new("role[#{role}]") }
|
93
95
|
end
|
@@ -96,6 +98,7 @@ module Cheffish
|
|
96
98
|
if recipes.size == 0
|
97
99
|
raise ArgumentError, "At least one recipe must be specified"
|
98
100
|
end
|
101
|
+
|
99
102
|
@run_list_removers ||= []
|
100
103
|
@run_list_removers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") }
|
101
104
|
end
|
@@ -104,6 +107,7 @@ module Cheffish
|
|
104
107
|
if roles.size == 0
|
105
108
|
raise ArgumentError, "At least one role must be specified"
|
106
109
|
end
|
110
|
+
|
107
111
|
@run_list_removers ||= []
|
108
112
|
@run_list_removers += roles.map { |role| Chef::RunList::RunListItem.new("role[#{role}]") }
|
109
113
|
end
|
data/lib/cheffish/recipe_dsl.rb
CHANGED
@@ -52,7 +52,7 @@ class Chef
|
|
52
52
|
|
53
53
|
# Create the data store chef-zero will use
|
54
54
|
options[:data_store] ||= begin
|
55
|
-
|
55
|
+
unless options[:chef_repo_path]
|
56
56
|
raise "chef_repo_path must be specified to with_chef_local_server"
|
57
57
|
end
|
58
58
|
|
@@ -63,7 +63,7 @@ class Chef
|
|
63
63
|
symbol_key = "#{type}_path".to_sym
|
64
64
|
|
65
65
|
options[symbol_key] ||= begin
|
66
|
-
if options[:chef_repo_path].
|
66
|
+
if options[:chef_repo_path].is_a?(String)
|
67
67
|
Chef::Util::PathHelper.join(options[:chef_repo_path], "#{type}s")
|
68
68
|
else
|
69
69
|
options[:chef_repo_path].map { |path| Chef::Util::PathHelper.join(path, "#{type}s") }
|
@@ -5,16 +5,16 @@ RSpec::Matchers.define :have_updated do |resource_name, *expected_actions|
|
|
5
5
|
@recipe = recipe
|
6
6
|
actual = @recipe.event_sink.events
|
7
7
|
actual_actions = actual.select { |event, resource, action| event == :resource_updated && resource.to_s == resource_name }
|
8
|
-
|
8
|
+
.map { |event, resource, action| action }
|
9
9
|
expect(actual_actions).to eq(expected_actions)
|
10
10
|
end
|
11
11
|
|
12
12
|
failure_message do
|
13
13
|
actual = @recipe.event_sink.events
|
14
14
|
updates = actual.select { |event, resource, action| event == :resource_updated }.to_a
|
15
|
-
result = "expected that the chef_run would #{expected_actions.join(
|
15
|
+
result = "expected that the chef_run would #{expected_actions.join(",")} #{resource_name}."
|
16
16
|
if updates.size > 0
|
17
|
-
result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(
|
17
|
+
result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(", ")}"
|
18
18
|
else
|
19
19
|
result << " Nothing was updated."
|
20
20
|
end
|
@@ -24,9 +24,9 @@ RSpec::Matchers.define :have_updated do |resource_name, *expected_actions|
|
|
24
24
|
failure_message_when_negated do
|
25
25
|
actual = @recipe.event_sink.events
|
26
26
|
updates = actual.select { |event, resource, action| event == :resource_updated }.to_a
|
27
|
-
result = "expected that the chef_run would not #{expected_actions.join(
|
27
|
+
result = "expected that the chef_run would not #{expected_actions.join(",")} #{resource_name}."
|
28
28
|
if updates.size > 0
|
29
|
-
result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(
|
29
|
+
result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(", ")}"
|
30
30
|
else
|
31
31
|
result << " Nothing was updated."
|
32
32
|
end
|
@@ -12,6 +12,7 @@ module Cheffish
|
|
12
12
|
::RSpec.shared_context "with a chef repo" do
|
13
13
|
before :each do
|
14
14
|
raise "Can only create one directory per test" if @repository_dir
|
15
|
+
|
15
16
|
@repository_dir = Dir.mktmpdir("chef_repo")
|
16
17
|
Chef::Config.chef_repo_path = @repository_dir
|
17
18
|
%w{client cookbook data_bag environment node role user}.each do |object_name|
|
data/lib/cheffish/version.rb
CHANGED
@@ -39,24 +39,26 @@ describe "Cheffish fingerprint key formatter" do
|
|
39
39
|
|
40
40
|
context "when computing key fingperprints" do
|
41
41
|
|
42
|
-
it "
|
43
|
-
expect
|
44
|
-
"88:7e:3a:bd:26:9f:b5:c5:d8:ae:52:f9:df:0b:64:a4:5c:17:0a:87")
|
42
|
+
it "raises when passing a PKCS#8 SHA1 private key fingerprint" do
|
43
|
+
expect { key_to_format(sample_private_key, :pkcs8sha1fingerprint) }.to raise_error
|
45
44
|
end
|
46
45
|
|
47
46
|
it "computes the PKCS#1 MD5 public key fingerprint correctly" do
|
48
47
|
expect(key_to_format(sample_public_key, :pkcs1md5fingerprint)).to eq(
|
49
|
-
"1f:e8:da:c1:16:c3:72:7d:90:e2:b7:64:c4:b4:55:20"
|
48
|
+
"1f:e8:da:c1:16:c3:72:7d:90:e2:b7:64:c4:b4:55:20"
|
49
|
+
)
|
50
50
|
end
|
51
51
|
|
52
52
|
it "computes the RFC4716 MD5 public key fingerprint correctly" do
|
53
53
|
expect(key_to_format(sample_public_key, :rfc4716md5fingerprint)).to eq(
|
54
|
-
"b0:13:4f:da:cf:8c:dc:a7:4a:1f:d2:3a:51:92:cf:6b"
|
54
|
+
"b0:13:4f:da:cf:8c:dc:a7:4a:1f:d2:3a:51:92:cf:6b"
|
55
|
+
)
|
55
56
|
end
|
56
57
|
|
57
58
|
it "defaults to the PKCS#1 MD5 public key fingerprint" do
|
58
59
|
expect(key_to_format(sample_public_key, :fingerprint)).to eq(
|
59
|
-
key_to_format(sample_public_key, :pkcs1md5fingerprint)
|
60
|
+
key_to_format(sample_public_key, :pkcs1md5fingerprint)
|
61
|
+
)
|
60
62
|
end
|
61
63
|
|
62
64
|
end
|
@@ -160,7 +160,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
160
160
|
it 'Converging chef_acl "nodes/x" with rights [ :read, :create, :update, :delete, :grant ] modifies all rights' do
|
161
161
|
expect_recipe do
|
162
162
|
chef_acl "nodes/x" do
|
163
|
-
rights
|
163
|
+
rights %i{create read update delete grant}, users: %w{u1 u2}, clients: %w{c1}, groups: %w{g1}
|
164
164
|
end
|
165
165
|
end.to be_updated
|
166
166
|
expect(get("nodes/x/_acl")).to partially_match(
|
@@ -229,11 +229,11 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
229
229
|
end
|
230
230
|
end.to be_updated
|
231
231
|
expect(get("nodes/x/_acl")).to partially_match(
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
232
|
+
"create" => { "actors" => exclude("foo") },
|
233
|
+
"read" => { "actors" => exclude("foo") },
|
234
|
+
"update" => { "actors" => exclude("foo") },
|
235
|
+
"delete" => { "actors" => exclude("foo") },
|
236
|
+
"grant" => { "actors" => exclude("foo") }
|
237
237
|
)
|
238
238
|
end
|
239
239
|
end
|
@@ -361,7 +361,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
361
361
|
end.to be_updated
|
362
362
|
%w{clients containers cookbooks data environments groups nodes roles}.each do |type|
|
363
363
|
expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
|
364
|
-
|
364
|
+
"read" => { "actors" => %w{u} }
|
365
|
+
)
|
365
366
|
end
|
366
367
|
end
|
367
368
|
end
|
@@ -408,7 +409,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
408
409
|
end.to be_updated
|
409
410
|
%w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type|
|
410
411
|
expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
|
411
|
-
|
412
|
+
"read" => { "actors" => %w{u} }
|
413
|
+
)
|
412
414
|
end
|
413
415
|
end
|
414
416
|
|
@@ -420,7 +422,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
420
422
|
end.to be_updated
|
421
423
|
%w{clients containers cookbooks data environments groups nodes roles}.each do |type|
|
422
424
|
expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
|
423
|
-
|
425
|
+
"read" => { "actors" => %w{u} }
|
426
|
+
)
|
424
427
|
end
|
425
428
|
end
|
426
429
|
|
@@ -447,7 +450,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
447
450
|
chef_acl "/organizations/foo/cookbooks/x/1.0.0" do
|
448
451
|
rights :read, users: %w{u}
|
449
452
|
end
|
450
|
-
end.to raise_error(
|
453
|
+
end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/cookbooks/x})
|
451
454
|
end
|
452
455
|
|
453
456
|
it "chef_acl '/organizations/foo/cookbooks/*/*' raises an error" do
|
@@ -456,7 +459,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
456
459
|
chef_acl "/organizations/foo/cookbooks/*/*" do
|
457
460
|
rights :read, users: %w{u}
|
458
461
|
end
|
459
|
-
end.to raise_error(
|
462
|
+
end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/cookbooks/*})
|
460
463
|
end
|
461
464
|
|
462
465
|
it 'chef_acl "/organizations/foo/data/x/y" raises an error' do
|
@@ -464,7 +467,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
464
467
|
chef_acl "/organizations/foo/data/x/y" do
|
465
468
|
rights :read, users: %w{u}
|
466
469
|
end
|
467
|
-
end.to raise_error(
|
470
|
+
end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/data/x})
|
468
471
|
end
|
469
472
|
|
470
473
|
it 'chef_acl "/organizations/foo/data/*/*" raises an error' do
|
@@ -473,7 +476,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
473
476
|
chef_acl "/organizations/foo/data/*/*" do
|
474
477
|
rights :read, users: %w{u}
|
475
478
|
end
|
476
|
-
end.to raise_error(
|
479
|
+
end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/data/*})
|
477
480
|
end
|
478
481
|
|
479
482
|
it 'chef_acl "/organizations/foo" changes the acl' do
|
@@ -609,7 +612,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
609
612
|
end.to be_updated
|
610
613
|
%w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type|
|
611
614
|
expect(get("#{type}/x/_acl")).to partially_match(
|
612
|
-
|
615
|
+
"read" => { "actors" => %w{u} }
|
616
|
+
)
|
613
617
|
end
|
614
618
|
end
|
615
619
|
|
@@ -621,7 +625,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
621
625
|
end.to be_updated
|
622
626
|
%w{clients containers cookbooks data environments groups nodes roles}.each do |type|
|
623
627
|
expect(get("#{type}/x/_acl")).to partially_match(
|
624
|
-
|
628
|
+
"read" => { "actors" => %w{u} }
|
629
|
+
)
|
625
630
|
end
|
626
631
|
end
|
627
632
|
|
@@ -633,7 +638,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
633
638
|
end.to be_updated
|
634
639
|
%w{admins billing-admins clients users x}.each do |n|
|
635
640
|
expect(get("groups/#{n}/_acl")).to partially_match(
|
636
|
-
|
641
|
+
"read" => { "actors" => %w{u} }
|
642
|
+
)
|
637
643
|
end
|
638
644
|
end
|
639
645
|
|
@@ -713,7 +719,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
713
719
|
end.to be_updated
|
714
720
|
%w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type|
|
715
721
|
expect(get("/organizations/foo/containers/#{type}/_acl")).to partially_match(
|
716
|
-
|
722
|
+
"read" => { "actors" => %w{u} }
|
723
|
+
)
|
717
724
|
end
|
718
725
|
end
|
719
726
|
|
@@ -768,7 +775,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
768
775
|
end.to be_updated
|
769
776
|
%w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type|
|
770
777
|
expect(get("containers/#{type}/_acl")).to partially_match(
|
771
|
-
|
778
|
+
"read" => { "actors" => %w{u} }
|
779
|
+
)
|
772
780
|
end
|
773
781
|
end
|
774
782
|
end
|
@@ -820,7 +828,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
820
828
|
it 'chef_acl with remove_rights [ :create, :read ], "u", "c", "g" removes all three' do
|
821
829
|
expect_recipe do
|
822
830
|
chef_acl "nodes/x" do
|
823
|
-
remove_rights
|
831
|
+
remove_rights %i{create read}, users: %w{u}, clients: %w{c}, groups: %w{g}
|
824
832
|
end
|
825
833
|
end.to be_updated
|
826
834
|
expect(get("nodes/x/_acl")).to partially_match(
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cheffish
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 15.0.
|
4
|
+
version: 15.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef Software Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-zero
|