【问题标题】:How do I use Terraform to maintain/manage IAM users如何使用 Terraform 维护/管理 IAM 用户
【发布时间】:2017-03-30 15:24:51
【问题描述】:

地形版本

Terraform v0.7.8 Terraform v0.7.11

受影响的资源

  • aws_iam_user

Terraform 配置文件

我正在尝试使用列表来管理 IAM 用户:

variable "iam_user_list" { default = "aaa,bbb,ccc,ddd,eee,fff" }

resource "aws_iam_user" "iam_user" {
    count = "${length(split(",", var.iam_user_list))}"
    name = "${element(split(",", var.iam_user_list), count.index)}"
    force_destroy = true
}

output "user_list" {
  value = "VPC IAM Base Users: ${var.iam_user_list}"
}

当 AWS 账户为空时,用户按预期创建
当我从列表末尾删除用户时,即 fff,按预期删除。 但是当我删除列表中间的用户,即bbb时,出现错误:

Modifying...
  name: "bbb" => "ccc"
Error applying plan:

1 error(s) occurred:

* aws_iam_user.iam_user.1: Error updating IAM User bbb: EntityAlreadyExists: User with name ccc already exists.
    status code: 409, request id: ed0b4447-abf3-11e6-9b38-0fb23af37c82

在 terraform aws_iam_user 中似乎没有用户存在检查,在 terraform 中管理 IAM 用户的解决方法/正确方法是什么?

【问题讨论】:

  • 有人使用 terraform 来维护他们的 IAM 用户吗?

标签: amazon-iam terraform


【解决方案1】:

感谢 Martin Atkins 在hashicorp-terraform Gitter room 的回答/建议:

这里讨论的问题是,当您将“count”与数组变量一起使用时,Terraform 并没有真正“看到”数组中的项目与资源之间的关系,所以当从中间删除一个值时列出该点之后的所有内容突然“减一”,Terraform 将想要全部替换它们。

这种用例将受益于 Terraform 中的一流迭代功能,但遗憾的是我们还没有 我建议不要尝试将用户列表作为变量传递,目前最可靠的方法是有一个单独的程序从某个地方读取用户列表并写出一个 .tf.json 文件,其中包含一个单独的 aws_iam_user 块每个用户。这样,Terraform 将了解哪个块属于哪个用户,因为本地标识符可以是用户名或某种用户 ID,从而可以维护相关性。

【讨论】:

  • 我知道这是一篇很老的帖子,但也许它对某人有用,使用 set 避免因一个问题而关闭
【解决方案2】:

Terraform 0.12.6 在资源上添加了 for_each,这对于解决所描述的问题非常有用。

假设我们编写了一个 terraform.tfvars,其中包含一些 IAM 用户名和组成员资格,如下所示:

user_names = {
  "test-user-1" = {
    path          = "/"
    force_destroy = true
    tag_email     = "nobody@example.com"
  }
  "test-user-2" = {
    path          = "/"
    force_destroy = true
    tag_email     = "nobody@example.com"
  }
}

group_memberships = {
  "test-user-1" = [ "SomeGroup", "AnotherGroup" ]
  "test-user-2" = [ "AndYetAnotherGroup" ]
}

然后我们可以使用 for_each 元参数来提取键和值,如下所示:

resource "aws_iam_user" "user" {
  for_each = "${var.user_names}"

  name          = each.key
  path          = each.value["path"]
  force_destroy = each.value["force_destroy"]

  tags = "${map("EmailAddress", each.value["tag_email"])}"
}

resource "aws_iam_user_group_membership" "group_membership" {
  for_each = "${var.group_memberships}"

  user   = each.key
  groups = each.value

  depends_on = [ "aws_iam_user.user" ]
}

请注意,map 变量中的每个项目都为 user_names 和 group_memberships,这些项目必须都是同一类型。我们不能混合使用地图和列表。这就是我将 group_memberships 与 user_names 分开的原因。如果不是这样,我们可以为每个用户定义另一个属性来指定组成员身份,但 Terraform 目前不支持。

如果您要以此制作一个模块,并希望输出一些关于每个用户的有用属性,您可以按如下方式完成:

output "user_ids" {
  value = {
    for user_name in aws_iam_user.user:
    user_name.name => user_name.unique_id
  }
}

output "user_arns" {
  value = {
    for user_name in aws_iam_user.user:
    user_name.name => user_name.arn
  }
}

生成的输出将是一个以用户名为键的映射。

user_arns = {
  "test-user-1" = "arn:aws:iam::123456789012:user/test-user-1"
  "test-user-2" = "arn:aws:iam::123456789012:user/test-user-2"
}

user_ids = {
  "test-user-1" = "AB2DEDN2O2NMLMNT4KI7G"
  "test-user-2" = "AB1DEFG2O2NNLJQ9YKH7J"
}

有了这个,我们可以添加、更新或删除用户和/或组成员资格,而不会影响 tfstate 中已知的 terraform 资源与代码中的配置之间的映射。这是因为每个资源的名称现在都包含用户名作为资源名称本身的一部分,并允许我们引用特定资源,而当使用“count =”时,我们有一个 count.index,但无法轻松映射特定用户访问特定资源。

【讨论】:

  • 人们正在寻找 Terraform v0.12.x 的准确答案,就是这个!另请注意,使用 v0.12.10,我可以在 user_names 映射内嵌套组成员列表。
  • @Kerr 你有例子吗?
  • @aalimovs 请参阅此要点以了解可用的 IAM 用户模块,包括组成员资格。 gist.github.com/kerr-bighealth/1e11b379f29e8aedc94826abd4a282cd
猜你喜欢
  • 2015-11-10
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 2021-05-21
  • 1970-01-01
  • 2017-07-07
  • 2021-10-05
  • 2019-11-28
相关资源
最近更新 更多