我正在尝试使用IAM角色来控制对应用程序中S3的访问。然而,我并没有准备好所有的东西来完成这项工作。当在AWS中运行时,我的代码会抛出一个";缺少凭据"例外,所以很明显我错过了一步。
我的印象是,如果不指定凭据,SDK将默认使用容器的标识,但事实似乎并非如此。我认为我的代码是错误的,或者我创建的"假定角色"策略没有指定正确的主体。我只是没能从医生那里弄清楚我应该做什么。
我的另一个想法是,也许我需要创建一个单独的角色来访问S3存储桶,然后编写一些代码来承担这个角色,并在我的S3客户端中使用这些凭据。
如有任何帮助,我们将不胜感激。
我正在使用Terraform来建立我的基础设施,并在下面包含了相关摘录。在文章的最后,我包含了用于访问S3的Typescript代码。
当前配置
- 我已经为我的ECS Fargate任务定义了一个角色
resource "aws_iam_role" "ecs_task_execution_role" {
name = "ecsTaskExecutionRole"
assume_role_policy = data.aws_iam_policy_document.ecs_task_execution_role.json
}
- 我已经为此任务定义了"假定角色"策略
data "aws_iam_policy_document" "ecs_task_execution_role" {
version = "2012-10-17"
statement {
sid = ""
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ecs-tasks.amazonaws.com"]
}
}
}
- 我定义了一个IAM策略,该策略管理对有问题的S3存储桶的访问:
resource "aws_iam_policy" "read_write_image_storage" {
name = "${var.environment}-read-write-image-storage"
description = "Allows read access to s3 bucket in the ${var.environment} environment"
policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Effect = "Allow",
Action = [
"s3:*"
],
Resource = [
aws_s3_bucket.image_storage.arn,
]
}]
})
}
- 我已将策略附加到运行容器的角色:
resource "aws_iam_role_policy_attachment" "read_write_image_storage" {
role = aws_iam_role.ecs_task_execution_role.name
policy_arn = aws_iam_policy.read_write_image_storage.arn
}
- 在与该任务相关的容器中运行的node.js代码中,我启动了一个默认的S3客户端,并尝试使用它来访问bucket:
const s3config = {
region: process.env.AWS_REGION,
};
const s3 = new S3(s3config);
export const putBlob = async (key: string, blob: Buffer) => {
// save buffer to an AWS S3 bucket
const params = {
Bucket: process.env.AWS_ATTACHMENT_STORAGE_BUCKETNAME,
Key: key,
Body: blob,
ContentType: "image/png",
};
try {
console.debug("Saving image to S3");
const result = await s3.upload(params).promise();
} catch(e) {
console.error(e.message) // MissingCredentials
throw 2
}
}
- 我已经定义了Fargate任务来使用步骤1中定义的角色
resource "aws_ecs_task_definition" "webapp" {
family = "webapp-task"
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
container_definitions = jsonencode([
{
"name" : "MyContainerDefinition",
"image" : "MyContainerImage",
"cpu" : 256,
"memory" : 512,
"essential" : true,
"portMappings" : [
{
"containerPort" : 80,
"hostPort" : 80,
"protocol" : "tcp"
}
],
}
])
}```
您必须设置task_role_arn。这与execution_role_arn
不同。