AWS Single Sign-On (AWS SSO) を Terraform で作成する

記事タイトルとURLをコピーする

はじめに

高橋 (ポインコ兄) です。
今回は Terrafoarm で AWS Single Sign-On (SSO) を作成してみます。

AWS SSO の基本的な部分については、以下ブログが参考になると思います。 blog.serverworks.co.jp

また、Terraform についてはこちらをどうぞ。 blog.serverworks.co.jp

今回使用する SSO についての Terraform AWS Document です。
以下の Resource と Data Source が使えます。

Resource: aws_ssoadmin_account_assignment https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_account_assignment

Resource: aws_ssoadmin_managed_policy_attachment https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_managed_policy_attachment

Resource: aws_ssoadmin_permission_set https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_permission_set

Resource: aws_ssoadmin_permission_set_inline_policy https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_permission_set_inline_policy

Data Source: aws_ssoadmin_instances https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssoadmin_instances

Data Source: aws_ssoadmin_permission_set https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssoadmin_permission_set

AWS SSO を有効にする

最初に AWS SSO を有効にする必要がありますが、残念ながら 2021/2/26 時点で Terraform は非対応です。 そのため、手動で有効にします (手順は先のブログを参考にしてください)。

ユーザー / グループを作成する

続いてユーザー / グループを作成しますが、こちらも Terraform で作成することはできません。 そのため、マネジメントコンソールで作成します。 f:id:swx-yusuke-takahashi:20220227054640p:plain

アクセス権限セットの作成

ここから Terraform で作成します。まずはアクセス権限セットの作成です。

data "aws_ssoadmin_instances" "example" {}
  
resource "aws_ssoadmin_permission_set" "PermissionSet" {
  for_each = toset([
    "TakahashiAdmin",
    "TakahashiRO",
    "TakahashiPoinco"
  ])
  name             = each.value
  description      = each.value
  instance_arn     = tolist(data.aws_ssoadmin_instances.example.arns)[0]
}

f:id:swx-yusuke-takahashi:20220227051502p:plain アクセス権限セットを for_each を使って 3つ 作成しました。 www.terraform.io

アクセス権限セットに管理ポリシーをアタッチ

作成したアクセス権限セット「TakahashiAdmin」に、管理ポリシー「AlexaForBusinessDeviceSetup」をアタッチしてみます。

resource "aws_ssoadmin_managed_policy_attachment" "example" {
  instance_arn       = aws_ssoadmin_permission_set.example["TakahashiAdmin"].instance_arn
  managed_policy_arn = "arn:aws:iam::aws:policy/AlexaForBusinessDeviceSetup"
  permission_set_arn = aws_ssoadmin_permission_set.example["TakahashiAdmin"].arn
}

f:id:swx-yusuke-takahashi:20220227051458p:plain アタッチされました。

アクセス権限セットのカスタムアクセス権限ポリシーを作成

管理ポリシーだけではなく、カスタムアクセス権限ポリシー (いわゆるインラインポリシー) を編集することもできます。

data "aws_iam_policy_document" "example" {
  statement {
    sid = "1"
    actions = [
      "s3:ListAllMyBuckets",
      "s3:GetBucketLocation",
    ]
    resources = [
      "arn:aws:s3:::*",
    ]
  }
}
  
resource "aws_ssoadmin_permission_set_inline_policy" "example" {
  inline_policy      = data.aws_iam_policy_document.example.json
  instance_arn       = aws_ssoadmin_permission_set.example["TakahashiAdmin"].instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.example["TakahashiAdmin"].arn
}

f:id:swx-yusuke-takahashi:20220227060608p:plain アクセス権限セット「TakahashiAdmin」に、S3 を List するカスタムアクセス権限ポリシーを作成できました。

AWS アカウント と ユーザー / グループ と アクセス権限セット の紐付け

特定の AWS アカウントと、グループ「TakahashiTestGroup」 - アクセス権限セット「TakahashiAdmin」を紐付けます。

resource "aws_ssoadmin_account_assignment" "example" {
  instance_arn       = aws_ssoadmin_permission_set.example["TakahashiAdmin"].instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.example["TakahashiAdmin"].arn
  
  principal_id   = data.aws_identitystore_group.Admin.group_id
  principal_type = "GROUP"
  
  target_id   = "xxxxxxxxxxxx"
  target_type = "AWS_ACCOUNT"
}

※ target_id の "xxxxxxxxxxxx" には実際の AWS アカウント ID が入ります

f:id:swx-yusuke-takahashi:20220227060025p:plain 紐付けられました。

AWS Organizations 管理の AWS アカウントの紐付け

AWS Organizations で管理されている AWS アカウントに対して紐付けをしたい場合は、以下のように書くことができます。

data "aws_organizations_organization" "example" {}
data "aws_identitystore_group" "RO" {
  identity_store_id = tolist(data.aws_ssoadmin_instances.example.identity_store_ids)[0]
  
  filter {
    attribute_path  = "DisplayName"
    attribute_value = "TakahashiTestGroupRO"
  }
}
  
resource "aws_ssoadmin_account_assignment" "example2" {
  for_each = toset(data.aws_organizations_organization.example.accounts[*].id)
  
  instance_arn       = aws_ssoadmin_permission_set.example["TakahashiRO"].instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.example["TakahashiRO"].arn
  
  principal_id   = data.aws_identitystore_group.RO.group_id
  principal_type = "GROUP"
  
  target_id   = each.value
  target_type = "AWS_ACCOUNT"
}

【※2022/03/11 追記】AWS アカウント と 「複数の」ユーザー / グループ と 「複数の」アクセス権限セット を一度に紐付ける

以下のようなコードで「複数の」ユーザー / グループ と 「複数の」アクセス権限セット を1つの AWS アカウントに紐付けることができます。
setproduct Function で、ユーザー / グループ と アクセス権限セットを組み合わていますが、戻り値が2次元の list となるためそのまま for_each のターゲットとして使うことができません。(ターゲットに使えるのは map と set式 (string) のみ)
そのため、for で list (map) に格納し、list (map) の各要素を key に変換して最終的に map にしています。

locals {
  pnames = [
    "TakahashiAdmin",
    "TakahashiRO",
    "TakahashiPoinco"
  ]
  gid = [
    data.aws_identitystore_group.Admin.group_id,
    data.aws_identitystore_group.RO.group_id
  ]
  assingment = [
    for tmp in setproduct(local.pnames, local.gid) : {
      pname = tmp[0]
      gid   = tmp[1]
    }
  ]
}
  
resource "aws_ssoadmin_account_assignment" "example" {
  for_each = {
    for tmp in local.assingment : "${tmp.pname} ${tmp.gid}" => tmp
  }
  
  instance_arn       = aws_ssoadmin_permission_set.example[each.value.pname].instance_arn
  permission_set_arn = aws_ssoadmin_permission_set.example[each.value.pname].arn
  
  principal_id   = each.value.gid
  principal_type = "GROUP"
  
  target_id   = each.value
  target_type = "AWS_ACCOUNT"
}

f:id:swx-yusuke-takahashi:20220310234243p:plain f:id:swx-yusuke-takahashi:20220310234247p:plain

あとがき

ユーザー / グループ、アクセス権限セットが多く、かつアカウントが頻繁に追加されるような環境では、Terraform を使って管理すると良いかもしれませんね。

暖かくなる前にせり鍋が食べたい兄でした。
それではまた、ごきげんよう。

高橋 悠佑 (ポインコ兄) (執筆記事一覧)

健康志向です