使用Terraform在实践中管理AWS IAM Identity Center(AWS Single Sign-On)的用户管理策略

首先

我打算使用AWS IAM身份中心(AWS单点登录)来考虑用户管理,并使用Terraform实现配置管理。

请参考我在GitHub上上传的代码。
(注:*.tfstate文件已经被添加到.gitignore中,不受git管理。)

 

建造图

スクリーンショット 2023-06-16 17.10.49.png

考虑到可以在无服务器环境下管理State文件,我们选择使用Terraform Cloud进行基础架构管理。

 

另外,在这个问题中我们没有考虑到包括多个环境部署和CI/CD设计等方面。

实施

Terraform Cloud和Github的连接

请参考此处以进行VSC连接。

 

启用AWS SSO/创建用户组。

很抱歉,目前的 Terraform 代碼設定尚不支援啟用 AWS SSO。因此,您需要從控制台選擇要啟用的地區,並手動進行啟用作業。

接下来,在AWS IAM身份中心创建用户/组,但是这也不能通过Terraform创建。因此,将在管理控制台中进行创建。

此外,您也可以在这里将希望加入群组的用户进行添加。

スクリーンショット 2023-06-21 12.13.29.png
スクリーンショット 2023-06-21 12.13.37.png

政策

本次我们准备了管理员、开发人员、访客和系统四个组,并预先确定了分配给每个组的策略。

管理员:SRE团队用户所属的组。授予AdministratorAccess权限。
开发者:除SRE团队之外的开发者组。授予对开发工作所需最低限度的访问权限。
访客:除开发团队之外的组。主要是只读访问权限。
系统:整合用于系统相关的IAM策略。

设定将Admin组附加Admin的权限集。

部署

已经实施的有以下项目。

由于使用Terraform资源的差异,我分别定义了管理策略和客户管理策略中要使用的变量。

########################################
# Terraformできないこと
# 下記に示すものはTerraformではできないので、手動でコンソール上(IAM Identity Center)から設定する必要がある

# 1. グループの作成・削除
# 2. ユーザーの追加・削除
# 3. グループにユーザーを追加・削除
########################################

data "aws_ssoadmin_instances" "example" {}

locals {
  groups = var.aws_sso_group
  policies = {
    Admin = {
      managed  = var.aws_sso_admin_managed_policies
      customer = var.aws_sso_admin_customer_policies
    }
    Guest = {
      managed  = var.aws_sso_guest_managed_policies
      customer = var.aws_sso_guest_customer_policies
    }
    Developer = {
      managed  = var.aws_sso_developer_managed_policies
      customer = var.aws_sso_developer_customer_policies
    }
    System = {
      managed  = var.aws_sso_system_managed_policies
      customer = var.aws_sso_system_customer_policies
    }
  }
  managed_policy_attachments = flatten([
    for group, policies in local.policies : [
      for policy in policies.managed : {
        group  = group
        policy = policy
      }
    ]
  ])
  customer_policy_attachments = flatten([
    for group, policies in local.policies : [
      for policy in policies.customer : {
        group  = group
        policy = policy
      }
    ]
  ])
}

########################################
# IAM Identity Center グループを取得
########################################
data "aws_identitystore_group" "group" {
  for_each = toset(local.groups)

  identity_store_id = tolist(data.aws_ssoadmin_instances.example.identity_store_ids)[0]

  alternate_identifier {
    unique_attribute {
      attribute_path  = "DisplayName"
      attribute_value = each.value
    }
  }
}
########################################
# アクセス許可セット作成
########################################
resource "aws_ssoadmin_permission_set" "PermissionSet" {
  for_each = toset(local.groups)

  name         = each.value
  description  = each.value
  instance_arn = tolist(data.aws_ssoadmin_instances.example.arns)[0]
}
locals {
  groups_to_permission_set = var.groups_to_permission_set
  assignment = [
    for tmp in setproduct(local.groups, values(data.aws_identitystore_group.group)) : {
      group_name          = tmp[0]
      group_id            = tmp[1].group_id
      permission_set_name = local.groups_to_permission_set[tmp[0]]
    }
  ]
}
########################################
# アクセス許可セットにポリシーをアタッチ
########################################
resource "aws_ssoadmin_managed_policy_attachment" "managed_policy_attachment" {
  for_each = { for item in local.managed_policy_attachments : "${item.group}.${item.policy}" => item }

  instance_arn       = aws_ssoadmin_permission_set.PermissionSet[each.value.group].instance_arn
  managed_policy_arn = each.value.policy
  permission_set_arn = aws_ssoadmin_permission_set.PermissionSet[each.value.group].arn
}

