Variant of AWS v4 signing without SDK
but the varaint below invokes sts.GetCallerIdentity
To use, simply export env vars and run the python script below.
The script will manually sign and invoke the api using the AWS_SECRET_ACCESS_KEY
as the secret
export AWS_ACCESS_KEY_ID=redacted
export AWS_SECRET_ACCESS_KEY=redacted
aws sts get-caller-identity --debug
import datetime
import hashlib
import hmac
import requests
import os
import http.client as http_client
http_client.HTTPConnection.debuglevel = 1
import logging
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
# AWS access keys
access_key = os.environ['AWS_ACCESS_KEY_ID']
secret_key = os.environ['AWS_SECRET_ACCESS_KEY']
# Request parameters
method = 'POST'
service = 'sts'
host = "sts.amazonaws.com"
region = 'us-east-1'
endpoint = '/'
# Create a datetime object for signing
t = datetime.datetime.utcnow()
amzdate = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d')
# Create the canonical request
canonical_uri = endpoint
canonical_querystring = ''
canonical_headers = 'content-type:application/x-www-form-urlencoded' + '\n' +'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n'
signed_headers = 'content-type;host;x-amz-date'
# https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html
payload = 'Action=GetCallerIdentity&Version=2011-06-15'
#payload = 'Action=GetSessionToken&DurationSeconds=3600&Version=2011-06-15'
#payload = 'Action=AssumeRole&&RoleSessionName=testAR&RoleArn=arn:aws:iam::291738886548:role/gcpsts&Version=2011-06-15'
payload_hash = hashlib.sha256(payload.encode('utf-8')).hexdigest()
canonical_request = (method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n'
+ canonical_headers + '\n' + signed_headers + '\n' + payload_hash)
# Create the string to sign
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())
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 the string
signing_key = getSignatureKey(secret_key, datestamp, region, service)
signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()
# Add signing information to the request
authorization_header = (algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' +
'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature)
print(authorization_header)
# Make the request
headers = {'content-type': 'application/x-www-form-urlencoded',
'host': host,
'x-amz-date': amzdate,
'Authorization': authorization_header}
request_url = 'https://' + host + canonical_uri
response = requests.post(request_url, headers=headers, data=payload,allow_redirects=False, timeout=5)
response.raise_for_status()
print(response.text)