AWS CDK - 如何将访问密钥秘密和秘密密钥 ID 作为环境参数传递给容器
AWS CDK - How to pass Access Key Secret and Secret Key Id as Env Param to Container
我正在使用 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,它会在您实例化 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);
简而言之,在我的博客post这里找到答案:
https://blog.michaelfecher.com/i-tell-you-a-secret-provide-database-credentials-to-an-ecs-fargate-task-in-aws-cdk
更详细地解释您的问题:
- 避免自定义创建的 IAM 角色并使用 CDK 生成的角色。它们对齐并使用 least-privilege 原则。在我的博客 post 中,不需要手动创建 IAM 角色。是的,我知道...我需要更新它。 ;)
- 使用相应资源的
grant*
方法,例如taskDefinition
。
这将为 1) 的生成角色创建策略声明
- 不要将环境变量用于机密。
网上有很多资源,告诉你为什么。
一个是这里:https://security.stackexchange.com/questions/197784/is-it-unsafe-to-use-environmental-variables-for-secret-data
特别是,在使用 ECS 时,请在任务定义中使用
secrets
参数(请参阅博客 post)。
- 看来,您传递的是令牌而不是实际的秘密值。
那是行不通的。令牌在
synth
/ Cloud Formation 生成期间解析。
- 您不需要
CfnOutput
。使用直接 Stack -> Stack 传递字段。
当在一个 CDK 应用程序中控制所有 Stacks 时,CfnOutput
真的很糟糕,您应该避免这种情况。
只有当您想要在独立部署和存储库的 CDK 应用程序之间共享时,这才有意义。
如果……不明白的,不要犹豫提问。
我正在使用 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,它会在您实例化 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);
简而言之,在我的博客post这里找到答案: https://blog.michaelfecher.com/i-tell-you-a-secret-provide-database-credentials-to-an-ecs-fargate-task-in-aws-cdk
更详细地解释您的问题:
- 避免自定义创建的 IAM 角色并使用 CDK 生成的角色。它们对齐并使用 least-privilege 原则。在我的博客 post 中,不需要手动创建 IAM 角色。是的,我知道...我需要更新它。 ;)
- 使用相应资源的
grant*
方法,例如taskDefinition
。 这将为 1) 的生成角色创建策略声明
- 不要将环境变量用于机密。
网上有很多资源,告诉你为什么。
一个是这里:https://security.stackexchange.com/questions/197784/is-it-unsafe-to-use-environmental-variables-for-secret-data
特别是,在使用 ECS 时,请在任务定义中使用
secrets
参数(请参阅博客 post)。 - 看来,您传递的是令牌而不是实际的秘密值。
那是行不通的。令牌在
synth
/ Cloud Formation 生成期间解析。 - 您不需要
CfnOutput
。使用直接 Stack -> Stack 传递字段。 当在一个 CDK 应用程序中控制所有 Stacks 时,CfnOutput
真的很糟糕,您应该避免这种情况。 只有当您想要在独立部署和存储库的 CDK 应用程序之间共享时,这才有意义。
如果……不明白的,不要犹豫提问。