Accessing AWS HTTP API Gateway Endpoint With AWS Signature Version 4 Authentication Using Python
AWS API Gateway provides a scalable and secure way to expose your APIs to external clients. To ensure secure access to your API Gateway endpoints, AWS recommends using AWS Signature Version 4 authentication. In this article, we'll explore how to authenticate and interact with an AWS API Gateway endpoint using Python, leveraging the power of AWS Signature Version 4.
1. Overview of AWS Signature Version 4:
AWS Signature Version 4 is a signing process for AWS requests that helps ensure the integrity and authenticity of requests made to AWS services. It involves generating and including a signature in the request headers, which is then verified by AWS. This method prevents unauthorized access and tampering of data.
2. Setting up the AWS IAM Role in Account A:
To access the AWS API Gateway endpoint of AWS Account A, we'll assume an IAM role in the target AWS account (Account B). Follow these steps to set up the IAM role:
- Log in to the AWS Account B Management Console.
- Navigate to the IAM service.
- Create a new IAM role provide necessary permissions to access the API Gateway endpoint. You can use below policy in account B IAM role.
1{
2 "Version": "2012-10-17",
3 "Statement": [
4 {
5 "Effect": "Allow",
6 "Action": [
7 "execute-api:Invoke"
8 ],
9 "Resource": "arn:aws:execute-api:*:*:*"
10 }
11 ]
12}
- Note down the ARN of the IAM role for later use.
- Now move to another account (Account A).
- Open IAM console and create a IAM role for lambda and below IAM policy.
1
2{
3 "Version": "2012-10-17",
4 "Statement": [
5 {
6 "Sid": "VisualEditor0",
7 "Effect": "Allow",
8 "Action": "sts:AssumeRole",
9 "Resource": [
10 "<Account-B-IAM-Role-ARN>"
11 ]
12 }
13 ]
14}
Note: Change "
- Now, Create a Lambda function to assume Account B IAM role and Access the API Gateway.
3. Create a Lambda Function using AWS Signature Version 4 in Python:
To authenticate the requests using AWS Signature Version 4 in Python, we'll need to install the boto3
library and use the requests
library. Follow these steps:
- Install the required Python packages:
pip install boto3 requests
. - Import the necessary modules in your Python script:
1import requests
2import datetime
3import hmac
4import hashlib
5import boto3
- Assume the IAM role using the
boto3
library:
1role_arn = '<IAM_ROLE_ARN>'
2sts_client = boto3.client('sts')
3response = sts_client.assume_role(
4 RoleArn=role_arn,
5 RoleSessionName='AssumedRoleSession'
6)
7access_key = response['Credentials']['AccessKeyId']
8secret_key = response['Credentials']['SecretAccessKey']
9session_token = response['Credentials']['SessionToken']
- Generate the necessary headers for the AWS API Gateway request:
1api_gateway_url = '<API_GATEWAY_URL>'
2now = datetime.datetime.utcnow()
3amz_date = now.strftime('%Y%m%dT%H%M%SZ')
4headers = {
5 'Host': '<API_GATEWAY_HOST>',
6 'X-Amz-Date': amz_date,
7 'X-Amz-Security-Token': session_token
8}
- Generate the canonical request, string to sign, signing key, and signature using the AWS Signature Version 4 algorithm. You can use the following code as a starting point:
1canonical_request = ...
2string_to_sign = ...
3date_key = ...
4region_key = ...
5service_key = ...
6signing_key = ...
7signature = ...
- Add the
Authorization
header to the request headers:
1auth_header = f"AWS4-HMAC-SHA256 Credential={access_key}/{credential_scope}, SignedHeaders=host;x
2
3-amz-date;x-amz-security-token, Signature={signature}"
4headers['Authorization'] = auth_header
- Sending Requests to the AWS API Gateway Endpoint:
To send a request to the AWS API Gateway endpoint, use the
requests
library:
1response = requests.get(api_gateway_url, headers=headers)
- Complete Python Code Example: Here's a complete example of Python code to access an AWS API Gateway endpoint using AWS Signature Version 4 authentication:
1
2import requests
3import datetime
4import hmac
5import hashlib
6import boto3
7
8def lambda_handler(event, context):
9
10 # Assign Variables
11 ## Cross Account IAM role
12 role_arn = 'arn:aws:iam::<account-number>:role/<Cross-Account-IAM-Role-For-API-Gateway>'
13 ## API gateway endpoint
14 host_url = '1xesdf32de.execute-api.ap-south-1.amazonaws.com'
15 ## API gateway URI
16 host_uri = '/hello'
17
18 # Create an STS client
19 sts_client = boto3.client('sts')
20
21 # Assume the IAM role to retrieve temporary credentials
22 response = sts_client.assume_role(
23 RoleArn=role_arn,
24 RoleSessionName='AssumedRoleSession'
25 )
26
27 # Extract the temporary credentials
28 access_key = response['Credentials']['AccessKeyId']
29 secret_key = response['Credentials']['SecretAccessKey']
30 session_token = response['Credentials']['SessionToken']
31
32 # API Gateway endpoint URL
33 api_gateway_url = "https://"+host_url+host_uri
34
35 # Generate the current timestamp
36 now = datetime.datetime.utcnow()
37 amz_date = now.strftime('%Y%m%dT%H%M%SZ')
38
39 # Generate the request headers
40 headers = {
41 'Host': host_url,
42 'X-Amz-Date': amz_date,
43 'X-Amz-Security-Token': session_token
44 }
45
46 # Generate the canonical request
47 canonical_request = f"GET\n/hello\n\nhost:{headers['Host']}\nx-amz-date:{amz_date}\nx-amz-security-token:{session_token}\n\nhost;x-amz-date;x-amz-security-token\n{hashlib.sha256(b'').hexdigest()}"
48
49 # Generate the string to sign
50 credential_scope = f"{now.strftime('%Y%m%d')}/ap-south-1/execute-api/aws4_request"
51 string_to_sign = f"AWS4-HMAC-SHA256\n{amz_date}\n{credential_scope}\n{hashlib.sha256(canonical_request.encode()).hexdigest()}"
52
53 # Generate the signing key
54 date_key = hmac.new(('AWS4' + secret_key).encode(), now.strftime('%Y%m%d').encode(), hashlib.sha256).digest()
55 region_key = hmac.new(date_key, 'ap-south-1'.encode(), hashlib.sha256).digest()
56 service_key = hmac.new(region_key, 'execute-api'.encode(), hashlib.sha256).digest()
57 signing_key = hmac.new(service_key, 'aws4_request'.encode(), hashlib.sha256).digest()
58
59 # Generate the signature
60 signature = hmac.new(signing_key, string_to_sign.encode(), hashlib.sha256).hexdigest()
61
62 # Generate the authorization header
63 auth_header = f"AWS4-HMAC-SHA256 Credential={access_key}/{credential_scope}, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature={signature}"
64 headers['Authorization'] = auth_header
65
66 # Send the signed request
67 response = requests.get(api_gateway_url, headers=headers)
68
69 # Print the response from the API Gateway endpoint
70 print(response.text)
4. Test your lambda:
Now you can test your lambda. Lambda will assume your AWS Account B IAM role, Get the temp credential and Access the API gateway Endpoint.
5. Conclusion:
In this article, we explored how to access an AWS API Gateway endpoint using AWS Signature Version 4 authentication. We learned how to assume an IAM role, generate the required headers, and send authenticated requests to the API Gateway endpoint using Python. By leveraging AWS Signature Version 4, you can ensure secure and authorized access to your API Gateway resources.
Remember to follow AWS security best practices and configure appropriate IAM roles and permissions to control access to your resources.
By implementing AWS Signature Version 4 authentication in your Python applications, you can interact securely with AWS API Gateway endpoints and build robust and scalable solutions.
Now you're ready to securely authenticate and interact with AWS API Gateway using AWS Signature Version 4 in Python!
We hope you found this article helpful. Stay tuned for more AWS-related tutorials and guides!