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] |