API を使って AWS Control Towerのランディングゾーンを設定してみた #AWSreInvent

2023.12.05

こんにちは。たかやまです。

先日AWS Control TowerのランディングゾーンをAPIで設定できるようになりました。

リリース時はドキュメント、API周りが整っていなかったため実際に構築まで行えなかったので今回そちらを試してみたいと思います。

やってみる

AWS CLI

AWS CLI 2.13.89 からControl Towerのランディングゾーンの設定をできるようになっています。

Bump version to 2.13.39 · aws/aws-cli@592065a

ランディングゾーン作成

ランディングゾーンを作成するにはcreate-landing-zoneのコマンドを実行します。
ただオプションの--manifestに指定するドキュメントがCfCTのものを参照しており、ランディングゾーンについてドキュメントからはなにを定義するのかわかりませんでした。

aws controltower create-landing-zone \
--landing-zone-version 3.2 \
--manifest file://LandingZoneManifest.json

--manifest (document)
The manifest.yaml file is a text file that describes your Amazon Web Services resources. For examples, review The manifest file .

create-landing-zone

こちらの実行手順のドキュメントにはサンプルとなるManifestがあったので、こちらをベースにテンプレートを作成してみたいと思います。

サンプルのManifestをベースに以下のManifestファイルを定義してみました。

LandingZoneManifest.json

{
  "accessManagement": {
    "enabled": false 
  },
  "securityRoles": {
    "accountId": "xxxxxxxxxxxx"
  },
  "governedRegions": ["ap-northeast-1"],
  "organizationStructure": {
    "sandbox": {
      "name": "Sandbox"
    },
    "security": {
      "name": "Security"
    }
  },
  "centralizedLogging": {
    "accountId": "xxxxxxxxxxxx",
    "configurations": {
      "accessLoggingBucket": {
        "retentionDays": 3650
      },
      "loggingBucket": {
        "retentionDays": 365
      },
      "enabled": true
    }
  }
}

ドキュメント側でマニフェストファイルの説明がないので、現時点で確認できる限り補足して項目の説明を記載しておきます。

  • accessManagement : IAM Identity Centerの有効/無効
  • securityRoles : SecurityアカウントのID
  • governedRegions : ガバナンス対象とするリージョン
  • organizationStructure
    • sandbox : Sandbox OUの名前
    • security : Security OUの名前
  • centralizedLogging
    • accountId : ログ集約先のアカウントID
    • configurations
    • loggingBucket : ログ用S3バケットの保持期間
    • accessLoggingBucket : アクセスログ用S3バケットの保持期間
    • kmsKeyArn : KMS暗号化に使用するKMSキーのARN (今回の検証では未指定)
    • enabled : CloudTrailログ集約の有効/無効

作成したManifestファイル指定して改めてランディングゾーンの作成するコマンドを実行した結果がこちらです。

> aws controltower create-landing-zone \
--landing-zone-version 3.2 \
--manifest file://LandingZoneManifest.json
{
    "arn": "arn:aws:controltower:ap-northeast-1:xxxxxxxxxxxx:landingzone/12LRS57CE8T82CX7",
    "operationIdentifier": "66e7b550-c503-4b3f-976a-4d41e39b544e"
}

無事ランディングゾーンが作成されました!

作成されたランディングゾーンを見てみると、ドキュメント通りリージョン拒否設定が有効されていないことがわかります。
リージョン拒否設定が必要な場合はコンソールから追加設定を実施してください。

Note
AWS Control Tower does not support the Region deny control when using APIs to configure and launch a landing zone. After successfully launching your landing zone using APIs, you can use the AWS Control Tower console to Configure the Region deny control.

Step 2: Launch your landing zone - AWS Control Tower

ランディングゾーン確認

ランディングゾーン情報を確認するにはlist-landing-zonesでARNを取得して、get-landing-zoneで詳細を確認します。

ランディングゾーンの一覧を取得するには以下のコマンドを実行します。

aws controltower list-landing-zones

実行例

> aws controltower list-landing-zones
{
    "landingZones": [
        {
            "arn": "arn:aws:controltower:ap-northeast-1:xxxxxxxxxxxx:landingzone/12LRS57CE8T82CX7"
        }
    ]
}

list-landing-zonesで取得したARNをget-landing-zoneのオプション--landing-zone-identifierに定義して、ランディングゾーンの詳細を取得します。

aws controltower get-landing-zone \
--landing-zone-identifier <LandingZone ARN>

