AWS CloudTrailのマルチリージョン証跡について

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。
この記事では、Security Hubで検出された「[CloudTrail.1] CloudTrail を有効にして、少なくとも 1 つのマルチリージョンの追跡で、読み取りと書き込みの管理イベントを含めた設定をする必要があります。」というセキュリティ課題の修正方法について解説します。

ポリシーの説明
[CloudTrail.1] CloudTrail を有効にして、少なくとも 1 つのマルチリージョンの追跡で、読み取りと書き込みの管理イベントを含めた設定をする必要があります。
CloudTrail の Security Hub コントロール – AWS Security Hub
このコントロールは、読み取りおよび書き込み管理イベントをキャプチャするマルチリージョン AWS CloudTrail 証跡が少なくとも 1 つあるかどうかを確認します。CloudTrail が無効になっているか、読み取りおよび書き込み管理イベントをキャプチャする CloudTrail 証跡が少なくとも 1 つ存在しない場合、コントロールは失敗します。
AWS CloudTrailは、AWS環境内で行われたすべてのアクションを記録するサービスであり、セキュリティインシデントの調査、リソースの変更履歴の追跡、コンプライアンス要件の遵守に不可欠です。マルチリージョントレイルを設定し、読み取りと書き込みの管理イベントを記録することで、グローバルサービスを含むすべてのリージョンにおける重要な操作を把握し、セキュリティと運用上の可視性を高めることができます。
修復方法
AWSコンソールでの修正手順
- CloudTrail > 証跡へ移動する

- 証跡の作成を選択し、証跡名、バケット名、KMSキー名を入力した後、次へを選択する
- イベントタイプで「管理イベント」を選択し、管理イベントでAPI アクティビティの「読み取り」と「書き込み」にチェックする
- 次へを選択し、内容に問題なければ証跡を作成する

Terraformでの修復手順
CloudTrailを適切に設定するためのTerraformコードを作成します。
# CloudTrailのログを保存するS3バケットの作成
resource "aws_s3_bucket" "cloudtrail_logs" {
bucket = "cloudtrail-logs-${data.aws_caller_identity.current.account_id}"
force_destroy = false
tags = {
Name = "CloudTrail Logs"
Environment = var.environment
}
}
# S3バケットのパブリックアクセスをブロック
resource "aws_s3_bucket_public_access_block" "cloudtrail_logs" {
bucket = aws_s3_bucket.cloudtrail_logs.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# バケットの暗号化設定
resource "aws_s3_bucket_server_side_encryption_configuration" "cloudtrail_logs" {
bucket = aws_s3_bucket.cloudtrail_logs.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
# CloudTrailログ用のS3バケットポリシー
resource "aws_s3_bucket_policy" "cloudtrail_logs" {
bucket = aws_s3_bucket.cloudtrail_logs.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AWSCloudTrailAclCheck"
Effect = "Allow"
Principal = {
Service = "cloudtrail.amazonaws.com"
}
Action = "s3:GetBucketAcl"
Resource = aws_s3_bucket.cloudtrail_logs.arn
},
{
Sid = "AWSCloudTrailWrite"
Effect = "Allow"
Principal = {
Service = "cloudtrail.amazonaws.com"
}
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.cloudtrail_logs.arn}/*"
Condition = {
StringEquals = {
"s3:x-amz-acl" = "bucket-owner-full-control"
}
}
}
]
})
}
# CloudTrailのKMS暗号化キー
resource "aws_kms_key" "cloudtrail" {
description = "KMS key for CloudTrail logs encryption"
deletion_window_in_days = 7
enable_key_rotation = true
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "Enable IAM User Permissions"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
}
Action = "kms:*"
Resource = "*"
},
{
Sid = "Allow CloudTrail to encrypt logs"
Effect = "Allow"
Principal = {
Service = "cloudtrail.amazonaws.com"
}
Action = [
"kms:GenerateDataKey*",
"kms:Decrypt"
]
Resource = "*"
}
]
})
}
# マルチリージョンCloudTrailの設定
resource "aws_cloudtrail" "main" {
name = "multi-region-trail"
s3_bucket_name = aws_s3_bucket.cloudtrail_logs.id
include_global_service_events = true
is_multi_region_trail = true
enable_logging = true
kms_key_id = aws_kms_key.cloudtrail.arn
# CloudTrailのログファイル検証を有効化
enable_log_file_validation = true
# 読み取りと書き込みの管理イベントを記録
event_selector {
read_write_type = "All"
include_management_events = true
}
# データイベントの設定(必要な場合)
dynamic "event_selector" {
for_each = var.enable_s3_data_events ? [1] : []
content {
read_write_type = "All"
data_resource {
type = "AWS::S3::Object"
values = ["arn:aws:s3:::"]
}
}
}
cloud_watch_logs_group_arn = "${aws_cloudwatch_log_group.cloudtrail.arn}:*"
cloud_watch_logs_role_arn = aws_iam_role.cloudtrail_cloudwatch.arn
depends_on = [
aws_s3_bucket_policy.cloudtrail_logs
]
}
# CloudWatch Logsグループ
resource "aws_cloudwatch_log_group" "cloudtrail" {
name = "/aws/cloudtrail/logs"
retention_in_days = 30
}
# CloudTrailがCloudWatch Logsに書き込むためのIAMロール
resource "aws_iam_role" "cloudtrail_cloudwatch" {
name = "cloudtrail-cloudwatch-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "cloudtrail.amazonaws.com"
}
}
]
})
}
# CloudTrailのCloudWatch Logs書き込み権限
resource "aws_iam_role_policy" "cloudtrail_cloudwatch" {
name = "cloudtrail-cloudwatch-policy"
role = aws_iam_role.cloudtrail_cloudwatch.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"logs:CreateLogStream",
"logs:PutLogEvents"
]
Resource = "${aws_cloudwatch_log_group.cloudtrail.arn}:*"
}
]
})
}
# 必要な変数の定義
variable "environment" {
type = string
description = "Environment name"
default = "production"
}
variable "enable_s3_data_events" {
type = bool
description = "Enable S3 data events logging"
default = false
}
# 現在のAWSアカウントIDの取得
data "aws_caller_identity" "current" {}
# 出力値
output "cloudtrail_arn" {
value = aws_cloudtrail.main.arn
}
output "cloudtrail_log_bucket" {
value = aws_s3_bucket.cloudtrail_logs.id
}
重要な設定ポイントと修正手順を説明します:
- CloudTrailの基本設定(最重要):
resource "aws_cloudtrail" "main" {
is_multi_region_trail = true # マルチリージョン有効化
include_global_service_events = true # グローバルサービスイベントを含む
enable_logging = true # ログ記録を有効化
event_selector {
read_write_type = "All" # 読み取り/書き込みイベントを記録
include_management_events = true # 管理イベントを含む
}
}
ログの保存とセキュリティ:
# S3バケットの暗号化
resource "aws_s3_bucket_server_side_encryption_configuration" "cloudtrail_logs" {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
# KMS暗号化の設定
resource "aws_kms_key" "cloudtrail" {
enable_key_rotation = true
}
最後に
今回は、CloudTrailを有効にし、マルチリージョントレイルで読み取りと書き込みの管理イベントをログ記録するように設定する方法についてご紹介しました。CloudTrailは、AWS環境におけるセキュリティとコンプライアンスの基盤となるサービスです。適切な設定を行うことで、セキュリティインシデントの早期発見と対応、および監査要件への準拠に役立ちます。
この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。
運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。
最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。