マルチアカウント環境でGuardDuty Malware Protectionを有効化する場合の注意点

マルチアカウント環境でGuardDuty Malware Protectionを有効化を検証し、その時の注意点についてまとめました。
2022.08.12

みなさん、こんにちは。

AWS事業本部コンサルティング部の芦沢(@ashi_ssan)です。

先日re:inforceで発表されたGuardDutyの神アップデート、チェックされてますか?

こちらのブログにも以下のように記載がある通り、マルチアカウント環境でMalware Protectionを有効化する場合、Service-Linked Roleの作成が必要なことがわかります。

GuardDutyのマルチアカウント管理の機能を利用してMalware Protectionも利用できます。自動で有効化する設定が可能です。

既存のアカウントに対してはService-Linked Roleが必要となるため、Malware Protectionを有効化できません。ワークアラウンドとして一度関連付けを解除してから再登録する方法が提示されています。詳細はこちらをご確認ください。

実際にやってみました。

いきなりまとめ

  • Malware Protectionを有効化できる条件
    1. Organizations管理者アカウントでprotection.guardduty.amazonaws.comからのサービスアクセスが有効化されている
    2. Malware Protectionを有効化するアカウントにService-Linked Role であるAWSServiceRoleForAmazonGuardDutyMalwareProtectionが作成されている
  • GuardDutyの委任管理者アカウントがOrganizations管理者アカウントではない場合、Malware Protection有効化時に有効化を行うメンバーアカウントの種類によっては別途Service-Linked Roleの作成が必要。
    • 不要(Malware Protection有効化時にロールが自動作成される)
      • GuardDutyの委任管理者アカウント
      • Organizations経由で追加されたアカウント (Organizationsメンバー)
    • 必要(Malware Protection有効化の前にService-Linked Roleを手動で作成する必要がある)
      • Organizations経由で追加されたアカウント (Organizations管理者)
  • GuardDutyの招待によって管理されたアカウントでは、関連付けを一度解除して再登録する必要がある

やってみた

今回は検証環境として、Control Towerが有効化されたOrganizations環境を使用します。

Organizations全体のMalware Protectionを有効化

はじめに、Organizations管理アカウントで以下コマンドを実行します。

CLIの実行環境がない場合はCloudShellから実行してください。

aws organizations enable-aws-service-access --service-principal malware-protection.guardduty.amazonaws.com

これによって、Organizations組織全体へのmalware-protection.guardduty.amazonaws.comエンドポイントからのサービスアクセスが許可されます。

Malware Protection機能の有効化

ここからはアカウントの種類によって手順が変化します。

  • GuardDutyの委任管理者アカウント
  • Organizations経由で追加されたアカウント (Organizationsメンバー)
  • Organizations経由で追加されたアカウント (Organizations管理者)

GuardDuty委任管理者アカウントの場合

GuardDuty委任管理者アカウントでログインしてください。

GuardDutyコンソールの設定 > Malware Protectionから「このアカウントではMalware Protectionが有効になっていません」の隣の有効にするをクリックします。

有効にするをクリックします。

有効にできました。

IAMロールを確認すると、AWSServiceRoleForAmazonGuardDutyMalwareProtectionが作成されていることが確認できます。

AWSServiceRoleForAmazonGuardDutyMalwareProtectionの信頼関係ポリシーはこちら

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "malware-protection.guardduty.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

