diff options
author | danielsdeleo <dan@getchef.com> | 2014-03-27 15:54:25 -0700 |
---|---|---|
committer | danielsdeleo <dan@getchef.com> | 2014-03-27 15:54:25 -0700 |
commit | ac3f5ee8c76fd6bbbb86c6c97bdfdcda2e6095b7 (patch) | |
tree | 41784135ab306ac80c1d83bf1b7b30f91c34f50b | |
parent | 1d786d4489ef0b2363b630e734cb205e098f651c (diff) | |
download | chef-ac3f5ee8c76fd6bbbb86c6c97bdfdcda2e6095b7.tar.gz |
Backport CHEF-4373 to 10.x
-rw-r--r-- | chef/lib/chef/api_client.rb | 22 | ||||
-rw-r--r-- | chef/spec/unit/api_client_spec.rb | 58 |
2 files changed, 80 insertions, 0 deletions
diff --git a/chef/lib/chef/api_client.rb b/chef/lib/chef/api_client.rb index 02dd34d0d5..ac09fc45b4 100644 --- a/chef/lib/chef/api_client.rb +++ b/chef/lib/chef/api_client.rb @@ -239,6 +239,9 @@ class Chef # Save this client via the REST API, returns a hash including the private key def save(new_key=false, validation=false) + # Implement CHEF-4373 with minimal churn to existing code: + return register_with_self_generated_key if new_key && validation && Chef::Config.local_key_generation + if validation r = Chef::REST.new(Chef::Config[:chef_server_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key]) else @@ -257,6 +260,25 @@ class Chef end end + def register_with_self_generated_key + r = Chef::REST.new(Chef::Config[:chef_server_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key]) + pkey = OpenSSL::PKey::RSA.generate(2048) + client_data = {:name => name, :admin => false , :public_key => pkey.public_key.to_pem} + # First, try and create a new registration + r = begin + r.post_rest("clients", client_data) + rescue Net::HTTPServerException => e + # If that fails, go ahead and try and update it + if e.response.code == "409" + r.put_rest("clients/#{name}", client_data) + else + raise e + end + end + private_key(pkey.to_pem) + self + end + def reregister r = Chef::REST.new(Chef::Config[:chef_server_url]) reregistered_self = r.put_rest("clients/#{name}", { :name => name, :admin => admin, :private_key => true }) diff --git a/chef/spec/unit/api_client_spec.rb b/chef/spec/unit/api_client_spec.rb index 24a15460aa..76c15fc164 100644 --- a/chef/spec/unit/api_client_spec.rb +++ b/chef/spec/unit/api_client_spec.rb @@ -251,6 +251,64 @@ describe Chef::ApiClient do end end + + context "and client side key generation is enabled" do + + let(:response) { {"uri"=> "https://example.com/clients/selfgenkeytest-1395958070", "public_key" => "rsa-key-data"} } + let(:pkey_in) { IO.read(File.join(CHEF_SPEC_DATA, "ssl/private_key.pem")) } + + let(:generated_key) { OpenSSL::PKey::RSA.new(pkey_in) } + let(:generated_public_key) { generated_key.public_key } + + before do + @client.name("deadsexy") + OpenSSL::PKey::RSA.stub(:generate).and_return(generated_key) + Chef::Config.stub(:local_key_generation).and_return true + end + + context "and the client doesn't exist" do + let(:response) { {"uri"=> "https://example.com/clients/selfgenkeytest-1395958070", "public_key" => "rsa-key-data"} } + let(:pkey_in) { IO.read(File.join(CHEF_SPEC_DATA, "ssl/private_key.pem")) } + + let(:generated_key) { OpenSSL::PKey::RSA.new(pkey_in) } + let(:generated_public_key) { generated_key.public_key } + + before do + @http_client.should_receive(:post_rest). + with("clients", :name => "deadsexy", :admin => false, :public_key => generated_public_key.to_pem). + and_return(response) + end + + it "creates the client with self generated key" do + @client.save(true, true) + @client.private_key.should == generated_key.to_pem + end + + end + + context "and the client already exists" do + before do + http_conflict_response = Net::HTTPConflict.new("409 blah blah", "409", "409") + http_conflict_error = Net::HTTPServerException.new("409 conflict", http_conflict_response) + + @http_client.should_receive(:post_rest). + with("clients", :name => "deadsexy", :admin => false, :public_key => generated_public_key.to_pem). + and_raise(http_conflict_error) + + @http_client.should_receive(:put_rest). + with("clients/deadsexy", :name => "deadsexy", :admin => false, :public_key => generated_public_key.to_pem). + and_return(response) + end + + it "creates the client with self generated key" do + @client.save(true, true) + @client.private_key.should == generated_key.to_pem + end + + end + + end + end end |