chef-zero 4.5.0 → 4.6.0
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 +5 -1
- data/Rakefile +33 -19
- data/bin/chef-zero +2 -1
- data/chef-zero.gemspec +2 -1
- data/lib/chef_zero/chef_data/cookbook_data.rb +5 -0
- data/lib/chef_zero/chef_data/data_normalizer.rb +3 -3
- data/lib/chef_zero/data_store/data_error.rb +4 -3
- data/lib/chef_zero/endpoints/actor_default_key_endpoint.rb +77 -0
- data/lib/chef_zero/endpoints/actor_endpoint.rb +108 -19
- data/lib/chef_zero/endpoints/actor_key_endpoint.rb +62 -0
- data/lib/chef_zero/endpoints/actor_keys_endpoint.rb +129 -0
- data/lib/chef_zero/endpoints/actors_endpoint.rb +38 -12
- data/lib/chef_zero/endpoints/organization_user_default_key_endpoint.rb +16 -0
- data/lib/chef_zero/endpoints/organization_user_key_endpoint.rb +17 -0
- data/lib/chef_zero/endpoints/organization_user_keys_endpoint.rb +17 -0
- data/lib/chef_zero/endpoints/principal_endpoint.rb +11 -2
- data/lib/chef_zero/endpoints/rest_object_endpoint.rb +19 -5
- data/lib/chef_zero/endpoints/server_api_version_endpoint.rb +1 -1
- data/lib/chef_zero/rest_base.rb +75 -32
- data/lib/chef_zero/rest_error_response.rb +3 -3
- data/lib/chef_zero/rest_request.rb +12 -1
- data/lib/chef_zero/rest_router.rb +44 -17
- data/lib/chef_zero/rspec.rb +1 -1
- data/lib/chef_zero/server.rb +46 -23
- data/lib/chef_zero/version.rb +1 -1
- data/spec/run_oc_pedant.rb +76 -33
- metadata +9 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca7530fffb7dc24422a41d298d2411f8661d5e7d
|
4
|
+
data.tar.gz: a18a46c9da1936c3d89ec33e83d7e97ed0b82bb6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e5a78f306534fc4849f8f40c1ba435d3efa9c8cebbd182e26b68e34c92a08aed491c5259780847c0cf05ab19480cc485b61b12b01992b27ddad4a776be81897
|
7
|
+
data.tar.gz: 4add88aed368a2044f817a5f7caa2429a27c2d6f23e81c3054ba4a68270250c404f926abaf571c354069fcbe61dcbc4163ec9dc31e7255e77d0dd75e5302d553
|
data/Gemfile
CHANGED
@@ -3,7 +3,11 @@ gemspec
|
|
3
3
|
|
4
4
|
# gem 'rest-client', :github => 'chef/rest-client'
|
5
5
|
|
6
|
-
gem 'oc-chef-pedant', :github => 'chef/chef-server'
|
6
|
+
gem 'oc-chef-pedant', :github => 'chef/chef-server'
|
7
|
+
|
8
|
+
group :changelog do
|
9
|
+
gem "github_changelog_generator"
|
10
|
+
end
|
7
11
|
|
8
12
|
# bundler resolve failure on "rspec_junit_formatter"
|
9
13
|
# gem 'chef-pedant', :github => 'opscode/chef-pedant', :ref => "server-cli-option"
|
data/Rakefile
CHANGED
@@ -3,33 +3,43 @@ require 'bundler/gem_tasks'
|
|
3
3
|
|
4
4
|
require 'chef_zero/version'
|
5
5
|
|
6
|
+
def run_oc_pedant(env={})
|
7
|
+
ENV.update(env)
|
8
|
+
require File.expand_path('spec/run_oc_pedant')
|
9
|
+
end
|
10
|
+
|
11
|
+
ENV_DOCS = <<END
|
12
|
+
Environment:
|
13
|
+
- RSPEC_OPTS Options to pass to RSpec
|
14
|
+
e.g. RSPEC_OPTS="--fail-fast --profile 5"
|
15
|
+
- PEDANT_OPTS Options to pass to oc-chef-pedant
|
16
|
+
e.g. PEDANT_OPTS="--focus-keys --skip-users"
|
17
|
+
- LOG_LEVEL Set the log level (default: warn)
|
18
|
+
e.g. LOG_LEVEL=debug
|
19
|
+
END
|
20
|
+
|
6
21
|
task :default => :pedant
|
7
22
|
|
8
|
-
desc "
|
23
|
+
desc "Run specs"
|
9
24
|
task :spec do
|
10
25
|
system('rspec spec/*_spec.rb')
|
11
26
|
end
|
12
27
|
|
13
|
-
desc "
|
14
|
-
task :pedant
|
15
|
-
require File.expand_path('spec/run_oc_pedant')
|
16
|
-
end
|
28
|
+
desc "Run oc-chef-pedant\n\n#{ENV_DOCS}"
|
29
|
+
task :pedant => :oc_pedant
|
17
30
|
|
18
|
-
desc "
|
31
|
+
desc "Run oc-chef-pedant with CHEF_FS set\n\n#{ENV_DOCS}"
|
19
32
|
task :cheffs do
|
20
|
-
|
21
|
-
require File.expand_path('spec/run_oc_pedant')
|
33
|
+
run_oc_pedant('CHEF_FS' => 'yes')
|
22
34
|
end
|
23
35
|
|
24
|
-
desc "
|
36
|
+
desc "Run oc-chef-pedant with FILE_STORE set\n\n#{ENV_DOCS}"
|
25
37
|
task :filestore do
|
26
|
-
|
27
|
-
require File.expand_path('spec/run_oc_pedant')
|
38
|
+
run_oc_pedant('FILE_STORE' => 'yes')
|
28
39
|
end
|
29
40
|
|
30
|
-
desc "run oc pedant"
|
31
41
|
task :oc_pedant do
|
32
|
-
|
42
|
+
run_oc_pedant
|
33
43
|
end
|
34
44
|
|
35
45
|
task :chef_spec do
|
@@ -42,11 +52,15 @@ task :berkshelf_spec do
|
|
42
52
|
system("cd #{gem_path} && thor spec:ci")
|
43
53
|
end
|
44
54
|
|
45
|
-
|
55
|
+
begin
|
56
|
+
require "github_changelog_generator/task"
|
46
57
|
|
47
|
-
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
58
|
+
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
59
|
+
config.future_release = ChefZero::VERSION
|
60
|
+
config.enhancement_labels = "enhancement,Enhancement,New Feature,Feature".split(",")
|
61
|
+
config.bug_labels = "bug,Bug,Improvement,Upstream Bug".split(",")
|
62
|
+
config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog,Exclude From Changelog,Question,Discussion".split(",")
|
63
|
+
end
|
64
|
+
rescue LoadError
|
65
|
+
puts "github_changelog_generator is not available. gem install github_changelog_generator to generate changelogs"
|
52
66
|
end
|
data/bin/chef-zero
CHANGED
@@ -31,7 +31,8 @@ OptionParser.new do |opts|
|
|
31
31
|
opts.banner = "Usage: chef-zero [ARGS]"
|
32
32
|
|
33
33
|
opts.on("-H", "--host HOST", "Host to bind to (default: 127.0.0.1)") do |value|
|
34
|
-
options[:host]
|
34
|
+
options[:host] ||= []
|
35
|
+
options[:host] << value
|
35
36
|
end
|
36
37
|
|
37
38
|
opts.on("-p", "--port PORT", "Port to listen on (e.g. 8889, or 8500-8600 or 8885,8888)") do |value|
|
data/chef-zero.gemspec
CHANGED
@@ -12,6 +12,8 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.homepage = 'http://www.opscode.com'
|
13
13
|
s.license = 'Apache 2.0'
|
14
14
|
|
15
|
+
s.required_ruby_version = ">= 2.1.0"
|
16
|
+
|
15
17
|
s.add_dependency 'mixlib-log', '~> 1.3'
|
16
18
|
s.add_dependency 'hashie', '>= 2.0', '< 4.0'
|
17
19
|
s.add_dependency 'uuidtools', '~> 2.1'
|
@@ -23,7 +25,6 @@ Gem::Specification.new do |s|
|
|
23
25
|
s.add_development_dependency 'pry-stack_explorer'
|
24
26
|
s.add_development_dependency 'rake'
|
25
27
|
s.add_development_dependency 'rspec'
|
26
|
-
s.add_development_dependency 'github_changelog_generator'
|
27
28
|
s.add_development_dependency 'chef'
|
28
29
|
|
29
30
|
s.bindir = 'bin'
|
@@ -108,6 +108,11 @@ module ChefZero
|
|
108
108
|
cookbook_arg(:replacing, cookbook, version_constraints)
|
109
109
|
end
|
110
110
|
|
111
|
+
def gem(*opts)
|
112
|
+
self[:gems] ||= []
|
113
|
+
self[:gems] << opts
|
114
|
+
end
|
115
|
+
|
111
116
|
def recipe(recipe, description)
|
112
117
|
self[:recipes][recipe] = description
|
113
118
|
end
|
@@ -17,8 +17,8 @@ module ChefZero
|
|
17
17
|
def self.normalize_client(client, name, orgname = nil)
|
18
18
|
client['name'] ||= name
|
19
19
|
client['clientname'] ||= name
|
20
|
-
client['admin'] = !!client['admin'] if client.
|
21
|
-
client['public_key']
|
20
|
+
client['admin'] = !!client['admin'] if client.key?('admin')
|
21
|
+
client['public_key'] = PUBLIC_KEY unless client.key?('public_key')
|
22
22
|
client['orgname'] ||= orgname
|
23
23
|
client['validator'] ||= false
|
24
24
|
client['validator'] = !!client['validator']
|
@@ -36,7 +36,7 @@ module ChefZero
|
|
36
36
|
|
37
37
|
def self.normalize_user(user, name, identity_keys, osc_compat, method=nil)
|
38
38
|
user[identity_keys.first] ||= name
|
39
|
-
user['public_key']
|
39
|
+
user['public_key'] = PUBLIC_KEY unless user.key?('public_key')
|
40
40
|
user['admin'] ||= false
|
41
41
|
user['admin'] = !!user['admin']
|
42
42
|
user['openid'] ||= nil
|
@@ -19,13 +19,14 @@
|
|
19
19
|
module ChefZero
|
20
20
|
module DataStore
|
21
21
|
class DataError < StandardError
|
22
|
+
attr_reader :path, :cause
|
23
|
+
|
22
24
|
def initialize(path, cause = nil)
|
23
25
|
@path = path
|
24
26
|
@cause = cause
|
27
|
+
path_for_msg = path.nil? ? "nil" : "/#{path.join('/')}"
|
28
|
+
super "Data path: #{path_for_msg}"
|
25
29
|
end
|
26
|
-
|
27
|
-
attr_reader :path
|
28
|
-
attr_reader :cause
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'chef_zero/rest_base'
|
2
|
+
|
3
|
+
module ChefZero
|
4
|
+
module Endpoints
|
5
|
+
# ActorDefaultKeyEndpoint
|
6
|
+
#
|
7
|
+
# This class handles DELETE/GET/PUT requests for client/user default public
|
8
|
+
# keys, i.e. requests with identity key "default". All others are handled
|
9
|
+
# by ActorKeyEndpoint.
|
10
|
+
#
|
11
|
+
# Default public keys are stored with the actor (client or user) instead of
|
12
|
+
# under user/client_keys. Handling those in a separate endpoint offloads
|
13
|
+
# the branching logic onto the router rather than branching in every
|
14
|
+
# endpoint method (`if request.rest_path[-1] == "default" ...`).
|
15
|
+
#
|
16
|
+
# /users/USER/keys/default
|
17
|
+
# /organizations/ORG/clients/CLIENT/keys/default
|
18
|
+
class ActorDefaultKeyEndpoint < RestBase
|
19
|
+
DEFAULT_PUBLIC_KEY_NAME = "default".freeze
|
20
|
+
|
21
|
+
def get(request)
|
22
|
+
# 404 if actor doesn't exist
|
23
|
+
actor_data = get_actor_data(request)
|
24
|
+
key_data = default_public_key_from_actor(actor_data)
|
25
|
+
|
26
|
+
# 404 if the actor doesn't have a default key
|
27
|
+
if key_data["public_key"].nil?
|
28
|
+
raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, request.rest_path)}")
|
29
|
+
end
|
30
|
+
|
31
|
+
json_response(200, default_public_key_from_actor(actor_data))
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete(request)
|
35
|
+
path = actor_path(request)
|
36
|
+
actor_data = get_actor_data(request) # 404 if actor doesn't exist
|
37
|
+
|
38
|
+
default_public_key = delete_actor_default_public_key!(request, path, actor_data)
|
39
|
+
json_response(200, default_public_key)
|
40
|
+
end
|
41
|
+
|
42
|
+
def put(request)
|
43
|
+
# 404 if actor doesn't exist
|
44
|
+
actor_data = get_actor_data(request)
|
45
|
+
|
46
|
+
new_public_key = parse_json(request.body)["public_key"]
|
47
|
+
actor_data["public_key"] = new_public_key
|
48
|
+
|
49
|
+
set_data(request, actor_path(request), to_json(actor_data))
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def actor_path(request)
|
55
|
+
return request.rest_path[0..3] if request.rest_path[2] == "clients"
|
56
|
+
request.rest_path[0..1]
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_actor_data(request)
|
60
|
+
path = actor_path(request)
|
61
|
+
parse_json(get_data(request, path))
|
62
|
+
end
|
63
|
+
|
64
|
+
def default_public_key_from_actor(actor_data)
|
65
|
+
{ "name" => DEFAULT_PUBLIC_KEY_NAME,
|
66
|
+
"public_key" => actor_data["public_key"],
|
67
|
+
"expiration_date" => "infinity" }
|
68
|
+
end
|
69
|
+
|
70
|
+
def delete_actor_default_public_key!(request, path, actor_data)
|
71
|
+
new_actor_data = actor_data.merge("public_key" => nil)
|
72
|
+
set_data(request, path, to_json(new_actor_data))
|
73
|
+
default_public_key_from_actor(actor_data)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -8,8 +8,19 @@ module ChefZero
|
|
8
8
|
# /organizations/ORG/users/NAME
|
9
9
|
# /users/NAME
|
10
10
|
class ActorEndpoint < RestObjectEndpoint
|
11
|
+
|
12
|
+
def get(request)
|
13
|
+
result = super
|
14
|
+
user_data = parse_json(result[2])
|
15
|
+
|
16
|
+
user_data.delete("public_key") unless request.api_v0?
|
17
|
+
|
18
|
+
json_response(200, user_data)
|
19
|
+
end
|
20
|
+
|
11
21
|
def delete(request)
|
12
22
|
result = super
|
23
|
+
|
13
24
|
if request.rest_path[0] == 'users'
|
14
25
|
list_data(request, [ 'organizations' ]).each do |org|
|
15
26
|
begin
|
@@ -18,12 +29,15 @@ module ChefZero
|
|
18
29
|
end
|
19
30
|
end
|
20
31
|
end
|
32
|
+
|
33
|
+
delete_actor_keys!(request)
|
21
34
|
result
|
22
35
|
end
|
23
36
|
|
24
37
|
def put(request)
|
25
38
|
# Find out if we're updating the public key.
|
26
39
|
request_body = FFI_Yajl::Parser.parse(request.body, :create_additions => false)
|
40
|
+
|
27
41
|
if request_body['public_key'].nil?
|
28
42
|
# If public_key is null, then don't overwrite it. Weird patchiness.
|
29
43
|
body_modified = true
|
@@ -33,18 +47,18 @@ module ChefZero
|
|
33
47
|
end
|
34
48
|
|
35
49
|
# Generate private_key if requested.
|
36
|
-
if request_body.
|
50
|
+
if request_body.key?('private_key')
|
37
51
|
body_modified = true
|
38
|
-
|
52
|
+
|
53
|
+
if request_body.delete('private_key')
|
39
54
|
private_key, public_key = server.gen_key_pair
|
40
55
|
updating_public_key = true
|
41
56
|
request_body['public_key'] = public_key
|
42
57
|
end
|
43
|
-
request_body.delete('private_key')
|
44
58
|
end
|
45
59
|
|
46
|
-
#
|
47
|
-
request.body =
|
60
|
+
# Put modified body back in `request.body`
|
61
|
+
request.body = to_json(request_body) if body_modified
|
48
62
|
|
49
63
|
# PUT /clients is patchy
|
50
64
|
request.body = patch_request_body(request)
|
@@ -53,27 +67,29 @@ module ChefZero
|
|
53
67
|
|
54
68
|
# Inject private_key into response, delete public_key/password if applicable
|
55
69
|
if result[0] == 200 || result[0] == 201
|
70
|
+
client_or_user_name = identity_key_value(request) || request.rest_path[-1]
|
71
|
+
|
72
|
+
if is_rename?(request)
|
73
|
+
rename_keys!(request, client_or_user_name)
|
74
|
+
end
|
75
|
+
|
56
76
|
if request.rest_path[0] == 'users'
|
57
|
-
key = nil
|
58
|
-
identity_keys.each do |identity_key|
|
59
|
-
key ||= request_body[identity_key]
|
60
|
-
end
|
61
|
-
key ||= request.rest_path[-1]
|
62
77
|
response = {
|
63
|
-
'uri' => build_uri(request.base_uri, [ 'users',
|
78
|
+
'uri' => build_uri(request.base_uri, [ 'users', client_or_user_name ])
|
64
79
|
}
|
65
80
|
else
|
66
|
-
response =
|
81
|
+
response = parse_json(result[2])
|
67
82
|
end
|
68
83
|
|
69
|
-
if request
|
84
|
+
if client?(request)
|
70
85
|
response['private_key'] = private_key ? private_key : false
|
71
86
|
else
|
72
87
|
response['private_key'] = private_key if private_key
|
88
|
+
response.delete('public_key') unless updating_public_key
|
73
89
|
end
|
74
90
|
|
75
|
-
response.delete('public_key') if !updating_public_key && request.rest_path[2] == 'users'
|
76
91
|
response.delete('password')
|
92
|
+
|
77
93
|
json_response(result[0], response)
|
78
94
|
else
|
79
95
|
result
|
@@ -81,13 +97,86 @@ module ChefZero
|
|
81
97
|
end
|
82
98
|
|
83
99
|
def populate_defaults(request, response_json)
|
84
|
-
response =
|
85
|
-
|
86
|
-
|
100
|
+
response = parse_json(response_json)
|
101
|
+
|
102
|
+
populated_response =
|
103
|
+
if client?(request)
|
104
|
+
ChefData::DataNormalizer.normalize_client(
|
105
|
+
response,
|
106
|
+
response["name"] || request.rest_path[-1],
|
107
|
+
request.rest_path[1]
|
108
|
+
)
|
109
|
+
else
|
110
|
+
ChefData::DataNormalizer.normalize_user(
|
111
|
+
response,
|
112
|
+
response["username"] || request.rest_path[-1],
|
113
|
+
identity_keys,
|
114
|
+
server.options[:osc_compat],
|
115
|
+
request.method
|
116
|
+
)
|
117
|
+
end
|
118
|
+
|
119
|
+
to_json(populated_response)
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
# Move key data to new path
|
125
|
+
def rename_keys!(request, new_client_or_user_name)
|
126
|
+
orig_keys_path = keys_path_base(request)
|
127
|
+
new_keys_path = orig_keys_path.dup
|
128
|
+
.tap {|path| path[-2] = new_client_or_user_name }
|
129
|
+
|
130
|
+
key_names = list_data_or_else(request, orig_keys_path, nil)
|
131
|
+
return unless key_names # No keys to move
|
132
|
+
|
133
|
+
key_names.each do |key_name|
|
134
|
+
# Get old data
|
135
|
+
orig_path = [ *orig_keys_path, key_name ]
|
136
|
+
data = get_data(request, orig_path, :data_store_exceptions)
|
137
|
+
|
138
|
+
# Copy data to new path
|
139
|
+
create_data(
|
140
|
+
request,
|
141
|
+
new_keys_path, key_name,
|
142
|
+
data,
|
143
|
+
:create_dir
|
144
|
+
)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Delete original data
|
148
|
+
delete_data_dir(request, orig_keys_path, :recursive, :data_store_exceptions)
|
149
|
+
end
|
150
|
+
|
151
|
+
def delete_actor_keys!(request)
|
152
|
+
path = keys_path_base(request)[0..-2]
|
153
|
+
delete_data_dir(request, path, :recursive, :data_store_exceptions)
|
154
|
+
rescue DataStore::DataNotFoundError
|
155
|
+
end
|
156
|
+
|
157
|
+
def client?(request, rest_path=nil)
|
158
|
+
rest_path ||= request.rest_path
|
159
|
+
request.rest_path[2] == "clients"
|
160
|
+
end
|
161
|
+
|
162
|
+
# Return the data store keys path for the request client or user, e.g.
|
163
|
+
#
|
164
|
+
# [ "organizations", <org>, "client_keys", <client>, "keys" ]
|
165
|
+
#
|
166
|
+
# Or:
|
167
|
+
#
|
168
|
+
# [ "user_keys", <user>, "keys" ]
|
169
|
+
#
|
170
|
+
def keys_path_base(request, client_or_user_name=nil)
|
171
|
+
rest_path = (rest_path || request.rest_path).dup
|
172
|
+
rest_path[-1] = client_or_user_name if client_or_user_name
|
173
|
+
|
174
|
+
if client?(request, rest_path)
|
175
|
+
[ *rest_path[0..1], "client_keys" ]
|
87
176
|
else
|
88
|
-
|
177
|
+
[ "user_keys" ]
|
89
178
|
end
|
90
|
-
|
179
|
+
.push(rest_path.last, "keys")
|
91
180
|
end
|
92
181
|
end
|
93
182
|
end
|