こんにちは、クラウドエンジニアの浅野です。

AWSを個人で利用したり、検証用にマルチアカウント環境(AWS Organizations)を構築している方も増えてきたのではないでしょうか。
環境を分けることで管理はしやすくなりますが、一方で「意図しないリージョンでのリソース作成」や「不適切な権限(ルートユーザーなど)での操作」といったセキュリティリスクも気になるところです。

そこで今回は、私が自分のAWSマルチアカウント環境で「最低限これくらいはやらないといけないだろう」と設定している、SCPとCloudWatchを活用した制御・監視の仕組みをご紹介します。

1. OrganizationsのSCPで利用リージョンを制限する

AWSは世界中にリージョンがありますが、普段使わないリージョンで誤ってリソースを作成してしまうと、気づかないうちにコストが発生してしまうリスクがあります。

そのため、私はOrganizationsのSCP(サービスコントロールポリシー)を利用して、「東京リージョン(ap-northeast-1)」と、グローバルサービスの操作に不可欠な「バージニア北部(us-east-1)」以外の操作を全面的に拒否しています。

実際のポリシーコードは以下の通りです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyActionsOutsideTokyoAndNVirginia",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": [
            "ap-northeast-1",
            "us-east-1"
          ]
        },
        "Null": {
          "aws:RequestedRegion": "false"
        }
      }
    }
  ]
}

2. SCPでIAMユーザーとルートユーザーを封じる

現在、私の環境では基本的に IAM Identity Center を利用してアクセスしています。
そのため、各アカウントで個別にIAMユーザーを作成して操作することはありませんし、強力すぎるルートユーザーでの操作も日常的には行いません。

そこで、万が一の不正利用を防ぐため、IAMユーザーとルートユーザーによる操作もSCPで明示的に拒否しています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyRootUser",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "ArnLike": {
          "aws:PrincipalArn": "arn:aws:iam::*:root"
        }
      }
    },
    {
      "Sid": "DenyIamUsers",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:PrincipalType": "IAMUser"
        }
      }
    }
  ]
}

3. SCPの落とし穴:「管理アカウント」には適用できない

ここまで強力なSCPですが、AWS Organizationsの仕様上、SCPは「管理アカウント(Management Account)」自身には適用できないという制約があります。

つまり、管理アカウント内で不正にIAMユーザーが作成されたり、ルートユーザーでログインされたりした場合、上記のSCPでは防ぐことができません。

4. CloudTrailとCloudWatch Alarmsで全アカウントを監視する

SCPで完全に防ぐことができない以上、「操作されたら確実に検知できる」仕組みが必要です。
そこで、私は以下の構成で監視基盤を作っています。

  1. OrganizationsでCloudTrailを組織単位で有効化する。
  2. 全アカウントの証跡ログを、管理アカウントのCloudWatch Logs(ロググループ)に集約設定する。
  3. そのロググループにメトリクスフィルターを作成し、特定のアクションを抽出してメトリクス化する。
  4. CloudWatch Alarmsを作成し、検知時にアラートを発報する。

設定しているメトリクスフィルター

① IAMユーザーの操作を検知

{ $.userIdentity.type = "IAMUser" }

② ルートユーザーの操作を検知
(AWSの内部サービスによる正規のイベントは除外)

{ $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" }

今のところ私自身がこの2つの操作を行うことはないため、「まずは最低限、操作があったこと自体を検知できるようにする」というアプローチをとっています。

おわりに

簡易的ではありますが、個人的にマルチアカウントを使うのであれば、最低限これくらい設定しておくと精神的にかなり安心できるのではないでしょうか。
他にも特定のIP以外からのアクセスを拒否したり、特定のサービス以外を拒否するなど、SCPでは様々な制御が可能です。

ちなみに今回は自前で設定する形をご紹介しましたが、AWS Control Tower を導入すれば、こうしたベストプラクティスに基づいたマルチアカウント環境のガバナンスを、より簡単かつセキュアに管理・実装することもできます。

また、今回はOrganizationsを使ったマルチアカウント環境を前提としましたが、AWSアカウントが1つだけの場合でも油断は禁物です。
SCPで強力な制御ができない分、CloudTrail、EventBridge、CloudWatch、そしてLambda関数などを組み合わせて、「不正な操作を検知したら自動でセッションを無効化(制御)する」といった仕組みは、最低限必ず実装しておくことを強くおすすめします。

AWS環境をもっとガチガチにセキュアにする方法は他にもいくらでもありますので、また別の機会にご紹介したいと思います!