Assume Roleを使ったTerraform実行で、Assume Role元のユーザ情報をCloudTrailに記録する方法
はじめに
TerraformでAWSリソースを操作する時に設定するproviderですが、以下が基本となります。
provider "aws" {
region = "ap-northeast-1"
}
この設定は基本ではあるものの、ローカルの認証情報(IAMユーザなど)を使ってTerraformを実行することになるので、Terraform実行者の権限によっては、権限不足でTerraform実行が失敗する可能性があり、複数人で開発する場合、少し不便なことがあります。
これに対処する方法の一つが、Assume Roleを使ったTerraform実行です。
providerは以下のような設定になります。
provider "aws" {
region = "ap-northeast-1"
assume_role {
role_arn = "arn:aws:iam::${var.aws_account_id}:role/TerraformExecutionInfraRole"
}
この設定だと、assume_roleで指定したTerraform実行用のロールの認証情報を使ってTerraformを実行することになるので、Terraform実行者の権限によって、権限不足でTerraform実行が失敗することは無くなります。
※勿論、Terraform実行ロールにassume roleする為の権限は、ローカルの認証情報に必要
Terraformで操作できる範囲を一元管理することもできますし、readonly + assume roleの権限のみ付与して、コンソールからはWrite不可、TerraformからはWrite可のような運用も可能です。
Assume Roleを使ったTerraform実行は、AWSのTerraformベストプラクティスでも推奨されています。
ただ、これには一点問題があります。
Assume Roleに詳しい方ならお気づきかと思いますが、誰がTerraformを実行しても、AWSを操作するのはTerraform実行用のロールなので、CloudTrailのイベント上、誰がTerraformを介してリソースを操作したのかが分からなくなってしまい、監査上少々問題があります。
この問題に対処する方法を本記事では紹介します。
設定方法
まず、assume_roleを指定するproviderとは別に、assume_roleを指定しないprovider(ローカルの認証情報を使用するprovider)を設定します
provider "aws" {
alias = "not_assume_role"
region = "ap-northeast-1"
}
assume_roleを指定するproviderをデフォルトとしたいので、適当なaliasを設定します。
このproviderを使用して、dataリソースである、aws_caller_identityを定義します。
data "aws_caller_identity" "not_assume_role" {
provider = aws.not_assume_role
}
このdataリソースは、ローカルの認証情報を使用して呼ばれるので、stateにもローカルの認証情報が保存されます。
terraform console
> data.aws_caller_identity.not_assume_role
{
"account_id" = "XXXXXXXXXXXX"
"arn" = "arn:aws:sts::XXXXXXXXXXXX:assumed-role/XXXXXXXXXXXX"
"id" = "XXXXXXXXXXXX"
"user_id" = "XXXXXXXXXXXXXXXXXXXXX:falcon@hoge.co.jp"
}
このdataリソースの中で、ユーザを一意に特定できる属性をassume_roleを指定するproviderのsession_nameに設定します。
今回の例だと、user_idが使えそうなので、以下のように設定します(:
はsession_nameに設定できないので_
に置き換え)。
provider "aws" {
region = "ap-northeast-1"
assume_role {
role_arn = "arn:aws:iam::${var.aws_account_id}:role/TerraformExecutionInfraRole"
session_name = replace(data.aws_caller_identity.not_assume_role.user_id, ":", "_")
}
}
これで、Assume Roleを使ったTerraform実行でも、CloudTrailのイベント上にユーザを一意に特定できる情報が記録され、誰がTerraformを介してリソースを操作したのかの特定が可能になります。
モザイクまみれで分かり辛いですが、principalIdとarnに付与されるサフィックスがaws-go-sdk-xxx
からsession_nameに設定した文字列に変更されています。
Discussion