chef-zero 4.5.0 → 4.6.0

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
  SHA1:
3
- metadata.gz: 6cc5716f0bde147efc79fb02be61275ea01aa654
4
- data.tar.gz: d1a2c69275d9a2bc901f5024f47be5b821320e98
3
+ metadata.gz: ca7530fffb7dc24422a41d298d2411f8661d5e7d
4
+ data.tar.gz: a18a46c9da1936c3d89ec33e83d7e97ed0b82bb6
5
5
  SHA512:
6
- metadata.gz: e0c7757da8314dad7ff5f58fe4423c7ee816b32138f59b16fcf9073e8b8fffc045b819781e81e119f85c553d44b6336e678c37d8aed0d729aae3f54ebbc48f3f
7
- data.tar.gz: a606ffcd42a0001e1f1a43854d9f373e15f6000a29eb52129a0b5a0298eeff28675bb6d8d4e6991c179fd4b24e0a241623f9388b0d1e733f1e1a254cb9c13272
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', :branch => "jk/authorization-tags"
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 "run specs"
23
+ desc "Run specs"
9
24
  task :spec do
10
25
  system('rspec spec/*_spec.rb')
11
26
  end
12
27
 
13
- desc "run oc pedant"
14
- task :pedant do
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 "run pedant with CHEF_FS set"
31
+ desc "Run oc-chef-pedant with CHEF_FS set\n\n#{ENV_DOCS}"
19
32
  task :cheffs do
20
- ENV['CHEF_FS'] = "yes"
21
- require File.expand_path('spec/run_oc_pedant')
33
+ run_oc_pedant('CHEF_FS' => 'yes')
22
34
  end
23
35
 
24
- desc "run pedant with FILE_STORE set"
36
+ desc "Run oc-chef-pedant with FILE_STORE set\n\n#{ENV_DOCS}"
25
37
  task :filestore do
26
- ENV['FILE_STORE'] = "yes"
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
- require File.expand_path('spec/run_oc_pedant')
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
- require 'github_changelog_generator/task'
55
+ begin
56
+ require "github_changelog_generator/task"
46
57
 
47
- GitHubChangelogGenerator::RakeTask.new :changelog do |config|
48
- # config.future_release = ChefZero::VERSION
49
- config.enhancement_labels = "enhancement,Enhancement,New Feature".split(',')
50
- config.bug_labels = "bug,Bug,Improvement,Upstream Bug".split(',')
51
- config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog".split(',')
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
@@ -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] = value
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|
@@ -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.has_key?('admin')
21
- client['public_key'] ||= 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'] ||= 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.has_key?('private_key')
50
+ if request_body.key?('private_key')
37
51
  body_modified = true
38
- if request_body['private_key']
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
- # Save request
47
- request.body = FFI_Yajl::Encoder.encode(request_body, :pretty => true) if body_modified
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', key ])
78
+ 'uri' => build_uri(request.base_uri, [ 'users', client_or_user_name ])
64
79
  }
65
80
  else
66
- response = FFI_Yajl::Parser.parse(result[2], :create_additions => false)
81
+ response = parse_json(result[2])
67
82
  end
68
83
 
69
- if request.rest_path[2] == 'clients'
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 = FFI_Yajl::Parser.parse(response_json, :create_additions => false)
85
- if request.rest_path[2] == 'clients'
86
- response = ChefData::DataNormalizer.normalize_client(response,request.rest_path[3], request.rest_path[1])
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
- response = ChefData::DataNormalizer.normalize_user(response, request.rest_path[3], identity_keys, server.options[:osc_compat], request.method)
177
+ [ "user_keys" ]
89
178
  end
90
- FFI_Yajl::Encoder.encode(response, :pretty => true)
179
+ .push(rest_path.last, "keys")
91
180
  end
92
181
  end
93
182
  end