実行例

aws controltower get-landing-zone \
--landing-zone-identifie arn:aws:controltower:ap-northeast-1:xxxxxxxxxxxx:landingzone/12LRS57CE8T82CX7
{
    "landingZone": {
        "arn": "arn:aws:controltower:ap-northeast-1:xxxxxxxxxxxx:landingzone/12LRS57CE8T82CX7",
        "driftStatus": {
            "status": "IN_SYNC"
        },
        "latestAvailableVersion": "3.2",
        "manifest": {
            "accessManagement": {
                "enabled": false
            },
            "securityRoles": {
                "accountId": "xxxxxxxxxxxx"
            },
            "governedRegions": [
                "ap-northeast-1"
            ],
            "organizationStructure": {
                "sandbox": {
                    "name": "Sandbox"
                },
                "security": {
                    "name": "Security"
                }
            },
            "centralizedLogging": {
                "accountId": "xxxxxxxxxxxx",
                "configurations": {
                    "loggingBucket": {
                        "retentionDays": 365
                    },
                    "accessLoggingBucket": {
                        "retentionDays": 3650
                    }
                },
                "enabled": true
            }
        },
        "status": "ACTIVE",
        "version": "3.2"
    }
}

ランディングゾーン削除

ランディングゾーンの削除するには以下のコマンドを実行します。

aws controltower delete-landing-zone \
--landing-zone-identifier <LandingZone ARN>
実行例(クリックで展開)
aws controltower delete-landing-zone \
--landing-zone-identifier arn:aws:controltower:ap-northeast-1:xxxxxxxxxxxx:landingzone/12LRS57CE8T82CX7
{
    "operationIdentifier": "39bf91fb-2186-4b92-8b0a-9855e07b25ae"
}

CloudFormation

ランディングゾーン作成

次にCloudFormationでランディングゾーンを作成してみます。

CloudFormation(CFn)のドキュメントはこちらです。
ただこちらのドキュメントも見ていただくと分かる通り、CLI同様にCFnで定義するManifestの詳細がわかりません。。

一応、別のドキュメントにサンプルテンプレートがありますが、こちらのテンプレートをデプロイするとInternal Error Occurredとなってしまいます。

エラー原因として、おそらくManifestのキーがパスカルケースで定義されていることが問題になっていると思われます。
(サンプルはJsonで定義されていますがYamlに変換しています)

ControlTower.yaml

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  Version:
    Type: String
    Default: "1.0.0"
    Description: The version number of Landing Zone
  GovernedRegions:
    Type: CommaDelimitedList
    Description: List of governed regions
  SecurityOuName:
    Type: String
    Description: The security Organizational Unit name
  SandboxOuName:
    Type: String
    Description: The sandbox Organizational Unit name
  CentralizedLoggingAccountId:
    Type: String
    Description: The AWS account ID for centralized logging
  SecurityAccountId:
    Type: String
    Description: The AWS account ID for security roles
  LoggingBucketRetentionPeriod:
    Type: Number
    Description: Retention period for centralized logging bucket
  AccessLoggingBucketRetentionPeriod:
    Type: Number
    Description: Retention period for access logging bucket

Resources:
  MyLandingZone:
    Type: AWS::ControlTower::LandingZone
    Properties:
      Version: !Ref Version
      Tags:
        - Key: "k1"
          Value: "v1b"
        - Key: "k3"
          Value: "v3"
      Manifest:
        GovernedRegions:
          Ref: GovernedRegions
        OrganizationStructure:
          Security:
            Name:
              Ref: SecurityOuName
          Sandbox:
            Name:
              Ref: SandboxOuName
        CentralizedLogging:
          AccountId:
            Ref: CentralizedLoggingAccountId
          Configurations:
            LoggingBucket:
              RetentionDays:
                Ref: LoggingBucketRetentionPeriod
            AccessLoggingBucket:
              RetentionDays:
                Ref: AccessLoggingBucketRetentionPeriod
        SecurityRoles:
          AccountId:
            Ref: SecurityAccountId
        AccessManagement:
          Enabled: "false"

CLIでデプロイしたランディングゾーンのManifestと同様にキャメルケースでキーを定義することでデプロイできるようになります。

