S3 is one of the largest object storage services on the planet. It boasts of storing over 400 trillion objects, according to the CEO Matt Garman, in the just concluded re: Invent 2024.
This means S3 is at a massive scale and stores objects and data from millions of AWS customers. If you are hearing about Amazon S3 for the first time, you can read an introduction to Amazon S3 here.
The massive scale of Amazon S3 has many security features that can be implemented to improve the security of the objects stored in the S3 bucket.
There have been incidents in the past that have caused security breaches to objects stored in S3 so it is important to secure your objects stored in S3 properly.
Whether you are using Amazon S3 to store website assets to be distributed via Cloudfront CDN, or you are storing sensitive documents of your customers in S3, or using S3 as a backup for database files, the security measures I am about to list will apply to the scenarios mentioned earlier.
Let’s examine the different strategies for securing your S3 bucket.
Encrypt the objects (encrypt at rest and in transit)
Files stored in S3 are usually plain files by default. If anyone gains access to the plain files, they will be able to gain access to the data inside the file. Encryption of the objects in your S3 bucket is one of the basic ways to secure your contents in a bucket. It ensures your files are secured and not easily accessible in the event of a data breach. Amazon S3 offers various ways to encrypt objects. Encryption can either be at rest for the object sitting inside an S3 bucket or in transit for an object sent to S3. The standard way to encrypt objects in transit is usually SSL/TLS.
The following are standard configurations in S3 for encrypting objects at rest
– SSE-S3 (Server-Side Encryption with S3 Managed Keys): Amazon S3 encrypts your data using AES-256 encryption manages the encryption keys for you and is the simplest to set up as S3 handles everything.
– SSE-KMS (Server-Side Encryption with AWS Key Management Service Keys): Uses AWS Key Management Service (KMS) to manage encryption keys, and offers more control over access permissions, key rotation, and logging key usage. It is suitable for compliance and regulatory requirements.
– SSE-C (Server-Side Encryption with Customer-Provided Keys): You provide your encryption keys, then Amazon S3 handles encryption and decryption using your provided key but does not store it. You must manage and provide the key for each request.
– DSSE-KMS (Dual-layer server-side encryption with AWS KMS keys): It encrypts data using two distinct layers of encryption, both managed by AWS Key Management Service (KMS). The first encryption layer is applied at the object level using a data encryption key (DEK), which is encrypted and managed by AWS KMS. The second encryption layer applies another level of encryption to the already encrypted object, ensuring dual-layer protection.
Apart from the encryption options offered by Amazon S3, which are usually termed Server-sided encryption. It is also possible to encrypt the data by using an encryption key and code, and then upload the encrypted file to Amazon S3. That way you own the encryption and decryption process end to end while Amazon S3 serves as a storage for the encrypted files. This method of encryption is called client-side encryption.
The following instructions explain how to configure SSE-KMS encryption for objects in Amazon S3.
Go to the S3 Console:
- Open the S3 Management Console.
Select a Bucket:
- Choose the bucket you want to enable encryption for.
Open the Properties Tab:
- Scroll to the Default Encryption section.
Enable SSE-KMS:
- Select Server-Side Encryption.
- Choose AWS Key Management Service key (SSE-KMS).
Specify a KMS Key:
- Select the KMS key you created earlier from the list.
- If the key does not appear, ensure the IAM role or user has the appropriate permissions to use the key.
Save Changes:
- Click Save to apply default encryption to the bucket.
By following these steps, you have securely configured SSE-KMS encryption for objects stored in Amazon S3.
Encryption is one way to secure the object in the bucket. Other methods ensure that unauthorized users do not have access to objects in the bucket. Let us take a look at the Bucket Policy in Amazon S3.
Use Bucket Policy to manage access (least privilege access)
Every S3 bucket has a policy configuration that is very similar to the IAM Policy configuration. It is a JSON format of definition used to describe and assign privileges and access to Users and Roles in AWS IAM. But a bucket policy is more streamlined and scoped to an Amazon S3 bucket. The policy allows you to configure the type of permissions that are allowed on the bucket. Permissions such as read, write, and delete permissions can all be configured on the bucket. The bucket policy can be used to enforce least privilege configurations by allowing granular privilege assignment to users, IP addresses, and roles within the AWS account and outside the AWS account.
When configuring access to S3 via Cloudfront, the bucket policy plays an important role in ensuring only a specific Cloudfront Origin Access is allowed to perform a Get operation in an S3 bucket. This ensures very high security for the objects in the bucket most especially when securing senstive data and want to allow only Cloudfront to retrieve this data when needed.
While the Bucket Policy is a wonderful way to manage access to S3, there is a standard security measure S3 has put in place that ensures objects are secure by default. Let us explain it further in the next point.
Block Public Access to Object
When an S3 bucket is created by default, all objects in the bucket are not accessible over the public internet. This is a best security practice to reduce the surface area of attack for objects in S3. I have seen cases where users want to make a bucket public or object public because it is needed as an S3 website.
While it is the fastest way to get your content to the public, it is not the ideal configuration for an S3 bucket. S3 will warn you of the dangers of exposing a bucket when you decide to make it public, indicating the huge security risk that comes with it. Most especially when the bucket contains sensitive data. It can be breached and data stolen from the S3 bucket.
It also does not make your AWS compliant to the AWS Well-Architected Framework and will be flagged when scanned with Security tools like AWS SecurityHub and Prowler (open-source) security vulnerability scanner).
One of the best ways to expose objects in S3 is via Cloudfront. This has two options
1. Exposing non-senstive objects like website hosting and downloadable files
2. Exposing sensitive objects like giving access to objects via login through your app. This scenario requires an extra layer of security on Cloudfront called Signed URL
Although S3 also has a signed URL option, but Cloudfront has the CDN feature which improves
Use CloudFront OAC
This point follows exactly after the S3 website configuration option in the previous point. So instead of exposing an S3 bucket to the internet and risking those vulnerabilities, it is advisable to use Cloudfront to expose it.
I have written a detailed post on my Medium blogpost about it here: https://medium.com/mycloudseries/how-to-configure-secure-file-access-on-s3-via-cloudfront-ae9ff0096005
The junior brother to this is using S3 Signed URL for accessing objects in S3 securely.
Use S3 preSigned URL
As mentioned under Block Public Access to Object point made earlier. Signed URLs from S3 can be used to give access to people securely for a short period. When the time expires, the file is no longer accessible. This is usually configured for a specific object in a bucket and the URL shared to whoever needs to access the object within that period of time. This is very useful is you need to give someone temporary access to download a file from S3 and be rest-assured that the person can not access that file after the time that it has been set for in the Signed URL configuration. You can use the following AWS documentation to configure preSigned URL: https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html
Use Access Points
Amazon S3 Access Points are a secure and simplified way to manage access to objects in an S3 bucket. Instead of managing a single bucket policy for all users and applications, you can create multiple access points, each with its own name, permissions, and network controls.
Each access point acts as an entryway to the bucket, tailored for specific use cases. For example, you can create one access point that allows only internal applications to read certain data, while another access point grants external partners limited access to upload files.
Access points integrate with VPCs (Virtual Private Clouds), enabling you to restrict access to your S3 bucket from specific private networks, enhancing security. They also support IAM policies, allowing fine-grained access control.
This approach is especially useful for shared buckets in multi-tenant environments or complex applications where different teams or services need distinct access rules. Instead of updating the entire bucket policy, you can manage permissions at the access point level, reducing complexity and improving security.
Access points make it easier to enforce compliance, manage permissions, and control network access, ensuring secure and efficient interactions with S3 buckets.
These are the steps on how to configure Access Points in Amazon S3
- Sign in to the AWS Management Console.
- Go to the Amazon S3 service.
- In the Buckets list, select the bucket for which you want to create an access point.
- Ensure the bucket exists and has objects you want to manage with access points.
- Open the Access Points tab in the selected bucket.
- Click Create Access Point.
- Provide a unique name for the access point (Access point names must be unique within an AWS account and region.)
- Specify the Network: Internet Access (Allows public access, typically not recommended for sensitive data), VPC Access (Restricts access to resources within a specific Virtual Private Cloud).
- Select a VPC to associate with the access point for private access.
- Set Permissions: Add or configure the IAM policy to define access rules for the access point
One more for the road, which speaks more to a secure way for accessing S3 via a VPC. Lets go to the next point and understand how it is different from Access Points though both of them can provide access to S3 via VPC.
VPC Endpoint
Accessing Amazon S3 via a VPC Endpoint means you can securely connect your Amazon Virtual Private Cloud (VPC) to Amazon S3 without using the public internet. Instead of sending data over the internet, traffic between your VPC and S3 flows through the highly secure and private AWS network.
A VPC Endpoint acts as a private gateway, allowing resources (like EC2 instances or Lambda functions) in your VPC to access S3 buckets directly. This eliminates the need for public IP addresses, NAT gateways, or internet gateways.
For example, if you have an application running in a private subnet of your VPC, you can use a VPC Endpoint to connect to S3 without exposing your data to the internet. The VPC Endpoint is configured to allow access to specific buckets or objects, ensuring fine-grained control.
When you create a VPC Endpoint for S3, AWS assigns a DNS name that applications in your VPC can use to connect to S3. Additionally, you can combine VPC Endpoints with S3 Bucket Policies to enforce that your bucket only accepts traffic from specific VPCs, adding an extra layer of security.
In summary, accessing S3 via a VPC Endpoint ensures private, secure, and reliable connectivity between your VPC and S3 without relying on the public internet.
Conclusion
Each of the security measures listed above is essential to securing the objects stored in your S3 bucket. It is also important to be updated about new security measures implemented by AWS from time to time to ensure the security of the objects stored in Amazon S3.