Thursday, 12 December 2024

Laravel application hosted on an EC2 instance in a public subnet to access S3

How to allow your Laravel application, running on an EC2 instance in a public subnet, to access S3 using an IAM role:

1. Attach an IAM Role to the EC2 Instance

Instead of hardcoding AWS credentials, you should use an IAM role. This allows the EC2 instance to receive temporary credentials automatically from the AWS metadata service, which is more secure and easier to maintain.

Steps to create and attach an IAM Role:

  1. Create the IAM Role:

    • Go to the IAM section in the AWS Management Console.
    • Click Roles > Create role.
    • Select AWS service as the trusted entity and choose EC2.
    • Click Next: Permissions and attach an appropriate policy for S3 access, for example, AmazonS3FullAccess or a custom policy.
    • Give your role a name and complete the creation process.
  2. Custom Policy Example (Read/Write to a Specific Bucket):

    json
    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::your-bucket-name/*" } ] }
  3. Attach the IAM Role to Your EC2 Instance:

    • Go to the EC2 Dashboard, select the instance that runs your Laravel application.
    • Click Actions > Security > Modify IAM Role.
    • Select the IAM role you created and attach it.

After attaching the IAM role, your EC2 instance will automatically have the necessary permissions to interact with S3 according to the policies you attached. You do not need to store or hardcode credentials on the server.

2. Configure Laravel to Use S3

Your Laravel application needs to know how to use S3 as a storage disk. This is configured in config/filesystems.php.

Update your .env file:

env
AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=your-region AWS_BUCKET=your-bucket-name

Since you’re using an IAM role, you can leave AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY empty. The AWS SDK will fetch temporary credentials from the EC2 instance’s metadata endpoint automatically.

Update config/filesystems.php:

php
's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), // leave empty for IAM role 'secret' => env('AWS_SECRET_ACCESS_KEY'), // leave empty for IAM role 'region' => env('AWS_DEFAULT_REGION', 'your-region'), 'bucket' => env('AWS_BUCKET', 'your-bucket-name'), ],

3. Network and Security Configuration

Since your EC2 instance is in a public subnet, ensure it can access the internet:

  • If your EC2 instance is associated with a public subnet that has an Internet Gateway, it likely already has outbound internet access.
  • If you were in a private subnet scenario, you would need a NAT Gateway or a similar setup.

Also, ensure the instance’s Security Group allows outbound traffic over HTTPS (port 443) to reach S3.

4. Test the Setup

You can test your setup within your Laravel application using the Storage facade:

php
use Illuminate\Support\Facades\Storage; // Example: Upload a test file to S3 Storage::disk('s3')->put('test.txt', 'This is a test file!');

If the file successfully appears in your S3 bucket, the configuration is working correctly.

Optional: Troubleshooting

  • Check that the IAM role has the correct permissions for the desired actions.
  • Review the Laravel logs (storage/logs/laravel.log) to see if any errors appear.
  • SSH into the EC2 instance and use the AWS CLI to test access:
    bash
    aws s3 ls s3://your-bucket-name

If you can list the bucket contents from the EC2 instance, it confirms that the instance has the proper credentials and network connectivity.

Summary:
By using an IAM role, you avoid hardcoding credentials. Laravel and the AWS SDK will automatically use the credentials provided by the EC2 instance’s metadata service. Ensure proper permissions, network access, and configuration in filesystems.php and .env. Then test by uploading or retrieving files from S3 via the Storage facade.

Note: You only need to create a VPC S3 endpoint if your EC2 instance does not have direct outbound internet access and you want it to access S3 privately within the VPC. Here are some scenarios:

  • If your EC2 instance is in a public subnet with a working Internet Gateway and can reach the internet (i.e., it has a public IP and Security Group rules allow outbound traffic):
    You do not need a VPC S3 endpoint. The instance can communicate with S3 over the public internet.

  • If your EC2 instance is in a private subnet without internet access (no NAT Gateway or outbound internet route):
    You will need a VPC S3 endpoint. This endpoint allows your EC2 instance to access S3 using private connectivity within AWS, without exposing traffic to the public internet.

So, the decision depends on your networking setup. If you already have internet access or a NAT Gateway for outbound traffic, you don’t need the endpoint. If you want to keep your traffic completely internal and not rely on public internet access, then setting up a VPC endpoint for S3 is the right approach.

Thank you.

No comments:

Post a Comment

Golang Advanced Interview Q&A