簡體   English   中英

在 CDK ShellStep(管道)步驟中使用 AWS CLI

[英]Use the AWS CLI in a CDK ShellStep (pipeline) step

我有一個 CDK Pipeline 堆棧,可以合成和部署一些基礎設施。 創建基礎設施后,我想構建一個知道 URL 到新建的 API 網關的前端反應應用程序。 構建應用程序后,我想將構建的文件移動到新創建的 S3 存儲桶中。

我的前兩個步驟沒問題。 我使用CfnOutput獲取 API URL 和存儲桶名稱。 然后,我在我的 shell 步驟中使用envFromCfnOutputs來構建具有正確環境變量設置的 React 應用程序。

我不知道如何將我的文件移動到 s3 存儲桶。 幾天來我一直在嘗試使用 s3deploy 找出一些東西,但遇到了各種權限問題。 我想我可以嘗試只使用 aws cli 並手動移動文件,但我不知道如何授予 CLI 命令添加和刪除對象的權限。 為了讓事情變得更復雜一些,我的基礎設施被部署到一個與我的管道所在位置不同的帳戶。

知道如何使用 CLI 或關於如何將構建的文件移動到存儲桶的其他想法嗎?

// set up pipeline
const pipeline = new CodePipeline(this, id, {
  crossAccountKeys: true,
  pipelineName: id,
  synth: mySynthStep
});

// add a stage with all my constructs
const pipelineStage = pipelineAddStage(myStage)

// create a shellstep that builds and moves the frontend assets
const frontend = new ShellStep('FrontendBuild', {
  input: source,
   commands: [
     'npm install -g aws-cli',
     'cd frontend',
     'npm ci',
     'VITE_API_BASE_URL="$AWS_API_BASE_URL" npm run build',
     'aws s3 sync ./dist/ s3://$AWS_FRONTEND_BUCKET_NAME/ --delete'
   ],
   envFromCfnOutputs: {
     AWS_API_BASE_URL: myStage.apiURL,
     AWS_FRONTEND_BUCKET_NAME: myStage.bucketName
   }
})

// add my step as a poststep to my stage.
pipelineStage.addPost(frontendApp);

ShellStep 可能在管道的 IAM 權限/角色下運行。 為 Pipeline 的角色添加額外的權限,這應該會影響 AWS CLI 調用。

在嘗試執行此操作之前,您可能還需要調用buildPipeline

pipeline.buildPipeline();
pipeline.pipeline.addToRolePolicy(...)

我想試一試,並建議跨賬戶管道的解決方案。

您弄清楚了如何構建 Web 應用程序的前半部分,這是通過將 cloudformation 的 output 傳遞到 shell 操作的環境來構建具有正確輸出的應用程序(例如 API 端點 url)。

您現在可以向CodeBuildStep添加權限並在其中附加策略以允許該步驟調用某些操作。 如果您的管道和您的存儲桶在同一個帳戶中(並且還需要更多操作的跨帳戶),那應該可以工作。 但是限定這些權限存在一個問題:

Pipeline 和 Bucket 是按照先創建 Pipeline 或自我更新的順序創建的,因此此時您不知道 Bucket Name 或其他任何內容。 然后它將資源部署到自己的帳戶或另一個帳戶。 因此,您需要指定一個事先已知的名稱。 這是一個普遍的問題,如果您還需要創建一個 Cloudfront Invalidation 等等,那么這個問題就會擴大。

我的方法如下(在我的例子中是跨賬戶部署):

  1. 在允許角色執行操作的資源旁邊創建角色(例如 ReadWrite S3 bucket,創建 Cloudfront Invalidation,...)具有預定義的名稱並允許匹配的委托人承擔該角色(在我的例子中是帳戶委托人)
代碼片段
  envFromCfnOutputs: {
    bucketName: devStage.webappBucketName,
    cloudfrontDistributionID: devStage.webbappCloudfrontDistributionId,
  },
  commands: [
    "yarn run build-webapp",
    // Assume role, see https://stackoverflow.com/questions/63241009/aws-sts-assume-role-in-one-command
    `export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" $(aws sts assume-role --role-arn arn:aws:iam::${devStage.account}:role/${webappDeploymentRoleName} --role-session-name WebappDeploySession --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" --output text))`,
    `aws s3 sync ${webappPath}/build s3://$bucketName`,
    `aws cloudfront create-invalidation --distribution-id $cloudfrontDistributionID --paths \"/*\"`,
  ],
2. 創建一個“CodeBuildStep”,它有權承擔該角色(通過預定義的名稱)代碼片段
new CodeBuildStep("Deploy Webapp", { rolePolicyStatements: [ new PolicyStatement({ actions: ["sts:AssumeRole"], resources: [ `arn:aws:iam::${devStage.account}:role/${webappDeploymentRoleName}`, ], effect: Effect.ALLOW, }), ], ... }
3. 在 `commands` 中,我使用預定義的角色名稱調用 `aws sts assume-role` 並將憑據保存到環境中以供后續調用使用 代碼片段
 envFromCfnOutputs: { bucketName: devStage.webappBucketName, cloudfrontDistributionID: devStage.webbappCloudfrontDistributionId, }, commands: [ "yarn run build-webapp", // Assume role, see https://stackoverflow.com/questions/63241009/aws-sts-assume-role-in-one-command `export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" $(aws sts assume-role --role-arn arn:aws:iam::${devStage.account}:role/${webappDeploymentRoleName} --role-session-name WebappDeploySession --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" --output text))`, `aws s3 sync ${webappPath}/build s3://$bucketName`, `aws cloudfront create-invalidation --distribution-id $cloudfrontDistributionID --paths \"/*\"`, ],
4. 我確實使用步驟 3 中的憑據調用其他 aws cli 操作,例如 `aws s3 sync...`。現在正確地限定了所需操作的范圍

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM