You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS CDK配置问题:Lambda无DynamoDB PutItem权限

解决Lambda写入DynamoDB的AccessDeniedException问题

问题描述

尝试构建一个可向DynamoDB写入数据的Lambda函数,该函数通过API Gateway访问并由Cognito用户池保护,但每次写入数据时都会抛出AccessDeniedException,提示Lambda角色无dynamodb:PutItem权限。曾尝试通过iam.PolicyStatement添加权限但未成功。

错误信息

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

解决方案

1. 修正Lambda环境变量中的表名

代码中硬编码了TEAMS_TABLE_NAME: "teams",但CDK默认会给生成的表添加栈前缀(比如SoccerTipGameInfrastructure-teams-xxxx),导致Lambda尝试访问的表和CDK创建并授权的表不是同一个。将环境变量改为使用CDK生成的实际表名:

environment: {
  TEAMS_TABLE_NAME: teamsTable.tableName, // 替换硬编码的"teams"
  COGNITO_PUBLIC_KEY: // 你的密钥内容
}

2. 明确权限声明(可选)

如果上述修改后仍有问题,可以替换teamsTable.grantReadWriteData(fastApiLambda);为更明确的权限声明,确保权限覆盖所需操作:

fastApiLambda.addToRolePolicy(new iam.PolicyStatement({
  actions: [
    'dynamodb:PutItem',
    'dynamodb:GetItem',
    'dynamodb:Scan',
    'dynamodb:UpdateItem',
    'dynamodb:DeleteItem'
  ],
  resources: [teamsTable.tableArn],
}));

3. 重新部署并验证

运行cdk deploy重新部署栈,然后在AWS控制台检查Lambda的执行角色:

  • 找到目标Lambda函数,进入"配置"->"权限"
  • 查看执行角色的权限策略,确认存在允许dynamodb:PutItem操作且资源为目标DynamoDB表ARN的策略

内容的提问来源于stack exchange,提问作者thomaswiiswitch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 05:32:49