AWS Organizations で使用する AWS CloudTrail の Amazon CloudWatch Logs への出力を委任管理アカウントのコンソールから有効化できない

AWS マネジメントコンソールからできないことは CLI や API ならできそうか見てみる
2023.06.05

こんにちは、AWS事業本部の平木です!

AWS Organizations (以下、 Organizations )で使用する AWS CloudTrail (以下、 CloudTrail )の Amazon CloudWatch Logs (以下、 CloudWatch Logs )への出力を委任管理アカウントの AWS マネジメントコンソール上で有効化しようとすると編集ボタンがグレーアウトしている問題を解決します。

いきなり結論

CloudTrail の委任管理者アカウントから CloudWatch Logs を有効化したい場合、
現在時点ではマネジメントコンソールからのオペレーションがサポートされていないため、
AWS CLI または CloudTrail API を使用する必要があります。

CloudTrail の委任管理者とは

Organizations 全体または特定の組織単位( OU )内の CloudTrail 設定について管理アカウントと
同じ管理タスクを実行できる権限が管理アカウントより割り当てられた組織内のメンバーアカウントです。

経緯

Organizations 配下のメンバーアカウントに対して CloudTrail の管理権限を委任している AWS アカウントで CloudWatch Logs を有効化しようとしたところ右下のように「編集」ボタンが押せないようになっていました。

原因を調べていたところ AWS 公式ドキュメントにて下記のように注記されていました。

コンソールオペレーションがサポートされていないため、委任された管理者アカウントは現在、
コンソールを使用して CloudWatch Logs ロググループを設定できません。
委任された管理者アカウントは、AWS CLI または CloudTrail API を使用して、CloudWatch Logs ロググループで組織の証跡を作成する必要があります。

引用: https://docs.aws.amazon.com/ja_jp/awscloudtrail/latest/userguide/creating-an-organizational-trail-in-the-console.html

委任管理アカウントから CloudWatch Logs を有効化する

AWS CLI または CloudTrail API なら有効化できるとのことなので、
東京リージョンにて AWS CLI を使用し AWS CloudShell から有効化してみます。

事前確認

まずは現在の設定の確認をします。

$ TRAIL_NAME=`aws cloudtrail list-trails \
	--query Trails[].TrailARN \
	--output text` && echo ${TRAIL_NAME}

$ aws cloudtrail get-trail --name ${TRAIL_NAME}
{
    "Trail": {
        "Name": "management-events",
        "S3BucketName": "aws-cloudtrail-logs-<管理アカウントのAWSアカウントID>-xxxxxxxx",
        "IncludeGlobalServiceEvents": true,
        "IsMultiRegionTrail": true,
        "HomeRegion": "ap-northeast-1",
        "TrailARN": "arn:aws:cloudtrail:ap-northeast-1:<管理アカウントのAWSアカウントID>:trail/management-events",
        "LogFileValidationEnabled": false,
        "HasCustomEventSelectors": true,
        "HasInsightSelectors": false,
        "IsOrganizationTrail": true
    }
}

上記のように CloudWatch Logs に関するパラメータは現在のところ確認できません。

IAM ロールとポリシーの作成

IAM ロールを作成するためにrole.jsonにCloudTrail用の信頼ポリシーを記述し、 IAM ロールを作成します。

$ cat << EOF > role.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "sts:AssumeRole"
            ],
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "cloudtrail.amazonaws.com"
                ]
            }
        }
    ]
}
EOF

$ IAM_ROLE_NAME=`aws iam create-role \
	--role-name CloudTrail_CloudWatchLogs_Role \
	--assume-role-policy-document file://role.json \
	--query Role.RoleName --output text` && echo ${IAM_ROLE_NAME}

$ IAM_ROLE_ARN=`aws iam get-role \
	--role-name ${IAM_ROLE_NAME} \
	--query Role.Arn --output text` && echo ${IAM_ROLE_ARN}

続いて IAM ポリシーを作成するためのポリシーをpolicy.jsonに記述し、 IAM ポリシーを作成します。