ControlTower.yaml

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  Version:
    Type: String
    Default: "1.0.0"
    Description: The version number of Landing Zone
  GovernedRegions:
    Type: CommaDelimitedList
    Description: List of governed regions
  SecurityOuName:
    Type: String
    Description: The security Organizational Unit name
  SandboxOuName:
    Type: String
    Description: The sandbox Organizational Unit name
  CentralizedLoggingAccountId:
    Type: String
    Description: The AWS account ID for centralized logging
  SecurityAccountId:
    Type: String
    Description: The AWS account ID for security roles
  LoggingBucketRetentionPeriod:
    Type: Number
    Description: Retention period for centralized logging bucket
  AccessLoggingBucketRetentionPeriod:
    Type: Number
    Description: Retention period for access logging bucket

Resources:
  MyLandingZone:
    Type: AWS::ControlTower::LandingZone
    Properties:
      Version: !Ref Version
      Tags:
        - Key: "k1"
          Value: "v1b"
        - Key: "k3"
          Value: "v3"
      Manifest:
        governedRegions:
          Ref: GovernedRegions
        organizationStructure:
          security:
            name:
              Ref: SecurityOuName
          sandbox:
            name:
              Ref: SandboxOuName
        centralizedLogging:
          accountId:
            Ref: CentralizedLoggingAccountId
          configurations:
            loggingBucket:
              retentionDays:
                Ref: LoggingBucketRetentionPeriod
            accessLoggingBucket:
              retentionDays:
                Ref: AccessLoggingBucketRetentionPeriod
          enabled: true
        securityRoles:
          accountId:
            Ref: SecurityAccountId
        accessManagement:
          enabled: false

こちらのテンプレートをCFnでデプロイしてみます。

aws cloudformation deploy --stack-name ControlTower \
--template-file ControlTower.yaml \
--parameter-overrides \
Version="3.2" \
GovernedRegions="ap-northest-1" \
SecurityOuName="Security" \
SandboxOuName="Sandbox" \
CentralizedLoggingAccountId="xxxxxxxxxxxx" \
SecurityAccountId="xxxxxxxxxxxx" \
LoggingBucketRetentionPeriod=3650 \
AccessLoggingBucketRetentionPeriod=365

今度は無事ランディングゾーン作成がされました!

ランディングゾーン更新

もちろんテンプレートを更新してUpdateも可能です。
ここではCloudTrailのログ集約をの設定をオフにしてUpdateしてみます。

ControlTower.yaml

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  Version:
    Type: String
    Default: "1.0.0"
    Description: The version number of Landing Zone
  GovernedRegions:
    Type: CommaDelimitedList
    Description: List of governed regions
  SecurityOuName:
    Type: String
    Description: The security Organizational Unit name
  SandboxOuName:
    Type: String
    Description: The sandbox Organizational Unit name
  CentralizedLoggingAccountId:
    Type: String
    Description: The AWS account ID for centralized logging
  SecurityAccountId:
    Type: String
    Description: The AWS account ID for security roles
  LoggingBucketRetentionPeriod:
    Type: Number
    Description: Retention period for centralized logging bucket
  AccessLoggingBucketRetentionPeriod:
    Type: Number
    Description: Retention period for access logging bucket

Resources:
  MyLandingZone:
    Type: AWS::ControlTower::LandingZone
    Properties:
      Version: !Ref Version
      Tags:
        - Key: "k1"
          Value: "v1b"
        - Key: "k3"
          Value: "v3"
      Manifest:
        governedRegions:
          Ref: GovernedRegions
        organizationStructure:
          security:
            name:
              Ref: SecurityOuName
          sandbox:
            name:
              Ref: SandboxOuName
        centralizedLogging:
          accountId:
            Ref: CentralizedLoggingAccountId
          configurations:
            loggingBucket:
              retentionDays:
                Ref: LoggingBucketRetentionPeriod
            accessLoggingBucket:
              retentionDays:
                Ref: AccessLoggingBucketRetentionPeriod
          enabled: false
        securityRoles:
          accountId:
            Ref: SecurityAccountId
        accessManagement:
          enabled: false

CFnの更新によってランディングゾーンの設定も更新されていることが確認できます。

ランディングゾーン削除

最後はCFnを削除したいと思います。

aws cloudformation delete-stack --stack-name ControlTower

こちらもControlTower削除処理が実行されていることが確認できました。

最後に

前回のアップデートブログではCLIが用意されておらず触れておりませんでしたが、無事CLI、CFnで操作が確認できました。

まだ、Manifestファイルまわりのドキュメントが整っていないように思うので、こちらのドキュメントも整備されることを期待しています。

以上、たかやま(@nyan_kotaroo)でした。