chef-zero 15.0.17 → 15.0.21
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 +36 -31
- data/LICENSE +201 -201
- data/Rakefile +73 -68
- data/bin/chef-zero +111 -111
- data/chef-zero.gemspec +34 -33
- data/lib/chef_zero/chef_data/acl_path.rb +140 -140
- data/lib/chef_zero/chef_data/cookbook_data.rb +237 -237
- data/lib/chef_zero/chef_data/data_normalizer.rb +276 -276
- data/lib/chef_zero/chef_data/default_creator.rb +476 -476
- data/lib/chef_zero/data_store/data_already_exists_error.rb +29 -29
- data/lib/chef_zero/data_store/data_error.rb +32 -32
- data/lib/chef_zero/data_store/data_not_found_error.rb +29 -29
- data/lib/chef_zero/data_store/default_facade.rb +143 -147
- data/lib/chef_zero/data_store/interface_v1.rb +67 -67
- data/lib/chef_zero/data_store/interface_v2.rb +18 -18
- data/lib/chef_zero/data_store/memory_store.rb +33 -33
- data/lib/chef_zero/data_store/memory_store_v2.rb +159 -159
- data/lib/chef_zero/data_store/raw_file_store.rb +143 -143
- data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +150 -150
- data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +105 -105
- data/lib/chef_zero/dist.rb +9 -9
- data/lib/chef_zero/endpoints/acl_endpoint.rb +39 -39
- data/lib/chef_zero/endpoints/acls_endpoint.rb +41 -41
- data/lib/chef_zero/endpoints/actor_default_key_endpoint.rb +78 -78
- data/lib/chef_zero/endpoints/actor_endpoint.rb +184 -184
- data/lib/chef_zero/endpoints/actor_key_endpoint.rb +62 -62
- data/lib/chef_zero/endpoints/actor_keys_endpoint.rb +129 -129
- data/lib/chef_zero/endpoints/actors_endpoint.rb +104 -104
- data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +32 -32
- data/lib/chef_zero/endpoints/container_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/containers_endpoint.rb +25 -25
- data/lib/chef_zero/endpoints/controls_endpoint.rb +16 -16
- data/lib/chef_zero/endpoints/cookbook_artifact_endpoint.rb +24 -24
- data/lib/chef_zero/endpoints/cookbook_artifact_identifier_endpoint.rb +68 -68
- data/lib/chef_zero/endpoints/cookbook_artifacts_endpoint.rb +34 -34
- data/lib/chef_zero/endpoints/cookbook_endpoint.rb +39 -39
- data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +136 -136
- data/lib/chef_zero/endpoints/cookbooks_base.rb +80 -80
- data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +19 -19
- data/lib/chef_zero/endpoints/data_bag_endpoint.rb +45 -45
- data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +25 -25
- data/lib/chef_zero/endpoints/data_bags_endpoint.rb +23 -23
- data/lib/chef_zero/endpoints/dummy_endpoint.rb +29 -29
- data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +24 -24
- data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +126 -126
- data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/environment_endpoint.rb +33 -33
- data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +23 -23
- data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/environment_role_endpoint.rb +36 -36
- data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/group_endpoint.rb +20 -20
- data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -13
- data/lib/chef_zero/endpoints/license_endpoint.rb +25 -25
- data/lib/chef_zero/endpoints/node_endpoint.rb +34 -34
- data/lib/chef_zero/endpoints/node_identifiers_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/nodes_endpoint.rb +34 -34
- data/lib/chef_zero/endpoints/not_found_endpoint.rb +11 -11
- data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +30 -30
- data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -26
- data/lib/chef_zero/endpoints/organization_endpoint.rb +47 -47
- data/lib/chef_zero/endpoints/organization_user_base.rb +15 -15
- data/lib/chef_zero/endpoints/organization_user_default_key_endpoint.rb +16 -16
- data/lib/chef_zero/endpoints/organization_user_endpoint.rb +26 -26
- data/lib/chef_zero/endpoints/organization_user_key_endpoint.rb +17 -17
- data/lib/chef_zero/endpoints/organization_user_keys_endpoint.rb +17 -17
- data/lib/chef_zero/endpoints/organization_users_endpoint.rb +43 -43
- data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -20
- data/lib/chef_zero/endpoints/organizations_endpoint.rb +61 -61
- data/lib/chef_zero/endpoints/policies_endpoint.rb +26 -26
- data/lib/chef_zero/endpoints/policy_endpoint.rb +24 -24
- data/lib/chef_zero/endpoints/policy_group_endpoint.rb +46 -46
- data/lib/chef_zero/endpoints/policy_group_policy_endpoint.rb +83 -83
- data/lib/chef_zero/endpoints/policy_groups_endpoint.rb +38 -38
- data/lib/chef_zero/endpoints/policy_revision_endpoint.rb +66 -66
- data/lib/chef_zero/endpoints/policy_revisions_endpoint.rb +15 -15
- data/lib/chef_zero/endpoints/principal_endpoint.rb +55 -55
- data/lib/chef_zero/endpoints/rest_list_endpoint.rb +42 -42
- data/lib/chef_zero/endpoints/rest_object_endpoint.rb +78 -78
- data/lib/chef_zero/endpoints/role_endpoint.rb +16 -16
- data/lib/chef_zero/endpoints/role_environments_endpoint.rb +14 -14
- data/lib/chef_zero/endpoints/sandbox_endpoint.rb +27 -27
- data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +51 -51
- data/lib/chef_zero/endpoints/search_endpoint.rb +208 -208
- data/lib/chef_zero/endpoints/searches_endpoint.rb +18 -18
- data/lib/chef_zero/endpoints/server_api_version_endpoint.rb +14 -14
- data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -30
- data/lib/chef_zero/endpoints/universe_endpoint.rb +15 -15
- data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +41 -41
- data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -19
- data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -19
- data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/version_endpoint.rb +13 -13
- data/lib/chef_zero/log.rb +7 -7
- data/lib/chef_zero/rest_base.rb +332 -332
- data/lib/chef_zero/rest_error_response.rb +11 -11
- data/lib/chef_zero/rest_request.rb +84 -88
- data/lib/chef_zero/rest_router.rb +72 -72
- data/lib/chef_zero/rspec.rb +355 -355
- data/lib/chef_zero/server.rb +730 -730
- data/lib/chef_zero/socketless_server_map.rb +92 -93
- data/lib/chef_zero/solr/query/binary_operator.rb +52 -52
- data/lib/chef_zero/solr/query/phrase.rb +23 -23
- data/lib/chef_zero/solr/query/range_query.rb +46 -46
- data/lib/chef_zero/solr/query/regexpable_query.rb +30 -30
- data/lib/chef_zero/solr/query/subquery.rb +37 -37
- data/lib/chef_zero/solr/query/term.rb +45 -45
- data/lib/chef_zero/solr/query/unary_operator.rb +41 -41
- data/lib/chef_zero/solr/solr_doc.rb +53 -53
- data/lib/chef_zero/solr/solr_parser.rb +208 -208
- data/lib/chef_zero/version.rb +3 -3
- data/lib/chef_zero.rb +10 -10
- data/spec/run_oc_pedant.rb +226 -226
- data/spec/search_spec.rb +36 -36
- data/spec/server_spec.rb +96 -96
- data/spec/socketless_server_map_spec.rb +74 -74
- data/spec/support/oc_pedant.rb +149 -149
- data/spec/support/secrets.json +6 -6
- data/spec/support/stickywicket.pem +27 -27
- metadata +35 -18
data/bin/chef-zero
CHANGED
@@ -1,111 +1,111 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# Trap interrupts to quit cleanly.
|
4
|
-
Signal.trap("INT") { exit 1 }
|
5
|
-
|
6
|
-
require "rubygems" unless defined?(Gem)
|
7
|
-
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
8
|
-
|
9
|
-
require "chef_zero/log"
|
10
|
-
require "chef_zero/dist"
|
11
|
-
require "chef_zero/version"
|
12
|
-
require "chef_zero/server"
|
13
|
-
require "chef_zero/data_store/raw_file_store"
|
14
|
-
require "optparse" unless defined?(OptionParser)
|
15
|
-
|
16
|
-
def parse_port(port)
|
17
|
-
array = []
|
18
|
-
port.split(",").each do |part|
|
19
|
-
a, b = part.split("-", 2)
|
20
|
-
if b
|
21
|
-
array = array.concat(a.to_i.upto(b.to_i).to_a)
|
22
|
-
else
|
23
|
-
array = array.
|
24
|
-
end
|
25
|
-
end
|
26
|
-
array
|
27
|
-
end
|
28
|
-
|
29
|
-
options = {}
|
30
|
-
|
31
|
-
OptionParser.new do |opts|
|
32
|
-
opts.banner = "Usage: #{ChefZero::Dist::CLIENT} [ARGS]"
|
33
|
-
|
34
|
-
opts.on("-H", "--host HOST", "Host to bind to (default: 127.0.0.1)") do |value|
|
35
|
-
options[:host] ||= []
|
36
|
-
options[:host] << value
|
37
|
-
end
|
38
|
-
|
39
|
-
opts.on("-p", "--port PORT", "Port to listen on (e.g. 8889, or 8500-8600 or 8885,8888)") do |value|
|
40
|
-
options[:port] ||= []
|
41
|
-
options[:port] += parse_port(value)
|
42
|
-
end
|
43
|
-
|
44
|
-
opts.on("--[no-]generate-keys", "Whether to generate actual keys or fake it (faster). Default: false.") do |value|
|
45
|
-
options[:generate_real_keys] = value
|
46
|
-
end
|
47
|
-
|
48
|
-
opts.on("-d", "--daemon", "Run as a daemon process") do |value|
|
49
|
-
options[:daemon] = value
|
50
|
-
end
|
51
|
-
|
52
|
-
opts.on("-l", "--log-level LEVEL", "Set the output log level") do |value|
|
53
|
-
options[:log_level] = value
|
54
|
-
end
|
55
|
-
|
56
|
-
opts.on("--log-file FILE", "Log to a file") do |value|
|
57
|
-
options[:log_file] = value
|
58
|
-
end
|
59
|
-
|
60
|
-
opts.on("--enterprise", "Whether to run in enterprise mode") do |value|
|
61
|
-
options[:single_org] = nil
|
62
|
-
options[:osc_compat] = false
|
63
|
-
end
|
64
|
-
|
65
|
-
opts.on("--multi-org", "Whether to run in multi-org mode") do |value|
|
66
|
-
options[:single_org] = nil
|
67
|
-
end
|
68
|
-
|
69
|
-
opts.on("--file-store PATH", "Persist data to files at the given path") do |value|
|
70
|
-
options[:data_store] = ChefZero::DataStore::RawFileStore.new(value)
|
71
|
-
end
|
72
|
-
|
73
|
-
opts.on("--[no-]ssl", "Use SSL with self-signed certificate(Auto generate before every run). Default: false.") do |value|
|
74
|
-
options[:ssl] = value
|
75
|
-
end
|
76
|
-
|
77
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
78
|
-
puts opts
|
79
|
-
exit
|
80
|
-
end
|
81
|
-
|
82
|
-
opts.on_tail("--version", "Show version") do
|
83
|
-
puts ChefZero::VERSION
|
84
|
-
exit
|
85
|
-
end
|
86
|
-
end.parse!
|
87
|
-
|
88
|
-
if options[:data_store]
|
89
|
-
options[:data_store] = ChefZero::DataStore::DefaultFacade.new(options[:data_store], options[:single_org], false)
|
90
|
-
end
|
91
|
-
|
92
|
-
if options[:log_file]
|
93
|
-
ChefZero::Log.init(options[:log_file])
|
94
|
-
end
|
95
|
-
|
96
|
-
server = ChefZero::Server.new(options)
|
97
|
-
|
98
|
-
if options[:daemon]
|
99
|
-
if Process.respond_to?(:daemon)
|
100
|
-
Process.daemon(true)
|
101
|
-
server.start(true)
|
102
|
-
else
|
103
|
-
if ENV["OS"] == "Windows_NT"
|
104
|
-
abort "Daemonization is not supported on Windows. Running 'start #{ChefZero::Dist::CLIENT}' will fork the process."
|
105
|
-
else
|
106
|
-
abort "Process.daemon requires Ruby >= 1.9"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
else
|
110
|
-
server.start(true)
|
111
|
-
end
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Trap interrupts to quit cleanly.
|
4
|
+
Signal.trap("INT") { exit 1 }
|
5
|
+
|
6
|
+
require "rubygems" unless defined?(Gem)
|
7
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
8
|
+
|
9
|
+
require "chef_zero/log"
|
10
|
+
require "chef_zero/dist"
|
11
|
+
require "chef_zero/version"
|
12
|
+
require "chef_zero/server"
|
13
|
+
require "chef_zero/data_store/raw_file_store"
|
14
|
+
require "optparse" unless defined?(OptionParser)
|
15
|
+
|
16
|
+
def parse_port(port)
|
17
|
+
array = []
|
18
|
+
port.split(",").each do |part|
|
19
|
+
a, b = part.split("-", 2)
|
20
|
+
if b
|
21
|
+
array = array.concat(a.to_i.upto(b.to_i).to_a)
|
22
|
+
else
|
23
|
+
array = array.push(a.to_i)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
array
|
27
|
+
end
|
28
|
+
|
29
|
+
options = {}
|
30
|
+
|
31
|
+
OptionParser.new do |opts|
|
32
|
+
opts.banner = "Usage: #{ChefZero::Dist::CLIENT} [ARGS]"
|
33
|
+
|
34
|
+
opts.on("-H", "--host HOST", "Host to bind to (default: 127.0.0.1)") do |value|
|
35
|
+
options[:host] ||= []
|
36
|
+
options[:host] << value
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("-p", "--port PORT", "Port to listen on (e.g. 8889, or 8500-8600 or 8885,8888)") do |value|
|
40
|
+
options[:port] ||= []
|
41
|
+
options[:port] += parse_port(value)
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on("--[no-]generate-keys", "Whether to generate actual keys or fake it (faster). Default: false.") do |value|
|
45
|
+
options[:generate_real_keys] = value
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on("-d", "--daemon", "Run as a daemon process") do |value|
|
49
|
+
options[:daemon] = value
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.on("-l", "--log-level LEVEL", "Set the output log level") do |value|
|
53
|
+
options[:log_level] = value
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on("--log-file FILE", "Log to a file") do |value|
|
57
|
+
options[:log_file] = value
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.on("--enterprise", "Whether to run in enterprise mode") do |value|
|
61
|
+
options[:single_org] = nil
|
62
|
+
options[:osc_compat] = false
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on("--multi-org", "Whether to run in multi-org mode") do |value|
|
66
|
+
options[:single_org] = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("--file-store PATH", "Persist data to files at the given path") do |value|
|
70
|
+
options[:data_store] = ChefZero::DataStore::RawFileStore.new(value)
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on("--[no-]ssl", "Use SSL with self-signed certificate(Auto generate before every run). Default: false.") do |value|
|
74
|
+
options[:ssl] = value
|
75
|
+
end
|
76
|
+
|
77
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
78
|
+
puts opts
|
79
|
+
exit
|
80
|
+
end
|
81
|
+
|
82
|
+
opts.on_tail("--version", "Show version") do
|
83
|
+
puts ChefZero::VERSION
|
84
|
+
exit
|
85
|
+
end
|
86
|
+
end.parse!
|
87
|
+
|
88
|
+
if options[:data_store]
|
89
|
+
options[:data_store] = ChefZero::DataStore::DefaultFacade.new(options[:data_store], options[:single_org], false)
|
90
|
+
end
|
91
|
+
|
92
|
+
if options[:log_file]
|
93
|
+
ChefZero::Log.init(options[:log_file])
|
94
|
+
end
|
95
|
+
|
96
|
+
server = ChefZero::Server.new(options)
|
97
|
+
|
98
|
+
if options[:daemon]
|
99
|
+
if Process.respond_to?(:daemon)
|
100
|
+
Process.daemon(true)
|
101
|
+
server.start(true)
|
102
|
+
else
|
103
|
+
if ENV["OS"] == "Windows_NT"
|
104
|
+
abort "Daemonization is not supported on Windows. Running 'start #{ChefZero::Dist::CLIENT}' will fork the process."
|
105
|
+
else
|
106
|
+
abort "Process.daemon requires Ruby >= 1.9"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
else
|
110
|
+
server.start(true)
|
111
|
+
end
|
data/chef-zero.gemspec
CHANGED
@@ -1,33 +1,34 @@
|
|
1
|
-
$:.unshift(__dir__ + "/lib")
|
2
|
-
require "chef_zero/version"
|
3
|
-
|
4
|
-
Gem::Specification.new do |s|
|
5
|
-
s.name = "chef-zero"
|
6
|
-
s.version = ChefZero::VERSION
|
7
|
-
s.summary = "Self-contained, easy-setup, fast-start in-memory Chef server for testing and solo setup purposes"
|
8
|
-
s.description = s.summary
|
9
|
-
s.author = "Chef Software, Inc."
|
10
|
-
s.email = "oss@chef.io"
|
11
|
-
s.homepage = "https://github.com/chef/chef-zero"
|
12
|
-
s.license = "Apache-2.0"
|
13
|
-
|
14
|
-
s.required_ruby_version = ">= 3.0"
|
15
|
-
|
16
|
-
# Note: 7.1.0 does not defaults its cache_format_version to 7.1 but 6.1 instead which gives deprecation warnings
|
17
|
-
# Remove the version constraint when we can upgrade to 7.1.1 post stable release of Activesupport 7.1
|
18
|
-
# Similar issue with 7.0 existed: https://github.com/rails/rails/pull/45293
|
19
|
-
s.add_dependency "activesupport", "
|
20
|
-
s.add_dependency "mixlib-log", ">= 2.0", "< 4.0"
|
21
|
-
s.add_dependency "hashie", ">= 2.0", "<
|
22
|
-
s.add_dependency "uuidtools", "~> 2.1"
|
23
|
-
s.add_dependency "ffi-yajl", "
|
24
|
-
s.add_dependency "rack", "~> 3.1", ">= 3.1.
|
25
|
-
s.add_dependency "rackup", "~> 2.2", ">= 2.2.1"
|
26
|
-
s.add_dependency "
|
27
|
-
|
28
|
-
|
29
|
-
s.
|
30
|
-
s.
|
31
|
-
s.
|
32
|
-
|
33
|
-
|
1
|
+
$:.unshift(__dir__ + "/lib")
|
2
|
+
require "chef_zero/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "chef-zero"
|
6
|
+
s.version = ChefZero::VERSION
|
7
|
+
s.summary = "Self-contained, easy-setup, fast-start in-memory Chef server for testing and solo setup purposes"
|
8
|
+
s.description = s.summary
|
9
|
+
s.author = "Chef Software, Inc."
|
10
|
+
s.email = "oss@chef.io"
|
11
|
+
s.homepage = "https://github.com/chef/chef-zero"
|
12
|
+
s.license = "Apache-2.0"
|
13
|
+
|
14
|
+
s.required_ruby_version = ">= 3.0"
|
15
|
+
|
16
|
+
# Note: 7.1.0 does not defaults its cache_format_version to 7.1 but 6.1 instead which gives deprecation warnings
|
17
|
+
# Remove the version constraint when we can upgrade to 7.1.1 post stable release of Activesupport 7.1
|
18
|
+
# Similar issue with 7.0 existed: https://github.com/rails/rails/pull/45293
|
19
|
+
s.add_dependency "activesupport", ">= 7", "< 8.1"
|
20
|
+
s.add_dependency "mixlib-log", ">= 2.0", "< 4.0"
|
21
|
+
s.add_dependency "hashie", ">= 2.0", "< 6.0"
|
22
|
+
s.add_dependency "uuidtools", "~> 2.1"
|
23
|
+
s.add_dependency "ffi-yajl", ">= 2.2", "< 4.0"
|
24
|
+
s.add_dependency "rack", "~> 3.1", ">= 3.1.16"
|
25
|
+
s.add_dependency "rackup", "~> 2.2", ">= 2.2.1"
|
26
|
+
s.add_dependency "unf_ext", "~> 0.0.8"
|
27
|
+
s.add_dependency "webrick"
|
28
|
+
|
29
|
+
s.bindir = "bin"
|
30
|
+
s.executables = ["chef-zero"]
|
31
|
+
s.require_path = "lib"
|
32
|
+
s.files = %w{LICENSE Gemfile Rakefile} + Dir.glob("*.gemspec") +
|
33
|
+
Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
|
34
|
+
end
|
@@ -1,140 +1,140 @@
|
|
1
|
-
module ChefZero
|
2
|
-
module ChefData
|
3
|
-
# Manages translations between REST and ACL data paths
|
4
|
-
# and parent paths.
|
5
|
-
#
|
6
|
-
# Suggestions
|
7
|
-
# - make /organizations/ORG/_acl and deprecate organization/_acl and organizations/_acl
|
8
|
-
# - add endpoints for /containers/(users|organizations|containers)(/_acl)
|
9
|
-
# - add PUT for */_acl
|
10
|
-
# - add endpoints for /organizations/ORG/data/containers and /organizations/ORG/cookbooks/containers
|
11
|
-
# - sane, fully documented ACL model
|
12
|
-
# - sane inheritance / override model: if actors or groups are explicitly
|
13
|
-
# specified on X, they are not inherited from X's parent
|
14
|
-
# - stop adding pivotal to acls (he already has access to what he needs)
|
15
|
-
module AclPath
|
16
|
-
ORG_DATA_TYPES = %w{clients cookbook_artifacts cookbooks containers data environments groups
|
17
|
-
nodes policies policy_groups roles sandboxes}.freeze
|
18
|
-
TOP_DATA_TYPES = %w{containers organizations users}.freeze
|
19
|
-
|
20
|
-
# ACL data paths for a partition are:
|
21
|
-
# / -> /acls/root
|
22
|
-
# /TYPE -> /acls/containers/TYPE
|
23
|
-
# /TYPE/NAME -> /acls/TYPE/NAME
|
24
|
-
#
|
25
|
-
# The root partition "/" has its own acls, so it looks like this:
|
26
|
-
#
|
27
|
-
# / -> /acls/root
|
28
|
-
# /users -> /acls/containers/users
|
29
|
-
# /organizations -> /acls/containers/organizations
|
30
|
-
# /users/schlansky -> /acls/users/schlansky
|
31
|
-
#
|
32
|
-
# Each organization is its own partition, so it looks like this:
|
33
|
-
#
|
34
|
-
# /organizations/blah -> /organizations/blah/acls/root
|
35
|
-
# /organizations/blah/roles -> /organizations/blah/acls/containers/roles
|
36
|
-
# /organizations/blah/roles/web -> /organizations/blah/acls/roles/web
|
37
|
-
# /organizations/ORG is its own partition. ACLs for anything under it follow
|
38
|
-
|
39
|
-
# This method takes a Chef REST path and returns the chef-zero path
|
40
|
-
# used to look up the ACL. If an object does not have an ACL directly,
|
41
|
-
# it will return nil. Paths like /organizations/ORG/data/bag/item will
|
42
|
-
# return nil, because it is the parent path (data/bag) that has an ACL.
|
43
|
-
def self.get_acl_data_path(path)
|
44
|
-
# Things under organizations have their own acls hierarchy
|
45
|
-
if path[0] == "organizations" && path.size >= 2
|
46
|
-
under_org = partition_acl_data_path(path[2..-1], ORG_DATA_TYPES)
|
47
|
-
if under_org
|
48
|
-
path[0..1] + under_org
|
49
|
-
end
|
50
|
-
else
|
51
|
-
partition_acl_data_path(path, TOP_DATA_TYPES)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
#
|
56
|
-
# Reverse transform from acl_data_path to path.
|
57
|
-
# /acls/root -> /
|
58
|
-
# /acls/** -> /**
|
59
|
-
# /organizations/ORG/acls/root -> /organizations/ORG
|
60
|
-
# /organizations/ORG/acls/** -> /organizations/ORG/**
|
61
|
-
#
|
62
|
-
# This means that /acls/containers/nodes maps to
|
63
|
-
# /containers/nodes, not /nodes.
|
64
|
-
#
|
65
|
-
def self.get_object_path(acl_data_path)
|
66
|
-
if acl_data_path[0] == "acls"
|
67
|
-
if acl_data_path[1] == "root"
|
68
|
-
[]
|
69
|
-
else
|
70
|
-
acl_data_path[1..-1]
|
71
|
-
end
|
72
|
-
elsif acl_data_path[0] == "organizations" && acl_data_path[2] == "acls"
|
73
|
-
if acl_data_path[3] == "root"
|
74
|
-
acl_data_path[0..1]
|
75
|
-
else
|
76
|
-
acl_data_path[0..1] + acl_data_path[3..-1]
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Method *assumes* acl_data_path is valid.
|
82
|
-
# /organizations/BLAH's parent is /organizations
|
83
|
-
#
|
84
|
-
# An example traversal up the whole tree:
|
85
|
-
# /organizations/foo/acls/nodes/mario ->
|
86
|
-
# /organizations/foo/acls/containers/nodes ->
|
87
|
-
# /organizations/foo/acls/containers/containers ->
|
88
|
-
# /organizations/foo/acls/root ->
|
89
|
-
# /acls/containers/organizations ->
|
90
|
-
# /acls/containers/containers ->
|
91
|
-
# /acls/root ->
|
92
|
-
# nil
|
93
|
-
def self.parent_acl_data_path(acl_data_path)
|
94
|
-
if acl_data_path[0] == "organizations"
|
95
|
-
under_org = partition_parent_acl_data_path(acl_data_path[2..-1])
|
96
|
-
if under_org
|
97
|
-
acl_data_path[0..1] + under_org
|
98
|
-
else
|
99
|
-
# ACL data path is /organizations/X/acls/root; therefore parent is "/organizations"
|
100
|
-
%w{acls containers organizations}
|
101
|
-
end
|
102
|
-
else
|
103
|
-
partition_parent_acl_data_path(acl_data_path)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# /acls/root -> nil
|
108
|
-
# /acls/containers/containers -> /acls/root
|
109
|
-
# /acls/TYPE/X -> /acls/containers/TYPE
|
110
|
-
#
|
111
|
-
# Method *assumes* acl_data_path is valid.
|
112
|
-
# Returns nil if the path is /acls/root
|
113
|
-
private_class_method
|
114
|
-
def self.partition_parent_acl_data_path(acl_data_path)
|
115
|
-
if acl_data_path.size == 3
|
116
|
-
if acl_data_path == %w{acls containers containers}
|
117
|
-
%w{acls root}
|
118
|
-
else
|
119
|
-
[ "acls", "containers", acl_data_path[1]]
|
120
|
-
end
|
121
|
-
else
|
122
|
-
nil
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
private_class_method
|
127
|
-
def self.partition_acl_data_path(path, data_types)
|
128
|
-
if path.size == 0
|
129
|
-
%w{acls root}
|
130
|
-
elsif data_types.include?(path[0])
|
131
|
-
if path.size == 0
|
132
|
-
[ "acls", "containers", path[0] ]
|
133
|
-
elsif path.size == 2
|
134
|
-
[ "acls", path[0], path[1] ]
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
1
|
+
module ChefZero
|
2
|
+
module ChefData
|
3
|
+
# Manages translations between REST and ACL data paths
|
4
|
+
# and parent paths.
|
5
|
+
#
|
6
|
+
# Suggestions
|
7
|
+
# - make /organizations/ORG/_acl and deprecate organization/_acl and organizations/_acl
|
8
|
+
# - add endpoints for /containers/(users|organizations|containers)(/_acl)
|
9
|
+
# - add PUT for */_acl
|
10
|
+
# - add endpoints for /organizations/ORG/data/containers and /organizations/ORG/cookbooks/containers
|
11
|
+
# - sane, fully documented ACL model
|
12
|
+
# - sane inheritance / override model: if actors or groups are explicitly
|
13
|
+
# specified on X, they are not inherited from X's parent
|
14
|
+
# - stop adding pivotal to acls (he already has access to what he needs)
|
15
|
+
module AclPath
|
16
|
+
ORG_DATA_TYPES = %w{clients cookbook_artifacts cookbooks containers data environments groups
|
17
|
+
nodes policies policy_groups roles sandboxes}.freeze
|
18
|
+
TOP_DATA_TYPES = %w{containers organizations users}.freeze
|
19
|
+
|
20
|
+
# ACL data paths for a partition are:
|
21
|
+
# / -> /acls/root
|
22
|
+
# /TYPE -> /acls/containers/TYPE
|
23
|
+
# /TYPE/NAME -> /acls/TYPE/NAME
|
24
|
+
#
|
25
|
+
# The root partition "/" has its own acls, so it looks like this:
|
26
|
+
#
|
27
|
+
# / -> /acls/root
|
28
|
+
# /users -> /acls/containers/users
|
29
|
+
# /organizations -> /acls/containers/organizations
|
30
|
+
# /users/schlansky -> /acls/users/schlansky
|
31
|
+
#
|
32
|
+
# Each organization is its own partition, so it looks like this:
|
33
|
+
#
|
34
|
+
# /organizations/blah -> /organizations/blah/acls/root
|
35
|
+
# /organizations/blah/roles -> /organizations/blah/acls/containers/roles
|
36
|
+
# /organizations/blah/roles/web -> /organizations/blah/acls/roles/web
|
37
|
+
# /organizations/ORG is its own partition. ACLs for anything under it follow
|
38
|
+
|
39
|
+
# This method takes a Chef REST path and returns the chef-zero path
|
40
|
+
# used to look up the ACL. If an object does not have an ACL directly,
|
41
|
+
# it will return nil. Paths like /organizations/ORG/data/bag/item will
|
42
|
+
# return nil, because it is the parent path (data/bag) that has an ACL.
|
43
|
+
def self.get_acl_data_path(path)
|
44
|
+
# Things under organizations have their own acls hierarchy
|
45
|
+
if path[0] == "organizations" && path.size >= 2
|
46
|
+
under_org = partition_acl_data_path(path[2..-1], ORG_DATA_TYPES)
|
47
|
+
if under_org
|
48
|
+
path[0..1] + under_org
|
49
|
+
end
|
50
|
+
else
|
51
|
+
partition_acl_data_path(path, TOP_DATA_TYPES)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Reverse transform from acl_data_path to path.
|
57
|
+
# /acls/root -> /
|
58
|
+
# /acls/** -> /**
|
59
|
+
# /organizations/ORG/acls/root -> /organizations/ORG
|
60
|
+
# /organizations/ORG/acls/** -> /organizations/ORG/**
|
61
|
+
#
|
62
|
+
# This means that /acls/containers/nodes maps to
|
63
|
+
# /containers/nodes, not /nodes.
|
64
|
+
#
|
65
|
+
def self.get_object_path(acl_data_path)
|
66
|
+
if acl_data_path[0] == "acls"
|
67
|
+
if acl_data_path[1] == "root"
|
68
|
+
[]
|
69
|
+
else
|
70
|
+
acl_data_path[1..-1]
|
71
|
+
end
|
72
|
+
elsif acl_data_path[0] == "organizations" && acl_data_path[2] == "acls"
|
73
|
+
if acl_data_path[3] == "root"
|
74
|
+
acl_data_path[0..1]
|
75
|
+
else
|
76
|
+
acl_data_path[0..1] + acl_data_path[3..-1]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Method *assumes* acl_data_path is valid.
|
82
|
+
# /organizations/BLAH's parent is /organizations
|
83
|
+
#
|
84
|
+
# An example traversal up the whole tree:
|
85
|
+
# /organizations/foo/acls/nodes/mario ->
|
86
|
+
# /organizations/foo/acls/containers/nodes ->
|
87
|
+
# /organizations/foo/acls/containers/containers ->
|
88
|
+
# /organizations/foo/acls/root ->
|
89
|
+
# /acls/containers/organizations ->
|
90
|
+
# /acls/containers/containers ->
|
91
|
+
# /acls/root ->
|
92
|
+
# nil
|
93
|
+
def self.parent_acl_data_path(acl_data_path)
|
94
|
+
if acl_data_path[0] == "organizations"
|
95
|
+
under_org = partition_parent_acl_data_path(acl_data_path[2..-1])
|
96
|
+
if under_org
|
97
|
+
acl_data_path[0..1] + under_org
|
98
|
+
else
|
99
|
+
# ACL data path is /organizations/X/acls/root; therefore parent is "/organizations"
|
100
|
+
%w{acls containers organizations}
|
101
|
+
end
|
102
|
+
else
|
103
|
+
partition_parent_acl_data_path(acl_data_path)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# /acls/root -> nil
|
108
|
+
# /acls/containers/containers -> /acls/root
|
109
|
+
# /acls/TYPE/X -> /acls/containers/TYPE
|
110
|
+
#
|
111
|
+
# Method *assumes* acl_data_path is valid.
|
112
|
+
# Returns nil if the path is /acls/root
|
113
|
+
private_class_method
|
114
|
+
def self.partition_parent_acl_data_path(acl_data_path)
|
115
|
+
if acl_data_path.size == 3
|
116
|
+
if acl_data_path == %w{acls containers containers}
|
117
|
+
%w{acls root}
|
118
|
+
else
|
119
|
+
[ "acls", "containers", acl_data_path[1]]
|
120
|
+
end
|
121
|
+
else
|
122
|
+
nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
private_class_method
|
127
|
+
def self.partition_acl_data_path(path, data_types)
|
128
|
+
if path.size == 0
|
129
|
+
%w{acls root}
|
130
|
+
elsif data_types.include?(path[0])
|
131
|
+
if path.size == 0
|
132
|
+
[ "acls", "containers", path[0] ]
|
133
|
+
elsif path.size == 2
|
134
|
+
[ "acls", path[0], path[1] ]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|