Terraform: 将 AWS 托管策略附加到角色的正确方法?

我想将一个预先存在的 AWS 托管角色附加到策略中,下面是我当前的代码:

resource "aws_iam_role_policy_attachment" "sto-readonly-role-policy-attach" {
role       = "${aws_iam_role.sto-test-role.name}"
policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
}

有没有更好的方法来建模托管策略,然后引用它,而不是硬编码 ARN?似乎每当我硬编码 ARN/路径或其他类似的东西,我通常会发现后来有一个更好的方法。

Terraform 中是否已经存在一些模拟管理策略的东西?还是说对 ARN 进行硬编码是“正确”的做法?

64186 次浏览

当使用 Terraform 本身不直接管理的值时,有几个选项。

第一个,也是最简单的选择是像这里一样硬编码值。如果您期望值永远不会改变,那么这是一个直截了当的答案。考虑到这些“固定策略”是有文档记录的,内置的 AWS 特性可能符合这个标准。

第二个选项是创建一个 Terraform 模块并将值硬编码到 那个中,然后从其他几个模块引用该模块。这允许您集中管理该值并多次使用它。只包含输出的模块是此类事情的常见模式,不过您也可以选择创建一个包含 aws_iam_role_policy_attachment资源的模块,其中包含来自变量的角色集。

The third option is to place the value in some location that Terraform can retrieve values from, such as Consul, and then retrieve it from there using a data source. With only Terraform in play, this ends up being largely equivalent to the second option, though it means Terraform will re-read it on each refresh rather than only when you update the module using terraform init -upgrade, and thus this could be a better option for values that change often.

第四种选择是使用一个专门的数据源,它可以直接从真理的来源读取值。Terraform 目前还没有 数据源来获取关于 AWS 管理策略的信息,所以对于您当前的情况来说,这不是一个选项,但是可以用来获取其他 AWS 定义的数据,比如 AWS IP 地址范围、服务 ARN 等。

在给定的情况下,哪一种适合取决于价值变化的频率,谁来管理变化,以及是否有专门的 Terraform 数据源。

IAM 策略数据源非常适合这个。数据资源用于描述 Terraform 没有主动管理但是被 Terraform 引用的数据或资源。

对于您的示例,您将为托管策略创建一个数据资源,如下所示:

data "aws_iam_policy" "ReadOnlyAccess" {
arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
}

在本例中,数据源的名称 ReadOnlyAccess完全取决于您。对于托管策略,为了保持一致性,我使用与策略名相同的名称,但是如果适合您的话,您也可以简单地将其命名为 readonly

然后,您将把 IAM 政策附加到您的角色上,具体如下:

resource "aws_iam_role_policy_attachment" "sto-readonly-role-policy-attach" {
role       = "${aws_iam_role.sto-test-role.name}"
policy_arn = "${data.aws_iam_policy.ReadOnlyAccess.arn}"
}

我有一个类似的情况,我不想在我的 terraform脚本中使用 arn,有两个原因,

  • 如果我们在 Web 控制台上执行此操作,我们不会真正查看 arn,而是搜索角色名,然后将其附加到角色
  • The arn is not easy to remember, looks like is not for human

我宁愿使用策略名称,而不是 arn,下面是我的示例

# Get the policy by name
data "aws_iam_policy" "required-policy" {
name = "AmazonS3FullAccess"
}


# Create the role
resource "aws_iam_role" "system-role" {
name = "data-stream-system-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid    = ""
Principal = {
Service = "ec2.amazonaws.com"
}
},
]
})
}




# Attach the policy to the role
resource "aws_iam_role_policy_attachment" "attach-s3" {
role       = aws_iam_role.system-role.name
policy_arn = data.aws_iam_policy.required-policy.arn
}