resource "aws_ssoadmin_customer_managed_policy_attachment" "customer_policy_attachment" {
  for_each = { for item in local.customer_policy_attachments : "${item.group}.${item.policy}" => item }

  instance_arn       = aws_ssoadmin_permission_set.PermissionSet[each.value.group].instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.PermissionSet[each.value.group].arn
  customer_managed_policy_reference {
    name = split("/", each.value.policy)[1]
    path = "/"
  }
}
########################################
# IAM Identity Center グループにアクセス許可セットを関連付け
########################################
resource "aws_ssoadmin_account_assignment" "example" {
  for_each = data.aws_identitystore_group.group

  instance_arn       = aws_ssoadmin_permission_set.PermissionSet[each.key].instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.PermissionSet[each.key].arn

  principal_id   = each.value.group_id
  principal_type = "GROUP"

  target_id   = var.account_id
  target_type = "AWS_ACCOUNT"
}

# variables.tfはvariable(変数)の宣言を行うところです。
variable "region" {
  description = "AWS region"
  default     = "ap-northeast-1"
}
# terraform cloudから取得
variable "AWS_ACCESS_KEY_ID" {}
variable "AWS_SECRET_ACCESS_KEY" {}

variable "account_id" {
  description = "The ID of the AWS account"
  type        = string
  # 12桁のアカウントID
  default     = "xxxxxxxxxxxx"
}


########################################
# IAM Identity Centerのグループ・許可セットを定義
# グループには同名の許可セットを関連付ける
########################################
variable "aws_sso_group" {
  description = "The list of identity store group"
  type        = list(string)
  default     = ["Admin", "Guest", "Developer", "System"]
  // Add more if needed
}

variable "groups_to_permission_set" {
  type = map(any)
  default = {
    Admin     = "Admin"
    Guest     = "Guest"
    Developer = "Developer"
    System    = "System"
    // Add more if needed
  }
}
########################################
# グループごとに使用するポリシーのarnを指定
# managedポリシーとカスタマー管理ポリシーでは作成するresourceが異なるので、それぞれvariableを用意
########################################
## Admin
variable "aws_sso_admin_managed_policies" {
  description = "The list of admin managed policies"
  type        = list(string)
  default = [
    "arn:aws:iam::aws:policy/AdministratorAccess"
  ]
}
variable "aws_sso_admin_customer_policies" {
  description = "The list of admin customer policies"
  type        = list(string)
  default     = []
}
## Guest
variable "aws_sso_guest_managed_policies" {
  description = "The list of guest managed policies"
  type        = list(string)
  default = []
}
variable "aws_sso_guest_customer_policies" {
  description = "The list of guest customer policies"
  type        = list(string)
  default = []
}
## Developer
variable "aws_sso_developer_managed_policies" {
  description = "The list of developer managed policies"
  type        = list(string)
  default = []
}
variable "aws_sso_developer_customer_policies" {
  description = "The list of developer customer policies"
  type        = list(string)
  default = []
}
## System
variable "aws_sso_system_managed_policies" {
  description = "The list of system managed policies"
  type        = list(string)
  default = []
}

variable "aws_sso_system_customer_policies" {
  description = "The list of system customer policies"
  type        = list(string)
  default = []
}

如果执行git push,将会触发对主分支的合并,并执行terraform plan和terraform apply。

在进行 git push 之前,最好通过使用 terraform fmt 进行格式整理(或将其集成到 CI/CD 中)。

最后

通过这次的实施,我想分享我所得到的洞察和学习。

    • Terraform Cloudを使用するとstateファイルの管理がすごく楽

 

    • Terraformで対応していないリソースのIaCをどのように管理・運用していくかチームで共通認識を作る必要がある

 

    • どこまでをvariable, localといった変数として扱うかの判断が難しい

 

    Terraformは楽しい?

请提供你需要改写的英文句子,我将为您提供中文的同义句。

【土改】

 

【Terraform Cloud】土壤云

 

【AWS SSO】亚马逊单一登录

 

广告
将在 10 秒后关闭
bannerAds