この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
上記エントリを書いた際(2020/10/29時点)には、TerraformでAWS SSO(Single Sign-On)のリソースをプロビジョニングすることはできませんでした。が、その後terraform-provider-awsのv3.23.0、v3.24.0で一部リソースのプロビジョニングができるようになりましたので、使ってみたいと思います。
追加された Resource / Data Source
Resource
- aws_ssoadmin_account_assignment
- aws_ssoadmin_managed_policy_attachment
- aws_ssoadmin_permission_set
- aws_ssoadmin_permission_set_inline_policy
Data Source
概要
AWS SSOの設定としてはざっくりとは以下があります。(SSOのIDストアを使う場合です。外部のIDシステムを使う場合「ユーザー・グループを作る」あたりが変わるはずです。)
- SSOの有効化
- ユーザー・グループを作る
- アクセス権限セット(Permission Set)作成
- アクセス権限セット(Permission Set)にポリシーをアタッチ
- ユーザー・グループ & アカウント & アクセス権限セット紐付け(Assignment)
このうち、今回Terraformでプロビジョニングできるようになったのは下の3つの部分です。
上2つはプロビジョニングはできませんが、Data Sourceを使って参照することができます。
やってみた
前提条件
- Organization下に3アカウント作成
- SSO有効化
- SSOのユーザー・グループ作成
まで行なった状態で、以降の設定をTerraformでやってみます。
それぞれ対応するグループも作成して、ユーザーを配下に所属させています。
Terraformでやることの詳細は以下です。
- アクセス権限セット(Permission Set)を3つ作成する
- 上記アクセス権限セット(Permission Set)に適切なポリシーをアタッチする
- 各グループと各アカウントとアクセス権限セット(Permission Set)を紐付ける(Assignment) = 2グループ x 3アカウントで6個のAssignmentが必要
- アクセス権限セット(Permission Set)にインラインポリシーを追加する
このあたりのSSOの概念がわからない方は、先に以下エントリをお読みいただければ幸いです。
ではやっていきましょう。
アクセス権限セット作成
data "aws_ssoadmin_instances" "main" {}
resource "aws_ssoadmin_permission_set" "main" {
for_each = toset([
"AdministratorAccess",
"ReadOnlyAccess"
])
name = each.value
instance_arn = tolist(data.aws_ssoadmin_instances.main.arns)[0]
}
data.aws_ssoadmin_instances
のarns
はset型なので上記のようにtolist(data.aws_ssoadmin_instances.main.arns)[0]
とする必要がある点に注意です。
アクセス権限セット(Permission Set)が作成されました。
アクセス権限セット(Permission Set)にポリシーをアタッチ
resource "aws_ssoadmin_managed_policy_attachment" "main" {
for_each = aws_ssoadmin_permission_set.main
instance_arn = tolist(data.aws_ssoadmin_instances.main.arns)[0]
managed_policy_arn = "arn:aws:iam::aws:policy/${each.key}"
permission_set_arn = each.value.arn
}
ユーザー・グループ & アカウント & アクセス権限セット紐付け(Assignment)
data "aws_organizations_organization" "main" {}
data "aws_identitystore_group" "admin" {
identity_store_id = tolist(data.aws_ssoadmin_instances.main.identity_store_ids)[0]
filter {
attribute_path = "DisplayName"
attribute_value = "admin"
}
}
resource "aws_ssoadmin_account_assignment" "admin" {
for_each = toset(data.aws_organizations_organization.main.accounts[*].id)
instance_arn = tolist(data.aws_ssoadmin_instances.main.arns)[0]
permission_set_arn = aws_ssoadmin_permission_set.main["AdministratorAccess"].arn
principal_id = data.aws_identitystore_group.admin.group_id
principal_type = "GROUP"
target_id = each.value
target_type = "AWS_ACCOUNT"
}
data "aws_identitystore_group" "readonly" {
identity_store_id = tolist(data.aws_ssoadmin_instances.main.identity_store_ids)[0]
filter {
attribute_path = "DisplayName"
attribute_value = "readonly"
}
}
resource "aws_ssoadmin_account_assignment" "readonly" {
for_each = toset(data.aws_organizations_organization.main.accounts[*].id)
instance_arn = tolist(data.aws_ssoadmin_instances.main.arns)[0]
permission_set_arn = aws_ssoadmin_permission_set.main["ReadOnlyAccess"].arn
principal_id = data.aws_identitystore_group.readonly.group_id
principal_type = "GROUP"
target_id = each.value
target_type = "AWS_ACCOUNT"
}
aws_ssoadmin_account_assignment.target_id
にaws_organizations_organization
Data Sourceのaccounts[*].id
を使うことで、Organizations配下のアカウントをすべて対象にしています。
各アカウントにて、admin・readonlyグループがそれぞれ適切な権限をもってアサインされました。
インラインポリシーも使ってみる
上記のアクセス権限セット(Permission Set)にアタッチしたポリシーはAWS管理ポリシーでしたが、インラインポリシーも併せてアタッチすることができます。 特定の送信元IP以外からの操作はすべて拒否するインラインポリシーをアタッチしてみましょう。
data "aws_iam_policy_document" "deny_ip" {
statement {
effect = "Deny"
actions = ["*"]
resources = ["*"]
condition {
test = "NotIpAddress"
variable = "aws:SourceIp"
values = ["xxx.xxx.xxx.xxx/32"]
}
}
}
resource "aws_ssoadmin_permission_set_inline_policy" "main" {
for_each = aws_ssoadmin_permission_set.main
instance_arn = tolist(data.aws_ssoadmin_instances.main.arns)[0]
inline_policy = data.aws_iam_policy_document.deny_ip.json
permission_set_arn = each.value.arn
}
admin userでログインしてみます。