summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanielsdeleo <dan@getchef.com>2014-03-27 15:54:25 -0700
committerdanielsdeleo <dan@getchef.com>2014-03-27 15:54:25 -0700
commitac3f5ee8c76fd6bbbb86c6c97bdfdcda2e6095b7 (patch)
tree41784135ab306ac80c1d83bf1b7b30f91c34f50b
parent1d786d4489ef0b2363b630e734cb205e098f651c (diff)
downloadchef-ac3f5ee8c76fd6bbbb86c6c97bdfdcda2e6095b7.tar.gz
Backport CHEF-4373 to 10.x
-rw-r--r--chef/lib/chef/api_client.rb22
-rw-r--r--chef/spec/unit/api_client_spec.rb58
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