この記事について
前回の記事では、Terraform で AWS Organizations の OU / アカウント / SCP を最小構成で一括構築し、今後のガバナンス基盤となる下地を整えました。
今回はその続編として、AWS IAM Identity Center(旧 AWS SSO)を Terraform で有効化し、権限セットの作成とアカウント割り当てまでを自動化します。
Organizations の状態ファイルを参照しつつ、SSO ユーザー・Permission Set をコードで管理することを目指します。
アーキテクチャ
ゴール(スクショ)
手順の流れ(ざっくり)
-
Organizations 側で Service Access を有効化
第一弾でsso.amazonaws.com
を Service Access に含めている前提です。 -
手動で Identity Center インスタンスを作成
AWS マネジメントコンソールの IAM Identity Center 画面で「今すぐ始める」をクリック。 -
Identity Center ユーザーを作成(任意)
aws_identitystore_user
を作成し、(Organization/SSO/ssouser)ユーザー ID を取得。 -
Permission Set を定義
例:AdministratorAccess
を 8 時間セッションで作成し、AWS 管理ポリシーをアタッチ。 -
アカウント割り当て
Organizations の remote state から取得したアカウント ID に対し、作成した Permission Set をユーザーへ割り当て。 -
Terraform 実行
terraform init && terraform apply
-
AWS CLI で SSO ログイン確認
aws sso login --profile <profile-name>
ディレクトリ構成
Organization/
├─ main.tf … Organizations 基盤(第一弾で構築済み)
└─ SSO/
├─ main.tf # Permission Set とアカウント割り当て
├─ variable.tf # 共通変数・remote state 設定
├─ provider.tf # AWS Provider 設定
├─ backend.tf # S3 バックエンド定義
├─ terraform.tfvars # サンプル変数ファイル
└─ ssouser/ # Identity Center ユーザー作成用モジュール
├─ main.tf
└─ terraform.tfvars
各種設定値
-
Permission Set
- 名称:
AdministratorAccess
- セッション有効期限: 8 時間
- 付与ポリシー:
arn:aws:iam::aws:policy/AdministratorAccess
- 名称:
-
Organizations の状態ファイル参照
org_state_bucket
org_state_key
org_state_region
-
ユーザー ID
-
user_id
を変数で受け取り、Permission Set の割り当てに利用
-
-
サンプル tfvars
- 環境名・アプリ名・リージョン・共通タグを定義
Terraform 実装例
Organization/SSO
main.tf
data "terraform_remote_state" "org" {
backend = "s3"
config = {
bucket = var.org_state_bucket
key = var.org_state_key
region = var.org_state_region
}
}
data "aws_ssoadmin_instances" "main" {}
locals {
account_ids = merge(
data.terraform_remote_state.org.outputs.member_account_ids,
{ security = data.terraform_remote_state.org.outputs.security_account_id }
)
}
# SSOユーザにはAdministratorAccessを固定で与える(実務では必ず最小権限)
# セッション有効期限は 8時間
resource "aws_ssoadmin_permission_set" "admin" {
name = "AdministratorAccess"
instance_arn = data.aws_ssoadmin_instances.main.arns[0]
session_duration = "PT8H"
}
# ポリシーをアタッチ
resource "aws_ssoadmin_managed_policy_attachment" "admin_attach" {
instance_arn = data.aws_ssoadmin_instances.main.arns[0]
managed_policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
permission_set_arn = aws_ssoadmin_permission_set.admin.arn
}
# アカウントにアタッチ
resource "aws_ssoadmin_account_assignment" "admin_assign" {
for_each = var.assigned_accounts
instance_arn = data.aws_ssoadmin_instances.main.arns[0]
permission_set_arn = aws_ssoadmin_permission_set.admin.arn
principal_type = "USER"
principal_id = var.user_id
target_type = "AWS_ACCOUNT"
target_id = local.account_ids[each.key]
}
variable.tf
# metadata
variable "env" {
type = string
validation {
condition = can(regex("^(dev|stg|prod|sandbox)$", var.env))
error_message = "env は dev|stg|prod|sandbox のいずれか。"
}
}
variable "app_name" {
type = string
validation {
condition = can(regex("^[A-Za-z0-9_-]{3,32}$", var.app_name))
error_message = "app_name は 3–32 文字の英数/ハイフン/アンダースコア。"
}
}
variable "region" {
type = string
validation {
condition = can(regex("^[a-z]{2}-[a-z]+-\\d$", var.region))
error_message = "region の形式が不正。例: ap-northeast-1"
}
}
variable "tags" {
description = "共通タグ(provider.default_tags とモジュールに渡す tags の両方で利用)"
type = map(string)
default = {}
}
# SSO
variable "org_state_bucket" {
description = "Organizationのtfstateが保存されているバケット名"
type = string
}
variable "org_state_key" {
description = "Organizationのtfstateが保存されているバケットのキー"
type = string
}
variable "org_state_region" {
description = "Organizationのtfstateが保存されているリージョン"
type = string
}
variable "user_id" {
description = "Identity Center ユーザーID"
type = string
}
variable "assigned_accounts" {
type = set(string)
description = "管理権限セットを付与する論理アカウント名(例: dev, network, security)"
}
terraform.tfvars
# terraform.tfvars
# 環境(dev | stg | prod | sandbox)
env = "prod"
# アプリケーション名(3–32 文字、英数/ハイフン/アンダースコア)
app_name = "hogehoge"
# AWS リージョン(例: ap-northeast-1)
region = "ap-northeast-1"
# 共通タグ
tags = {
Project = "hogehoge"
}
# Organization の tfstate 情報
org_state_bucket = "aws-remotebackend-bootstrap-tfstate-ap-northeast-1-111111111111" # マスク済み
org_state_key = "state/organization/terraform.tfstate"
org_state_region = "ap-northeast-1"
# Identity Center ユーザーID(UUIDはマスク済み)
user_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# 割り当て先アカウント(SSO使用アカウントを列挙)
assigned_accounts = ["dev", "network", "security"]
Organization/SSO/ssouser
main.tf
terraform {
required_version = ">= 1.9.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.9"
}
}
}
provider "aws" {
region = var.region
}
data "aws_ssoadmin_instances" "this" {}
variable "region" {
description = "Identity Centerを有効化しているリージョン"
type = string
default = "ap-northeast-1"
}
variable "user" {
description = "作成するIdentity Centerユーザー属性"
type = object({
user_name = string # 一意なユーザー名(例: taro.portfolio)
given_name = string # 名
family_name = string # 姓
display_name = string # 表示名
email = string # メールアドレス(招待/通知に使用)
phone = optional(string) # 省略可
})
default = {
user_name = "taro.portfolio"
given_name = "Taro"
family_name = "Yamada"
display_name = "Taro Yamada"
email = "taro@example.com"
# phone = "+81-90-1234-5678"
}
}
resource "aws_identitystore_user" "this" {
identity_store_id = data.aws_ssoadmin_instances.this.identity_store_ids[0]
user_name = var.user.user_name
display_name = var.user.display_name
name {
given_name = var.user.given_name
family_name = var.user.family_name
}
emails {
value = var.user.email
primary = true
}
# phoneを指定したときだけ作成
dynamic "phone_numbers" {
for_each = try(var.user.phone, null) != null ? [var.user.phone] : []
content {
value = phone_numbers.value
type = "mobile"
}
}
}
output "identity_store_id" {
value = data.aws_ssoadmin_instances.this.identity_store_ids[0]
}
output "user_id" {
value = aws_identitystore_user.this.user_id
}
terraform.tfvars
region = "ap-northeast-1"
user = {
user_name = "example-user"
given_name = "Taro"
family_name = "Yamada"
display_name = "Taro Yamada"
email = "example-user@example.com"
}
構築後の Terraform profile 設定
~/.aws/config
に SSO プロファイルを設定します。
[default]
region = ap-northeast-1
output = json
[profile admin]
sso_session = hogehoge
sso_account_id = 111111111111 # 管理アカウントID
sso_role_name = AdministratorAccess
region = ap-northeast-1
output = json
[profile security]
sso_session = hogehoge
sso_account_id = 222222222222 # セキュリティアカウントID
sso_role_name = AdministratorAccess
region = ap-northeast-1
output = json
[sso-session hogehoge]
sso_start_url = https://d-xxxxxxxxxx.awsapps.com/start
sso_region = ap-northeast-1
sso_registration_scopes = sso:account:access
ログイン確認:
aws sso login --profile dev-admin
Terraform 実行時:
AWS_PROFILE=dev-admin terraform plan
運用上の注意
-
最小権限の徹底
サンプルではAdministratorAccess
を付与していますが、実運用では必要な権限だけを付与する Permission Set を作成してください。 -
Identity Center はリージョン単位
SSO を有効化したリージョン以外では利用できません。 -
ユーザー管理
aws_identitystore_user
でメールや電話番号をコード化できますが、ID 連携(SAML/SCIM)する場合は外部 IdP 側の設定が必要です。 -
State 管理
Organizations の状態ファイルを参照するため、var.org_state_bucket
var.org_state_key
var.org_state_region
の値は正確に設定してください