Amazon GuardDuty が EKS ランタイムモニタリングをサポートしたため手動でセットアップしてみた

Amazon GuardDuty が Amazon EKS のランタイムモニタリングをサポートしました。今回はモニタリング基盤を手動でセットアップしてみようと思います。
2023.04.09

こんにちは!AWS事業本部コンサルティング部のたかくに(@takakuni_)です。

Amazon GuardDuty が Amazon EKS のコンテナランタイムを監視するようになりました。

今回提供されたランタイムモニタリング機能では DaemonSet 形式で GuardDuty エージェントをデプロイし、ファイルアクセス、プロセス実行、ネットワーク接続など、ホスト上のオペレーティング システム レベルの動作を監視します。

GuardDuty エージェントの管理方法には、自動管理手動管理の2種類があり、今回はセットアップ編と題して、後者の手動管理を主に解説できればと思います。

前提条件

執筆時点(2023/4/8 時点)では 今回の Amazon GuardDuty ランタイムモニタリングには、いくつか制約事項があるためピックアップします。

最新情報は 公式ドキュメント - EKS Runtime Monitoring をご覧ください。

カバレッジ機能の提供

GuardDuty では新しくカバレッジ機能を提供しました。

カバレッジでは EKS ランタイムモニタリングが行えるかどうかのステータスを表す画面です。

ランタイムモニタリングを行なっているクラスターの割合を表示したり、ランタイムモニタリングが行えない場合のトラブルシューティングとしても役立つ画面になっています。

EKS ランタイムモニタリングを利用するには

手動管理の場合、 EKS ランタイムモニタリングを利用するには、以下のステップを踏む必要があります。

  • Amazon GuardDuty コンソールからランタイムモニタリング機能の有効化を行う
  • VPC Endpoint を配置して EKS クラスターがサービスエンドポイントに到達できるようにする
  • EKS add-ons を有効化し EKS クラスターに GuardDuty エージェントをデプロイする

ランタイムモニタリングの有効化

GuardDuty コンソールから 「EKS Protection」 をクリックし、「EKS ランタイムモニタリング」を有効化していきます。

設定の編集画面に遷移すると、今回新たに追加された 「EKS ランタイムモニタリング」と「エージェントを自動的に管理する」が設定できます。

今回は手動管理のため、以下で設定します。

  • EKS ランタイムモニタリング:有効
  • エージェントを自動的に管理する:無効

VPC Endpoint を配置

EKS クラスターが サービスエンドポイントに到達するためには VPC Endpoint (com.amazonaws.${region}.guardduty-data) が必要です。

NAT Gateway や 直接パブリック IP でサービスエンドポイントには到達できません。

The Amazon EKS worker node instances can run in non-public subnets. The GuardDuty agent running on these nodes can't reach the public endpoint for GuardDuty without using an Amazon VPC endpoint.

Understanding why GuardDuty chose Amazon VPC endpoint

ちなみにですが、 VPC Endpoint を作らず NAT Gateway 越しに GuardDuty エージェントがサービスエンドポイントを解決しようとすると、以下のようなエラーになります。

takakuni@~ % kubectl logs aws-guardduty-agent-bxq2r -n amazon-guardduty 
2023-04-08T13:26:28.465770Z  INFO amzn_guardduty_agent: GuardDuty agent starting with 8 worker thread(s) and 100 max blocking threads.
2023-04-08T13:26:28.569217Z  INFO amzn_guardduty_agent: Agent fingerprint: f3962a7b731cfd20ce9570140f7d481102c18ca98465439ddb299a047f6ef95e
2023-04-08T13:26:28.583339Z ERROR amzn_guardduty_agent::dependency_checks: Failed to ping agent endpoint due to reqwest::Error {
    kind: Request,
    url: Url {
        scheme: "https",
        cannot_be_a_base: false,
        username: "",
        password: None,
        host: Some(
            Domain(
                "guardduty-data.ap-northeast-1.amazonaws.com",
            ),
        ),
        port: None,
        path: "/ping",
        query: None,
        fragment: None,
    },
    source: hyper::Error(
        Connect,
        ConnectError(
            "dns error",
            Os {
                code: 16,
                kind: ResourceBusy,
                message: "Device or resource busy",
            },
        ),
    ),
}
2023-04-08T13:26:28.583367Z ERROR amzn_guardduty_agent: Dependency check failed - Failed to communicate with back-end services, please check your network configuration
Error: Pipeline(DependencyError("Failed to communicate with back-end services, please check your network configuration"))

セキュリティグループの設定

VPC Endpoint で作成するセキュリティグループでは、 HTTPS (443 番ポート) で EKS クラスターを実行している VPC の CIDR を許可する必要があります。

表にすると以下のようになります。

インバウンドルール

タイプ プロトコル ポート範囲 CIDR
HTTPS TCP 443 EKS クラスターを実行している VPC の CIDR

