Consolidate S3 Presigned URL Generation and Object Downloads via an Endpoint Associated with Static IPs
This solution simplifies access to Amazon S3 by creating secure, custom presigned URLs for object downloads through a single endpoint with a unique domain and static IPs. It's tailored for clients who require consolidation of both API and S3 endpoints under a unified domain with static IPs. The use case involves users following an IP and domain Allowlist firewall policy, limiting API access to specific domains and IPs.
The architecture employs key AWS services, including AWS Global Accelerator, Amazon API Gateway, AWS Lambda, Application Load Balancer(ALB), VPC Endpoint, and Amazon S3. This design centralizes the API for generating presigned URLs and the S3 endpoint under a single domain, linked to an AWS Global Accelerator with two static IPs. Consequently, users can effortlessly request presigned URLs and download S3 objects through a unified domain endpoint with static IPs.
This architecture is especially beneficial for customers with strict policies or compliance requirements, such as those in the public, medical, and finance sectors.
-
Amazon Global Accelerator
-
Application Load Balancer
-
Amazon API Gateway
-
AWS Lambda (Python3 or Node.js)
-
Amazon S3
-
A user initiates a request to generate a presigned URL via the custom endpoint served through AWS Global Accelerator, using the custom domain name and associated IP addresses.
-
An AWS Lambda function is responsible for generating the presigned URL, pointing to the custom endpoint. It responds with a 301 redirect containing the generated presigned URL. Through the redirected presigned URL, the user automatically downloads the object via the custom endpoint served through AWS Global Accelerator, utilizing the custom domain name and associated IP addresses.
-
Provisioning of static IPs by AWS Global Accelerator.
-
Registration of Global Accelerator’s Alias as an A Record into the Amazon Route53 Public Hosted Zone with the Custom Domain Name.
-
Creation of an Amazon S3 bucket with a bucket name matching the registered Custom Domain Name.
-
Creation of VPC endpoints for API Gateway and S3 Service.
-
Configuration of an internal-facing Application Load Balancer to connect to AWS Global Accelerator.
-
Assignment of a custom domain name for API Gateway with an ACM certificate attached.
-
Deployment of a private API Gateway integrated with a Lambda function.
-
The Lambda Function is equipped with an IAM Role attached (with Get Object Permissions).
Decide a public domain name for the unified S3 endpoint, the domain name will also be used as the S3 bucket name.
Create a public hosted zone in Amazon Route 53. Its domain name has to match with the api domain.
Request or import a SSL certificate for your web application domain in AWS Certificate Manager (ACM).
Clone code from the CDK repository and ensure that AWS CDK is installed.
Edit the constant variable “options”.
export const options = {
certificateArn: '{arn of the acm which created before}',
dnsAttr: {
zoneName: '{public hosted zone name}',
hostedZoneId: 'hosted zone Id',
},
domainNamePrefix: '{Prefix for the domain}',
presignPath: 'presign',
objectsPath: 'objects',
};
With the following command, you can deploy two stacks: one for the VPC and another for the application.
$ npm install
$ cdk synth
$ cdk deploy --all
Verify that the domain for this pattern has static IPs.
nslookup ${s3-bucket-prefix}.${domain}
Upload the file to the '/objects' folder in the S3 bucket.
Call the URL from a browser or Postman using the following format.
https://${s3-bucket-prefix}.${domain}/presign/objects/${uploaded-filename}
The response will return with a 301 redirect status code containing the presigned URL, initiating the download of the test file you uploaded earlier.
Execute the following command to destroy both the VPC and application stacks.
$ cdk destroy --all
Empty and delete the object S3 bucket and logs S3 bucket that are not deleted by default.
Bucket name is ${s3-bucket-prefix}.${domain} and ${s3-bucket-prefix}.${domain}-logs.
If you prefer to use the AWS CLI for deleting the buckets, you can execute the command like below.
Replace ${s3-bucket-prefix}
and ${domain}
with the values you set in previous steps.
$ aws s3 rm s3://${s3-bucket-prefix}.${domain} --recursive
$ aws s3 rb s3://${s3-bucket-prefix}.${domain} --force
$ aws s3 rm s3://${s3-bucket-prefix}.${domain}-logs --recursive
$ aws s3 rb s3://${s3-bucket-prefix}.${domain}-logs --force
https://aws.amazon.com/blogs/developer/generate-presigned-url-modular-aws-sdk-javascript/
See CONTRIBUTING for more information.
This library is licensed under the MIT-0 License. See the LICENSE file.