AWS CDK - 如何将 Access Key Secret 和 Secret Key Id 作为 Env Param 传递给容器

Posted

技术标签:

【中文标题】AWS CDK - 如何将 Access Key Secret 和 Secret Key Id 作为 Env Param 传递给容器【英文标题】:AWS CDK - How to pass Access Key Secret and Secret Key Id as Env Param to Container 【发布时间】:2021-02-20 01:30:49 【问题描述】:

我正在使用 CDK 在 AWS 上构建我们的基础设施。我为我的微服务创建了我的 IAM 用户,以便在定义的策略下与 AWS 服务通信。我的问题是我无法获取 aws 密钥和 id,然后将其作为 Env 变量传递给我的容器。见下文:

首先,我创建我的 IAM 用户,我的微服务将使用该用户。

const user = new User(this, "user", 
  userName: `$myAppEnv-api-iam-user`,
);

其次,我正在尝试创建访问密钥。

const accessKey = new CfnAccessKey(this, "ApiUserAccessKey", 
      userName: user.userName,
);

const accessKeyId = new CfnOutput(this, "AccessKeyId", 
      value: accessKey.ref,
);

const accessKeySecret = new CfnOutput(this, "SecretAccessKeyId", 
      value: accessKey.attrSecretAccessKey,
);

接下来,我想将它作为环境变量传递。

const apiContainer = apiTaskDefinition.addContainer(containerId, 
      image: apiImage,
      environment: 
        APP_ENV: myAppEnv,
        AWS_ACCESS_KEY_ID: awsAccessKeyId.value || ":(",
        AWS_SECRET_ACCESS_KEY: awsSecretAccessKey.value || ":(",
        NOTIFICATIONS_TABLE_ARN: notificationsTableDynamoDBArn,
        NOTIFICATIONS_QUEUE_URL: notificationsQueueUrl,
      ,
      cpu: 256,
      memoryLimitMiB: 512,
      logging: new AwsLogDriver( streamPrefix: `$myAppEnv-ec-api` ),
    );

当我的 CDK 部署成功完成时,我看到打印出以下内容:/

Outputs:
staging-ecstack.AccessKeyId = SOMETHING
staging-ecstack.SecretAccessKeyId = SOMETHINGsy12X21xSSOMETHING2X2

你知道我怎么能做到这一点吗?

【问题讨论】:

【参考方案1】:

一般来说,创建 IAM 用户不是这里的方法 - 您最好使用 IAM 角色。使用 CDK,它会在您实例化 taskDefinition 构造时自动为您创建一个 taskRole。您可以使用各种grant* 方法为堆栈中的其他构造分配权限,例如described here:

const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDef');
const container = taskDefinition.addContainer('web', 
  image: ecs.ContainerImage.fromRegistry("apps/myapp"),
  memoryLimitMiB: 256,
);
// Grant this task role access to use other resources
myDynamodbTable.grantReadWriteData(taskDefinition.taskRole);
mySnsTopic.grantPublish(taskDefinition.taskRole);

【讨论】:

感谢您的回答 :) 我没有尝试过,但是您是说我的 Node 应用程序可以在不提供凭据的情况下使用 AWS-SDK? 没错。它只需要一个具有正确权限的角色。 好的,谢谢伙计!我会尝试并希望将其标记为已接受的答案!【参考方案2】:

简而言之,在我的博文中找到答案: https://blog.michaelfecher.com/i-tell-you-a-secret-provide-database-credentials-to-an-ecs-fargate-task-in-aws-cdk

更详细地解释您的问题:

    避免自定义创建的 IAM 角色并使用 CDK 生成的角色。它们是一致的并使用最小特权原则。在我的博客文章中,不需要手动创建 IAM 角色。是的,我知道...我需要更新它。 ;) 使用对应资源的grant*方法,例如taskDefinition。 这将为 1) 生成的角色创建一个策略声明 不要将环境变量用于机密。 网上有很多资源,告诉你为什么。 一个是这里:https://security.stackexchange.com/questions/197784/is-it-unsafe-to-use-environmental-variables-for-secret-data 特别是在使用 ECS 时,请在任务定义中使用 secrets 参数(请参阅博文)。 看来,您传递的是令牌而不是实际的秘密值。 那是行不通的。令牌在 synth / Cloud Formation 生成期间解析。 您不需要CfnOutput。使用直接 Stack -> Stack 传递字段。 CfnOutput 确实是某事,当您在一个 CDK 应用程序中控制所有堆栈时,您应该避免这种情况。 仅当您想在 CDK 应用程序之间共享时才有意义,这些应用程序是分开的部署和存储库。

如果……不清楚,请不要犹豫提出问题。

【讨论】:

以上是关于AWS CDK - 如何将 Access Key Secret 和 Secret Key Id 作为 Env Param 传递给容器的主要内容,如果未能解决你的问题,请参考以下文章

如何将现有资源从不同的 AWS 账户导入 AWS CDK

AWS - 如何使用 CDK/CloudFormation 将服务链接角色传递给自动缩放组?

Typescript - AWS CDK 启用 CORS

如何将 VPC 和安全组分配给 AWS CDK 中的 Lambda?

如何将生命周期策略添加到 AWS CDK Typescript 中的现有 S3 存储桶

如何通过python更新AWS Secrets Manager?