如何在CDK打包Java Lambda函数时跨账号访问CodeArtifact?
跨AWS账号CodeArtifact访问解决方案
问题根源
CDK打包Lambda时,容器环境默认没有AWS凭证,导致无法调用aws codeartifact get-authorization-token命令获取权限,进而无法拉取账号A的commons包。以下是三种可行的解决方法:
方法1:容器内通过STS AssumeRole获取临时凭证(推荐开发/测试环境)
步骤1:更新账号A的角色信任策略
修改账号A的CDK代码,允许账号B的实体Assume此角色:
const codeArtifactAccessRole = new Role(this, "CodeArtifactAccessRole", { assumedBy: new CompositePrincipal( new ServicePrincipal("codebuild.amazonaws.com"), new AccountPrincipal("账号B的AWS账号ID") // 新增:允许账号B的主体Assume该角色 ), });
部署账号A的Stack以生效。
步骤2:修改账号B的Lambda打包命令
在打包容器内先Assume账号A的角色,获取临时凭证后再执行CodeArtifact和Maven命令:
command: [ // 安装jq用于解析STS返回的JSON(Java 11镜像默认无jq) "apk add --no-cache jq && " + // Assume账号A的角色并保存凭证 "aws sts assume-role --role-arn 账号A的CodeArtifactAccessRoleArn --role-session-name codeartifact-bundling --query 'Credentials' --output json > /tmp/creds.json " + // 导出临时凭证环境变量 "&& export AWS_ACCESS_KEY_ID=$(jq -r '.AccessKeyId' /tmp/creds.json) " + "&& export AWS_SECRET_ACCESS_KEY=$(jq -r '.SecretAccessKey' /tmp/creds.json) " + "&& export AWS_SESSION_TOKEN=$(jq -r '.SessionToken' /tmp/creds.json) " + // 获取CodeArtifact令牌 "&& export CODEARTIFACT_AUTH_TOKEN=`aws codeartifact get-authorization-token --domain domain --domain-owner 账号A的账号ID --region 区域 --query authorizationToken --output text` " + // 执行Maven打包 "&& mvn -s .mvn/settings.xml clean install " + "&& cp target/custom-email-sender-1.0.jar /asset-output/", ]
同时确保账号B中执行CDK的用户/角色拥有sts:AssumeRole权限,允许访问账号A的CodeArtifactAccessRole。
方法2:使用CodeBuild完成Lambda打包(适合CI/CD生产环境)
利用账号A已配置的CodeBuild信任角色,将打包逻辑转移到CodeBuild中,避免本地凭证问题:
步骤1:在账号B的CDK中定义CodeBuild项目
import * as codebuild from 'aws-cdk-lib/aws-codebuild'; // 创建CodeBuild项目,负责打包Lambda代码 const buildProject = new codebuild.Project(this, "LambdaBuildProject", { environment: { buildImage: codebuild.LinuxBuildImage.fromDockerRegistry("maven:3.8-openjdk-11"), }, source: codebuild.Source.fromAsset(path.join(__dirname, "..", "..", "functions/custom-email-sender")), // 定义CodeBuild角色,允许Assume账号A的角色 role: new Role(this, "CodeBuildRole", { assumedBy: new ServicePrincipal("codebuild.amazonaws.com"), inlinePolicies: { AssumeCodeArtifactRole: new PolicyDocument({ statements: [ new PolicyStatement({ actions: ["sts:AssumeRole"], resources: ["账号A的CodeArtifactAccessRoleArn"], }), ], }), }, }), buildSpec: codebuild.BuildSpec.fromObject({ version: "0.2", phases: { install: { commands: [ "aws sts assume-role --role-arn 账号A的CodeArtifactAccessRoleArn --role-session-name codebuild-codeartifact --query 'Credentials' --output json > /tmp/creds.json", "export AWS_ACCESS_KEY_ID=$(jq -r '.AccessKeyId' /tmp/creds.json)", "export AWS_SECRET_ACCESS_KEY=$(jq -r '.SecretAccessKey' /tmp/creds.json)", "export AWS_SESSION_TOKEN=$(jq -r '.SessionToken' /tmp/creds.json)", "export CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token --domain domain --domain-owner 账号A的账号ID --region 区域 --query authorizationToken --output text)", ], }, build: { commands: ["mvn -s .mvn/settings.xml clean install"], }, }, artifacts: { files: ["target/custom-email-sender-1.0.jar"], }, }), }); // 获取CodeBuild打包产物 const buildOutput = buildProject.getArtifact("artifact"); // 基于CodeBuild产物创建Lambda函数 const customEmailSenderFunction = new Function( this, customEmailSenderFunctionName, { runtime: Runtime.JAVA_11, timeout: Duration.minutes(3), memorySize: 1024, handler: "com.example.entrypoint.CustomEmailSenderHandlerEntrypoint::handleRequest", code: Code.fromBucket(buildOutput.s3Bucket, buildOutput.s3ObjectKey), environment: { QUEUE_URL: emailQueue.queueUrl, }, logRetention: RetentionDays.THREE_MONTHS, } );
步骤2:更新账号A的角色信任策略
允许账号B的CodeBuild角色Assume:
const codeArtifactAccessRole = new Role(this, "CodeArtifactAccessRole", { assumedBy: new CompositePrincipal( new ServicePrincipal("codebuild.amazonaws.com"), new ArnPrincipal("账号B的CodeBuildRoleArn") // 新增:允许指定CodeBuild角色访问 ), });
方法3:本地打包传递凭证(仅开发环境临时使用)
将本地AWS凭证传递给打包容器,仅适合本地开发场景:
bundling: { // ...其他配置 environment: { AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID || "", AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY || "", AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN || "", }, }
执行CDK前先在本地导出凭证:
export AWS_ACCESS_KEY_ID="你的本地AK" export AWS_SECRET_ACCESS_KEY="你的本地SK" npx cdk synth -- -v -o dist
此方法不适合CI/CD环境,存在凭证泄露风险。
关键注意事项
- 确保账号B的实体(用户/角色/CodeBuild角色)拥有
sts:AssumeRole权限,允许访问账号A的CodeArtifactAccessRole。 - Maven的
settings.xml需正确配置CodeArtifact仓库地址,使用获取到的endpoint和token。
内容的提问来源于stack exchange,提问作者Alexiz Hernandez
相关产品推荐
相关产品推荐

