use subclass for new version of signed connection Signed-off-by: Tomaz Muraus <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/65579bf0 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/65579bf0 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/65579bf0 Branch: refs/heads/trunk Commit: 65579bf0f3836767fb1c9fed3b4253d9a4e6e4dd Parents: b3e463f Author: Gertjan Oude Lohuis <[email protected]> Authored: Mon Feb 2 16:02:04 2015 +0100 Committer: Tomaz Muraus <[email protected]> Committed: Fri Mar 6 15:58:12 2015 +0100 ---------------------------------------------------------------------- libcloud/common/aws.py | 96 +++++++++++++++++++----------------- libcloud/compute/drivers/ec2.py | 12 +++-- 2 files changed, 57 insertions(+), 51 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/65579bf0/libcloud/common/aws.py ---------------------------------------------------------------------- diff --git a/libcloud/common/aws.py b/libcloud/common/aws.py index 9e5a19e..823f5cd 100644 --- a/libcloud/common/aws.py +++ b/libcloud/common/aws.py @@ -135,23 +135,61 @@ class AWSTokenConnection(ConnectionUserAndKey): class SignedAWSConnection(AWSTokenConnection): def add_default_params(self, params): + params['SignatureVersion'] = '2' + params['SignatureMethod'] = 'HmacSHA256' + params['AWSAccessKeyId'] = self.user_id params['Version'] = self.version + params['Timestamp'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', + time.gmtime()) + params['Signature'] = self._get_aws_auth_param(params, self.key, + self.action) + return params + + def _get_aws_auth_param(self, params, secret_key, path='/'): + """ + Creates the signature required for AWS, per + http://bit.ly/aR7GaQ [docs.amazonwebservices.com]: + + StringToSign = HTTPVerb + "\n" + + ValueOfHostHeaderInLowercase + "\n" + + HTTPRequestURI + "\n" + + CanonicalizedQueryString <from the preceding step> + """ + keys = list(params.keys()) + keys.sort() + pairs = [] + for key in keys: + value = str(params[key]) + pairs.append(urlquote(key, safe='') + '=' + + urlquote(value, safe='-_~')) + + qs = '&'.join(pairs) + + hostname = self.host + if (self.secure and self.port != 443) or \ + (not self.secure and self.port != 80): + hostname += ":" + str(self.port) + + string_to_sign = '\n'.join(('GET', hostname, path, qs)) + + b64_hmac = base64.b64encode( + hmac.new(b(secret_key), b(string_to_sign), + digestmod=sha256).digest() + ) + + return b64_hmac.decode('utf-8') + + +class V4SignedAWSConnection(AWSTokenConnection): - if self.signature_version == 2: - params['SignatureVersion'] = '2' - params['SignatureMethod'] = 'HmacSHA256' - params['AWSAccessKeyId'] = self.user_id - params['Timestamp'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', - time.gmtime()) - params['Signature'] = self._get_aws_auth_param(params, self.key, - self.action) + def add_default_params(self, params): + params['Version'] = self.version return params def pre_connect_hook(self, params, headers): - if self.signature_version == 4: - now = datetime.utcnow() - headers['X-AMZ-Date'] = now.strftime('%Y%m%dT%H%M%SZ') - headers['Authorization'] = self._get_authorization_v4_header(params, headers, now) + now = datetime.utcnow() + headers['X-AMZ-Date'] = now.strftime('%Y%m%dT%H%M%SZ') + headers['Authorization'] = self._get_authorization_v4_header(params, headers, now) return params, headers @@ -203,40 +241,6 @@ class SignedAWSConnection(AWSTokenConnection): return 'AWS4-HMAC-SHA256 Credential=%s/%s, SignedHeaders=%s, Signature=%s' % \ (self.user_id, credential_scope, signed_headers, signature) - def _get_aws_auth_param(self, params, secret_key, path='/'): - """ - Creates the signature required for AWS, per - http://bit.ly/aR7GaQ [docs.amazonwebservices.com]: - - StringToSign = HTTPVerb + "\n" + - ValueOfHostHeaderInLowercase + "\n" + - HTTPRequestURI + "\n" + - CanonicalizedQueryString <from the preceding step> - """ - keys = list(params.keys()) - keys.sort() - pairs = [] - for key in keys: - value = str(params[key]) - pairs.append(urlquote(key, safe='') + '=' + - urlquote(value, safe='-_~')) - - qs = '&'.join(pairs) - - hostname = self.host - if (self.secure and self.port != 443) or \ - (not self.secure and self.port != 80): - hostname += ":" + str(self.port) - - string_to_sign = '\n'.join(('GET', hostname, path, qs)) - - b64_hmac = base64.b64encode( - hmac.new(b(secret_key), b(string_to_sign), - digestmod=sha256).digest() - ) - - return b64_hmac.decode('utf-8') - class AWSDriver(BaseDriver): def __init__(self, key, secret=None, secure=True, host=None, port=None, http://git-wip-us.apache.org/repos/asf/libcloud/blob/65579bf0/libcloud/compute/drivers/ec2.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py index f87c797..4401da4 100644 --- a/libcloud/compute/drivers/ec2.py +++ b/libcloud/compute/drivers/ec2.py @@ -34,7 +34,7 @@ from libcloud.utils.xml import fixxpath, findtext, findattr, findall from libcloud.utils.publickey import get_pubkey_ssh2_fingerprint from libcloud.utils.publickey import get_pubkey_comment from libcloud.utils.iso8601 import parse_date -from libcloud.common.aws import AWSBaseResponse, SignedAWSConnection +from libcloud.common.aws import AWSBaseResponse, SignedAWSConnection, V4SignedAWSConnection from libcloud.common.types import (InvalidCredsError, MalformedResponseError, LibcloudError) from libcloud.compute.providers import Provider @@ -1703,15 +1703,17 @@ class EC2Connection(SignedAWSConnection): version = API_VERSION host = REGION_DETAILS['us-east-1']['endpoint'] responseCls = EC2Response - signature_version = 2 service_name = 'ec2' -class EC2V4Connection(EC2Connection): +class EC2V4Connection(V4SignedAWSConnection): """ Represents a single connection to an EC2 Endpoint using signature version 4. """ - signature_version = 4 + version = API_VERSION + host = REGION_DETAILS['us-east-1']['endpoint'] + responseCls = EC2Response + service_name = 'ec2' class ExEC2AvailabilityZone(object): @@ -5531,7 +5533,7 @@ class EC2NodeDriver(BaseEC2NodeDriver): Amazon EC2 node driver. """ - connectionCls = EC2Connection + connectionCls = EC2V4Connection type = Provider.EC2 name = 'Amazon EC2' website = 'http://aws.amazon.com/ec2/'