アウトバウンドルール

無しで OK

vpce.tf

vpce.tf

resource "aws_security_group" "vpce" {
  name        = "${local.prefix}-sg-vpce"
  description = "${local.prefix}-sg-vpce"
  vpc_id      = module.vpc.vpc_id

  ingress {
    description = "HTTPS from VPC CIDR"
    protocol    = "tcp"
    from_port   = 443
    to_port     = 443
    cidr_blocks = [
      module.vpc.vpc_cidr_block
    ]
  }

  tags = {
    Name = "${local.prefix}-sg-vpce"
  }
}

resource "aws_vpc_endpoint" "guardduty_data" {
  vpc_id = module.vpc.vpc_id
  vpc_endpoint_type = "Interface"
  service_name = "com.amazonaws.${data.aws_region.current.name}.guardduty-data"
  policy = templatefile("${path.module}/iam_policy_document/vpc_endpoint_gd_data.json", {
    account_id = data.aws_caller_identity.self.account_id
  })
  security_group_ids = [aws_security_group.vpce.id]
  private_dns_enabled = true
  subnet_ids = module.vpc.private_subnets
  tags = {
    Name = "${local.prefix}-vpce-guardduty-data"
  }
}

VPC エンドポイントポリシー

上記のように VPC Endpoint のセキュリティグループは、 ポート 443 を 0.0.0.0/0 で許可する必要があります。そのため、セキュリティをより強固に保つには、 VPC エンドポイントポリシーを利用して、より細かな制御を行う必要があります。

VPC

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Action": "*",
			"Resource": "*",
			"Effect": "Allow",
			"Principal": "*"
		},
		{
			"Condition": {
				"StringNotEquals": {
					"aws:PrincipalAccount": "111122223333" 
				}
			},
			"Action": "*",
			"Resource": "*",
			"Effect": "Deny",
			"Principal": "*"
		}
	]
}
/iam_policy_document/vpc_endpoint_gd_data.json

/iam_policy_document/vpc_endpoint_gd_data.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "*",
      "Resource": "*",
      "Effect": "Allow",
      "Principal": "*"
    },
    {
      "Condition": {
        "StringNotEquals": {
          "aws:PrincipalAccount": "${account_id}"
        }
      },
      "Action": "*",
      "Resource": "*",
      "Effect": "Deny",
      "Principal": "*"
    }
  ]
}

料金

幸いなことに、 EKS Runtime Monitoring が有効かつ、 EKS クラスター上で GuardDuty エージェントを実行している場合(EKS add-onsが有効な場合)、 ランタイムモニタリングのために設置した VPC Endpoint (com.amazonaws.${region}.guardduty-data) は無料で利用できます。

As long as you have enabled EKS Runtime Monitoring and have a GuardDuty agent running on your EKS clusters, you won't get charged for the network costs to send the secure telemetry (Runtime event types) to GuardDuty.

Understanding why GuardDuty chose Amazon VPC endpoint

EKS add-ons の有効化

今回のランタイムモニタリング機能は EKS の add-ons (aws-guardduty-agent) 機能を利用します。

コンソールまたは、AWS CLI, IaC から EKS の add-ons を有効化します。

コンソールからは、「Amazon GuardDuty EKS Runtime Monitoring」と表示されていますが、実際の識別子は aws-guardduty-agent です。

EKS add-ons を有効化すると、 DaemonSet 形式で GuardDuty エージェント (Pod) が配置されていきます。

【抜粋】 eks.tf

eks.tf

resource "aws_eks_addon" "aws_guardduty_agent" {
  cluster_name = aws_eks_cluster.cluster.name
  addon_name = "aws-guardduty-agent"
  addon_version = "v1.0.0-eksbuild.1"
  resolve_conflicts = "OVERWRITE"
}

カバレッジの確認

上記の手順が完了すると、 EKS クラスターがランタイムモニタリングを監視できる状態になります。

カバレッジで 該当する EKS クラスターが Healty になっていることを確認します。

手動管理の場合、カバレッジがすぐに Healty と認識しない可能性があります。

私の場合、半日ほど経過した後にカバレッジが Healty と識別されました。

2023/4/29 追記

カバレッジが Healty になるまで半日経過を要していた部分が、EKS クラスターデプロイから数分で認識される仕様に改善されました!

まとめ

以上、 「Amazon GuardDuty が EKS ランタイムモニタリングをサポートしたため手動でセットアップしてみた」でした。

VPC, EKS クラスター 作成から GuardDuty エージェントのセットアップまでを含めたサンプルコードを以下のレポジトリに載せています。(※ 随時更新します)

takakuni-classmethod/gd-rumtime-protection

ぜひ、カバレッジを有効活用いただき、EKS ランタイムモニタリングをご活用ください。

以上、AWS事業本部コンサルティング部のたかくに(@takakuni_)でした!