Generate Signed URL using AWS CloudFront for S3 objects

 
It has been a while since I wrote the last blog. I am glad that I come up with S3 and Cloud Front to discuss with you all.

As you all know, I am practicing AWS and its use-cases in IT industries. Amazon S3 is an 
industry-leading object storage service. Where we can store files securely.

On S3: All objects are private, only the bucket account owner initially has access to the object. If you want a user to have access to a specific bucket or objects without making them public, you can provide the user with the appropriate permissions using an IAM policy.

Scenario: An Organization wants to share their S3 file with Non- Organization Users (Non-IAM Users) without making it public.

Solutions:

1. PreSigned URL: You can also create a pre-signed URL for non-aws-users who can interact with objects without the need for AWS credentials or IAM permissions.

PreSigned URL: This is an URL that we can provide to non-users to grant temporary access to S3 object and the user can read or write to the object.

Any user with a valid pre-signed URL can interact with the objects. For example, if a pre-signed URL generated using READ AWS CLI access, a user only can have GET (READ) access to S3 Object. if a PUT pre-signed URL is provided, the User can do READ and WRITE operations.

Using below AWS CLI we can generate PreSigned URL,
aws s3 presign s3://awsexamplebucket/test2.txt --expires-in 604800
Read More Here

What is Drawback?
The URL on be invalid till 7 Days. We can only set the maximum expiration time to 7 days.

How to generate an URL that lasts longer than 7 days?

2. Generate Signed URL using AWS CloudFront:
 
Basically, S3 content(private content) stays behind the CloudFront and which has access to the s3. In your CloudFront distribution, specify one or more trusted signers (IAM users who have an active CloudFront key pair ), who are the AWS accounts that have permission to create signed URLs. Using those CloudFront keys we can create a signed URL

Prerequisites: This configuration only works if SSE-KMS Encryption for bucket DISABLE

Note: Configuring CloudFront to serve public content from an S3 bucket is pretty straight forward. If you want to serve private content through CloudFront setup is more complicated. Below are the steps needed for CloudFront to serve private S3 content through signed CloudFront URLs.

Step 01: Create an S3 Bucket with content Assume it was done in advanced
Step 02: Create a CloudFront Distribution
Now that we have an S3 bucket, let's create a CloudFront distribution.

Navigate to AWS CloudFront services-->Click “Create” →”Web”-->Get Started
Leave everything as default except below listed configuration

Origin Domain Name:
URL to the S3 bucket (ie. “mybucketname.s3.amazonaws.com”)
Origin Path: mybucketname/path/to/folder (only if you want share the specific object)
Origin ID: OriginID automatically generates
Viewer Protocol Policy: “Redirect HTTP to HTTPS”
Restrict Bucket Access: “Yes”
Origin Access Identity: “Create a New Identity”
Grant Read Permissions on Bucket: “Yes, Update Bucket Policy” - Updates the bucket policy so that CloudFront can access it.
Allowed HTTP Methods: “GET,HEAD” (Only provide Read Option)
Restrict Viewer Access: “Yes”
Trusted Signers: “Self”
Compress Objects Automatically: “Yes”

After creating a CloudFront distribution it will take some time (usually about 15 minutes) for initialization to complete. To avoid random issues, make sure the distribution status is “Deployed” before you start accessing it.

Step 03: Create a CloudFront Key Pair
To sign CloudFront URLs you have to use a “CloudFront Key Pair.” To make it even more challenging…

Navigate to IAM Services-->Click “Security Credentials”-->Expand “Cloudfront Key Pairs”--> Click “Create Public key” and “PrivateKeys”


Close the dialog, and save the “Access Key ID” of the key pair you just generated.
You’ll use the Access Key ID and the contents of the private key file to create signed CloudFront URLs later.

Step 04: Generate Signed URL Using AWS-SDK
You can either use PHP, Javascript, Python, Perl, etc to generate signed URLs. In this case, I'm using the AWS SDK/Javascript.
Make Sure AWS SDK is installed on your pc

Note: To use the SDK, we'll need to use AWS.CloudFront.Signer class.

Open the Terminal, Create a file called Signed_Url.js and Past content like below.

Note: When pasting cloudfront private key make sure "\n" between the line like below -----BEGIN RSA PRIVATE KEY-----\n and \n
-----END RSA PRIVATE KEY-----"

 var AWS = require('aws-sdk');

// load CloudFront key pair from environment variables
// Important: when storing your CloudFront private key as an environment variable string,
// you'll need to replace all line breaks with \n, like this:
CF_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEQWDfwfaregareg00vK\n-----END RSA PRIVATE KEY-----"
CF_ACCESS_KEY_ID="AWXFFIVIF123DDD"

//var cloudfront = new AWS.CloudFront({apiVersion: '2020-05-31'});
console.log(CF_ACCESS_KEY_ID);
console.log(CF_PRIVATE_KEY);

const signer = new AWS.CloudFront.Signer(CF_ACCESS_KEY_ID, CF_PRIVATE_KEY);

// 2 days as milliseconds to use for link expiration
const twoDays = 2*24*60*60*1000

// sign a CloudFront URL that expires 2 days from now
const signedUrl = signer.getSignedUrl({
  url: 'https://d1f2oiipwxw8ti.cloudfront.net/Sri_Lanka_2019.ics',
  expires: Math.floor((Date.now() + twoDays)/1000), // Unix UTC timestamp for now + 2 days
})

console.log(signedUrl);

In the Terminal Navigate to your 
Signed_Url.js and Type “node Signed_Url.js” and Click Enter

This will return the Signed link and You can share it with the people you want.

Find the Full Code Here

Unfortunately, I could not share the Terraform code to deploy Cloudfront. However, I will update you guys on this blog sooon.

Thanks.










, , , , ,

No comments:

Post a Comment