summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan McLellan <btm@loftninjas.org>2012-08-06 13:18:03 -0700
committerBryan McLellan <btm@loftninjas.org>2012-08-06 13:18:03 -0700
commit92872c4fe201bcacfef76b281684e5164c9f935b (patch)
treed48cb04e5d5800a6122e6d506beb37f64ea86806
parent10e5932e10071d22256f67fbec9edae1281de682 (diff)
parent791478bfefa1ea68908bd11a3bb0b07b32c8daf6 (diff)
downloadchef-92872c4fe201bcacfef76b281684e5164c9f935b.tar.gz
Merge branch 'CHEF-3095-w-backcompat'
-rw-r--r--chef/chef.gemspec2
-rw-r--r--chef/lib/chef/client.rb6
-rw-r--r--chef/lib/chef/config.rb29
-rw-r--r--chef/lib/chef/knife.rb4
-rw-r--r--chef/lib/chef/rest/auth_credentials.rb7
-rw-r--r--chef/spec/unit/client_spec.rb24
-rw-r--r--chef/spec/unit/rest/auth_credentials_spec.rb50
7 files changed, 104 insertions, 18 deletions
diff --git a/chef/chef.gemspec b/chef/chef.gemspec
index 34f39790f6..ccdd5bccb0 100644
--- a/chef/chef.gemspec
+++ b/chef/chef.gemspec
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
s.add_dependency "mixlib-config", ">= 1.1.2"
s.add_dependency "mixlib-cli", ">= 1.1.0"
s.add_dependency "mixlib-log", ">= 1.3.0"
- s.add_dependency "mixlib-authentication", ">= 1.1.0"
+ s.add_dependency "mixlib-authentication", ">= 1.3.0"
s.add_dependency "mixlib-shellout"
s.add_dependency "ohai", ">= 0.6.0"
diff --git a/chef/lib/chef/client.rb b/chef/lib/chef/client.rb
index ed052c1fdd..8f57cdd5a0 100644
--- a/chef/lib/chef/client.rb
+++ b/chef/lib/chef/client.rb
@@ -224,6 +224,12 @@ class Chef
raise Chef::Exceptions::CannotDetermineNodeName, msg
end
+ # node names > 90 bytes only work with authentication protocol >= 1.1
+ # see discussion in config.rb.
+ if name.bytesize > 90
+ Chef::Config[:authentication_protocol_version] = "1.1"
+ end
+
name
end
diff --git a/chef/lib/chef/config.rb b/chef/lib/chef/config.rb
index 727314280f..65e985848b 100644
--- a/chef/lib/chef/config.rb
+++ b/chef/lib/chef/config.rb
@@ -232,7 +232,36 @@ class Chef
# (persist across rabbitmq restarts)
amqp_consumer_id "default"
+ # Sets the version of the signed header authentication protocol to use (see
+ # the 'mixlib-authorization' project for more detail). Currently, versions
+ # 1.0 and 1.1 are available; however, the chef-server must first be
+ # upgraded to support version 1.1 before clients can begin using it.
+ #
+ # Version 1.1 of the protocol is required when using a `node_name` greater
+ # than ~90 bytes (~90 ascii characters), so chef-client will automatically
+ # switch to using version 1.1 when `node_name` is too large for the 1.0
+ # protocol. If you intend to use large node names, ensure that your server
+ # supports version 1.1. Automatic detection of large node names means that
+ # users will generally not need to manually configure this.
+ #
+ # In the future, this configuration option may be replaced with an
+ # automatic negotiation scheme.
+ authentication_protocol_version "1.0"
+
+ # This key will be used to sign requests to the Chef server. This location
+ # must be writable by Chef during initial setup when generating a client
+ # identity on the server.
+ #
+ # The chef-server will look up the public key for the client using the
+ # `node_name` of the client.
client_key platform_specific_path("/etc/chef/client.pem")
+
+ # If there is no file in the location given by `client_key`, chef-client
+ # will temporarily use the "validator" identity to generate one. If the
+ # `client_key` is not present and the `validation_key` is also not present,
+ # chef-client will not be able to authenticate to the server.
+ #
+ # The `validation_key` is never used if the `client_key` exists.
validation_key platform_specific_path("/etc/chef/validation.pem")
validation_client_name "chef-validator"
web_ui_client_name "chef-webui"
diff --git a/chef/lib/chef/knife.rb b/chef/lib/chef/knife.rb
index 03b8ef4690..c664503cee 100644
--- a/chef/lib/chef/knife.rb
+++ b/chef/lib/chef/knife.rb
@@ -352,6 +352,10 @@ class Chef
if Chef::Config[:node_name].nil?
#raise ArgumentError, "No user specified, pass via -u or specifiy 'node_name' in #{config[:config_file] ? config[:config_file] : "~/.chef/knife.rb"}"
+ elsif Chef::Config[:node_name].bytesize > 90
+ # node names > 90 bytes only work with authentication protocol >= 1.1
+ # see discussion in config.rb.
+ Chef::Config[:authentication_protocol_version] = "1.1"
end
end
diff --git a/chef/lib/chef/rest/auth_credentials.rb b/chef/lib/chef/rest/auth_credentials.rb
index ec9341015b..b95defcdb5 100644
--- a/chef/lib/chef/rest/auth_credentials.rb
+++ b/chef/lib/chef/rest/auth_credentials.rb
@@ -43,9 +43,10 @@ class Chef
Chef::Log.debug("Signing the request as #{client_name}")
# params_in = {:http_method => :GET, :path => "/clients", :body => "", :host => "localhost"}
- request_params = request_params.dup
- request_params[:timestamp] = Time.now.utc.iso8601
- request_params[:user_id] = client_name
+ request_params = request_params.dup
+ request_params[:timestamp] = Time.now.utc.iso8601
+ request_params[:user_id] = client_name
+ request_params[:proto_version] = Chef::Config[:authentication_protocol_version]
host = request_params.delete(:host) || "localhost"
sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object(request_params)
diff --git a/chef/spec/unit/client_spec.rb b/chef/spec/unit/client_spec.rb
index 64bb8799de..d1f0fe130e 100644
--- a/chef/spec/unit/client_spec.rb
+++ b/chef/spec/unit/client_spec.rb
@@ -51,6 +51,30 @@ shared_examples_for Chef::Client do
@client.node = @node
end
+ describe "authentication protocol selection" do
+ after do
+ Chef::Config[:authentication_protocol_version] = "1.0"
+ end
+
+ context "when the node name is <= 90 bytes" do
+ it "does not force the authentication protocol to 1.1" do
+ Chef::Config[:node_name] = ("f" * 90)
+ # ugly that this happens as a side effect of a getter :(
+ @client.node_name
+ Chef::Config[:authentication_protocol_version].should == "1.0"
+ end
+ end
+
+ context "when the node name is > 90 bytes" do
+ it "sets the authentication protocol to version 1.1" do
+ Chef::Config[:node_name] = ("f" * 91)
+ # ugly that this happens as a side effect of a getter :(
+ @client.node_name
+ Chef::Config[:authentication_protocol_version].should == "1.1"
+ end
+ end
+ end
+
describe "run" do
it "should identify the node and run ohai, then register the client" do
diff --git a/chef/spec/unit/rest/auth_credentials_spec.rb b/chef/spec/unit/rest/auth_credentials_spec.rb
index 8dcc48a8b6..a2034f96ed 100644
--- a/chef/spec/unit/rest/auth_credentials_spec.rb
+++ b/chef/spec/unit/rest/auth_credentials_spec.rb
@@ -97,20 +97,42 @@ describe Chef::REST::AuthCredentials do
it "generates signature headers for the request" do
Time.stub!(:now).and_return(@request_time)
- expected = {}
- expected["HOST"] = "localhost"
- expected["X-OPS-AUTHORIZATION-1"] = "kBssX1ENEwKtNYFrHElN9vYGWS7OeowepN9EsYc9csWfh8oUovryPKDxytQ/"
- expected["X-OPS-AUTHORIZATION-2"] = "Wc2/nSSyxdWJjjfHzrE+YrqNQTaArOA7JkAf5p75eTUonCWcvNPjFrZVgKGS"
- expected["X-OPS-AUTHORIZATION-3"] = "yhzHJQh+lcVA9wwARg5Hu9q+ddS8xBOdm3Vp5atl5NGHiP0loiigMYvAvzPO"
- expected["X-OPS-AUTHORIZATION-4"] = "r9853eIxwYMhn5hLGhAGFQznJbE8+7F/lLU5Zmk2t2MlPY8q3o1Q61YD8QiJ"
- expected["X-OPS-AUTHORIZATION-5"] = "M8lIt53ckMyUmSU0DDURoiXLVkE9mag/6Yq2tPNzWq2AdFvBqku9h2w+DY5k"
- expected["X-OPS-AUTHORIZATION-6"] = "qA5Rnzw5rPpp3nrWA9jKkPw4Wq3+4ufO2Xs6w7GCjA=="
- expected["X-OPS-CONTENT-HASH"] = "1tuzs5XKztM1ANrkGNPah6rW9GY="
- expected["X-OPS-SIGN"] = "version=1.0"
- expected["X-OPS-TIMESTAMP"] = "2010-04-10T17:34:20Z"
- expected["X-OPS-USERID"] = "client-name"
-
- @auth_credentials.signature_headers(@request_params).should == expected
+ actual = @auth_credentials.signature_headers(@request_params)
+ actual["HOST"].should == "localhost"
+ actual["X-OPS-AUTHORIZATION-1"].should == "kBssX1ENEwKtNYFrHElN9vYGWS7OeowepN9EsYc9csWfh8oUovryPKDxytQ/"
+ actual["X-OPS-AUTHORIZATION-2"].should == "Wc2/nSSyxdWJjjfHzrE+YrqNQTaArOA7JkAf5p75eTUonCWcvNPjFrZVgKGS"
+ actual["X-OPS-AUTHORIZATION-3"].should == "yhzHJQh+lcVA9wwARg5Hu9q+ddS8xBOdm3Vp5atl5NGHiP0loiigMYvAvzPO"
+ actual["X-OPS-AUTHORIZATION-4"].should == "r9853eIxwYMhn5hLGhAGFQznJbE8+7F/lLU5Zmk2t2MlPY8q3o1Q61YD8QiJ"
+ actual["X-OPS-AUTHORIZATION-5"].should == "M8lIt53ckMyUmSU0DDURoiXLVkE9mag/6Yq2tPNzWq2AdFvBqku9h2w+DY5k"
+ actual["X-OPS-AUTHORIZATION-6"].should == "qA5Rnzw5rPpp3nrWA9jKkPw4Wq3+4ufO2Xs6w7GCjA=="
+ actual["X-OPS-CONTENT-HASH"].should == "1tuzs5XKztM1ANrkGNPah6rW9GY="
+ actual["X-OPS-SIGN"].should =~ %r{(version=1\.0)|(algorithm=sha1;version=1.0;)}
+ actual["X-OPS-TIMESTAMP"].should == "2010-04-10T17:34:20Z"
+ actual["X-OPS-USERID"].should == "client-name"
+
+ end
+
+ describe "when configured for version 1.1 of the authn protocol" do
+ before do
+ Chef::Config[:authentication_protocol_version] = "1.1"
+ end
+
+ after do
+ Chef::Config[:authentication_protocol_version] = "1.0"
+ end
+
+ it "generates the correct signature for version 1.1" do
+ Time.stub!(:now).and_return(@request_time)
+ actual = @auth_credentials.signature_headers(@request_params)
+ actual["HOST"].should == "localhost"
+ actual["X-OPS-CONTENT-HASH"].should == "1tuzs5XKztM1ANrkGNPah6rW9GY="
+ actual["X-OPS-SIGN"].should == "algorithm=sha1;version=1.1;"
+ actual["X-OPS-TIMESTAMP"].should == "2010-04-10T17:34:20Z"
+ actual["X-OPS-USERID"].should == "client-name"
+
+ # mixlib-authN will test the actual signature stuff for each version of
+ # the protocol so we won't test it again here.
+ end
end
end
end