| Conditions | 4 |
| Total Lines | 59 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | import datetime |
||
| 34 | def create_v4_signature(self, request_params): |
||
| 35 | ''' |
||
| 36 | Create URI and signature headers based on AWS V4 signing process. |
||
| 37 | Refer to https://docs.aws.amazon.com/AlexaWebInfoService/latest/ApiReferenceArticle.html for request params. |
||
| 38 | :param request_params: dictionary of request parameters |
||
| 39 | :return: URL and header to be passed to requests.get |
||
| 40 | ''' |
||
| 41 | |||
| 42 | method = 'GET' |
||
| 43 | service = 'awis' |
||
| 44 | host = 'awis.us-west-1.amazonaws.com' |
||
| 45 | region = 'us-west-1' |
||
| 46 | endpoint = 'https://awis.amazonaws.com/api' |
||
| 47 | request_parameters = urlencode([(key, request_params[key]) for key in sorted(request_params.keys())]) |
||
| 48 | |||
| 49 | # Key derivation functions. See: |
||
| 50 | # http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python |
||
| 51 | def sign(key, msg): |
||
| 52 | return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest() |
||
| 53 | |||
| 54 | def getSignatureKey(key, dateStamp, regionName, serviceName): |
||
| 55 | kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp) |
||
| 56 | kRegion = sign(kDate, regionName) |
||
| 57 | kService = sign(kRegion, serviceName) |
||
| 58 | kSigning = sign(kService, 'aws4_request') |
||
| 59 | return kSigning |
||
| 60 | |||
| 61 | # Create a date for headers and the credential string |
||
| 62 | t = datetime.datetime.utcnow() |
||
| 63 | amzdate = t.strftime('%Y%m%dT%H%M%SZ') |
||
| 64 | datestamp = t.strftime('%Y%m%d') # Date w/o time, used in credential scope |
||
| 65 | |||
| 66 | # Create canonical request |
||
| 67 | canonical_uri = '/api' |
||
| 68 | canonical_querystring = request_parameters |
||
| 69 | canonical_headers = 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n' |
||
| 70 | signed_headers = 'host;x-amz-date' |
||
| 71 | payload_hash = hashlib.sha256(''.encode('utf8')).hexdigest() |
||
| 72 | canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash |
||
| 73 | |||
| 74 | # Create string to sign |
||
| 75 | algorithm = 'AWS4-HMAC-SHA256' |
||
| 76 | credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request' |
||
| 77 | string_to_sign = algorithm + '\n' + amzdate + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf8')).hexdigest() |
||
| 78 | |||
| 79 | # Calculate signature |
||
| 80 | signing_key = getSignatureKey(self.secret_access_key, datestamp, region, service) |
||
| 81 | |||
| 82 | # Sign the string_to_sign using the signing_key |
||
| 83 | signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest() |
||
| 84 | |||
| 85 | # Add signing information to the request |
||
| 86 | authorization_header = algorithm + ' ' + 'Credential=' + self.access_id + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature |
||
| 87 | headers = {'X-Amz-Date':amzdate, 'Authorization':authorization_header, 'Content-Type': 'application/xml', 'Accept': 'application/xml'} |
||
| 88 | |||
| 89 | # Create request url |
||
| 90 | request_url = endpoint + '?' + canonical_querystring |
||
| 91 | |||
| 92 | return request_url, headers |
||
| 93 | |||
| 197 |