$ cat << EOF > policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AWSCloudTrailCreateLogStream2014110",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-1:<委任管理アカウントのAWSアカウントID>:log-group:trail-log:log-stream:*_CloudTrail_*",
                "arn:aws:logs:ap-northeast-1:<委任管理アカウントのAWSアカウントID>::log-group:trail-log:log-stream:<Organizations ID>_*"
            ]
        },
        {
            "Sid": "AWSCloudTrailPutLogEvents20141101",
            "Effect": "Allow",
            "Action": [
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-1:<委任管理アカウントのAWSアカウントID>::log-group:trail-log:log-stream:*_CloudTrail_*",
                "arn:aws:logs:ap-northeast-1:<委任管理アカウントのAWSアカウントID>::log-group:trail-log:log-stream:<Organizations ID>_*"
            ]
        }
    ]
}
EOF

$ IAM_POLICY_ARN=`aws iam create-policy \
	--policy-name CloudTrail_CloudWatchLogs_Policy \
	--policy-document file://policy.json \
	--query Policy.Arn --output text` && echo ${IAM_POLICY_ARN}

作成した IAM ポリシーを IAM ロールにアタッチします。

$ aws iam attach-role-policy \
	--role-name ${IAM_ROLE_NAME} \
	--policy-arn ${IAM_POLICY_ARN}

続いてログ出力するための ロググループを作成します。
既存のものを使用したい場合は、スキップいただいて問題ありませんが、
先に作成した IAM ポリシーを修正してください。

$ aws logs create-log-group --log-group-name trail-log

$ LOG_GROUP_ARN=`aws logs describe-log-groups \
	--log-group-name-prefix trail-log \
	--query 'logGroups[].arn' --output text`  && echo ${LOG_GROUP_ARN}

CloudTrail の更新

先に作成した IAM ロールと CloudWatch Logs のロググループを引数に使用し、
UpdateTrail API を使用し更新します。

$ aws cloudtrail update-trail \
        --name ${TRAIL_NAME} \
        --cloud-watch-logs-log-group-arn ${LOG_GROUP_ARN} \
        --cloud-watch-logs-role-arn ${IAM_ROLE_ARN}

事後確認

最後に正常に CloudWatch Logs が有効化できたか確認します。

$ aws cloudtrail get-trail --name ${TRAIL_NAME}
{
    "Trail": {
        "Name": "management-events",
        "S3BucketName": "aws-cloudtrail-logs-<管理アカウントのAWSアカウントID>-xxxxxxxx",
        "IncludeGlobalServiceEvents": true,
        "IsMultiRegionTrail": true,
        "HomeRegion": "ap-northeast-1",
        "TrailARN": "arn:aws:cloudtrail:ap-northeast-1:<管理アカウントのAWSアカウントID>:trail/management-events",
        "LogFileValidationEnabled": false,
+        "CloudWatchLogsLogGroupArn": "arn:aws:logs:ap-northeast-1:<委任管理アカウントのAWSアカウントID>:log-group:trail-log:*", ←新規
+        "CloudWatchLogsRoleArn": "arn:aws:iam::<委任管理アカウントのAWSアカウントID>:role/CloudTrail_CloudWatchLogs_Role", ←新規
        "HasCustomEventSelectors": true,
        "HasInsightSelectors": false,
        "IsOrganizationTrail": true
    }
}

AWS マネジメントコンソール上でも有効化されていることが確認できます。

無効化したい場合

下記コマンドを実行することで、委任管理アカウントから無効化できそうです。

$ aws cloudtrail update-trail \
        --name ${TRAIL_NAME} \
        --cloud-watch-logs-log-group-arn "" \
        --cloud-watch-logs-role-arn ""

終わりに

今回は CloudTrail の委任管理アカウントから CloudWatch Logs を AWS マネジメントコンソールから有効化できない問題を API 経由で解消しました。
この記事がどなたかの役に立てば嬉しいです。