AWS CDK-如何将访问密钥秘密和秘密密钥ID作为Env参数传递给容器

问题描述

我正在使用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

您知道我如何实现这一目标吗?

解决方法

通常来说,创建IAM用户并不是走这条路-最好使用IAM角色。使用CDK,它将在实例化taskRole构造时自动为您创建taskDefinition。您可以使用各种described heregrant*方法将权限分配给堆栈中的其他构造:

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

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

要更详细地说明您的问题,

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

如果……。尚不清楚,请随时提出问题。