Skip to content
Open
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ styles/
# Allow

!styles/config/vocabularies/Percona/**
.cache/
229 changes: 201 additions & 28 deletions docs/manage/automate-s3-access.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,88 @@
# Automate access to S3 buckets for Percona Backup for MongoDB

When you run MongoDB and Percona Backup for MongoDB using AWS resources (on EC2 instances or using EKS), you can automate access to AWS S3 buckets for Percona Backup for MongoDB. Percona Backup for MongoDB uses the AWS environment variables and metadata to access S3 buckets so that you don’t have to explicitly specify the S3 credentials in the PBM configuration file. Thereby you control the access to your cloud infrastructure from a single place.
When you run Percona Backup for MongoDB in AWS environment (on EC2 instances or using EKS), you can automate access to AWS S3 buckets for Percona Backup for MongoDB. Percona Backup for MongoDB uses the environment variables and metadata to access S3 buckets so that you don’t have to explicitly specify the S3 credentials in the PBM configuration file. Thereby you control the access to your cloud infrastructure from a single place.

## IAM instance profile
## Assume a role from an EC2 instance

IAM (Identity Access Management) is the AWS service that allows you to securely control access to AWS resources.
You can configure Percona Backup for MongoDB to assume an IAM role. To make this work, the `pbm-agent` leverages the AWS environment variables to assume the specified role. The steps are the following:

Using the IAM instance profile, you can automate access to S3 buckets for Percona Backup for MongoDB running on EC2 instance. The steps are the following:
1. Ensure that the EC2 instance where `pbm-agent` is running has an [IAM instance profile :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) attached. The role associated with this instance profile must have a permissions policy that allows it to assume the target role.

1. Create the [IAM instance profile :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) and the permission policy within where you specify the access level that grants the access to S3 buckets.
For example, if your target role is `arn:aws:iam::TARGET_ACCOUNT_ID:role/pbm-target-role`, create a policy with the following content and attach it to your EC2 instance role:

2. Attach the IAM profile to an EC2 instance.

3. Configure an S3 storage bucket and verify the connection from the EC2 instance to it.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::TARGET_ACCOUNT_ID:role/pbm-target-role"
}
]
}
```
> Remember to replace `TARGET_ACCOUNT_ID` and `pbm-target-role` with your actual target account ID and role name.

2. Create the target IAM role that PBM will assume. This involves setting up a trust relationship and attaching the necessary S3 permissions.

Check warning on line 27 in docs/manage/automate-s3-access.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/manage/automate-s3-access.md#L27

[Google.Will] Avoid using 'will'.
Raw output
{"message": "[Google.Will] Avoid using 'will'.", "location": {"path": "docs/manage/automate-s3-access.md", "range": {"start": {"line": 27, "column": 41}}}, "severity": "WARNING"}

* **Trust Policy**: The trust policy of the target role must allow the EC2 instance's role to assume it.

For example, if your EC2 instance role is `arn:aws:iam::EC2_ACCOUNT_ID:role/pbm-ec2-instance-role`, use the following trust policy for your target role:

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::EC2_ACCOUNT_ID:role/pbm-ec2-instance-role"
},
"Action": "sts:AssumeRole"
}
]
}
```
> Remember to replace `EC2_ACCOUNT_ID` and `pbm-ec2-instance-role` with the account ID and role name of your EC2 instance.

* **Permissions Policy**: The target role must have a permissions policy attached that grants the necessary S3 access for PBM.

Here is an example policy that grants the required permissions. Attach it to your target role:

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::your-pbm-bucket/*"
},
{
"Effect": "Allow",
"Action": "s3:ListBucket",
Comment on lines +62 to +69
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The permissions in the S3 policy may be insufficient. The policy includes s3:GetBucketLocation but is missing s3:ListBucket permissions on the same resource level. Line 63 has s3:GetBucketLocation in the array with object-level permissions (arn:aws:s3:::your-pbm-bucket/*), but GetBucketLocation is a bucket-level operation and should be applied to arn:aws:s3:::your-pbm-bucket (without the /*). Consider moving s3:GetBucketLocation to be with s3:ListBucket on lines 69-70, or add it as a separate statement.

Suggested change
"s3:DeleteObject",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::your-pbm-bucket/*"
},
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::your-pbm-bucket/*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],

Copilot uses AI. Check for mistakes.
"Resource": "arn:aws:s3:::your-pbm-bucket"
}
]
}
```
> Remember to replace `your-pbm-bucket` with the name of your S3 bucket.

3. Set the `AWS_ROLE_ARN` environment variable to the ARN of the target role in the environment where you start the `pbm-agent` process. You can also set `AWS_SESSION_NAME` (optional, but recommended for audit trails).

```bash
export AWS_ROLE_ARN=arn:aws:iam::ACCOUNT_ID:role/pbm-target-role
export AWS_SESSION_NAME=pbm-session-$(hostname)
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AWS environment variable name AWS_SESSION_NAME should be AWS_ROLE_SESSION_NAME according to AWS SDK documentation. The correct environment variable for specifying the session name when assuming a role is AWS_ROLE_SESSION_NAME, not AWS_SESSION_NAME.

Suggested change
export AWS_SESSION_NAME=pbm-session-$(hostname)
export AWS_ROLE_SESSION_NAME=pbm-session-$(hostname)

Copilot uses AI. Check for mistakes.
```

4. In the [PBM configuration](../install/backup-storage.md) provide remote storage information, but leave the `s3.credentials` section empty. PBM will use the assumed role's credentials.

Check warning on line 84 in docs/manage/automate-s3-access.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/manage/automate-s3-access.md#L84

[Google.Will] Avoid using 'will'.
Raw output
{"message": "[Google.Will] Avoid using 'will'.", "location": {"path": "docs/manage/automate-s3-access.md", "range": {"start": {"line": 84, "column": 148}}}, "severity": "WARNING"}

4. Provide the [remote storage information for PBM in a config file](../install/backup-storage.md). Leave the `s3.credentials` array empty

```yaml
storage:
type: s3
Expand All @@ -25,35 +91,144 @@
bucket: <bucket-name>
```

!!! note
!!! note

If you specify S3 credentials, they override the EC2 instance environment variables and metadata, and are used for authentication instead.
When `AWS_ROLE_ARN` is set, the credentials from the assumed role take precedence over the EC2 instance profile's credentials. However, if you specify `s3.credentials` in the PBM configuration file, they will override any other IAM-based credentials.


5. Start the `pbm-agent` process
5. Restart the `pbm-agent` process.

!!! admonition "See also"

AWS documentation: [How can I grant my Amazon EC2 instance access to an Amazon S3 bucket? :octicons-link-external-16:](https://aws.amazon.com/premiumsupport/knowledge-center/ec2-instance-access-s3-bucket/)

## IAM Roles for Service Accounts (IRSA)

!!! admonition "Version added: 2.0.3"

[IRSA :octicons-link-external-16:](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) is the native way for AWS EKS (Amazon Elastic Kubernetes Service) to allow applications running in EKS pods to access the AWS API using permissions configured in AWS IAM roles.

To benefit from using the AWS IRSA credentials with PBM, the high-level steps are the following:

1. [Create a cluster :octicons-link-external-16:](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/setting-up-eks-cluster.html) with `eksctl` and OIDC provider setup enabled. This feature works with EKS clusters version 1.13 and above.
2. Create an IAM role and specify the policy that defines the access to an S3 bucket.
3. Create a service account and annotate it with the IAM role.
3. Configure your pod by using the service account created in the previous step and assume the IAM role.
4. Provide the remote storage information for PBM in a config file. Leave the `s3.credentials` array empty, since PBM uses the `AWS_ROLE_ARN`/`AWS_WEB_IDENTITY_TOKEN_FILE` environment variables which are either automatically provided (i.e. injected by Kubernetes mutating admission controller in EKS) or which you can define manually (if you don't want to the admission controller to modify your pods)

[IRSA :octicons-link-external-16:](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) is the native way for AWS EKS (Amazon Elastic Kubernetes Service) to allow applications running in pods to access the AWS API, using permissions configured in AWS IAM roles. This is the recommended approach for granting S3 access to Percona Backup for MongoDB in an EKS environment.

To configure IRSA for PBM, follow these steps:

1. Set up an OIDC provider for your EKS cluster

IRSA requires an OpenID Connect (OIDC) provider to be associated with your cluster.

First, check if you already have an OIDC provider. Replace `<cluster_name>` with your EKS cluster's name.
```bash
aws eks describe-cluster --name <cluster_name> --query "cluster.identity.oidc.issuer" --output text
```
If the command returns a URL, your OIDC provider is already set up. If not, create one using `eksctl`. Replace `<region>` and `<cluster-name>` with your cluster's region and name.
```bash
eksctl utils associate-iam-oidc-provider --region <region> --cluster <cluster-name> --approve
```

2. Create an IAM policy for S3 access

This policy defines the permissions that PBM needs to access your S3 bucket.

Create a JSON file (e.g., `pbm-s3-policy.json`) with the following content. Remember to replace `your-pbm-bucket` with your actual bucket name.

Check failure on line 130 in docs/manage/automate-s3-access.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/manage/automate-s3-access.md#L130

[Google.Latin] Use 'for example' instead of 'e.g.'.
Raw output
{"message": "[Google.Latin] Use 'for example' instead of 'e.g.'.", "location": {"path": "docs/manage/automate-s3-access.md", "range": {"start": {"line": 130, "column": 21}}}, "severity": "ERROR"}
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::your-pbm-bucket/*"
},
{
"Effect": "Allow",
"Action": "s3:ListBucket",
Comment on lines +140 to +147
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The permissions in the S3 policy may be insufficient. The policy includes s3:GetBucketLocation in the object-level permissions (line 141: arn:aws:s3:::your-pbm-bucket/*), but GetBucketLocation is a bucket-level operation and should be applied to arn:aws:s3:::your-pbm-bucket (without the /*). Consider moving s3:GetBucketLocation to be with s3:ListBucket on lines 147-148, or add it as a separate statement for the bucket resource.

Suggested change
"s3:DeleteObject",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::your-pbm-bucket/*"
},
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::your-pbm-bucket/*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],

Copilot uses AI. Check for mistakes.
"Resource": "arn:aws:s3:::your-pbm-bucket"
}
]
}
```

Now, create the IAM policy using the AWS CLI.

Check warning on line 154 in docs/manage/automate-s3-access.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/manage/automate-s3-access.md#L154

[Google.WordList] Use 'command-line tool' instead of 'CLI'.
Raw output
{"message": "[Google.WordList] Use 'command-line tool' instead of 'CLI'.", "location": {"path": "docs/manage/automate-s3-access.md", "range": {"start": {"line": 154, "column": 42}}}, "severity": "WARNING"}
```bash
aws iam create-policy --policy-name pbm-s3-access-policy --policy-document file://pbm-s3-policy.json
```

3. Create an IAM role

This role will be assumed by the Kubernetes service account used by your PBM pods.

Check warning on line 161 in docs/manage/automate-s3-access.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/manage/automate-s3-access.md#L161

[Google.Will] Avoid using 'will'.
Raw output
{"message": "[Google.Will] Avoid using 'will'.", "location": {"path": "docs/manage/automate-s3-access.md", "range": {"start": {"line": 161, "column": 11}}}, "severity": "WARNING"}

First, create a trust policy JSON file (e.g., `pbm-trust-policy.json`). This policy allows your Kubernetes service account to assume the role. Replace `<account-id>`, `<region>`, and `<oidc-id>` with your AWS account ID, EKS cluster region, and the OIDC ID from step 1.

Check failure on line 163 in docs/manage/automate-s3-access.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/manage/automate-s3-access.md#L163

[Google.Latin] Use 'for example' instead of 'e.g.'.
Raw output
{"message": "[Google.Latin] Use 'for example' instead of 'e.g.'.", "location": {"path": "docs/manage/automate-s3-access.md", "range": {"start": {"line": 163, "column": 41}}}, "severity": "ERROR"}

> **Note:** The OIDC ID is the unique identifier at the end of the OIDC issuer URL returned in step 1. For example, if the issuer URL is `https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE`, then the OIDC ID is `EXAMPLED539D4633E53DE1B71EXAMPLE`.

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<account-id>:oidc-provider/oidc.eks.<region>.amazonaws.com/id/<oidc-id>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.<region>.amazonaws.com/id/<oidc-id>:aud": "sts.amazonaws.com",
"oidc.eks.<region>.amazonaws.com/id/<oidc-id>:sub": "system:serviceaccount:<namespace>:<service-account-name>"
}
}
}
]
}
```
> **Note:** Replace `<namespace>` and `<service-account-name>` with the namespace and name of the service account your PBM pods will use.

Check warning on line 187 in docs/manage/automate-s3-access.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/manage/automate-s3-access.md#L187

[Vale.Spelling] Did you really mean 'namespace'?
Raw output
{"message": "[Vale.Spelling] Did you really mean 'namespace'?", "location": {"path": "docs/manage/automate-s3-access.md", "range": {"start": {"line": 187, "column": 73}}}, "severity": "WARNING"}

Check warning on line 187 in docs/manage/automate-s3-access.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/manage/automate-s3-access.md#L187

[Google.Will] Avoid using 'will'.
Raw output
{"message": "[Google.Will] Avoid using 'will'.", "location": {"path": "docs/manage/automate-s3-access.md", "range": {"start": {"line": 187, "column": 129}}}, "severity": "WARNING"}

Create the IAM role:
```bash
aws iam create-role --role-name pbm-s3-access-role --assume-role-policy-document file://pbm-trust-policy.json
```

4. Attach the policy to the role

Attach the S3 access policy you created in step 2 to the role you created in step 3. Replace `<account-id>` with your AWS account ID.
```bash
aws iam attach-role-policy --role-name pbm-s3-access-role --policy-arn arn:aws:iam::<account-id>:policy/pbm-s3-access-policy
```

5. Annotate the Kubernetes service account

Now, you need to associate the IAM role with the Kubernetes service account that your `pbm-agent` pods use. This is done by annotating the service account.

First, get the ARN of the role you created:
```bash
aws iam get-role --role-name pbm-s3-access-role --query "Role.Arn" --output text
```

Then, annotate the service account. Replace `<namespace>`, `<service-account-name>`, and `<role_arn>` with the correct values.
```bash
kubectl annotate serviceaccount <service-account-name> -n <namespace> \
eks.amazonaws.com/role-arn="<role_arn>"
Comment on lines +210 to +213
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Inconsistent placeholder format. Throughout the document, placeholders use different formats: <cluster_name> (line 119), <region> and <cluster-name> (line 123), <account-id>, <region>, and <oidc-id> (line 163), <namespace> and <service-account-name> (lines 180, 187), and <role_arn> (line 213). Consider using a consistent format for all placeholders, either all with hyphens (e.g., <cluster-name>) or all with underscores (e.g., <cluster_name>).

Suggested change
Then, annotate the service account. Replace `<namespace>`, `<service-account-name>`, and `<role_arn>` with the correct values.
```bash
kubectl annotate serviceaccount <service-account-name> -n <namespace> \
eks.amazonaws.com/role-arn="<role_arn>"
Then, annotate the service account. Replace `<namespace>`, `<service-account-name>`, and `<role-arn>` with the correct values.
```bash
kubectl annotate serviceaccount <service-account-name> -n <namespace> \
eks.amazonaws.com/role-arn="<role-arn>"

Copilot uses AI. Check for mistakes.
```
If your pods are already running, you will need to restart them to apply the changes and inject the AWS environment variables.

Check warning on line 215 in docs/manage/automate-s3-access.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/manage/automate-s3-access.md#L215

[Google.Will] Avoid using 'will'.
Raw output
{"message": "[Google.Will] Avoid using 'will'.", "location": {"path": "docs/manage/automate-s3-access.md", "range": {"start": {"line": 215, "column": 39}}}, "severity": "WARNING"}

6. Configure PBM storage

Finally, configure your PBM storage to use S3, but do not provide any credentials. PBM will automatically use the credentials provided by IRSA.

Check warning on line 219 in docs/manage/automate-s3-access.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/manage/automate-s3-access.md#L219

[Google.Will] Avoid using 'will'.
Raw output
{"message": "[Google.Will] Avoid using 'will'.", "location": {"path": "docs/manage/automate-s3-access.md", "range": {"start": {"line": 219, "column": 88}}}, "severity": "WARNING"}

Your storage configuration should look like this:
```yaml
storage:
type: s3
s3:
region: <your-s3-region>
bucket: <your-pbm-bucket>
```

!!! note

If IRSA-related credentials are defined, they have the priority over any IAM instance profile. However, if you intentionally specify S3 credentials in PBM configuration file, they override any IRSA/IAM instance profile related credentials and are used for authentication instead.
If IRSA-related credentials are defined, they have priority over any IAM instance profile. However, if you intentionally specify S3 credentials in the PBM configuration file, they override any IRSA/IAM instance profile related credentials and are used for authentication instead.

!!! admonition "See also"

Expand All @@ -62,8 +237,6 @@
* [Introducing fine-grained IAM roles for service accounts :octicons-link-external-16:](https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/)
* [How do I use the IAM roles for service accounts (IRSA) feature with Amazon EKS to restrict access to an Amazon S3 bucket? :octicons-link-external-16:](https://aws.amazon.com/premiumsupport/knowledge-center/eks-restrict-s3-bucket/)



*[EC2]: Elastic Compute Cloud
*[EKS]: Elastic Kubernetes Service
*[IAM]: Identity Access Management
Expand Down