summaryrefslogtreecommitdiff
path: root/lib/chef/rest
diff options
context:
space:
mode:
authordanielsdeleo <dan@opscode.com>2013-10-03 16:52:18 -0700
committerdanielsdeleo <dan@opscode.com>2013-10-08 15:01:47 -0700
commit2f82c5b421d2a99cd0c098b4a2d5047d19cdc531 (patch)
tree2f465844923b13a6f6f74b1437ca209e77b64cf0 /lib/chef/rest
parentd391b30f9d3e77505285dfddbea77908d6a36968 (diff)
downloadchef-2f82c5b421d2a99cd0c098b4a2d5047d19cdc531.tar.gz
move http authenticator to its own file
Diffstat (limited to 'lib/chef/rest')
-rw-r--r--lib/chef/rest/authenticator.rb85
1 files changed, 85 insertions, 0 deletions
diff --git a/lib/chef/rest/authenticator.rb b/lib/chef/rest/authenticator.rb
new file mode 100644
index 0000000000..13f33cde25
--- /dev/null
+++ b/lib/chef/rest/authenticator.rb
@@ -0,0 +1,85 @@
+#--
+# Author:: Daniel DeLeo (<dan@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/rest/auth_credentials'
+require 'chef/exceptions'
+require 'openssl'
+
+class Chef
+ class REST
+ class Authenticator
+
+ attr_reader :signing_key_filename
+ attr_reader :raw_key
+ attr_reader :attr_names
+ attr_reader :auth_credentials
+
+ attr_accessor :sign_request
+
+ def initialize(opts={})
+ @raw_key = nil
+ @sign_request = true
+ @signing_key_filename = opts[:signing_key_filename]
+ @key = load_signing_key(opts[:signing_key_filename], opts[:raw_key])
+ @auth_credentials = AuthCredentials.new(opts[:client_name], @key)
+ end
+
+ def handle_request(method, url, headers={}, data=false)
+ headers.merge!(authentication_headers(method, url, data)) if sign_requests?
+ [method, url, headers, data]
+ end
+
+ def handle_response(http_response, rest_request, return_value)
+ [http_response, rest_request, return_value]
+ end
+
+ def sign_requests?
+ auth_credentials.sign_requests? && @sign_request
+ end
+
+ def client_name
+ @auth_credentials.client_name
+ end
+
+ def load_signing_key(key_file, raw_key = nil)
+ if (!!key_file)
+ @raw_key = IO.read(key_file).strip
+ elsif (!!raw_key)
+ @raw_key = raw_key.strip
+ else
+ return nil
+ end
+ @key = OpenSSL::PKey::RSA.new(@raw_key)
+ rescue SystemCallError, IOError => e
+ Chef::Log.warn "Failed to read the private key #{key_file}: #{e.inspect}"
+ raise Chef::Exceptions::PrivateKeyMissing, "I cannot read #{key_file}, which you told me to use to sign requests!"
+ rescue OpenSSL::PKey::RSAError
+ msg = "The file #{key_file} or :raw_key option does not contain a correctly formatted private key.\n"
+ msg << "The key file should begin with '-----BEGIN RSA PRIVATE KEY-----' and end with '-----END RSA PRIVATE KEY-----'"
+ raise Chef::Exceptions::InvalidPrivateKey, msg
+ end
+
+ def authentication_headers(method, url, json_body=nil)
+ request_params = {:http_method => method, :path => url.path, :body => json_body, :host => "#{url.host}:#{url.port}"}
+ request_params[:body] ||= ""
+ auth_credentials.signature_headers(request_params)
+ end
+
+ end
+ end
+end