| Index: boto/auth.py
|
| diff --git a/boto/auth.py b/boto/auth.py
|
| index 6c6c1f211b549c588f64dddca5478b6e93fd31e0..084dde9efa811318d84ee8a691e96c003934f4c2 100644
|
| --- a/boto/auth.py
|
| +++ b/boto/auth.py
|
| @@ -34,8 +34,8 @@ import boto.plugin
|
| import boto.utils
|
| import hmac
|
| import sys
|
| -import time
|
| import urllib
|
| +from email.utils import formatdate
|
|
|
| from boto.auth_handler import AuthHandler
|
| from boto.exception import BotoClientError
|
| @@ -77,7 +77,8 @@ class HmacKeys(object):
|
| self._provider = provider
|
| self._hmac = hmac.new(self._provider.secret_key, digestmod=sha)
|
| if sha256:
|
| - self._hmac_256 = hmac.new(self._provider.secret_key, digestmod=sha256)
|
| + self._hmac_256 = hmac.new(self._provider.secret_key,
|
| + digestmod=sha256)
|
| else:
|
| self._hmac_256 = None
|
|
|
| @@ -111,9 +112,11 @@ class HmacAuthV1Handler(AuthHandler, HmacKeys):
|
| method = http_request.method
|
| auth_path = http_request.auth_path
|
| if not headers.has_key('Date'):
|
| - headers['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
|
| - time.gmtime())
|
| + headers['Date'] = formatdate(usegmt=True)
|
|
|
| + if self._provider.security_token:
|
| + key = self._provider.security_token_header
|
| + headers[key] = self._provider.security_token
|
| c_string = boto.utils.canonical_string(method, auth_path, headers,
|
| None, self._provider)
|
| b64_hmac = self.sign_string(c_string)
|
| @@ -136,8 +139,7 @@ class HmacAuthV2Handler(AuthHandler, HmacKeys):
|
| def add_auth(self, http_request, **kwargs):
|
| headers = http_request.headers
|
| if not headers.has_key('Date'):
|
| - headers['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
|
| - time.gmtime())
|
| + headers['Date'] = formatdate(usegmt=True)
|
|
|
| b64_hmac = self.sign_string(headers['Date'])
|
| auth_hdr = self._provider.auth_header
|
| @@ -157,8 +159,7 @@ class HmacAuthV3Handler(AuthHandler, HmacKeys):
|
| def add_auth(self, http_request, **kwargs):
|
| headers = http_request.headers
|
| if not headers.has_key('Date'):
|
| - headers['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
|
| - time.gmtime())
|
| + headers['Date'] = formatdate(usegmt=True)
|
|
|
| b64_hmac = self.sign_string(headers['Date'])
|
| s = "AWS3-HTTPS AWSAccessKeyId=%s," % self._provider.access_key
|
| @@ -179,20 +180,22 @@ class QuerySignatureHelper(HmacKeys):
|
| params['Timestamp'] = boto.utils.get_ts()
|
| qs, signature = self._calc_signature(
|
| http_request.params, http_request.method,
|
| - http_request.path, http_request.host)
|
| + http_request.auth_path, http_request.host)
|
| boto.log.debug('query_string: %s Signature: %s' % (qs, signature))
|
| if http_request.method == 'POST':
|
| headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
|
| http_request.body = qs + '&Signature=' + urllib.quote(signature)
|
| + http_request.headers['Content-Length'] = str(len(http_request.body))
|
| else:
|
| http_request.body = ''
|
| - http_request.path = (http_request.path + '?' + qs + '&Signature=' + urllib.quote(signature))
|
| - # Now that query params are part of the path, clear the 'params' field
|
| - # in request.
|
| - http_request.params = {}
|
| + # if this is a retried request, the qs from the previous try will
|
| + # already be there, we need to get rid of that and rebuild it
|
| + http_request.path = http_request.path.split('?')[0]
|
| + http_request.path = (http_request.path + '?' + qs +
|
| + '&Signature=' + urllib.quote(signature))
|
|
|
| class QuerySignatureV0AuthHandler(QuerySignatureHelper, AuthHandler):
|
| - """Class SQS query signature based Auth handler."""
|
| + """Provides Signature V0 Signing"""
|
|
|
| SignatureVersion = 0
|
| capability = ['sign-v0']
|
| @@ -206,7 +209,7 @@ class QuerySignatureV0AuthHandler(QuerySignatureHelper, AuthHandler):
|
| keys.sort(cmp = lambda x, y: cmp(x.lower(), y.lower()))
|
| pairs = []
|
| for key in keys:
|
| - val = bot.utils.get_utf8_value(params[key])
|
| + val = boto.utils.get_utf8_value(params[key])
|
| pairs.append(key + '=' + urllib.quote(val))
|
| qs = '&'.join(pairs)
|
| return (qs, base64.b64encode(hmac.digest()))
|
| @@ -238,7 +241,7 @@ class QuerySignatureV2AuthHandler(QuerySignatureHelper, AuthHandler):
|
|
|
| SignatureVersion = 2
|
| capability = ['sign-v2', 'ec2', 'ec2', 'emr', 'fps', 'ecs',
|
| - 'sdb', 'iam', 'rds', 'sns', 'sqs']
|
| + 'sdb', 'iam', 'rds', 'sns', 'sqs', 'cloudformation']
|
|
|
| def _calc_signature(self, params, verb, path, server_name):
|
| boto.log.debug('using _calc_signature_2')
|
| @@ -249,6 +252,8 @@ class QuerySignatureV2AuthHandler(QuerySignatureHelper, AuthHandler):
|
| else:
|
| hmac = self._hmac.copy()
|
| params['SignatureMethod'] = 'HmacSHA1'
|
| + if self._provider.security_token:
|
| + params['SecurityToken'] = self._provider.security_token
|
| keys = params.keys()
|
| keys.sort()
|
| pairs = []
|
| @@ -303,7 +308,8 @@ def get_auth_handler(host, config, provider, requested_capability=None):
|
| names = [handler.__name__ for handler in checked_handlers]
|
| raise boto.exception.NoAuthHandlerFound(
|
| 'No handler was ready to authenticate. %d handlers were checked.'
|
| - ' %s ' % (len(names), str(names)))
|
| + ' %s '
|
| + 'Check your credentials' % (len(names), str(names)))
|
|
|
| if len(ready_handlers) > 1:
|
| # NOTE: Even though it would be nice to accept more than one handler
|
| @@ -313,7 +319,10 @@ def get_auth_handler(host, config, provider, requested_capability=None):
|
| # on the wrong account.
|
| names = [handler.__class__.__name__ for handler in ready_handlers]
|
| raise boto.exception.TooManyAuthHandlerReadyToAuthenticate(
|
| - '%d AuthHandlers ready to authenticate, '
|
| - 'only 1 expected: %s' % (len(names), str(names)))
|
| + '%d AuthHandlers %s ready to authenticate for requested_capability '
|
| + '%s, only 1 expected. This happens if you import multiple '
|
| + 'pluging.Plugin implementations that declare support for the '
|
| + 'requested_capability.' % (len(names), str(names),
|
| + requested_capability))
|
|
|
| return ready_handlers[0]
|
|
|