typescriptaws-lambdaamazon-dynamodbaws-amplify

Allow Lambda function in Amplify to access data


In my amplify (Gen2) project my basic amplify file structure is:

├── amplify
│   ├── backend.ts
│   ├── custom-functions
│   │   └── helloworld
│   │       ├── index.py
│   │       └── resource.ts
│   ├── data
│   │   └── resource.ts
│   ├── package.json
│   └── tsconfig.json

This is the file ./amplify/data/resource.ts:

import { type ClientSchema, a, defineData } from "@aws-amplify/backend";
import { sayHello } from "../custom-functions/helloworld/resource";

const schema = a.schema({
  Procurement: a
    .model({
      name: a.string(),
      price: a.float(),
      account: a.string(),
      s3AttachmentCount: a.integer(),
      s3Attachments: a.string(),
      comments: a.string()
    })
    .authorization((allow) => [allow.publicApiKey(), allow.resource(sayHello).to(['read','write','delete'])]),
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: "apiKey",
    // API Key is used for a.allow.public() rules
    apiKeyAuthorizationMode: {
      expiresInDays: 30,
    },
  },
    
  })
});

The issue is I want the lambda function to be allowed to access my data.

But the allow variable doesn't have the function resource because it is of type BaseAllowModifier which is defined as

export type BaseAllowModifier = Omit<AllowModifier, 'resource'>;

Here is what the documentation says:

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'])
    ]
  })
});

I recognize defineStorage is a different function but I am hoping there is a similar solution.

Thanks


Solution

  • Hey took a while but I figured out a solution. In the backend.ts file you can add iam policy statements to the lambda function.

    So your backend.ts will look something like this:

    import { defineBackend } from '@aws-amplify/backend';
    import { data } from './data/resource';
    import { sayhello } from './custom-functions/helloworld/resource';
    
    import * as sns from "aws-cdk-lib/aws-sns"
    import * as iam from "aws-cdk-lib/aws-iam"
    
    const backend = defineBackend({
      data,
      sayhello,
    });
    
    
    // Adds the IAM role/policy for lambda to access the DynamoData
    const pythonLambda = backend.sayhello.resources.lambda
    
    const topicStack = backend.createStack("LambdaStack")
    const topic = new sns.Topic(topicStack, "Topic", {
      displayName: "LambdaStackTopic",
    })
    
    
    const statement = new iam.PolicyStatement({
      sid: "AllowLambdaReadWriteDynamo",
      actions: [
        "dynamodb:*",
      ],
      resources: [
        topic.topicArn,
        'arn:aws:ssm:eu-west-1:<SOME OTHER ACCOUNT ARN>'
      ]
    })
    
    pythonLambda.addToRolePolicy(statement)
    ```