如何获取移动应用程序访问安全S3对象的STS凭据



我已经在AWS Fargate中部署了后端服务。我想获取STS令牌,以便从本地移动应用程序中检索一组安全的S3对象。我使用Terraform创建基础设施。我已经创建了一个Fargate任务角色task-role。因此,对于这个特定的用例,我创建了一个新的角色native-app-role,并将task-role分配为具有承担native-app-role权限的可信关系。

以下是Terraform代码:

# Fargate Role with trust relationship to ECS
data "aws_iam_policy_document" "fg_task_role_assume_role_policy_doc" {
statement {
actions = [
"sts:AssumeRole"
]
effect = "Allow"
principals {
type = "Service"
identifiers = [
"ecs-tasks.amazonaws.com"
]
}
}
}

resource "aws_iam_role" "task_role" {
name = "${var.application}-${var.namespace}-fargate-task-role"
assume_role_policy = data.aws_iam_policy_document.fg_task_role_assume_role_policy_doc.json
tags = {
Name = "${var.application}-${var.namespace}-fargate-task-role" # virtual-agent-alpha-fargate-task-role
}
}

# Native app role with trust relationship to Fargate role
data "aws_iam_policy_document" "native_app_iam_policy_doc" {
statement {
actions = [
"sts:AssumeRole"
]
effect = "Allow"
principals {
type = "AWS"
identifiers = [
aws_iam_role.task_role.arn
]
}
}
}
resource "aws_iam_role" "virtual_agent_native_iam_role" {
name = "${var.application}-${var.namespace}-native-application-role"
assume_role_policy = data.aws_iam_policy_document.native_app_iam_policy_doc.json
tags = {
Name = "${var.application}-native-${var.namespace}-role"
}
}

然后我使用以下Kotlin代码来获取STS凭据:注:roleArnvirtual_agent_native_iam_role的ARN

fun getS3ReadOnlyTempCredentials(roleArn: String, bucket: String, objectKey: String, expiry: Expiry = Expiry(15, ChronoUnit.MINUTES)): AwsStsCredentials {
val duration = Duration.of(expiry.duration, expiry.unit).toSeconds().toInt()
val request = AssumeRoleRequest().apply {
this.roleArn = roleArn
roleSessionName = UUID.randomUUID().toString()
durationSeconds = duration
policy = """
{
"Id": "${UUID.randomUUID()}",
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::$bucket/$objectKey",
"Principal": {
"AWS": [ $roleArn ]
}
}
]
}
""".trimIndent()
}
return stsClient.assumeRole(request).credentials.let {
AwsStsCredentials(it.accessKeyId, it.secretAccessKey, it.sessionToken, ZonedDateTime.now().plusSeconds(duration.toLong()) )
}

当我执行此操作时,我会得到以下错误:com.amazonaws.services.securitytoken.model.AWSSecurityTokenServiceException: User: arn:aws:sts::913597729265:assumed-role/virtual-agent-alpha-fargate-task-role/c082fba5-3d13-4030-a457-9a18fb105efd is not authorized to perform: sts:AssumeRole on resource: "arn:aws:iam::913597729265:role/virtual-agent-alpha-native-application-role" (Service: AWSSecurityTokenService; Status Code: 403; Error Code: AccessDenied; Request ID: 573630b6-b02a-4185-ae5b-9360d05b4225)

上面的错误表明virtual-agent-alpha-fargate-task-role没有权限假定virtual-native-role,但我已经通过Terraform的aws_iam_resourceaussumeRole属性添加了信任关系。

有人能指出我做错了什么吗?

我认为您的角色创建是错误的。您在代码中创建的策略必须是地形模板中virtual_agent_native_iam_role的一部分。

您也不需要在代码中假设role,您可以将任务配置为使用您在地形模板中创建的执行角色。查看此处了解更多信息。

我可以尝试用两种替代方案来帮助您,但要做到这一点,我需要确认您的用例。正如我所理解的,您需要为特定用户提供读取(在定义的时间间隔内(特定s3对象的访问权限。如果是这样的话,这里是我的建议:

第一种选择是尝试让你的解决方案发挥作用。但您需要对其进行测试,因为我在这里没有这种场景:首先,我将删除virtual_agent_native_iam_role,只保留task_role。我仍然需要使用task_role和特定的$bucket/$objectKey来调用AssumeRole。但是,您的角色配置中缺少一些内容。根据假设角色api文档:

生成的会话权限是角色基于身份的策略和会话策略的交集。

因此,为了使其发挥作用,您的task_role策略应该具有允许对s3进行更广泛访问的权限,并且您的方法调用只会限制现有的策略。在这种情况下,我会在地形模板中为您的task_role附加一个新策略,以允许对bucket中的所有对象执行操作s3:GetObject(或者,如果需要,根据您的用例,对您帐户中的所有bucket执行操作(。

AssumeRole调用将用于限制对特定bucket/objectkey的临时凭据的访问。

但我相信还有第二种选择会简单得多。但您需要评估它是否适用于您的用例:

S3允许您为特定对象创建一个临时url,允许拥有url的用户在特定时间间隔内获取该对象。对于该解决方案,您还需要为task_role添加一个具有s3:GetObject权限的策略。但在这种情况下,您将不需要在代码中调用AssumeRole方法。您只需调用该方法即可创建预签名的url并将其发送回用户。您可以在这里找到有关使用javasdk的替代实现的更多详细信息。

在这种情况下,用户将只能访问所选对象。不是整个桶。

我解决了这个问题。我犯的错误是没有向具有AssumeRole权限的task_role提供权限。问题中的其他内容都做对了。因此,在task_role的地形图中,我必须附加一个具有正确权限的自定义策略。

Terraform代码:

data "aws_iam_policy_document" "virtual_agent_native_assume_role_policy_doc" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
resources = ["*"]
}
}
resource "aws_iam_policy" "virtual_agent_native_assume_role_policy" {
name = "${var.application}-${var.namespace}-native-role-assume-role-policy"
policy = data.aws_iam_policy_document.virtual_agent_native_assume_role_policy_doc.json
}
resource "aws_iam_role_policy_attachment" "task_role_virtual_agent_native_assume_role_policy_att" {
role = aws_iam_role.task_role.name
policy_arn = aws_iam_policy.virtual_agent_native_assume_role_policy.arn
}

最新更新