コンテナセキュリティ — コンテナだからって安全じゃない
ECSタスクロール、EKS IRSA、ECRスキャンを講義形式で解説
みなさん、おはようございます。今日は、コンテナのセキュリティについて。
「コンテナ」と聞くと、「軽量」「隔離」「安全」というイメージを持つ人が多いでしょう。ですが、その認識は不正確です。実は、コンテナだからこそ発生する特有のセキュリティ課題があります。
イメージの脆弱性、ランタイムのアクセス制御、ネットワーク隔離。ECS や EKS での運用では、これらすべてに対応する必要があります。
コンテナとセキュリティ課題
では、具体的に何が問題か。
- イメージの安全性:Docker イメージの中に、脆弱性のあるライブラリが入ってないか?
- ランタイムのアクセス制御:実行中のコンテナが、何にアクセスできるのか?
- ネットワーク隔離:複数のコンテナが走ってるとき、互いに通信しちゃったら?
——こんなことがあるわけです。
では、これをどう守るか。
ECS での IAM ロール — 「実行ロール vs タスクロール」
AWS で最も一般的なコンテナサービス ECS(Elastic Container Service)では、コンテナを「タスク」と呼びます。Web アプリケーション、バックグラウンドジョブなど、各種ワークロードがタスクとして実行されます。
重要なのは、ECS タスクには 2 つの異なる IAM ロールがあるということです。これを理解していないと、権限設定で落とし穴にはまります。
実行ロール(Task Execution Role)は、ECS エージェント(コンテナオーケストレーターの一部)が使うロールです。役割は、ECR からコンテナイメージをプルする、CloudWatch Logs にログを送信する、Secrets Manager から秘密情報を取得する、といったタスク起動に必要な操作です。
タスクロール(Task Role)は、コンテナ内で実行されるアプリケーション自体が使うロールです。S3 にアクセスする、DynamoDB に書き込む、SQS からメッセージを読む、といったアプリケーション本体の仕事に必要な権限です。
この分離がポイントです。実行ロールはインフラレベルの操作のみを許可し、タスクロールはアプリケーションレベルのビジネスロジック操作のみを許可することで、最小権限の原則が実現されます。
実装例
では、具体的に。
あなたが Web アプリケーションをコンテナ化します。
その Web アプリ——S3 から画像ファイルを読むとします。
では、IAM 設定は——
実行ロールには、ECRからイメージをダウンロードするための権限(GetDownloadUrlForLayer、BatchGetImage)、CloudWatch Logsにログを出力するための権限(CreateLogGroup、CreateLogStream、PutLogEvents)、そしてSecrets Managerから秘密情報を取得する権限が必要です。一方、タスクロールには、S3から特定のバケットに限定してGetObjectする権限だけが必要です。
こうして——実行ロールはね、「ECS の基盤を支える権限」で。
タスクロールはね、「アプリケーション自体の仕事」を担うわけです。
EKS と IRSA — 「Pod 単位の IAM ロール」
では、次のレベルに進みます。
EKS(Elastic Kubernetes Service)です。
Kubernetes を AWS で動かすときに使うサービスですね。
EKS の場合——セキュリティはもっと複雑になります。
なぜなら——Kubernetes はね、複数の Pod(コンテナのグループ)が1つのノード(EC2 インスタンス)で走るから。
では、各 Pod が異なる AWS リソースにアクセスしたいとき——どうするのか?
従来のやり方なら——ノード全体に1つの IAM ロールをアタッチして、全部の Pod がそれを共有する。
でもね——それ、セキュリティ的には最悪なんですよ。
「Pod A は S3 にアクセスしたいけど、Pod B は DynamoDB にアクセスしたい」
——こういう場合に、ノード全体に「S3 + DynamoDB」両方の権限をアタッチすると——Pod A が間違って DynamoDB に触っちゃう可能性がある。
では、どうする?
IRSA(IAM Roles for Service Accounts)です。
これはね——Kubernetes の「Service Account」という仕組みと、AWS IAM ロールを結びつけるメカニズムです。
IRSA の仕組み
具体的には——
- Kubernetes のネームスペース内に「Service Account」を作成する
- その Service Account に、IAM ロールを紐付ける(IRSA によって)
- Pod を起動するときに「このサービスアカウントを使え」と指定する
- Pod が AWS リソースにアクセスするときに、そのロールが使われる
背後では——OpenID Connect(OIDC)という仕組みが働いてます。
でも、ユーザーとしては——「Service Account に IAM ロールを紐付ける」という簡単な操作をするだけです。
結果
では、何が実現されるか?
Pod A:Service Account A を使う → IAM ロール A(S3 のみ) Pod B:Service Account B を使う → IAM ロール B(DynamoDB のみ)
こうして——Pod 単位での最小権限が実現されるわけです。
IRSA = Pod 単位で IAM ロールを割り当てる。Kubernetes らしいセキュリティ。
Pod Identity(新しい選択肢)
あ、ちょっと補足があります。
AWS が最近、Pod Identity という——IRSA の進化版を出しました。
IRSA は OIDC を使ってるんですけど——Pod Identity はね——もっと直接的に Pod に IAM ロールを割り当てる仕組みです。
EKS 1.29 以降で推奨されるやり方になってます。
でも、試験的には——IRSA を理解してれば大丈夫です。
ECR スキャン — 「イメージの脆弱性検査」
では、次のテーマ。
コンテナイメージ自体の安全性です。
あなたが Docker イメージを——ECR(Elastic Container Registry)にプッシュするとします。
その中にね——脆弱性のあるライブラリが混じってたら——どうなるか?
そのイメージをベースに、本番環境でコンテナを起動する。
脆弱性があるから——攻撃者に侵入されちゃう。
では、これを防ぐには?
ECR Image Scanning です。
これはね——ECR にプッシュされたイメージに対して——自動的に脆弱性スキャンを実行するやつです。
スキャンのプロセス
まずDockerイメージをECRにプッシュします。するとECRが自動的にスキャンを開始して、既知の脆弱性データベース、つまりCVEと比較します。脆弱性が見つかったら報告されて、深刻度別に分類されます。クリティカル、ハイ、ミディアム、ロー、インフォメーショナルの5段階です。
——こういう流れです。
で、見つかった脆弱性は——ECR のコンソールに表示されます。
「このイメージに CRITICAL の脆弱性が 3 個、HIGH が 5 個ある」——こんな感じで。
スキャン結果を基に、デプロイを制御
では、脆弱性が見つかったら——デプロイすべきじゃないですよね。
ここで登場するのが——ECR Scan Results Filtering とか、デプロイメント時のポリシー制御です。
例えば——
「CRITICAL の脆弱性が 1 個以上あるイメージは、本番にデプロイさせない」
——こういうルールを設定できるわけです。
CI/CD パイプラインで——
まずDockerイメージをビルドして、ECRにプッシュします。ECRが自動でスキャンして、スキャン結果を確認します。脆弱性がなければEKSにデプロイ。脆弱性があればデプロイ中止。
——こういう流れができるわけです。
ECR Scan = イメージの脆弱性チェック。本番デプロイ前の最後の砦。
CVE とスキャン精度
ちょっと注意があります。
ECR のスキャンはね——既知の脆弱性(CVE)をチェックします。
つまり——CVE データベースに登録されていない、最新の脆弱性は——検出されないんです。
なので、ECR Scan はね——「完全な安全」を保証するものじゃなくて——「既知の危ない脆弱性は避ける」くらいのレベルです。
それでも——やらないより、やったほうが圧倒的にマシです。
Fargate vs EC2 — 「セキュリティの視点から」
ちょっと寄り道をします。
ECS でコンテナを走すとき——2つの選択肢がある。
Fargate:AWS が管理する、サーバーレスコンテナサービス EC2:自分で EC2 インスタンスを管理
セキュリティの観点から——何が違うか?
Fargate の利点
インスタンスを管理しない:
EC2 インスタンスのセキュリティアップデート、パッチ管理——全部を AWS がやってくれます。
つまり——「サーバーのセキュリティ」という概念が消えるわけです。
コンテナイメージだけに集中できる。
隔離性が高い:
Fargate では——基本的に、複数のユーザーのコンテナが同じインスタンスで走りません。
つまり——「隣の Pod が自分の Pod をハッキングする」ってリスクが低い。
EC2 の利点
コスト:
Fargate は割高です。EC2 を自分で管理したほうが——安いことが多い。
カスタマイズ:
EC2 なら——インスタンスタイプ、EBS ボリュームサイズ、ネットワーク設定——自由にカスタマイズできます。
では——セキュリティとコストのトレードオフをどう考えるか?
一般的なガイドライン:
本番環境:Fargate を使う(セキュリティ > コスト) 開発・ステージング:EC2 を使う(コスト < セキュリティ) 機密性が高いワークロード:Fargate 必須
ネットワークセキュリティ — 「Pod 間通信の制御」
では、最後のテーマ。
EKS でね——複数の Pod が走ってるとき——Pod 間の通信をどう制御するか?
例えば——
「Web Pod は通信を受け付ける。Database Pod も Web Pod と通信する。でも、Web Pod 同士は通信しない」
——こういう要件ですね。
ネットワークポリシー
Kubernetes には——Network Policy という仕組みがあります。
これはね——Pod 間のトラフィックを制御するファイアウォールみたいなものです。
例えば——
YAML形式のネットワークポリシーで、tierがdatabaseというラベルを持つPodへのアクセスは、tierがappというラベルを持つPodからのアクセスのみを許可し、プロトコルはTCP、ポートは5432に限定するという定義ができます。
そうするとね——自動的にね、ネットワークルールが適用される。
Database Pod には——App label を持つ Pod からの通信だけが来る。他からの通信は全部ブロック。
Network Policy = Kubernetes 内部のファイアウォール。Pod 間通信を制御。
実務的なセキュリティチェックリスト
では、まとめます。
ECS / EKS でコンテナセキュリティを実装するなら——
- 実行ロール / タスクロール を正しく分離:起動権限と実行権限を分ける
- IRSA を使用(EKS の場合):Pod 単位での最小権限
- ECR Scan を有効化:デプロイ前に脆弱性チェック
- 本番環境なら Fargate を検討:セキュリティ重視の場合
- Network Policy を定義(EKS の場合):Pod 間通信を最小化
これらが——全部統合されるとき——
コンテナは、仮想マシン以上のセキュリティを得るわけです。
隔離性、最小権限、監査可能性——これらが全部、Kubernetes の仕組みの中に組み込まれるから。
では、次のテーマに行きましょう。