Skip to content

Instantly share code, notes, and snippets.

@dvekeman
Created May 14, 2020 11:27
Show Gist options
  • Save dvekeman/a0a9814e6465e1914b605374de0de3fa to your computer and use it in GitHub Desktop.
Save dvekeman/a0a9814e6465e1914b605374de0de3fa to your computer and use it in GitHub Desktop.
# Adapted from:
# https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
import datetime
import hashlib
import hmac
import os
import requests
# ************* REQUEST VALUES *************
def execute(
method='GET',
service='execute-api',
host=None,
region='eu-west-1',
path='/',
endpoint=None,
request_parameters='',
access_key = None,
secret_key = None,
data: str = '',
extra_headers = None,
content_type: str = 'application/json'
):
if extra_headers is None:
extra_headers = {}
if endpoint is None:
endpoint = f'https://{host}{path}'
if access_key is None:
access_key = os.environ.get('SIGNATURE_KEY')
if secret_key is None:
secret_key = os.environ.get('SIGNATURE_SECRET')
if access_key is None or secret_key is None:
print('No access key is available.')
raise Exception('No access key is available.')
# Create a date for headers and the credential string
t = datetime.datetime.utcnow()
amzdate = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d') # Date w/o time, used in credential scope
# Explanation of the steps, see
# https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
canonical_uri = path
canonical_querystring = request_parameters
canonical_headers = 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n'
signed_headers = 'host;x-amz-date'
if method.upper() == 'POST':
canonical_headers = 'content-type:' + content_type + '\n' + canonical_headers
signed_headers = 'content-type;' + signed_headers
payload_hash = hashlib.sha256(data.encode('utf-8')).hexdigest()
canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
# print('canonical_request: %s', canonical_request)
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'
string_to_sign = algorithm + '\n' + amzdate + '\n' + credential_scope + '\n' + hashlib.sha256(
canonical_request.encode('utf-8')).hexdigest()
# print('string_to_sign: %s', string_to_sign)
signing_key = getSignatureKey(secret_key, datestamp, region, service)
signature = hmac.new(signing_key, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()
authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature
headers = {
'x-amz-date': amzdate,
'Authorization': authorization_header,
**extra_headers
}
if method.upper() == 'POST':
headers['Content-Type'] = content_type
request_url = endpoint + '?' + canonical_querystring
print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
print('Request URL = ' + request_url)
print('Request HEADERS = ' + str(headers))
if method.upper() == 'GET':
r = requests.get(request_url, headers=headers)
elif method.upper() == 'POST':
r = requests.post(url=request_url, data=data, headers=headers)
elif method.upper() == 'PUT':
r = requests.put(url=request_url, data=data, headers=headers)
elif method.upper() == 'DELETE':
r = requests.delete(url=request_url, data=data, headers=headers)
else:
raise Exception(f'Unsupported method "{method}"')
print('\nRESPONSE++++++++++++++++++++++++++++++++++++')
print('Response code: %d\n' % r.status_code)
print(r.text)
return r
# Key derivation functions. See:
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def sign(key, msg):
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
def getSignatureKey(key, dateStamp, regionName, serviceName):
kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, 'aws4_request')
return kSigning
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment