summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordanielsdeleo <dan@getchef.com>2014-03-25 16:51:03 -0700
committerdanielsdeleo <dan@getchef.com>2014-03-25 16:51:03 -0700
commit6231d5f3faa6d94051c3a7878742b3b9a684e374 (patch)
treed49aa16f17f5fb47ccf53e17df46861b33abf30a /lib
parent6b045b48bb40b0fc912d7077b7de5f7987c6cdc9 (diff)
downloadchef-6231d5f3faa6d94051c3a7878742b3b9a684e374.tar.gz
Add optional client-side key generation when registering
Diffstat (limited to 'lib')
-rw-r--r--lib/chef/api_client/registration.rb55
-rw-r--r--lib/chef/config.rb11
2 files changed, 57 insertions, 9 deletions
diff --git a/lib/chef/api_client/registration.rb b/lib/chef/api_client/registration.rb
index f44c326d5d..213d0b7f49 100644
--- a/lib/chef/api_client/registration.rb
+++ b/lib/chef/api_client/registration.rb
@@ -30,14 +30,13 @@ class Chef
# a new client/node identity by borrowing the validator client identity
# when creating a new client.
class Registration
- attr_reader :private_key
attr_reader :destination
attr_reader :name
def initialize(name, destination)
@name = name
@destination = destination
- @private_key = nil
+ @server_generated_private_key = nil
end
# Runs the client registration process, including creating the client on
@@ -90,29 +89,67 @@ class Chef
end
def create
- response = http_api.post("clients", :name => name, :admin => false)
- @private_key = response["private_key"]
+ response = http_api.post("clients", post_data)
+ @server_generated_private_key = response["private_key"]
response
end
def update
- response = http_api.put("clients/#{name}", :name => name,
- :admin => false,
- :private_key => true)
+ response = http_api.put("clients/#{name}", put_data)
if response.respond_to?(:private_key) # Chef 11
- @private_key = response.private_key
+ @server_generated_private_key = response.private_key
else # Chef 10
- @private_key = response["private_key"]
+ @server_generated_private_key = response["private_key"]
end
response
end
+ 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
+
+ def post_data
+ post_data = { :name => name, :admin => false }
+ post_data[:public_key] = generated_public_key if self_generate_keys?
+ post_data
+ end
+
+
def http_api
@http_api_as_validator ||= Chef::REST.new(Chef::Config[:chef_server_url],
Chef::Config[:validation_client_name],
Chef::Config[:validation_key])
end
+ # 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.
+ def self_generate_keys?
+ Chef::Config.local_key_generation
+ end
+
+ def private_key
+ if self_generate_keys?
+ generated_private_key.to_pem
+ else
+ @server_generated_private_key
+ end
+ end
+
+ def generated_private_key
+ @generated_key ||= OpenSSL::PKey::RSA.generate(2048)
+ end
+
+ def generated_public_key
+ generated_private_key.public_key.to_pem
+ end
+
def file_flags
base_flags = File::CREAT|File::TRUNC|File::RDWR
# Windows doesn't have symlinks, so it doesn't have NOFOLLOW
diff --git a/lib/chef/config.rb b/lib/chef/config.rb
index da3f3790f6..3099d876c1 100644
--- a/lib/chef/config.rb
+++ b/lib/chef/config.rb
@@ -432,6 +432,17 @@ class Chef
default(:validation_key) { chef_zero.enabled ? nil : platform_specific_path("/etc/chef/validation.pem") }
default :validation_client_name, "chef-validator"
+ # When creating a new client via the validation_client account, Chef 11
+ # servers allow the client to generate a key pair locally and sent the
+ # public key to the server. This is more secure and helps offload work from
+ # the server, enhancing scalability. If enabled and the remote server
+ # implements only the Chef 10 API, client registration will not work
+ # properly.
+ #
+ # The default value is `false` (Server generates client keys). Set to
+ # `true` to enable client-side key generation.
+ default(:local_key_generation) { false }
+
# Zypper package provider gpg checks. Set to true to enable package
# gpg signature checking. This will be default in the
# future. Setting to false disables the warnings.