class Chef::ApiClient::Registration
Chef::ApiClient::Registration
¶ ↑
Manages the process of creating or updating a Chef::ApiClient
on the server and writing the resulting private key to disk. Registration
uses the validator credentials for its API calls. This allows it to bootstrap a new client/node identity by borrowing the validator client identity when creating a new client.
Attributes
destination[R]
name[R]
Public Class Methods
new(name, destination, http_api: nil)
click to toggle source
# File lib/chef/api_client/registration.rb, line 37 def initialize(name, destination, http_api: nil) @name = name @destination = destination @http_api = http_api @server_generated_private_key = nil end
Public Instance Methods
api_client(response)
click to toggle source
# File lib/chef/api_client/registration.rb, line 121 def api_client(response) return response if response.is_a?(Chef::ApiClient) client = Chef::ApiClient.new client.name(name) client.public_key(api_client_key(response, "public_key")) client.private_key(api_client_key(response, "private_key")) client end
api_client_key(response, key_name)
click to toggle source
# File lib/chef/api_client/registration.rb, line 131 def api_client_key(response, key_name) if response[key_name] if response[key_name].respond_to?(:to_pem) response[key_name].to_pem else response[key_name] end elsif response["chef_key"] response["chef_key"][key_name] end end
assert_destination_writable!()
click to toggle source
# File lib/chef/api_client/registration.rb, line 73 def assert_destination_writable! abs_path = File.expand_path(destination) unless File.exist?(File.dirname(abs_path)) begin FileUtils.mkdir_p(File.dirname(abs_path)) rescue Errno::EACCES raise Chef::Exceptions::CannotWritePrivateKey, "I can't create the configuration directory at #{File.dirname(abs_path)} - check permissions?" end end if (File.exist?(abs_path) && !File.writable?(abs_path)) || !File.writable?(File.dirname(abs_path)) raise Chef::Exceptions::CannotWritePrivateKey, "I can't write your private key to #{abs_path} - check permissions?" end end
create()
click to toggle source
# File lib/chef/api_client/registration.rb, line 105 def create response = http_api.post("clients", post_data) @server_generated_private_key = response["private_key"] response end
create_or_update()
click to toggle source
# File lib/chef/api_client/registration.rb, line 95 def create_or_update create rescue Net::HTTPClientException => e # If create fails because the client exists, attempt to update. This # requires admin privileges. raise unless e.response.code == "409" update end
file_flags()
click to toggle source
# File lib/chef/api_client/registration.rb, line 191 def file_flags base_flags = File::CREAT | File::TRUNC | File::RDWR # Windows doesn't have symlinks, so it doesn't have NOFOLLOW if defined?(File::NOFOLLOW) && !Chef::Config[:follow_client_key_symlink] base_flags |= File::NOFOLLOW end base_flags end
generated_private_key()
click to toggle source
# File lib/chef/api_client/registration.rb, line 183 def generated_private_key @generated_key ||= OpenSSL::PKey::RSA.generate(2048) end
generated_public_key()
click to toggle source
# File lib/chef/api_client/registration.rb, line 187 def generated_public_key generated_private_key.public_key.to_pem end
http_api()
click to toggle source
# File lib/chef/api_client/registration.rb, line 159 def http_api @http_api ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], { api_version: "0", client_name: Chef::Config[:validation_client_name], signing_key_filename: Chef::Config[:validation_key], }) end
post_data()
click to toggle source
# File lib/chef/api_client/registration.rb, line 153 def post_data post_data = { name: name, admin: false } post_data[:public_key] = generated_public_key if self_generate_keys? post_data end
private_key()
click to toggle source
# File lib/chef/api_client/registration.rb, line 175 def private_key if self_generate_keys? generated_private_key.to_pem else @server_generated_private_key end end
put_data()
click to toggle source
# File lib/chef/api_client/registration.rb, line 143 def put_data base_put_data = { name: name, admin: false } if self_generate_keys? base_put_data[:public_key] = generated_public_key else base_put_data[:private_key] = true end base_put_data end
run()
click to toggle source
Runs the client registration process, including creating the client on the chef-server and writing its private key to disk.
# File lib/chef/api_client/registration.rb, line 54 def run assert_destination_writable! retries = Config[:client_registration_retries] || 5 client = nil begin client = api_client(create_or_update) rescue Net::HTTPFatalError => e # HTTPFatalError implies 5xx. raise if retries <= 0 retries -= 1 Chef::Log.warn("Failed to register new client, #{retries} tries remaining") Chef::Log.warn("Response: HTTP #{e.response.code} - #{e}") retry end write_key client end
self_generate_keys?()
click to toggle source
Whether or not to generate keys locally and post the public key to the server. Delegates to `Chef::Config.local_key_generation`. Servers before 11.0 do not support this feature.
# File lib/chef/api_client/registration.rb, line 171 def self_generate_keys? Chef::Config.local_key_generation end
update()
click to toggle source
# File lib/chef/api_client/registration.rb, line 111 def update response = http_api.put("clients/#{name}", put_data) if response.respond_to?(:private_key) # Chef 11 @server_generated_private_key = response.private_key else # Chef 10 @server_generated_private_key = response["private_key"] end response end
write_key()
click to toggle source
# File lib/chef/api_client/registration.rb, line 87 def write_key ::File.open(destination, file_flags, 0600) do |f| f.print(private_key) end rescue IOError => e raise Chef::Exceptions::CannotWritePrivateKey, "Error writing private key to #{destination}: #{e}" end