Skip to content
GitHub Discord

IAM permissions boundaries

Use permissions boundaries to set the maximum permissions for all IAM roles that’ll be created in your app.

In this example, the Function has the s3:ListAllMyBuckets and sqs:ListQueues permissions. However, we create a permissions boundary that only allows s3:ListAllMyBuckets. And we apply it to all Roles in the app using the global $transform.

As a result, the Function is only allowed to list S3 buckets. If you open the deployed URL, you’ll see that the SQS list call fails.

Learn more about AWS IAM permissions boundaries.

sst.config.ts
// Create a permission boundary
const permissionsBoundary = new aws.iam.Policy("MyPermissionsBoundary", {
policy: aws.iam.getPolicyDocumentOutput({
statements: [
{
actions: ["s3:ListAllMyBuckets"],
resources: ["*"],
},
],
}).json,
});
// Apply the boundary to all roles
$transform(aws.iam.Role, (args) => {
args.permissionsBoundary = permissionsBoundary;
});
// The boundary automatically applies to this Function's role
const app = new sst.aws.Function("MyApp", {
handler: "index.handler",
permissions: [
{
actions: ["s3:ListAllMyBuckets", "sqs:ListQueues"],
resources: ["*"],
},
],
url: true,
});
index.ts
import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3";
import { SQSClient, ListQueuesCommand } from "@aws-sdk/client-sqs";
const s3 = new S3Client();
const sqs = new SQSClient();
export const handler = async () => {
const response = [];
// List buckets
try {
await s3.send(new ListBucketsCommand());
response.push("s3:ListBuckets - success");
} catch (e: any) {
response.push(`s3:ListBuckets - failed (${e.message})`);
}
// List queues
try {
await sqs.send(new ListQueuesCommand());
response.push("sqs:ListQueues - success");
} catch (e: any) {
response.push(`sqs:ListQueues - failed (${e.message})`);
}
return {
statusCode: 200,
body: `<pre>${JSON.stringify(response, null, 2)}</pre>`,
};
};

View the full example.