export const meta = {
  title: `IAM Permissions Boundary for Amplify-generated roles`,
  description: `Apply a Permissions Boundary to all IAM Roles created by Amplify CLI.`
};

To set the maximum permissions that can be granted to IAM Roles created by Amplify CLI, configure a [permissions boundary](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) for the project. Then, Amplify-generated IAM roles can perform only the actions that are allowed by both the roles’ policies and permissions boundary. You can configure a different permissions boundary for each environment. For example, this enables you to deny a dev environment all access to a prod environment's resources.

The IAM permissions boundary will apply to all IAM Roles created by Amplify. This includes the "auth role" assumed by users that log into the app and the "unauth role" assumed by guest users. It also applies to Lambda execution roles, Cognito user group roles, and any role configured in a [custom resource stack](/cli/usage/customcf).

The IAM Policy, to be used as a permissions boundary, must be configured outside of Amplify CLI. A permissions boundary is an IAM Policy and can be created following the guide [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create-console.html). This is usually part of an AWS Organization rule or other corporate governance requirement. Once you have created an IAM Policy to use as a permissions boundary, copy the IAM Policy ARN for the next steps.

## Set up a permissions boundary in a new project

To initialize a project with a permissions boundary run:

```
amplify init --permissions-boundary <iam-policy-arn>
```

## Set up a permissions boundary in a new environment

When creating a new Amplify environment using `amplify env add` the permissions boundary from the current environment is automatically applied to the new environment.

To specify a different permissions boundary for the new environment, run:

```
amplify env add --permissions-boundary <iam-policy-arn>
```

To explicitly specify that the new environment should NOT have a permissions boundary, run:

```
amplify env add --permissions-boundary ''
```

If Amplify CLI is not able to automatically apply the permissions boundary to the new environment and `--permissions-boundary` is not specified, it will prompt for a IAM Policy ARN as a permissions boundary.

## Update an environment's permissions boundary

To modify the permissions boundary of the current environment, run:

```
amplify env update
```

In non-interactive shells use

```
amplify env update --permissions-boundary <iam-policy-arn>
```

The IAM permissions boundary will be applied on the next `amplify push`.

## Set up a permissions boundary in a cross-account Amplify project

Amplify CLI cannot automatically apply the existing boundary to a new environment in a different AWS account if the `--yes` flag is used during `amplify env add`. In this case, a new permissions boundary must be specified using `amplify env add --yes --permissions-boundary <iam-policy-arn>` or to explicitly remove the permissions boundary from the new environment use `amplify env add --yes --permissions-boundary ''`.

## Permissions boundary usage example

For example, assume that your environment named `dev` should not be allowed to call a DynamoDB table named `users`. To enforce this rule, you can use the following policy to set the permissions boundary for the `dev` environment.

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Deny",
      "Action": "dynamodb:Scan",
      "Resource": "arn:aws:dynamodb:<region>:<account-id>:table/users"
    }
  ]
}
```

### Setup

[Create a policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_managed-policies.html) on the AWS console

Add a permissions boundary for a new environment, run:

```
amplify env add --permissions-boundary <iam-policy-arn>
```

Verify if the permissions boundary has been applied by checking the AWS IAM console for the `authRole` and `unauthRole` created by Amplify CLI.

To add a DynamoDB table, run:

```
amplify add storage
```

```
? Please select from one of the below mentioned services:
  Content (Images, audio, video, etc.)
> NoSQL Database
? Please provide table name:
> users
```

To test if the environment enforces the permissions boundary, we can utilize a Lambda function with resource access permissions to the DynamoDB table.

To add a Lambda function, run:

```
amplify add function
```

```
? Select which capability you want to add: Lambda function (serverless function)
? Provide an AWS Lambda function name: lambdafunction
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: Hello World
? Do you want to configure advanced settings? Yes
? Do you want to access other resources in this project from your Lambda function? Yes
? Select the categories you want this function to have access to. storage
? Select the operations you want to permit on users read
```

In the Lambda function `index.js` file, add:

<BlockSwitcher>

<Block name="AWS SDK V2">

```js
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();

const params = {
  TableName: process.env.STORAGE_USERS_NAME
};

exports.handler = async (event, context) => {
  try {
    const data = await docClient.scan(params).promise();
    return { body: JSON.stringify(data) };
  } catch (err) {
    return { error: err };
  }
};
```
</Block>

<Block name="AWS SDK V3">

```js
import { DynamoDBClient, ScanCommand } from "@aws-sdk/client-dynamodb";
const docClient = new DynamoDBClient();

const params = {
  TableName: process.env.STORAGE_USERS_NAME,
};

export const handler = async (event, context) => {
  try {
    const data = new ScanCommand(params);
    const response = await docClient.send(data);
    return { body: JSON.stringify(response) };
  } catch (err) {
    return { error: err };
  }
};
```

</Block>

</BlockSwitcher>

To push the resources, run:

```
amplify push
```

Once the push completes, run the Lambda function in the AWS console. You should observe the following error message in the execution result.

```
User: <assumed-role-arn> is not authorized to perform: dynamodb:Scan on resource: <dynamodb-arn> with an explicit deny in a permissions boundary
```
