Grant access to other resources
In order for Amplify Functions to interact with other resources they must be given access. There are two ways to grant Amplify Functions access to other resources:
Using the access
property
The access
property is a property found in each of the define*
functions for defining Amplify resources. It allows you specify the necessary actions using common language.
Say you have a function that generates reports each month from your Data resource and needs to store the generated reports in Storage:
import { defineStorage } from '@aws-amplify/backend';import { generateMonthlyReports } from '../functions/generate-monthly-reports/resource';
export const storage = defineStorage({ name: 'myReports', access: (allow) => ({ 'reports/*': [ allow.resource(generateMonthlyReports).to(['read', 'write', 'delete']) ] })});
This access definition will add the environment variable myReports_BUCKET_NAME
to the function. This environment variable can be accessed on the env
object.
Here's an example of how it can be used to upload some content to S3.
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';import { env } from '$amplify/env/generate-monthly-reports';
const s3Client = new S3Client();
export const handler = async () => { const command = new PutObjectCommand({ Bucket: env.MY_REPORTS_BUCKET_NAME, Key: `reports/${new Date().toISOString()}.csv`, Body: new Blob([''], { type: 'text/csv;charset=utf-8;' }) });
await s3Client.send(command);};
Using CDK
When permissions are needed to access resources beyond the capabilities of the access
property, you must use CDK.
Functions are created with an execution role, which is an IAM role that contains policies that dictate what resources your Function can interact with when it executes. This role can be extended using the addToRolePolicy()
method:
import { defineBackend } from "@aws-amplify/backend"import * as iam from "aws-cdk-lib/aws-iam"import * as sns from "aws-cdk-lib/aws-sns"import { weeklyDigest } from "./functions/weekly-digest/resource"
const backend = defineBackend({ weeklyDigest,})
const weeklyDigestLambda = backend.weeklyDigest.resources.lambda
const topicStack = backend.createStack("WeeklyDigest")const topic = new sns.Topic(topicStack, "Topic", { displayName: "digest",})
const statement = new iam.PolicyStatement({ sid: "AllowPublishToDigest", actions: ["sns:Publish"], resources: [topic.topicArn],})
weeklyDigestLambda.addToRolePolicy(statement)
However some constructs provide a grant*
method to grant access to common policy actions. Revisiting the example above you can grant the same access with grantPublish
:
import { defineBackend } from "@aws-amplify/backend"import * as iam from "aws-cdk-lib/aws-iam"import * as sns from "aws-cdk-lib/aws-sns"import { weeklyDigest } from "./functions/weekly-digest/resource"
const backend = defineBackend({ weeklyDigest,})
const weeklyDigestLambda = backend.weeklyDigest.resources.lambda
const topicStack = backend.createStack("WeeklyDigest")const topic = new sns.Topic(topicStack, "Topic", { displayName: "digest"})
topic.grantPublish(weeklyDigestLambda)