AWS においてはマルチアカウント戦略が重要とされています。
たとえば、開発環境/ステージング環境/本番環境といった各環境は、セキュリティ、ガバナンス面で分離すべきです。
- メンバーの権限管理がすっきりする
- 特定の環境の作業が他環境に影響しない
このようなマルチアカウント管理を実現するためのベストプラクティスとして、AWS Organizations の利用が挙げられます。 AWS Organizations は複数の AWS アカウントを統合できるサービスで、アカウントを作成できるだけでなく、それらの階層化や一括したポリシー管理も可能です。
今日はこれを試してみました。
AWS Control Tower のマルチアカウント構成
AWS Organizations を有効にしたアカウントは「マスタアカウント」の扱いとなり、メンバーアカウントを API で作成できます。 このメンバーアカウントは OU (組織単位: Organization Unit) と呼ばれるグループにぶらさげることができます。また、OU は階層化が可能です。 さらに OU には SCP (Service Control Policy) を設定でき、それにより OU に所属する全アカウントをポリシー制御できます。
このようなマルチアカウント戦略のベストプラクティスを詰め込んだのが AWS Control Tower です。 この Control Tower を例に取ると、以下のような構成になります。
- コア OU
- ログアーカイブアカウント
- 監査メンバーアカウント
- カスタム OU
- 自由に使う OU。ステージング環境用アカウントや本番環境用アカウントなど
ログアーカイブや監査メンバーアカウントは共通アカウントと呼ばれ、各アカウントのログや監査情報を一元管理します。 このようにアカウントごと分離することで、全体状況を把握するとともに、削除不能、改ざん不能な形での管理が可能というわけです。
もっとも Control Tower は現時点で日本の region では使うことができません。 そういうわけで、今日はまずこれに似たマルチアカウント構成を terraform で作ってみます。
terraform
terraform の設定は、アカウントを作るだけなら全く難しくありません。 以下のようにすることであっという間に、ログアーカイブ、監査メンバー、そして開発環境用の AWS アカウントが作成できます。
terraform { required_version = "~> 0.12.24" required_providers { aws = "~> 2.60.0" } backend "s3" { bucket = "kiririmode-terraform-state" key = "terraform/organizations.tfstate" region = "ap-northeast-1" dynamodb_table = "terraform_state_lock" } } provider "aws" { region = "ap-northeast-1" } resource "aws_organizations_organization" "org" { aws_service_access_principals = [ "cloudtrail.amazonaws.com", "config.amazonaws.com", "ssm.amazonaws.com", ] enabled_policy_types = [ "SERVICE_CONTROL_POLICY", "TAG_POLICY", ] feature_set = "ALL" } resource "aws_organizations_organizational_unit" "core" { name = "core" parent_id = aws_organizations_organization.org.roots[0].id } resource "aws_organizations_organizational_unit" "custom" { name = "custom" parent_id = aws_organizations_organization.org.roots[0].id } resource "aws_organizations_account" "audit" { name = "audit" email = "hoge@exampmle.com" parent_id = aws_organizations_organizational_unit.core.id } resource "aws_organizations_account" "log" { name = "log" email = "fuga@example.com" parent_id = aws_organizations_organizational_unit.core.id } resource "aws_organizations_account" "dev" { name = "dev" email = "piyo@example.com" parent_id = aws_organizations_organizational_unit.custom.id }
作成した AWS アカウントのルートアカウントでログインを試みる際にわかるのですが、パスワードが設定されていません。 このため、パスワード初期化 (パスワードを忘れた場合のフロー) でパスワードを設定する必要があります。面白いですね。
また、作成された AWS アカウントを AWS Organizations の管理下から外そうとすると怒られます。 作成後、ある程度の時間をあける必要がありそうです。