AmazonGuardDutyMalwareProtectionServiceRolePolicyのポリシードキュメントはこちら

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ec2:DescribeVolumes",
                "ec2:DescribeSnapshots",
                "ecs:ListClusters",
                "ecs:ListContainerInstances",
                "ecs:ListTasks",
                "ecs:DescribeTasks",
                "eks:DescribeCluster"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "ec2:CreateSnapshot",
            "Resource": "arn:aws:ec2:*:*:volume/*",
            "Condition": {
                "Null": {
                    "aws:ResourceTag/GuardDutyExcluded": "true"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "ec2:CreateSnapshot",
            "Resource": "arn:aws:ec2:*:*:snapshot/*",
            "Condition": {
                "ForAnyValue:StringEquals": {
                    "aws:TagKeys": "GuardDutyScanId"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "ec2:CreateTags",
            "Resource": "arn:aws:ec2:*:*:*/*",
            "Condition": {
                "StringEquals": {
                    "ec2:CreateAction": "CreateSnapshot"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "ec2:CreateTags",
            "Resource": "arn:aws:ec2:*:*:snapshot/*",
            "Condition": {
                "StringLike": {
                    "ec2:ResourceTag/GuardDutyScanId": "*"
                },
                "ForAllValues:StringEquals": {
                    "aws:TagKeys": [
                        "GuardDutyExcluded",
                        "GuardDutyFindingDetected"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DeleteSnapshot",
                "ec2:ModifySnapshotAttribute"
            ],
            "Resource": "arn:aws:ec2:*:*:snapshot/*",
            "Condition": {
                "StringLike": {
                    "ec2:ResourceTag/GuardDutyScanId": "*"
                },
                "Null": {
                    "aws:ResourceTag/GuardDutyExcluded": "true"
                }
            }
        },
        {
            "Effect": "Deny",
            "Action": [
                "ec2:ModifySnapshotAttribute"
            ],
            "Resource": "arn:aws:ec2:*:*:snapshot/*",
            "Condition": {
                "StringEquals": {
                    "ec2:Add/group": "all"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "kms:CreateGrant",
            "Resource": "arn:aws:kms:*:*:key/*",
            "Condition": {
                "Null": {
                    "aws:ResourceTag/GuardDutyExcluded": "true"
                },
                "StringLike": {
                    "kms:EncryptionContext:aws:ebs:id": "snap-*"
                },
                "ForAllValues:StringEquals": {
                    "kms:GrantOperations": [
                        "Decrypt",
                        "CreateGrant",
                        "GenerateDataKeyWithoutPlaintext",
                        "ReEncryptFrom",
                        "ReEncryptTo",
                        "RetireGrant",
                        "DescribeKey"
                    ]
                },
                "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "kms:ReEncryptTo",
                "kms:ReEncryptFrom"
            ],
            "Resource": "arn:aws:kms:*:*:key/*",
            "Condition": {
                "StringLike": {
                    "kms:ViaService": "ec2.*.amazonaws.com"
                },
                "Null": {
                    "aws:ResourceTag/GuardDutyExcluded": "true"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "kms:DescribeKey",
            "Resource": "arn:aws:kms:*:*:key/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups",
                "logs:CreateLogGroup",
                "logs:PutRetentionPolicy"
            ],
            "Resource": "arn:aws:logs:*:*:log-group:/aws/guardduty/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:DescribeLogStreams"
            ],
            "Resource": "arn:aws:logs:*:*:log-group:/aws/guardduty/*:log-stream:*"
        }
    ]
}

Organizations経由で追加されたアカウント (Organizationsメンバー)の場合

GuardDuty委任管理者アカウントでログインしてください。

GuardDutyコンソールの設定 > アカウントから対象のメンバーアカウントにチェックを入れた状態でアクションタブのMalware Protectionを有効化するをクリックします。

Malware Protectionを有効にするをクリックします。

有効化できました。

有効化を行ったメンバーアカウントのIAMロールを確認すると、AWSServiceRoleForAmazonGuardDutyMalwareProtectionが作成されていることが確認できます。

また、こちらからOrganizations配下のGuardDuty委任管理者アカウント以外のMalware Protectionを一括で有効化できます。

この一括有効化の対象にはOrganizations管理者アカウントも含まれるため、以下の条件を満たしていない場合は、Organization管理者権限が不足しているという内容のエラーが出力されました。

  • Organization管理者アカウント側でService-Linked RoleであるAWSServiceRoleForAmazonGuardDutyMalwareProtectionが作成されている

一括で有効化したい場合には、後述するOrganizations経由で追加されたアカウント (Organizations管理者)を実行してから一括有効化することをおすすめします。

Organizations経由で追加されたアカウント (Organizations管理者)の場合

GuardDuty委任管理者アカウントからOrganizations管理者アカウントのMalware Protectionを有効化する場合は、事前にOrganizations管理者アカウントのService-Linked Roleを作成する必要があります。


まずは、Organizations管理者アカウントでログインし、以下コマンドを実行してください。

aws iam create-service-linked-role --aws-service-name malware-protection.guardduty.amazonaws.com

コマンド実行後、以下のような出力があればOKです。

{
    "Role": {
        "Path": "/aws-service-role/malware-protection.guardduty.amazonaws.com/",
        "RoleName": "AWSServiceRoleForAmazonGuardDutyMalwareProtection",
        "RoleId": "XXXXXXXXXXXXXXXXXXXX",
        "Arn": "arn:aws:iam::123456789012:role/aws-service-role/malware-protection.guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDutyMalwareProtection",
        "CreateDate": "2022-08-04T07:45:57+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": [
                        "sts:AssumeRole"
                    ],
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "malware-protection.guardduty.amazonaws.com"
                        ]
                    }
                }
            ]
        }
    }
}

続いて、GuardDuty委任管理者アカウントでOrganizations管理者アカウントのMalware Protectionを有効化します。

ここからの手順は「Organizations経由で追加されたアカウント (Organizationsメンバー)」と同じ手順なので省略します。

その他(GuardDutyの招待によって管理されたアカウントの場合)

GuardDutyでの複数アカウント管理はOrganizationsによるアカウント管理以外に、招待によるアカウント管理があります。

GuardDutyの招待によるアカウント管理についてはこちらのブログが参考になります。

招待によって管理されたアカウントに対し、Malware Protectionを有効化する場合は以下の手順が必要になる想定です。

  1. GuardDuty管理者アカウントで、メンバーアカウントの関連付けの解除を行う
  2. メンバーアカウントから、Malware Protectionを有効化する
  3. GuardDuty管理者アカウントで、メンバーアカウントを再度関連付けする

詳しくは公式ドキュメントの「Enable Malware Protection for existing accounts in the Organization managed via invitation」をご覧ください。

最後に

今回は、マルチアカウント環境でMalware Protection有効化の検証を行い、その時に気づいた注意点についてまとめました。

本ブログが誰かの役に立てれば幸いです。

以上、AWS事業本部コンサルティング部の芦沢(@ashi_ssan)でした。