typescript AWS CDK允许Lambda将项目写入AWS DynamoDB

dgsult0t  于 2023-05-19  发布在  TypeScript
关注(0)|答案(2)|浏览(248)

我尝试构建一个lambda函数,它能够将项目添加到dynamo db中。lambda通过API网关访问,并通过用户池进行保护。但是,每次我尝试向数据库中添加内容时,都会出现以下错误:

An error occurred (AccessDeniedException) when calling the PutItem operation: User: arn:aws:sts::{account-id}:assumed-role/SoccerTipGameInfrastructu-fastApiLambdaServiceRole-121EKY67BICBU/SoccerTipGameInfrastructureS-fastApiLambda1F147E7F-Zvo7rWg8oFGY is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:eu-central-1:{account-id}:table/teams because no identity-based policy allows the dynamodb:PutItem action

这是我的CDK文件:

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apiGateway from 'aws-cdk-lib/aws-apigateway';
import * as ddb from 'aws-cdk-lib/aws-dynamodb';
import * as cog from 'aws-cdk-lib/aws-cognito'
import { BillingMode } from 'aws-cdk-lib/aws-dynamodb';
import { table } from 'console';
import * as cognito from 'aws-cdk-lib/aws-cognito';
import * as iam from 'aws-cdk-lib/aws-iam'

export class AppInfrastructureStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Cognito Userpool
    const userPool = new cognito.UserPool(this, 'userpool', {
      // not relevant
    });

    userPool.addDomain('CognitoDomain', {
      // not relevant
    });

    const clientReadAttributes = new cognito.ClientAttributes()
    .withStandardAttributes({
      // not relevant
    })
    .withCustomAttributes(...['isAdmin']);

    const clientWriteAttributes = new cognito.ClientAttributes()
      .withStandardAttributes({
          // not relevant
        })
      .withCustomAttributes(...[]);

    const userPoolClient = new cognito.UserPoolClient(this, 'userpool-client', {
      // not relevant
    });

    // DB Table
    const teamsTable = new ddb.Table(this, "teams", {
      partitionKey: {name: "team_id", type: ddb.AttributeType.STRING},
      billingMode: ddb.BillingMode.PAY_PER_REQUEST,
    });

    // Base Layer with fastapi installed
    const fastApiBaseLayer = new lambda.LayerVersion(this, "fastApiBaseLayer", {
      code: lambda.Code.fromAsset("lambda_base_layer/layer.zip"),
      compatibleRuntimes: [lambda.Runtime.PYTHON_3_9],
    });

    // Lambda function
    const fastApiLambda = new lambda.Function(this, "fastApiLambda", {
      runtime: lambda.Runtime.PYTHON_3_9,
      code: lambda.Code.fromAsset("../app"),
      handler: "main.handler",
      layers: [fastApiBaseLayer],
      environment: {
        TEAMS_TABLE_NAME: "teams",
        COGNITO_PUBLIC_KEY: // not relevant
      }
    });

    const authorizer = new apiGateway.CognitoUserPoolsAuthorizer(this, 'userPoolAuth', {
      cognitoUserPools: [userPool]
    })

    // Api Gateway
    const fastApiApiGateway = new apiGateway.RestApi(this, "fastApiApiGateway", {
      restApiName: "fastApiApiGateway",
      defaultMethodOptions: {
        authorizationType: apiGateway.AuthorizationType.COGNITO,
        authorizer
      }
    });

    // Lambda to ApiGateway
    const lambdaApiIntegration = new apiGateway.LambdaIntegration(fastApiLambda);

    fastApiApiGateway.root.addProxy({
      defaultIntegration: lambdaApiIntegration
    });

    teamsTable.grantReadWriteData(fastApiLambda);
  }
}

你能帮我吗
我已经尝试通过iam.PolicyStatement添加权限,但没有成功。

hs1ihplo

hs1ihplo1#

您的错误表明您正在尝试写入名为teams的DynamoDB表,但CDK代码没有创建具有此名称的表:

const teamsTable = new ddb.Table(this, "teams", {
      partitionKey: {name: "team_id", type: ddb.AttributeType.STRING},
      billingMode: ddb.BillingMode.PAY_PER_REQUEST,
    });

如果您查看了ddb.Table的CDK文档,您会发现您指定了CloudFormation Id:
https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.Table.html
如果你想解析表名,你必须将其作为环境变量传递到lambda函数中,而不是使用字符串:

const fastApiLambda = new lambda.Function(this, "fastApiLambda", {
      runtime: lambda.Runtime.PYTHON_3_9,
      code: lambda.Code.fromAsset("../app"),
      handler: "main.handler",
      layers: [fastApiBaseLayer],
      environment: {
        TEAMS_TABLE_NAME: teamsTable.tableName,
        COGNITO_PUBLIC_KEY: // not relevant
      }
    });
pw9qyyiw

pw9qyyiw2#

通过定义tableName创建表,而不依赖于CFN命名:

const teamsTable = new ddb.Table(this, "teams", {
      partitionKey: {name: "team_id", type: ddb.AttributeType.STRING},
      billingMode: ddb.BillingMode.PAY_PER_REQUEST,
      tableName: "teams"
    });

另一种确保你不会遇到这些的方法是不要硬编码变量,所以你应该把表名从构造传递到你的Lambda env变量作为代码:

const fastApiLambda = new lambda.Function(this, "fastApiLambda", {
      runtime: lambda.Runtime.PYTHON_3_9,
      code: lambda.Code.fromAsset("../app"),
      handler: "main.handler",
      layers: [fastApiBaseLayer],
      environment: {
        TEAMS_TABLE_NAME: teamsTable.tableName,
        COGNITO_PUBLIC_KEY: // not relevant
      }
    });

相关问题