Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 OpenStack LLC # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2011 - 2012 Justin Santa Barbara # All Rights Reserved. # # 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.
""" Utility class which adds allows a request to be signed with an AWS style signature, which can then be used for authentication via the keystone ec2 authentication extension """
""" Detect if the credentials are for a v4 signed request, since AWS removed the SignatureVersion field from the v4 request spec... This expects a dict of the request headers to be passed in the credentials dict, since the recommended way to pass v4 creds is via the 'Authorization' header see http://docs.aws.amazon.com/general/latest/gr/ sigv4-signed-request-examples.html
Alternatively X-Amz-Algorithm can be specified as a query parameter, and the authentication data can also passed as query parameters.
Note a hash of the request body is also required in the credentials for v4 auth to work in the body_hash key, calculated via: hashlib.sha256(req.body).hexdigest() """ # Alternatively the Authorization data can be passed via # the query params list, check X-Amz-Algorithm=AWS4-HMAC-SHA256 'AWS4-HMAC-SHA256'):
"""Generate auth string according to what SignatureVersion is given.""" credentials['verb'], credentials['host'], credentials['path']) credentials['verb'], credentials['host'], credentials['path'], credentials['headers'], credentials['body_hash'])
if signature_version is not None: raise Exception('Unknown signature version: %s' % signature_version) else: raise Exception('Unexpected signature format')
def _get_utf8_value(value): """Get the UTF8-encoded version of a value.""" value = str(value) else:
"""Generate AWS signature version 0 string."""
"""Generate AWS signature version 1 string."""
def _canonical_qs(params): """ Construct a sorted, correctly encoded query string as required for _calc_signature_2 and _calc_signature_4 """
"""Generate AWS signature version 2 string.""" else:
body_hash): """Generate AWS signature version 4 string."""
hashlib.sha256).digest()
""" Signature key derivation, see http://docs.aws.amazon.com/general/latest/gr/ signature-v4-examples.html#signature-v4-examples-python """ datestamp)
""" Get specified auth parameter, provided via one of: - the Authorization header - the X-Amz-* query parameters """ '%s=' % param_name)[2].split(',')[0] except KeyError: param_str = params.get('X-Amz-%s' % param_name)
""" Get the X-Amz-Date' value, which can be either a header or paramter
Note AWS supports parsing the Date header also, but this is not currently supported here as it will require some format mangling So the X-Amz-Date value must be YYYYMMDDTHHMMSSZ format, then it can be used to match against the YYYYMMDD format provided in the credential scope. see: http://docs.aws.amazon.com/general/latest/gr/ sigv4-date-handling.html """ except KeyError: return params.get('X-Amz-Date')
# Get the list of headers to include, from either # - the Authorization header (SignedHeaders key) # - the X-Amz-SignedHeaders query parameter for (k, v) in headers.iteritems()) continue # Note we discard any port suffix (h, headers_lower[h].split(':')[0])) else:
# Create canonical request: # http://docs.aws.amazon.com/general/latest/gr/ # sigv4-create-canonical-request.html # Get parameters and headers in expected string format self._canonical_qs(params), canonical_header_str(), auth_param('SignedHeaders'), body_hash))
# Check the date, reject any request where the X-Amz-Date doesn't # match the credential scope raise Exception('Request date mismatch error')
# Create the string to sign # http://docs.aws.amazon.com/general/latest/gr/ # sigv4-create-string-to-sign.html param_date, credential_scope, hashlib.sha256(cr).hexdigest()))
# Calculate the derived key, this requires a datestamp, region # and service, which can be extracted from the credential scope # Finally calculate the signature! hashlib.sha256).hexdigest() |