解説の構成:
本解説は、ユーザーのブラウザから始まり、AWS上のWebサーバー(ECS上のコンテナ)に到達し、コンテンツが返されるまでの一連の流れを追いながら、各段階で重要となるセキュリティ設定を「層(レイヤー)」に分けて解説していきます。これは「多層防御(Defense in Depth)」というセキュリティの基本的な考え方に基づいています。一つの防御壁が突破されても、次の壁で食い止める、という考え方です。お城を守るのに、城壁だけでなく、堀や石垣、見張り櫓など、複数の防御策を組み合わせるのと同じイメージです。
- Webアクセスの基本的な流れとECS構成の概要
- レイヤー1: 通信経路の保護 (暗号化) - HTTPS/TLS/SSL
- レイヤー2: ネットワーク境界の防御 - WAF, Shield, Security Group, NACL
- レイヤー3: リクエストの振り分けと制御 - ロードバランサー (ALB) のセキュリティ
- レイヤー4: アプリケーション実行環境の保護 - ECS/Fargate のセキュリティ
- レイヤー5: アプリケーション自身の保護 - Webサーバー/アプリケーションの脆弱性対策
- レイヤー6: データの保護 - データストレージのセキュリティ
- レイヤー7: 監視、監査、運用体制 - 継続的なセキュリティ維持
- まとめ: セキュリティはチームで取り組む継続的な活動
それでは、壮大なセキュリティの世界へ旅立ちましょう!
1. Webアクセスの基本的な流れとECS構成の概要
まず、セキュリティ設定の話に入る前に、ブラウザからWebサーバーにアクセスする際の基本的な流れと、今回解説の舞台となるAWS ECS構成について、簡単におさらいしておきましょう。
1.1. ブラウザからWebサーバーへのアクセスの流れ(簡易版)
あなたがブラウザのアドレスバーに https://www.example.com
と入力してエンターキーを押すと、裏側では以下のようなことが起こっています。
-
名前解決 (DNS): ブラウザはまず、
www.example.com
というドメイン名に対応する IPアドレス (インターネット上の住所のようなもの) を知る必要があります。そのために、DNS (Domain Name System) サーバーに問い合わせを行います。「www.example.com
さんの住所はどこですか?」と聞くイメージです。DNSサーバーは、「その住所は192.0.2.1
ですよ」と教えてくれます。 - 接続要求 (TCP/IP): IPアドレスが分かると、ブラウザはそのIPアドレスを持つサーバーに対して、「接続してもいいですか?」と要求を送ります (TCPの3ウェイハンドシェイク)。サーバーが「いいですよ」と応答すると、通信経路が確立されます。
-
リクエスト送信 (HTTP/HTTPS): ブラウザは確立された通信経路を使って、「
www.example.com
のトップページ(通常は/
)の情報をください」という HTTPリクエスト をサーバーに送ります。https://
で始まっている場合は、この通信内容が HTTPS によって暗号化されます。 - サーバー処理: リクエストを受け取ったWebサーバーは、要求されたコンテンツ(HTMLファイル、画像ファイルなど)を探したり、プログラムを実行して動的にコンテンツを生成したりします。
- レスポンス返却 (HTTP/HTTPS): Webサーバーは、用意したコンテンツを HTTPレスポンス としてブラウザに送り返します。これもHTTPSであれば暗号化されています。レスポンスには、コンテンツ本体の他に、処理結果を示すステータスコード(例: 200 OK - 成功, 404 Not Found - 見つからない, 500 Internal Server Error - サーバー内部エラー)などが含まれます。
- コンテンツ表示: ブラウザは受け取ったレスポンス(特にHTML)を解釈し、画面上にWebページとして描画(レンダリング)します。もしHTML内に画像やCSS、JavaScriptファイルへのリンクがあれば、ブラウザはそれらに対しても同様にリクエストを送り、取得して表示に反映させます。
この一連の流れの中で、悪意のある第三者(攻撃者)が情報を盗み見たり、改ざんしたり、サービスを妨害したりしようとする様々な脅威が存在します。だからこそ、各ステップで適切なセキュリティ対策が必要になるのです。
1.2. AWS ECS構成の概要
次に、今回の解説の前提となる AWS ECS (Elastic Container Service) を使った構成について簡単に説明します。ECSは、コンテナ という技術を使ってアプリケーションを実行・管理するためのAWSのサービスです。
- コンテナとは?: アプリケーションとその実行に必要なライブラリや設定などをひとまとめにしたパッケージのようなものです。これにより、「開発環境では動いたのに、本番環境では動かない」といった問題を減らし、どこでも同じようにアプリケーションを実行できます。Docker というツールがコンテナ技術の代表例です。
- ECSとは?: このコンテナをAWS上で簡単に、そして大規模に動かすためのオーケストレーションサービスです。コンテナの起動・停止、スケーリング(負荷に応じてコンテナ数を増減させること)、ヘルスチェック(コンテナが正常に動いているかの確認)などを自動で行ってくれます。
典型的なECSを使ったWebアプリケーションの構成は以下のようになります。
- ユーザー (ブラウザ): Webサイトにアクセスします。
- AWS WAF (Web Application Firewall): 不正なリクエスト(攻撃など)を最初にブロックする壁です。
- Application Load Balancer (ALB): 受け取ったリクエストを、後ろで動いている複数のコンテナ(ECSタスク)に適切に振り分ける役割をします。HTTPSの処理(暗号化・復号)もここで行うことが多いです (TLS終端)。
- AWS Certificate Manager (ACM): HTTPS通信に必要なSSL/TLS証明書を管理・提供します。ALBと連携して使われます。
- ECS Service: 実行するコンテナの数や、どのタスク定義(後述)を使うかなどを管理します。負荷に応じてコンテナ数を自動調整(オートスケーリング)する設定もここで行います。
- ECS Task: 実際にアプリケーションが動いているコンテナ(1つまたは複数)の実行単位です。各タスクは独立した環境で動きます。
- コンテナ (in Task): NginxやApacheといったWebサーバーソフトウェアや、アプリケーションコード(PHP, Java, Python, Node.jsなど)がこの中で動いています。
- Amazon ECR (Elastic Container Registry): コンテナの元となる「イメージ」(設計図のようなもの)を保存しておく場所です。ECSはここからイメージを取得してコンテナを起動します。
- CloudWatch: 各種ログ(ALBアクセスログ、アプリケーションログなど)の収集・監視や、リソース(CPU使用率など)のモニタリング、アラート通知を行います。
- Secrets Manager / Parameter Store: データベースのパスワードなどの機密情報を安全に管理し、コンテナから参照できるようにします。
- IAM (Identity and Access Management): AWSの各サービスへのアクセス権限を管理します。「誰が」「どのリソースに」「何を」できるかを細かく制御します。
- (その他関連サービス): 上記以外にも、脅威検知のGuardDuty、セキュリティ状況を一元管理するSecurity Hub、設定変更を追跡するConfig、API操作ログを記録するCloudTrail、DDoS攻撃から保護するShieldなど、多くのセキュリティ関連サービスが連携して利用されます。
このように、AWS ECS構成では、様々なAWSサービスを組み合わせて、スケーラブル(拡張性がある)で可用性(止まりにくい)の高い、そしてセキュアなWebアプリケーション基盤を構築します。
さあ、準備は整いました。いよいよ各レイヤーでの具体的なセキュリティ設定を見ていきましょう。
2. レイヤー1: 通信経路の保護 (暗号化) - HTTPS/TLS/SSL
ユーザーのブラウザと、AWS上の最初の入口であるALB(またはCloudFrontなどのCDN)との間の通信を保護することは、セキュリティの第一歩であり、非常に重要です。ここで中心となる技術が HTTPS (Hypertext Transfer Protocol Secure) です。
2.1. HTTPSとは何か? なぜ必要なのか?
- HTTP (Hypertext Transfer Protocol): WebブラウザとWebサーバーが情報をやり取りするための基本的なルール(プロトコル)です。しかし、HTTPは通信内容が 平文(暗号化されていない) で送受信されるため、途中で第三者に盗聴されたり、改ざんされたりするリスクがあります。
- HTTPS: HTTPに SSL/TLS (Secure Sockets Layer / Transport Layer Security) という暗号化技術を組み合わせたものです。これにより、通信内容が暗号化され、安全に情報をやり取りできるようになります。
HTTPSを利用する主なメリット(=利用しない場合のリスク):
- 盗聴防止 (機密性): 通信内容が暗号化されるため、途中で第三者に傍受されても、内容を読み取ることが困難になります。これにより、ログイン情報(ID/パスワード)、クレジットカード情報、個人情報などの機密情報を安全に送受信できます。もしHTTP通信でこれらの情報を送ると、ネットワーク上の誰かに丸見えになってしまう可能性があります(カフェのフリーWi-Fiなどは特に危険!)。
- 改ざん防止 (完全性): 通信内容が途中で書き換えられていないことを保証します。例えば、攻撃者がWebサイトからダウンロードするファイルにマルウェアを仕込んだり、表示される情報を偽の情報に書き換えたりすることを防ぎます。
- なりすまし防止 (認証): 通信相手のサーバーが、本当にアクセスしたい正規のサーバーであることを証明します。これは SSL/TLS証明書(サーバー証明書) によって実現されます。証明書には、サーバーの運営組織の情報や、信頼できる第三者機関(認証局, CA)による署名が含まれており、ブラウザはこれを検証することで、接続先が本物であることを確認します。これにより、偽サイト(フィッシングサイト)への誘導を防ぐことができます。
現代のWebサイトにおいて、HTTPSは「必須」です。 Google Chromeなどの主要ブラウザは、HTTPサイトに対して「保護されていない通信」という警告を表示するようになり、ユーザーに不安を与えます。また、Google検索のランキング要因にもHTTPSが使われているため、SEO(検索エンジン最適化)の観点からも重要です。個人情報を扱わないサイトであっても、改ざんやなりすましを防ぎ、ユーザーに安心感を与えるためにHTTPS化は不可欠です。
2.2. AWS Certificate Manager (ACM) による証明書管理
HTTPS通信を行うためには、前述のSSL/TLS証明書が必要です。この証明書は、認証局(CA)から購入するか、Let's Encryptのような無料の認証局を利用して取得する必要があります。証明書には有効期限があり、定期的な更新も必要です。この証明書の管理は、意外と手間がかかる作業でした。
そこでAWSが提供しているのが AWS Certificate Manager (ACM) です。
-
ACMのメリット:
- 無料のパブリック証明書: ACMを利用すると、AWSのサービス(ALB, CloudFrontなど)で利用できるパブリックSSL/TLS証明書を 無料 で発行できます。
- 自動更新: ACMで発行した証明書は、有効期限が近づくと 自動的に更新 されます。これにより、証明書の期限切れによるサービス停止のリスクを大幅に削減できます。これは非常に大きなメリットです!
- 簡単な管理: AWSマネジメントコンソールやAPI/CLIを通じて、証明書の発行、管理、削除が簡単に行えます。
- インポートも可能: 外部の認証局から購入した証明書をACMにインポートして管理することもできます(ただし、この場合は自動更新されません)。
実践的な設定 (ACMでの証明書発行):
- AWSマネジメントコンソールでACMを開きます。
- 「証明書をリクエスト」を選択し、「パブリック証明書をリクエスト」を選びます。
- 証明書が必要なドメイン名(例:
www.example.com
,*.example.com
のようなワイルドカードも可)を入力します。 -
ドメインの所有権の検証方法 を選択します。
- DNS検証 (推奨): ACMが指定するCNAMEレコードを、ドメインを管理しているDNSサーバー(Route 53など)に追加することで検証します。自動でレコードを追加できる場合もあり、最も簡単で確実です。証明書の自動更新のためにもDNS検証が推奨されます。
- Eメール検証: ドメインの管理者として登録されているメールアドレス(admin@example.com など)に送られてくるメール内のリンクをクリックして検証します。手動操作が必要で、更新時にも再度メール確認が必要になる場合があります。
- 検証が完了すると、証明書が発行され、「発行済み」ステータスになります。
これで、ALBなどで利用できる証明書の準備ができました。
2.3. ALBでのTLS終端設定
TLS終端 (TLS Termination) とは、クライアント(ブラウザ)からの暗号化されたHTTPSリクエストを、ロードバランサー (ALB) で受け取り、そこで復号(暗号化を解除)することです。そして、ALBから後ろのECSタスク(Webサーバー)へは、暗号化されていないHTTP通信でリクエストを転送します。
-
TLS終端のメリット:
- 負荷軽減: 暗号化・復号処理はCPUに負荷がかかります。この処理をALBに集中させることで、後ろにある多数のECSタスク(Webサーバー)の負荷を軽減できます。Webサーバーは本来のコンテンツ配信処理に専念できます。
- 証明書管理の集約: SSL/TLS証明書の管理(インストール、更新)をALB一箇所で行えばよいため、管理が非常に楽になります。各Webサーバーに証明書を設定する必要がありません。
- 柔軟なルーティング: ALBはリクエストの内容(パス、ホスト名など)を見て、適切なターゲットグループ(ECSサービスの集合)に振り分けることができますが、そのためにはリクエストの内容を読み取る必要があります。TLS終端を行うことで、ALBがHTTPヘッダーなどを確認できるようになります。
実践的な設定 (ALBリスナー設定):
- AWSマネジメントコンソールでEC2のロードバランサーセクションを開き、対象のALBを選択します。
- 「リスナー」タブを開き、「リスナーの追加」をクリックします。
- プロトコル に HTTPS、ポート に 443 を選択します。
- デフォルトアクション で、「転送先」を選択し、リクエストを転送したいECSサービスが属する ターゲットグループ を指定します。
-
セキュリティポリシー を選択します。これは、ALBがクライアントとのTLS接続で使用する暗号スイート(暗号化アルゴリズムの組み合わせ)やTLS/SSLプロトコルのバージョンを定義するものです。AWSが推奨する最新のポリシー (例:
ELBSecurityPolicy-TLS-1-2-Ext-2018-06
やELBSecurityPolicy-FS-1-2-Res-2020-10
) を選択することが重要です。 古いポリシーは脆弱な暗号化方式を含んでいる可能性があります。 - デフォルトのSSL/TLSサーバー証明書 で、「ACMから」を選択し、先ほどACMで発行またはインポートした証明書を選択します。
- 「リスナーの作成」をクリックします。
ALBからECSタスクへの通信:
通常、ALBでTLS終端を行う場合、ALBからECSタスクへは HTTP で通信します。そのため、ECSタスク側(コンテナ内のWebサーバー)はHTTP (通常ポート80や8080など) でリクエストを受け付けるように設定します。ターゲットグループのヘルスチェックもHTTPで行います。
ただし、より高いセキュリティ要件がある場合(例えば、コンプライアンス要件で内部通信も暗号化が必要な場合など)は、ALBからECSタスクへの通信もHTTPSにすることが可能です(TLS再暗号化)。この場合、ECSタスク側にも証明書が必要になり、管理が少し複雑になります。多くのケースでは、AWSのプライベートネットワーク内での通信は信頼できるものとして、ALBでのTLS終端で十分と判断されます。
2.4. HTTPからHTTPSへのリダイレクト
HTTPSリスナー (ポート443) を設定したら、ユーザーが誤ってHTTP (ポート80) でアクセスしてきた場合にも、自動的にHTTPSに誘導(リダイレクト)するように設定することが推奨されます。これにより、全ての通信が確実に暗号化されるようになります。
実践的な設定 (ALBリスナー ルール):
- ALBのリスナー設定で、HTTP (ポート80) のリスナーを追加または編集します。
- そのリスナーの デフォルトアクション を「リダイレクト先」に設定します。
- リダイレクト設定で、プロトコル を HTTPS、ポート を 443 に指定します。
-
レスポンスコード は「
HTTP_301
(Moved Permanently)」を選択するのが一般的です(SEO的にも有利)。 - 設定を保存します。
これで、http://www.example.com
にアクセスしたユーザーは、自動的に https://www.example.com
に転送されるようになります。
2.5. HSTS (HTTP Strict Transport Security)
HSTSは、一度HTTPSでサイトにアクセスしたブラウザに対して、「次回以降、このサイトには必ずHTTPSで接続してください(HTTPでの接続は試みないでください)」と指示する仕組みです。これはHTTPレスポンスヘッダー (Strict-Transport-Security
) を使って実現されます。
-
HSTSのメリット:
- SSLストリッピング攻撃の防止: 攻撃者が中間者攻撃(Man-in-the-Middle attack)を行い、ユーザーのHTTPS接続を強制的にHTTP接続にダウングレードさせ、通信を盗聴しようとする「SSLストリッピング」という攻撃があります。HSTSが有効になっていると、ブラウザは最初からHTTPSでしか接続しようとしないため、この攻撃を防ぐことができます。
- HTTPリダイレクトの省略: HSTSが有効な場合、ブラウザはHTTPでのアクセスを試みることなく、直接HTTPSでアクセスするため、わずかながらパフォーマンスが向上し、リダイレクト処理中の盗聴リスクもなくなります。
実践的な設定 (ALB or Webサーバー):
HSTSヘッダー (Strict-Transport-Security: max-age=<expire-time>; includeSubDomains; preload
) は、ALBから直接付与することはできません(2023年時点)。そのため、通常は後ろにある ECSタスク内のWebサーバー(Nginx, Apacheなど) または アプリケーション で設定します。
-
Nginxでの設定例 (
nginx.conf
やサイト設定ファイル内):add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
-
max-age
: ブラウザがHSTSポリシーを記憶しておく期間(秒単位)。31536000秒 = 1年。最初は短い期間でテストし、問題なければ長くします。 -
includeSubDomains
: サブドメイン(例:blog.example.com
)にもHSTSポリシーを適用します。サブドメインも全てHTTPS化されている場合に指定します。 -
preload
: HSTSプリロードリストへの登録を申請するためのオプション。主要ブラウザはこのリストに載っているドメインには、初回アクセス時からHTTPSで接続しようとします。登録にはincludeSubDomains
の指定と長いmax-age
が必要です。注意深く検討してから利用します。
-
HSTS設定時の注意点:
- 一度HSTSを設定すると、
max-age
で指定した期間、ブラウザはHTTPでのアクセスを強制的に拒否します。もしHTTPS設定に問題が発生した場合、サイトに全くアクセスできなくなるリスクがあります。そのため、全てのページとリソース(画像、CSS、JSなど)が確実にHTTPSで提供できることを確認してから、max-age
を長く設定するようにしてください。最初は短い期間(例:max-age=300
5分)でテストし、問題がないことを確認してから徐々に延ばしていくのが安全です。 -
preload
を有効にする場合は、そのドメインと全てのサブドメインが永続的にHTTPSで提供される準備が必要です。リストからの削除は簡単ではありません。
3. レイヤー2: ネットワーク境界の防御 - WAF, Shield, Security Group, NACL
通信が暗号化されて安全になったとしても、悪意のあるリクエストそのものがサーバーに到達してしまっては意味がありません。次の防御レイヤーは、AWSネットワークの入口で、不正なトラフィックをフィルタリングし、攻撃からWebアプリケーションを守るための仕組みです。
3.1. AWS WAF (Web Application Firewall)
WAFは、その名の通り、Webアプリケーションを標的とした攻撃(脆弱性を突く攻撃)から守るためのファイアウォールです。ALBやCloudFrontの手前に配置し、HTTP/HTTPSリクエストの内容を検査して、悪意のあるパターン(シグネチャ)に一致するリクエストや、定義したルールに違反するリクエストをブロックします。
WAFで防御できる主な攻撃:
- SQLインジェクション (SQLi): データベースへの不正な問い合わせ(SQL文)を注入し、情報を盗んだり、データを改ざん・削除したりする攻撃。
- クロスサイトスクリプティング (XSS): 悪意のあるスクリプトをWebページに注入し、他のユーザーのブラウザ上で実行させることで、セッション情報(クッキー)を盗んだり、意図しない操作を行わせたりする攻撃。
- OSコマンドインジェクション: Webサーバー上で不正なOSコマンドを実行させる攻撃。
- パス・トラバーサル: 本来アクセスできないはずのサーバー上のファイル(設定ファイルなど)に不正にアクセスしようとする攻撃。
- HTTPフラッド攻撃: 大量のリクエストを送りつけてサーバーを過負荷にし、サービスを提供不能にするDoS (Denial of Service) / DDoS (Distributed DoS) 攻撃の一種。
- ボットによる不正アクセス: 不正なボット(自動化プログラム)によるスクレイピング(情報収集)、スパム投稿、不正ログイン試行など。
AWS WAFの主要機能と設定:
- Web ACL (Access Control List): WAFのルールの集合体です。ALBなどのAWSリソースにこのWeb ACLを関連付けます。
-
ルール (Rules): リクエストを検査するための条件と、条件に一致した場合のアクション(ALLOW, BLOCK, COUNT, CAPTCHA)を定義します。ルールには以下の種類があります。
-
マネージドルール (Managed Rule Groups): AWSやセキュリティベンダー(Marketplace)が提供・管理する、既知の脅威に対応したルールセットです。これを有効にするだけで、多くの一般的な攻撃を防御できます。
-
AWS Managed Rules:
-
Core rule set (CRS)
: OWASP Top 10などの一般的な脆弱性をカバーする基本的なルールセット。まずはこれを有効にすることが強く推奨されます。 -
Known bad inputs rule set
: 既知の悪意のある入力パターンをブロック。 -
SQL database rule set
: SQLインジェクションに特化したルール。 -
PHP application rule set
,WordPress application rule set
など、特定のアプリケーション向けのルールセットもあります。
-
- Marketplace Rules: F5, Imperva, Fortinetなどのセキュリティ専門ベンダーが提供する、より高度で専門的なルールセット(有料)。
-
AWS Managed Rules:
-
カスタムルール (Custom Rules): 自分で条件を定義するルールです。
- IPアドレス制限: 特定のIPアドレスや国からのアクセスを許可またはブロック。
- レートベースルール: 短時間に大量のリクエストを送ってくるIPアドレスからのアクセスを制限(HTTPフラッド対策)。例えば、「5分間に2000リクエストを超えたIPアドレスはブロックする」といった設定が可能です。
- 文字列/正規表現マッチ: リクエストのヘッダー、ボディ、URIなどに特定の文字列やパターンが含まれる場合にブロック。
- サイズ制限: リクエストボディのサイズが異常に大きい場合にブロック。
- カスタムロジック: 複数の条件をAND/ORで組み合わせることも可能です。
-
マネージドルール (Managed Rule Groups): AWSやセキュリティベンダー(Marketplace)が提供・管理する、既知の脅威に対応したルールセットです。これを有効にするだけで、多くの一般的な攻撃を防御できます。
実践的なWAF運用:
- まずはマネージドルール (Core rule set) から: 最初はAWS Managed RulesのCore rule setを COUNTモード で導入し、どのようなリクエストが検知されるかをログで確認します。COUNTモードでは、ルールに一致してもブロックせず、ログに記録するだけなので、正常な通信を誤ってブロックしてしまう(偽陽性 / False Positive)リスクを避けられます。
- ログの監視とチューニング: WAFのログ (CloudWatch LogsやS3に出力可能) を定期的に確認し、誤検知がないか、また検知漏れ(偽陰性 / False Negative)がないかを分析します。誤検知がある場合は、特定のルールを除外したり、カスタムルールで許可したりするチューニングが必要です。逆に、検知すべき攻撃がすり抜けている場合は、ルールを追加・強化します。このチューニング作業がWAF運用の肝となります。
- レートベースルールの活用: アプリケーションの特性に合わせて、適切な閾値でレートベースルールを設定し、ブルートフォース攻撃(総当たり攻撃)やDoS攻撃を緩和します。
-
IPレピュテーションリストの活用: 不正な活動に関与したと知られているIPアドレスリスト(脅威インテリジェンス)を利用して、アクセスを事前にブロックすることも有効です。AWS Managed Rulesにも
Amazon IP reputation list
があります。 - CAPTCHA / Challenge: ボットからのアクセスが疑われる場合に、人間であることを証明させるためのチャレンジ(CAPTCHA画像認証など)を表示させるアクションも利用できます。
- アプリケーションの変更に追随: アプリケーションの仕様変更(新しいAPIエンドポイントの追加など)があった場合、WAFのルールが影響を受けないか、必要に応じてチューニングを行います。
WAFは非常に強力な防御策ですが、設定や運用にはある程度の知識と経験が必要です。しかし、まずはAWS Managed Rulesを導入するだけでも、セキュリティレベルを大幅に向上させることができます。
3.2. AWS Shield
AWS Shieldは、DDoS (Distributed Denial of Service) 攻撃 からアプリケーションを保護するためのマネージドサービスです。DDoS攻撃は、多数の侵害されたコンピューター(ボットネット)から大量の不正なトラフィックを送りつけ、ターゲットのサーバーやネットワークリソースを枯渇させ、サービスを提供不能に陥れる攻撃です。
AWS Shieldには2つのレベルがあります。
-
Shield Standard:
- 無料 で、全てのAWSアカウントで 自動的に有効 になっています。
- ネットワークレイヤー (L3) およびトランスポートレイヤー (L4) での一般的なDDoS攻撃(SYNフラッド、UDPリフレクション攻撃など)を検知し、自動的に緩和します。
- 特別な設定は不要です。ALBやCloudFrontなどのAWSサービスを利用していれば、その恩恵を受けられます。
-
Shield Advanced:
- 有料 のサービスです(月額固定料金 + データ転送料金)。
- より高度で大規模なDDoS攻撃 に対する強化された保護を提供します。アプリケーションレイヤー (L7) の攻撃(HTTPフラッドなど)にも対応します。
- 24時間365日のDDoS対応チーム (DRT - DDoS Response Team) によるサポートが受けられます。攻撃発生時には、DRTが状況を分析し、カスタムの緩和策を適用してくれます。
- 保護対象リソース(ALB, CloudFront, Route 53, Global Accelerator, EC2インスタンスのElastic IP)における DDoS攻撃に起因する利用料金の増加分に対するコスト保護 が受けられます。攻撃によって意図せず高額な請求が発生するリスクを軽減できます。
- 攻撃に関する詳細な診断情報やメトリクス(CloudWatch経由)にアクセスできます。
- AWS WAFが無料で利用可能 になります(WAF自体の利用料はかかりませんが、ルール数に応じた料金は発生します)。Shield Advancedを契約する場合、通常はWAFと組み合わせて利用します。
実践的な考慮事項:
- Shield Standardは基本: まずはShield Standardによる基本的な保護があることを認識しておきましょう。
- Shield Advancedの必要性判断: Shield Advancedが必要かどうかは、アプリケーションの重要度、ダウンタイムの影響度、過去の攻撃経験、予算などを考慮して判断します。ミッションクリティカルなサービスや、過去にDDoS攻撃を受けたことがあるサービス、高い可用性が求められるサービスでは、導入を検討する価値があります。
- WAFとの連携: Shield Advancedを導入する場合、WAFと連携させてL7 DDoS対策を強化することが重要です。例えば、WAFのレートベースルールやカスタムルールを使って、異常なトラフィックパターンを検知・ブロックします。DRTもWAFルールのチューニングを支援してくれます。
- ヘルスチェックの設定: Shield Advancedは、Route 53のヘルスチェックと連携して、攻撃によるサービスの健全性低下を検知し、緩和策をトリガーすることができます。適切なヘルスチェック設定が重要です。
3.3. セキュリティグループ (Security Group - SG)
セキュリティグループは、ECSタスクやALBなどのAWSリソース(具体的にはENI - Elastic Network Interface)に適用される、ステートフルな仮想ファイアウォール です。主に、リソースへの インバウンド(入ってくる通信) と アウトバウンド(出ていく通信) のトラフィックを、プロトコルとポート番号に基づいて制御します。
- ステートフルとは?: 一度許可された通信(例えば、ユーザーからALBへのHTTPSリクエスト)に対する 戻りの通信(ALBからユーザーへのHTTPSレスポンス) は、アウトバウンドルールで明示的に許可しなくても、自動的に許可される という性質を指します。これにより、設定がシンプルになります。
ECS構成におけるセキュリティグループの基本的な設定:
-
ALB用のセキュリティグループ (例:
alb-sg
)-
インバウンドルール:
- ユーザーからのアクセスを許可する必要があります。通常は、世界中(
0.0.0.0/0
および::/0
)からの HTTPS (TCPポート443) を許可します。 - HTTPからHTTPSへのリダイレクトを行う場合は、HTTP (TCPポート80) も同様に許可します。
- もしWAFを使用している場合、 WAFがALBの前にいることを示す マネージドプレフィックスリスト (AWSが管理するWAFのIPアドレス範囲) からのアクセスのみを許可するように設定すると、よりセキュアになります(WAFをバイパスするアクセスを防ぐ)。ただし、この設定は少し高度です。
- ユーザーからのアクセスを許可する必要があります。通常は、世界中(
-
アウトバウンドルール:
- デフォルトでは全ての通信(
0.0.0.0/0
)が許可されていますが、より厳密にするなら、ECSタスクがリッスンしているポート(例: ターゲットグループで設定したポート、通常はHTTPの80や8080など)への通信のみを、ECSタスクが属するセキュリティグループ (ecs-task-sg
) 宛に許可します。
- デフォルトでは全ての通信(
-
インバウンドルール:
-
ECSタスク用のセキュリティグループ (例:
ecs-task-sg
)-
インバウンドルール:
-
ALBからのアクセスのみ を許可します。送信元として、ALBのセキュリティグループ (
alb-sg
) を指定します。ポートは、コンテナ内のWebサーバーがリッスンしているポート(例: TCP 80, 8080)を指定します。これにより、ALBを経由しない不正なアクセスをブロックできます。これが非常に重要です! - 他のリソース(例えば、管理用の踏み台サーバー)からのアクセスが必要な場合は、そのソースIPやセキュリティグループからの必要なポート(SSH: 22など、ただし通常コンテナにはSSHしない)のみを最小限で許可します。
-
ALBからのアクセスのみ を許可します。送信元として、ALBのセキュリティグループ (
-
アウトバウンドルール:
- コンテナが外部(インターネット)や他のAWSサービス(S3, DynamoDB, Secrets Manager, ECRなど)にアクセスする必要がある場合は、その通信を許可します。
-
最小権限の原則: 本当に必要な通信先とポートのみを許可するようにします。例えば、
- 外部へのHTTP/HTTPSアクセスが必要なら、TCP 80, 443 を
0.0.0.0/0
へ許可。 - RDSデータベース (MySQL) へのアクセスが必要なら、TCP 3306 を RDSのセキュリティグループ宛に許可。
- AWSの各種サービスAPI (ECR, Secrets Managerなど) へのアクセスには、HTTPS (TCP 443) のアウトバウンドが必要です。VPCエンドポイント を利用すると、インターネットを経由せずにAWSサービスにアクセスできるため、よりセキュアかつ効率的です(後述)。
- 外部へのHTTP/HTTPSアクセスが必要なら、TCP 80, 443 を
- 何もアウトバウンド通信が必要ない場合は、全て拒否することも検討します。
-
インバウンドルール:
セキュリティグループ運用のベストプラクティス:
-
最小権限の原則: 常に、必要最小限のポートと送信元/送信先のみを許可します。
0.0.0.0/0
(Anywhere) の許可は慎重に行います。特にインバウンドでのAnywhere許可は、ALBのHTTPS/HTTPポート以外では避けるべきです。 -
分かりやすい名前と説明: 各セキュリティグループには、その役割がわかるような名前(例:
my-app-alb-sg
,my-app-ecs-task-sg
,my-app-db-sg
)を付け、説明欄に詳細を記述します。 - グループ化: 関連するリソース(例: 同じアプリケーションのALBとECSタスク)でセキュリティグループを共有せず、役割ごとに個別のセキュリティグループを作成します(ただし、ルールの共通化のために関連付けることはあります)。
- 未使用ルールの削除: 不要になったルールは放置せず、定期的に見直して削除します。
- IaC (Infrastructure as Code) での管理: TerraformやCloudFormationなどのIaCツールを使ってセキュリティグループをコードで管理することで、変更履歴の追跡、レビュー、再現性の確保が容易になります。
セキュリティグループは、AWSネットワークセキュリティの基本であり、正しく設定することが非常に重要です。
3.4. ネットワークACL (Network Access Control List - NACL)
NACLは、セキュリティグループと同様にトラフィックを制御するファイアウォールですが、いくつかの重要な違いがあります。
- 適用レベル: NACLは サブネットレベル で適用されます。そのサブネット内に出入りする全てのトラフィックが対象となります。一方、セキュリティグループはインスタンス(ENI)レベルで適用されます。
- ステートレス: NACLは ステートレス です。つまり、インバウンドで許可した通信に対する 戻りの通信 も、アウトバウンドルールで明示的に許可 する必要があります。例えば、インバウンドでHTTPS (443) を許可した場合、そのレスポンスが戻るためには、アウトバウンドで エフェメラルポート(通常 1024-65535) への通信を許可する必要があります。このため、NACLの設定はセキュリティグループよりも複雑になりがちです。
- ルール評価: NACLのルールには 番号 が付けられており、番号の小さいルールから順に評価 され、最初に一致したルールのアクション(ALLOW or DENY)が適用されます。最後に暗黙のDENYルール(全て拒否)があります。
- 明示的な拒否 (DENY): NACLでは、特定のIPアドレスやポートからの通信を明示的に 拒否 (DENY) するルールを作成できます。セキュリティグループにはDENYルールはありません(許可ルールに一致しないものは暗黙的に拒否される)。
NACLの使い所:
- サブネット全体の防御壁: サブネット全体に対して、明らかに不要または悪意のあるトラフィック(特定の攻撃元IPアドレス、不要なプロトコルなど)を入口/出口でブロックするための追加レイヤーとして使用します。
- セキュリティグループの補完: セキュリティグループの設定ミスがあった場合の保険として、より広範なレベルで基本的なフィルタリングを行います。
- 特定のIPアドレスのブロック: 特定の攻撃元IPアドレスからのアクセスをサブネットレベルで完全に遮断したい場合にDENYルールを使用します。
実践的な考え方:
- デフォルトNACL: デフォルトでは、全てのインバウンドおよびアウトバウンドトラフィックを許可するNACLがVPC作成時に用意されています。多くの場合、セキュリティグループで詳細な制御を行い、NACLはデフォルト(全て許可)のままにしておく ことが多いです。NACLの設定を誤ると、意図しない通信断が発生しやすく、トラブルシューティングも複雑になるためです。
- 利用する場合の注意点: もしNACLでカスタムルールを設定する場合は、ステートレスであることを十分に理解し、戻りの通信のためのエフェメラルポート範囲(TCP 1024-65535)をアウトバウンドで許可することを忘れないでください。また、ルールの評価順序にも注意が必要です。
まとめ: ネットワーク境界防御の多層性
- Shield: DDoS攻撃からの保護 (L3/L4/L7)
- WAF: Webアプリケーションへの攻撃からの保護 (L7)
- Security Group: リソースレベルでの精密なアクセス制御 (ステートフル)
- NACL: サブネットレベルでの広範なアクセス制御 (ステートレス、補助的)
これらのサービスを適切に組み合わせることで、不正なトラフィックがアプリケーションに到達するリスクを大幅に低減できます。
4. レイヤー3: リクエストの振り分けと制御 - ロードバランサー (ALB) のセキュリティ
ALBは単にリクエストを後ろのサーバーに振り分けるだけでなく、セキュリティに関わる重要な機能も担っています。レイヤー1で触れたTLS終端や証明書管理もその一部ですが、他にも考慮すべき点があります。
4.1. TLS終端と証明書管理 (再掲)
- ACMと連携し、最新のSSL/TLS証明書を自動更新・適用します。
- クライアントとの通信を暗号化し、盗聴、改ざん、なりすましを防ぎます。
4.2. セキュリティポリシーの選択
- ALBリスナー設定で選択するセキュリティポリシーは、クライアントとのTLS接続で使用される暗号スイートとプロトコルバージョンを決定します。
-
常にAWSが推奨する最新のポリシーを選択してください。 例えば、古いSSLv3やTLSv1.0/1.1には既知の脆弱性があります。
ELBSecurityPolicy-TLS-1-2-Ext-2018-06
やELBSecurityPolicy-FS-1-2-Res-2020-10
など、TLS 1.2以上をサポートし、前方秘匿性 (Forward Secrecy) を持つ強力な暗号スイートを含むポリシーを選びます。 - 会社のセキュリティポリシーやコンプライアンス要件(例: PCI DSS)によっては、特定のプロトコルバージョンや暗号スイートの使用が義務付けられている場合もあります。
4.3. アクセスログの有効化と分析
- ALBは、受信した全てのリクエストに関する詳細なログ(アクセスログ)を記録し、指定したS3バケットに保存する機能があります。
- アクセスログは必ず有効にしてください。 このログには、リクエスト日時、クライアントIPアドレス、リクエストパス、HTTPメソッド、ステータスコード、レスポンス時間、ユーザーエージェント、TLSバージョン、暗号スイートなど、非常に多くの有用な情報が含まれています。
-
ログの活用:
- トラブルシューティング: アプリケーションのエラー(5xxエラーなど)の原因調査。どのリクエストでエラーが発生したか、どのターゲットに転送されたかなどを追跡できます。
- セキュリティインシデント調査: 不正アクセスや攻撃の試みがあった場合に、攻撃元IPアドレス、攻撃パターン(特定のパスへの集中アクセスなど)、影響範囲などを分析するための重要な証跡となります。
- 利用状況分析: アクセス数の多いページ、アクセス元の地域、利用されているブラウザの種類などを把握し、サービスの改善に役立てます。
- ログ分析基盤: 大量のアクセスログを効率的に分析するために、Amazon Athena (S3上のデータを直接SQLでクエリできるサービス) や Amazon OpenSearch Service (旧 Elasticsearch Service)、あるいはサードパーティのログ管理ツール (Splunk, Datadogなど) と連携させることが一般的です。CloudWatch Logs Insightsでもある程度の分析は可能です。
実践的な設定 (ALBアクセスログ):
- ALBの属性編集画面で、「アクセスログ」セクションの「編集」をクリックします。
- 「有効化」にチェックを入れます。
- ログの保存先となる S3バケット を指定します(必要であれば新規作成)。バケットポリシーが自動で設定され、ALBがログを書き込めるようになります。
- オプションで、ログファイルを分かりやすく整理するための プレフィックス (フォルダ名のようなもの)を指定できます。
- 設定を保存します。ログファイルは通常5〜60分間隔でS3バケットに出力されます。
4.4. 不要なリスナーの削除
- テスト用などに作成した不要なリスナー(特にセキュリティ設定が甘いもの)が残っていると、それが攻撃の侵入口になる可能性があります。
- 定期的にALBのリスナー設定を確認し、現在使用していないリスナーは削除するようにします。
4.5. ALBによる認証機能 (高度な設定)
ALBには、ターゲットのアプリケーションにリクエストを転送する前に、ユーザー認証を行う機能もあります。
- Amazon Cognito連携: AWSのID管理サービスであるCognitoと連携し、ユーザー認証(サインアップ、サインイン、ソーシャルログインなど)をALBレベルで行えます。認証されたユーザーからのリクエストのみをバックエンドに転送する、といったことが可能です。
- OIDC (OpenID Connect) 連携: Google, Facebook, OktaなどのOIDC互換のIDプロバイダー (IdP) と連携し、企業内のSSO (シングルサインオン) 基盤などを使って認証を行えます。
これらの機能を使うと、アプリケーション側での認証実装の負担を軽減できますが、設定はやや複雑になります。特定の社内向けツールや、特定のユーザーグループのみにアクセスを許可したい場合などに有効な選択肢となります。
5. レイヤー4: アプリケーション実行環境の保護 - ECS/Fargate のセキュリティ
いよいよリクエストがアプリケーションを実行するコンテナ環境 (ECS) に到達しました。ここでも様々なセキュリティ対策が必要です。ECSには、コンテナを動かすインフラをAWSが管理する Fargate と、ユーザーがEC2インスタンスを管理する EC2起動タイプ がありますが、ここでは主に両者に共通する点と、Fargate利用を念頭に置いた解説をします(EC2起動タイプの場合は、ホストOSのセキュリティ管理も追加で必要になります)。
5.1. タスク定義 (Task Definition) のセキュリティ設定
タスク定義は、ECSで起動するコンテナの設計図のようなものです。ここで多くの重要なセキュリティ設定を行います。
-
タスク実行IAMロール (ecsTaskExecutionRole):
- 目的: ECS Agent(コンテナを管理するプログラム)が、コンテナイメージをECRからプルしたり、コンテナログをCloudWatch Logsに送信したりするために必要な権限を定義するIAMロールです。
-
設定:
AmazonECSTaskExecutionRolePolicy
というAWS管理ポリシーに必要な権限が含まれています。通常はこのポリシーをアタッチしたロールを作成し、タスク定義で指定します。 - 注意点: このロールに、必要以上の権限(例えば、S3への書き込み権限など)を与えないようにします。あくまでECSがタスクを実行するために最低限必要な権限のみを付与します(最小権限の原則)。
-
タスクIAMロール (taskRole):
- 目的: コンテナ内で実行されるアプリケーション が、他のAWSサービス(S3, DynamoDB, Secrets Manager, SQSなど)にアクセスするために必要な権限を定義するIAMロールです。
- 設定: アプリケーションが必要とするAWSリソースへのアクセス権限(例: 特定のS3バケットへの読み取り権限、特定のDynamoDBテーブルへの書き込み権限)だけを許可するカスタムIAMポリシーを作成し、それをアタッチしたロールをタスク定義で指定します。
- 非常に重要: このロールを適切に設定することで、AWSアクセスキーやシークレットキーをコードや設定ファイルにハードコードする必要がなくなります。 アプリケーションはAWS SDKを通じて、自動的にこのロールの一時的な認証情報を取得してAWS APIを呼び出すことができます。これはセキュリティ上、非常に大きなメリットです。絶対にアクセスキーをコンテナ内に埋め込まないでください!
-
最小権限の徹底: アプリケーションが本当に必要とするアクションとリソースに限定して権限を付与します。例えば、「S3の全バケットへのフルアクセス (
s3:*
)」のような広範な権限は絶対に避け、「特定のバケット (my-app-data-bucket
) へのオブジェクト読み取り (s3:GetObject
) と書き込み (s3:PutObject
) のみ許可」のように具体的に指定します。IAM Access Analyzerなどのツールを活用して、付与した権限が実際に使われているか、過剰でないかを確認することも有効です。
-
ネットワークモード (Network Mode):
-
awsvpc
モード (推奨): 各ECSタスクに独自の ENI (Elastic Network Interface) とプライベートIPアドレスが割り当てられます。これにより、タスクごとに個別のセキュリティグループを適用 できるため、きめ細やかなネットワーク制御が可能になります。Fargateではawsvpc
モードが必須です。 -
bridge
モード: コンテナはホストEC2インスタンスのネットワーク名前空間を共有します(Dockerのデフォルトと同様)。ポートマッピングが必要になり、タスクごとのセキュリティグループ制御はできません。 -
host
モード: コンテナはホストEC2インスタンスのネットワークを直接使用します。ポートの競合が発生しやすく、セキュリティリスクも高まるため、通常は避けるべきです。 -
結論: 可能であれば常に
awsvpc
モードを使用し、タスク単位でのセキュリティグループ制御を活用しましょう。
-
-
セキュリティグループの関連付け:
awsvpc
モードを使用する場合、タスク定義またはサービス作成時に、ECSタスクに適用するセキュリティグループを指定します。前述の通り、このセキュリティグループ (ecs-task-sg
) のインバウンドルールでは、ALBのセキュリティグループ (alb-sg
) からのアクセスのみを許可するように設定します。 -
読み取り専用ルートファイルシステム (ReadOnlyRootFilesystem):
- コンテナ定義でこのオプションを
true
に設定すると、コンテナのルートファイルシステムが読み取り専用になります。 - メリット: もしコンテナ内で動作するアプリケーションに脆弱性があり、攻撃者によって不正なコードが実行されたとしても、ファイルシステムへの書き込み(マルウェアの設置、設定ファイルの改ざんなど)を防ぐことができます。これにより、攻撃の影響を局所化できます。
- 注意点: アプリケーションが一時ファイルなどをファイルシステムに書き込む必要がある場合は、別途 ボリューム (Volume) をマウントし、そのボリュームに対して書き込みを行うようにアプリケーションを改修する必要があります。Fargateでは、タスクに紐づく一時的なエフェメラルストレージ(デフォルトで20GiB)があり、これをボリュームとしてマウントできます。
- コンテナ定義でこのオプションを
-
特権コンテナ (Privileged) の回避:
- コンテナ定義の
privileged
オプションは、コンテナにホストOSに対するほぼ全ての権限(ルート権限に近い)を与えます。これは、コンテナの分離性を破壊し、深刻なセキュリティリスクをもたらします。 -
特別な理由がない限り、絶対に
privileged
をtrue
に設定しないでください。 通常のWebアプリケーションでは必要ありません。もし必要だと感じた場合は、設計を見直すことを検討してください。
- コンテナ定義の
-
リソース制限 (CPU, Memory):
- タスク定義またはコンテナ定義で、各タスク/コンテナが使用できるCPUユニットとメモリ量を指定します。
-
目的:
- パフォーマンスの安定化: 他のタスクによるリソースの使いすぎを防ぎ、安定したパフォーマンスを確保します。
- コスト管理: 無駄なリソース消費を抑えます。
- DoS攻撃への耐性向上: あるコンテナが攻撃を受けて暴走した場合でも、他のコンテナやホストへの影響を制限します。
- 適切な値を見つけるには、負荷テストや実際の運用モニタリングが必要です。
5.2. コンテナイメージのセキュリティ
ECSで実行するコンテナは、コンテナイメージ を元に作成されます。このイメージ自体に脆弱性が含まれていては、いくらインフラ側のセキュリティを固めても意味がありません。
-
信頼できるベースイメージの使用:
- コンテナイメージを作成する際の元となる ベースイメージ は、公式リポジトリ(Docker Hubの公式イメージなど)や、信頼できる提供元からのものを利用します。出所の不明なイメージは、マルウェアが仕込まれている可能性があります。
- Alpine Linux ベースのイメージや、Distroless イメージ(アプリケーションの実行に必要な最低限のランタイムのみを含むイメージ)など、軽量で、含まれるパッケージが少ない イメージを選択することで、攻撃対象領域(Attack Surface)を減らすことができます。
-
Dockerfileのベストプラクティス:
-
最小限のパッケージ: コンテナイメージには、アプリケーションの実行に本当に必要なパッケージやライブラリのみをインストールします。不要なツール(
curl
,wget
,netcat
など)や開発用ライブラリは含めないようにします。マルチステージビルドを活用すると、最終的なイメージからビルド時のみに必要なツールを除去できます。 -
USER
命令の使用: Dockerfileの最後でUSER
命令を使い、コンテナ内のプロセスを 非rootユーザー で実行するようにします。もしコンテナ内でコード実行の脆弱性が悪用された場合でも、root権限を奪われるリスクを低減できます。 - 機密情報を含めない: Dockerfileやイメージ内に、パスワード、APIキー、証明書などの機密情報を絶対にハードコードしないでください。これらは後述するSecrets Managerなどを利用して外部から注入します。
-
最小限のパッケージ: コンテナイメージには、アプリケーションの実行に本当に必要なパッケージやライブラリのみをインストールします。不要なツール(
-
ECR (Elastic Container Registry) イメージスキャン:
- ECRは、リポジトリにプッシュされたコンテナイメージに対して、既知の脆弱性 (CVE - Common Vulnerabilities and Exposures) をスキャンする機能を提供しています。
- 「スキャンオンプッシュ (Scan on push)」 を有効にしておくことで、イメージがプッシュされるたびに自動的にスキャンが実行されます。
- スキャン結果(脆弱性の深刻度、CVE番号、修正可能なバージョンなど)は、AWSコンソールやAPIで確認できます。
-
運用:
- CI/CDパイプラインにイメージスキャンを組み込み、重大 (Critical) または高 (High) の脆弱性 が見つかった場合は、デプロイをブロックするなどのルールを設定します。
- 定期的にECRのスキャン結果を確認し、新たに見つかった脆弱性に対応(ベースイメージの更新、ライブラリのアップデートなど)します。
- 全ての脆弱性にすぐ対応できるとは限りませんが、リスクを評価し、対応計画を立てることが重要です。
- サードパーティツールによるスキャン: ECRのスキャン機能に加えて、Trivy, Clair, Sysdig Falco などのオープンソースまたは商用のコンテナセキュリティツールをCI/CDパイプラインやレジストリに組み込んで、より詳細なスキャンやポリシーチェックを行うことも一般的です。これらのツールは、OSパッケージだけでなく、アプリケーションの依存ライブラリ(Node.jsのnpmパッケージ, Pythonのpipパッケージなど)の脆弱性も検出できる場合があります。
5.3. シークレット管理
アプリケーションは、データベースのパスワード、外部サービスのAPIキー、証明書の秘密鍵など、様々な機密情報(シークレット)を必要とします。これらの情報を安全に管理し、コンテナに渡すことは非常に重要です。
-
やってはいけないこと:
- コードや設定ファイルにハードコードする: 最も危険な方法です。コードが漏洩した場合、シークレットも漏洩します。
- コンテナイメージに含める: イメージが外部に流出するリスクがあります。
-
環境変数に直接設定する (プレーンテキストで):
docker inspect
やコンテナ内のプロセスから容易に参照できてしまうため、安全ではありません。特にタスク定義に直接プレーンテキストで記述するのは避けるべきです。
-
推奨される方法: AWS Secrets Manager / AWS Systems Manager Parameter Store の利用:
- AWS Secrets Manager: シークレットの保存、ローテーション(自動更新)、アクセス制御に特化したサービスです。データベース認証情報などの自動ローテーション機能が強力です。料金はシークレットごと、APIコールごとに発生します。
-
AWS Systems Manager Parameter Store: 設定データやシークレットをキーと値のペアで保存できるサービスです。
SecureString
タイプを選択すると、KMS (Key Management Service) を使って暗号化して保存できます。標準パラメータは無料枠が大きく、比較的安価に利用できます。シークレットのローテーション機能はSecrets Managerほど充実していません。 - どちらを選ぶか?: 高度なローテーション機能やライフサイクル管理が必要な場合はSecrets Manager、シンプルなキーバリュー管理で十分な場合やコストを抑えたい場合はParameter Store (SecureString) が選択肢になります。両方を使い分けることも一般的です。
-
ECSタスク定義での参照方法:
- Secrets ManagerまたはParameter Storeに必要なシークレットを登録します。
- タスク定義のコンテナ定義セクションで、環境変数 (
environment
) やシークレット (secrets
) の設定項目を使用します。 -
secrets
オプション (推奨):- 環境変数名を指定し、その値として Secrets ManagerのシークレットARN または Parameter StoreのパラメータARN を
valueFrom
で指定します。 - 例 (Secrets Manager):
"secrets": [ { "name": "DATABASE_PASSWORD", "valueFrom": "arn:aws:secretsmanager:region:account-id:secret:my-db-secret-name-AbCdEf" } ]
- 例 (Parameter Store):
"secrets": [ { "name": "API_KEY", "valueFrom": "arn:aws:ssm:region:account-id:parameter/my-app/api-key" } ]
- この方法を使うと、ECS Agentがコンテナ起動時に指定されたシークレットを取得し、環境変数としてコンテナに設定します。タスク実行IAMロール (ecsTaskExecutionRole) に、該当するシークレットへのアクセス権限 (
secretsmanager:GetSecretValue
やssm:GetParameters
) が必要です。
- 環境変数名を指定し、その値として Secrets ManagerのシークレットARN または Parameter StoreのパラメータARN を
- アプリケーションからの直接取得: コンテナ内のアプリケーションがAWS SDKを使い、タスクIAMロール (taskRole) の権限でSecrets ManagerやParameter Storeから直接シークレットを取得する方法もあります。この場合、シークレットを環境変数として公開する必要がなく、より安全です。ただし、アプリケーション側での対応が必要になります。
-
IAMポリシーによるアクセス制御: Secrets ManagerやParameter Storeに保存されたシークレットへのアクセスは、IAMポリシーで厳密に制御します。タスク実行IAMロールやタスクIAMロールには、必要最小限のシークレットに対する読み取り権限のみ を付与します。
5.4. Fargate利用時の考慮事項
Fargateを使用する最大のメリットは、基盤となるEC2インスタンスのOS管理(パッチ適用、セキュリティ設定など)をAWSに任せられる ことです。これにより、運用負荷が大幅に軽減され、ホストOSレベルの脆弱性を心配する必要が少なくなります。AWSが責任を持ってインフラのセキュリティを維持してくれます(責任共有モデル)。ただし、コンテナイメージ、アプリケーション、IAMロール、ネットワーク設定など、ユーザーが管理する部分のセキュリティは引き続きユーザーの責任です。
5.5. EC2起動タイプ利用時の考慮事項 (参考)
もしEC2起動タイプを使用する場合は、以下の追加のセキュリティ対策が必要です。
-
ホストOSのセキュリティ強化 (Hardening):
- ECS用に最適化されたAMI(Amazon Machine Image)を使用します。
- OSへのパッチ適用を定期的に行います(Systems Manager Patch Managerなどを活用)。
- 不要なサービスやポートを無効化します。
- CISベンチマークなどのセキュリティ基準に従って設定を強化します。
- ECS Agentの更新: ホストOS上で動作するECS Agentも定期的に最新バージョンに更新する必要があります。
- ホストへのアクセス制御: EC2インスタンスへのSSHアクセスは、必要な担当者に限定し、踏み台サーバー(Bastion Host)経由にする、IAMと連携したアクセス管理(Systems Manager Session Managerなど)を利用するなどの対策を行います。セキュリティグループでもアクセス元を厳しく制限します。
- Dockerデーモンのセキュリティ設定: Dockerデーモンの設定も確認し、セキュリティリスクがないか確認します。
Fargateはこのあたりの運用負荷をなくしてくれるため、多くのケースで推奨される選択肢となっています。
6. レイヤー5: アプリケーション自身の保護 - Webサーバー/アプリケーションの脆弱性対策
これまでインフラ側のセキュリティ対策を見てきましたが、最終的にユーザーのリクエストを処理するのはコンテナ内で動作するWebサーバー(Nginx, Apacheなど)と、その上で動くアプリケーション(PHP, Java, Python, Node.js, Rubyなどで書かれたコード)です。これら自体に脆弱性があっては、せっかくの多層防御も突破されてしまいます。
6.1. OS/ミドルウェアのセキュリティ
コンテナイメージに含まれるOS(Alpine, Ubuntuなど)やミドルウェア(Nginx, Apache, PHP, Node.jsなど)にも脆弱性が見つかることがあります。
-
パッチ管理/バージョンの更新:
-
ベースイメージの定期的な再ビルド: 使用しているベースイメージ(例:
node:18-alpine
)の新しいバージョンがリリースされたら、定期的にイメージを再ビルドし、最新のセキュリティパッチが適用された状態を維持します。CI/CDパイプラインに組み込んで自動化するのが理想です。 - ミドルウェア/ライブラリの更新: アプリケーションが依存しているミドルウェアやライブラリ(例: Nginx, OpenSSL, Log4j)にも脆弱性が見つかることがあります。ECRイメージスキャンや他の脆弱性スキャンツールで検出された場合は、速やかにアップデートします。
-
ベースイメージの定期的な再ビルド: 使用しているベースイメージ(例:
- 不要なサービス/モジュールの無効化: Webサーバー(Nginx, Apache)の設定で、使用していないモジュールは無効化します。これにより、攻撃対象領域を減らすことができます。
-
設定ファイルの保護: 設定ファイル(
nginx.conf
,.htaccess
など)に不要な情報(コメントアウトされた機密情報など)を残さないようにし、ファイルパーミッションを適切に設定して、Webサーバープロセスが必要最低限の権限でアクセスできるようにします。
6.2. アプリケーション自体の脆弱性対策 (OWASP Top 10 を例に)
Webアプリケーションの脆弱性は多岐にわたりますが、OWASP (Open Web Application Security Project) が定期的に発表している OWASP Top 10 は、最も一般的で危険度の高い脆弱性のリストとして広く認知されています。開発者はこれらの脆弱性を理解し、対策を講じる必要があります。ECS環境における対策も含めて見ていきましょう。
(注: OWASP Top 10 は数年ごとに更新されます。ここでは代表的なものを挙げます)
-
A01: アクセス制御の不備 (Broken Access Control):
- 内容: 認証されたユーザーが、本来アクセス権限のない機能やデータにアクセスできてしまう脆弱性。例: 一般ユーザーが管理者ページにアクセスできる、他のユーザーの情報を閲覧・編集できる。
-
対策:
- 認証と認可の分離: ログインしているか(認証)だけでなく、その操作を行う権限があるか(認可)を全てのアクセスに対してサーバーサイドで厳密にチェックする。
- 最小権限の原則: ユーザーには必要最低限の権限のみを付与する。
- 推測されにくいIDを使用する(例: 連番でないUUIDなど)。
- フレームワークのアクセス制御機能を活用する。
- ECS環境での考慮: タスクIAMロールも最小権限にし、アプリケーションが不正に高い権限でAWSリソースにアクセスできないようにする。
-
A02: 暗号化の失敗 (Cryptographic Failures):
- 内容: 機密データ(パスワード、クレジットカード情報、個人情報など)の保護が不十分な状態。平文での保存・転送、古い・弱い暗号化アルゴリズムの使用など。
-
対策:
- 転送時の暗号化: HTTPSを常に使用する (レイヤー1で対策済み)。ALBとECS間の通信も必要なら暗号化。
- 保管時の暗号化: パスワードは強力なハッシュ関数(bcrypt, Argon2など)とソルトを用いてハッシュ化して保存する。その他の機密データは、強力な暗号化アルゴリズム(AES-256など)で暗号化して保存する。AWS KMSを利用して暗号鍵を安全に管理する。
- キャッシュされたデータの保護: 機密情報がキャッシュ(ブラウザキャッシュ、サーバーキャッシュ)に平文で残らないようにする。
- ECS環境での考慮: Secrets ManagerやParameter Store (SecureString) を活用し、機密情報を安全に管理・注入する。
-
A03: インジェクション (Injection):
- 内容: 信頼できない入力データを、SQLクエリ、OSコマンド、LDAPクエリなどにそのまま組み込んでしまい、意図しない命令を実行させてしまう脆弱性。SQLインジェクションが代表例。
-
対策:
- サーバーサイドでの入力値検証: 入力値が期待される形式・型・範囲であることを検証する。
-
エスケープ処理: 特殊な意味を持つ文字(例: SQLの
'
や--
)を無害化(エスケープ)してからクエリなどに組み込む。 - プレースホルダ (Prepared Statements) の使用 (SQLi対策): SQLクエリの骨組みを先にデータベースに送り、後から入力値をパラメータとして渡す方式。入力値がSQL文の一部として解釈されるのを防ぐ最も効果的な対策。
- ORM (Object-Relational Mapping) の安全な使用: ORMライブラリが提供する安全なAPIを使用する。
- ECS環境での考慮: WAF (レイヤー2) でSQLインジェクションなどの攻撃パターンを検知・ブロックする。
-
A04: 安全でない設計 (Insecure Design):
- 内容: アプリケーションの設計・アーキテクチャ段階での考慮不足に起因する脆弱性。ビジネスロジックの欠陥など。これはコードレベルのバグというより、根本的な設計の問題。
-
対策:
- 脅威モデリング: 設計段階で潜在的な脅威や攻撃経路を洗い出し、対策を組み込む。
- セキュア設計原則の適用: 最小権限、多層防御、フェイルセーフなどの原則を設計に取り入れる。
- セキュリティ要件を明確化し、設計レビューを行う。
- ECS環境での考慮: AWS Well-Architected Frameworkのセキュリティの柱などを参考に、クラウドネイティブなセキュア設計を行う。
-
A05: セキュリティ設定ミス (Security Misconfiguration):
- 内容: OS、ミドルウェア、フレームワーク、アプリケーションなどのセキュリティ設定がデフォルトのままだったり、不適切だったりすることによる脆弱性。不要な機能の有効化、デフォルトパスワードの使用、エラーメッセージでの詳細情報の表示など。
-
対策:
- 設定のレビューと強化 (Hardening): 各コンポーネントのセキュリティ設定をレビューし、不要な機能を無効化、デフォルトパスワードの変更、最小権限の設定などを行う。CISベンチマークなどを参考にする。
- エラーハンドリング: 詳細なエラーメッセージ(スタックトレースなど)をユーザーに見せないようにする。ログには記録する。
- 自動化された設定チェック: AWS Configやサードパーティツールで設定の不備を継続的にチェックする。
- ECS環境での考慮: タスク定義、セキュリティグループ、IAMロールなどのAWSリソースの設定ミスがないか確認する。CloudFormation GuardやTerraformのチェックツールをCI/CDに組み込む。
-
A06: 脆弱性のあるコンポーネントや古いコンポーネントの使用 (Vulnerable and Outdated Components):
- 内容: 利用しているライブラリ、フレームワーク、その他のソフトウェアコンポーネントに既知の脆弱性が存在する場合。Log4Shell (Log4jの脆弱性) が記憶に新しい例。
-
対策:
- 依存関係の管理: 使用している全てのコンポーネント(OSパッケージ、ライブラリ、フレームワーク)とそのバージョンを把握する。
- 脆弱性スキャン: ECRイメージスキャン、GitHub Dependabot, Snyk, Trivyなどのツールを使って、依存関係に含まれる既知の脆弱性を定期的にスキャンする。
- コンポーネントの更新: 脆弱性が見つかった場合は、速やかにパッチ適用またはバージョンアップを行う。サポートが終了したコンポーネントは使用しない。
- 不要な依存関係の削除: 使用していないコンポーネントは削除する。
- ECS環境での考慮: CI/CDパイプラインでコンテナイメージと依存関係のスキャンを必須とし、重大な脆弱性があればデプロイを停止する。
-
A07: 認証・識別の失敗 (Identification and Authentication Failures):
- 内容: ユーザー認証(本人確認)やセッション管理に関する脆弱性。推測されやすいパスワード、ブルートフォース攻撃への対策不足、セッションIDの漏洩・固定化など。
-
対策:
- 強固なパスワードポリシー: 長さ、複雑さの要件、定期的な変更推奨。
- ブルートフォース対策: アカウントロックアウト、CAPTCHA、レート制限などを導入する。
- 多要素認証 (MFA) の導入: パスワードに加えて、別の認証要素(SMSコード、認証アプリなど)を要求する。特に重要な操作や管理者アカウントには必須。
- 安全なセッション管理: 推測困難で長いセッションIDを使用し、HTTPSでのみ送信 (Secure属性)、ログアウト時に無効化、定期的なタイムアウト設定。
- クレデンシャルスタッフィング対策: 他のサイトから漏洩したID/パスワードリストを使った不正ログイン試行を検知する仕組み。
- ECS環境での考慮: ALBの認証機能 (Cognito連携など) や、AWS WAFのレートベースルール、ボット対策機能などを活用する。
-
A08: ソフトウェアとデータの整合性の不備 (Software and Data Integrity Failures):
- 内容: ソフトウェアの更新プロセス(CI/CDパイプラインなど)や、アプリケーションが利用するデータの完全性が検証されていないことによる脆弱性。安全でないデシリアライゼーションなど。
-
対策:
- CI/CDパイプラインの保護: パイプライン自体へのアクセス制御、コード署名、依存関係の検証(SBOM - Software Bill of Materials の活用など)。
- 安全でないデシリアライゼーション対策: 外部からのシリアライズされたデータをデシリアライズ(オブジェクトに戻す)する際には、入力値を厳密に検証するか、安全な代替フォーマット(JSONなど)を使用する。可能な限り避ける。
- データの完全性チェック: 重要なデータには署名やハッシュ値を用いて、改ざんされていないか検証する。
- ECS環境での考慮: ECRからプルするイメージが改ざんされていないことを確認する(ECRは自動でチェック)。CI/CDパイプラインでコード署名や脆弱性スキャンを徹底する。
-
A09: セキュリティログとモニタリングの不備 (Security Logging and Monitoring Failures):
- 内容: 攻撃や不正なアクティビティを検知・調査するために必要なログが十分に記録されていなかったり、監視されていなかったりする状態。
-
対策: (レイヤー7で詳述)
- 十分なログ記録: ログイン試行(成功・失敗)、アクセス制御の失敗、入力値検証エラー、サーバーエラーなど、セキュリティイベントに関するログを十分に記録する。
- ログの一元管理と分析: ログを中央のシステム(CloudWatch Logs, OpenSearchなど)に集約し、リアルタイムで監視・分析する。
- アラート設定: 不審なアクティビティ(多数のログイン失敗、アクセス拒否の多発など)が検知された場合にアラートを発生させる。
- インシデント対応計画: インシデント発生時の対応手順を定め、訓練しておく。
- ECS環境での考慮: CloudWatch Logs, CloudTrail, GuardDuty, Security HubなどのAWSサービスを最大限活用する。
-
A10: サーバーサイドリクエストフォージェリ (SSRF - Server-Side Request Forgery):
- 内容: 攻撃者が、脆弱なWebアプリケーションを騙して、サーバー自身(またはサーバーからアクセス可能な内部ネットワーク上の他のサーバー)に対して意図しないリクエストを送信させる攻撃。内部システムの情報漏洩や不正操作につながる可能性がある。
-
対策:
- 入力値検証: アプリケーションが外部から受け取ったURLやホスト名を元にリクエストを送信する場合、その宛先を厳密に検証する。
- 許可リスト (Allow List) の使用: サーバーからのリクエスト送信先を、既知の安全なドメインやIPアドレスのリストに限定する。拒否リスト (Deny List) はバイパスされる可能性があるため不十分。
- ネットワークレベルでの制御: セキュリティグループやNACLで、ECSタスクからアクセスできる内部ネットワークの範囲を最小限に制限する。
- メタデータサービスへのアクセス制限: EC2インスタンスメタデータサービス (IMDS) へのアクセスが必要ない場合は、コンテナレベルで無効化するか、IMDSv2(セッション指向の認証が必要)の使用を強制する。FargateではデフォルトでタスクIAMロールの認証情報エンドポイントへのアクセスは制限されているが、他のメタデータへのアクセスは注意が必要。
- ECS環境での考慮: タスクIAMロールの権限を最小限にし、仮にSSRFが成功しても攻撃者が得られる権限を限定する。セキュリティグループでアウトバウンド通信を厳しく制限する。VPCエンドポイントを活用し、パブリックIPを持たないリソースへのアクセス経路を限定する。
これらのOWASP Top 10対策は、セキュアコーディングの基本となります。開発チーム全体で意識を高め、コードレビューや静的/動的アプリケーションセキュリティテスト (SAST/DAST) を実施することが重要です。
6.3. Content Security Policy (CSP)
CSPは、クロスサイトスクリプティング (XSS) やデータインジェクション攻撃を緩和するための追加のセキュリティレイヤーです。これは、Webサーバーがブラウザに対して、「このページでは、どのオリジン(ドメイン)から読み込んだスクリプト、スタイルシート、画像などを信頼するか」を指定するHTTPレスポンスヘッダー (Content-Security-Policy
) です。
-
仕組み: ブラウザはCSPヘッダーを受け取ると、そこで指定されたポリシーに従います。例えば、「スクリプトは自ドメイン (
self
) とhttps://apis.google.com
からのみ許可する」というポリシーが設定されている場合、他のドメインから読み込もうとしたスクリプトや、HTML内に直接記述されたインラインスクリプトは実行されません。 - メリット: たとえアプリケーションにXSS脆弱性が存在し、攻撃者がスクリプトを注入できたとしても、CSPによってそのスクリプトの実行をブラウザレベルで防ぐことができます。
-
設定方法: Nginx, Apache, またはアプリケーションコードで
Content-Security-Policy
ヘッダーを出力します。ポリシーの定義は非常に柔軟ですが、設定は複雑になることもあります。最初はreport-uri
ディレクティブを使って違反レポートを収集するモードで開始し、徐々にポリシーを強化していくのが安全です。-
例 (比較的厳格なポリシー):
(これはあくまで例であり、サイトの構成に合わせて調整が必要です)
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com; style-src 'self' https://trusted-cdn.com; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';
-
例 (比較的厳格なポリシー):
6.4. その他のセキュリティヘッダー
CSP以外にも、設定しておくことが推奨されるセキュリティ関連のHTTPレスポンスヘッダーがあります。これらもWebサーバーやアプリケーションで設定します。
-
X-Frame-Options
: クリックジャッキング攻撃(透明なiframeを重ねてユーザーに意図しないクリックをさせる攻撃)を防ぐために、他のサイトが自サイトを<iframe>
や<frame>
,<object>
で埋め込むことを許可するかどうかを指定します。通常はDENY
(全ての埋め込みを拒否) またはSAMEORIGIN
(同一オリジンからのみ許可) を設定します。 -
X-Content-Type-Options
: ブラウザがContent-Type
ヘッダーを無視してMIMEタイプを推測(MIMEスニッフィング)するのを防ぎます。MIMEスニッフィングが悪用されると、本来スクリプトではないファイルがスクリプトとして実行されるなどのリスクがあります。通常はnosniff
を設定します。 -
Referrer-Policy
: ユーザーがリンクをクリックして他のサイトに遷移する際に、Referer
ヘッダーでどの程度の情報を送信するかを制御します。プライバシー保護や情報漏洩リスクの観点から、strict-origin-when-cross-origin
(推奨) やno-referrer
などを設定します。 -
Permissions-Policy
(旧Feature-Policy
): ブラウザが持つ特定の機能(カメラ、マイク、位置情報など)へのアクセスを、サイト自身または埋め込まれたiframeに対して許可するかどうかを制御します。不要な機能へのアクセスを制限することで、プライバシーとセキュリティを向上させます。
これらのヘッダーを設定することで、ブラウザ側での防御機能を強化できます。
7. レイヤー6: データの保護 - データストレージのセキュリティ
Webアプリケーションは、多くの場合、データベース (RDS, DynamoDBなど) やオブジェクトストレージ (S3) などのデータストアを利用します。これらのデータストア自体のセキュリティと、そこに保存されるデータの保護も非常に重要です。
7.1. データベース (RDS, DynamoDBなど) へのアクセス制御
-
ネットワークレベルの制御 (セキュリティグループ):
- データベースリソース(RDSインスタンス、DynamoDB VPCエンドポイントなど)に専用のセキュリティグループ(例:
db-sg
)を設定します。 -
インバウンドルール: ECSタスクのセキュリティグループ (
ecs-task-sg
) からの、データベースが必要とするポート(例: MySQL/Aurora: 3306, PostgreSQL: 5432)へのアクセスのみを許可します。絶対に0.0.0.0/0
(Anywhere) からのアクセスを許可しないでください。 - アウトバウンドルール: 通常、データベースから外部への通信は不要なため、アウトバウンドは全て拒否するか、必要な場合のみ最小限に許可します。
- データベースリソース(RDSインスタンス、DynamoDB VPCエンドポイントなど)に専用のセキュリティグループ(例:
-
認証:
- 強力なパスワード: データベースユーザーには、推測困難で十分に長いパスワードを設定します。
- パスワード管理 (Secrets Manager連携): データベースのマスターパスワードやアプリケーション用ユーザーのパスワードは、AWS Secrets Managerで管理し、定期的にローテーション(自動更新)するように設定するのがベストプラクティスです。アプリケーションはタスクIAMロールの権限でSecrets Managerからパスワードを取得します。
- IAMデータベース認証 (RDS): RDS (MySQL/PostgreSQL) では、IAMユーザーやロールを使ってデータベースに認証できる機能があります。パスワードを使わずに認証できるため、より安全な選択肢となります。アプリケーションはタスクIAMロールの一時的な認証情報を使ってデータベースに接続します。設定はやや複雑ですが、パスワード管理の手間が省けます。
-
DynamoDB: DynamoDBへのアクセスはIAMロールによって制御されます。タスクIAMロールに、必要なテーブルとアクション(
GetItem
,PutItem
,Query
など)に対する最小限の権限を付与します。
- 認可 (データベース内部): データベース内部でも、アプリケーションが使用するユーザーには、必要最小限のテーブルやビューに対する権限(SELECT, INSERT, UPDATE, DELETE)のみを付与します。管理者権限を持つユーザーをアプリケーションに使わせないようにします。
7.2. オブジェクトストレージ (S3) へのアクセス制御
S3は非常に便利ですが、設定ミスによる情報漏洩が後を絶ちません。アクセス制御は慎重に行う必要があります。
- バケットポリシーとIAMポリシー: S3バケットへのアクセスは、バケットポリシー(バケット全体に適用)とIAMポリシー(ユーザーやロールに適用)の両方で制御できます。両方のポリシーが許可している場合にアクセス可能になります。
-
最小権限の原則: ECSタスクのタスクIAMロールには、アプリケーションが必要とする 特定のバケット と 特定のプレフィックス (フォルダ) に対する、必要最小限のアクション (
s3:GetObject
,s3:PutObject
,s3:ListBucket
など) のみを許可します。s3:*
のようなワイルドカード権限は避けます。 - パブリックアクセスのブロック: S3バケットとその中のオブジェクトが、意図せずインターネット全体に公開されないように、「パブリックアクセスブロック」 設定を有効にすることが強く推奨されます。アカウントレベルとバケットレベルの両方で設定できます。Webサイトの静的コンテンツをホスティングするなど、意図的に公開する場合を除き、原則としてブロックを有効にすべきです。
- アクセスポイント (Access Points): 特定のバケットに対するアクセスを、特定のネットワーク(VPC)やIAMプリンシパルに限定するための専用のエンドポイントを作成できます。これにより、バケットポリシーを複雑にすることなく、きめ細やかなアクセス制御を実現できます。
-
VPCエンドポイント (Gateway / Interface): ECSタスクがインターネットを経由せずにS3にアクセスできるように、S3用のVPCエンドポイントを作成します。
- Gatewayエンドポイント: ルートテーブルに設定し、特定のS3への通信をAWSネットワーク内で完結させます。追加料金はかかりません。
- Interfaceエンドポイント (PrivateLink): サブネット内にENIを作成し、プライベートIPアドレス経由でS3 APIにアクセスします。オンプレミスからのアクセスも可能になります。料金がかかりますが、より柔軟なネットワーク構成が可能です。
- VPCエンドポイントを利用することで、セキュリティが向上し(インターネットへの露出がない)、場合によってはデータ転送料金も節約できます。エンドポイントポリシーを使って、そのエンドポイント経由でのアクセスをさらに制限することも可能です。
7.3. データの暗号化
保存されているデータ (Encryption at Rest) と転送中のデータ (Encryption in Transit) の両方を暗号化することが重要です。
-
保管時の暗号化 (Encryption at Rest):
- RDS: RDSインスタンス作成時に暗号化オプションを有効にします。AWS KMS (Key Management Service) で管理されるキー、または独自のキーを使用してデータが暗号化されます。既存のインスタンスを後から暗号化するのは少し手間がかかるため、最初から有効にすることが推奨されます。リードレプリカやスナップショットも暗号化されます。
- DynamoDB: デフォルトで全てのテーブルがAWS所有のキーで暗号化されます。必要に応じてAWS管理キー (KMS) または顧客管理キー (KMS) を使用して暗号化レベルを強化することもできます。
-
S3:
-
サーバーサイド暗号化 (SSE): S3にオブジェクトをアップロードする際に暗号化を要求できます。
-
SSE-S3
: S3が管理するキーで暗号化 (デフォルトで有効化可能)。 -
SSE-KMS
: AWS KMSで管理するキーで暗号化(より詳細な制御が可能)。 -
SSE-C
: クライアントが提供するキーで暗号化(キー管理はユーザー責任)。
-
- バケットポリシーで、暗号化されていないオブジェクトのアップロードを拒否するように設定できます (
aws:SecureTransport
条件キーとs3:x-amz-server-side-encryption
条件キー)。 - デフォルト暗号化: バケット設定でデフォルトの暗号化方式 (SSE-S3 or SSE-KMS) を指定しておくと、アップロード時に暗号化を指定しなくても自動的に暗号化されます。これを有効にしておくことを強く推奨します。
-
サーバーサイド暗号化 (SSE): S3にオブジェクトをアップロードする際に暗号化を要求できます。
- EBS (EC2起動タイプの場合): EC2インスタンスにアタッチされるEBSボリュームも、作成時に暗号化を有効にできます。デフォルトで暗号化を強制する設定も可能です。
- KMS (Key Management Service): これらの暗号化の裏側で鍵管理を行っているのがKMSです。KMSでは、鍵の作成、ローテーション、アクセス制御ポリシー(キーポリシー)の設定などが可能です。キーポリシーを適切に設定し、鍵へのアクセス権限を最小限にすることが重要です。
-
転送時の暗号化 (Encryption in Transit):
- ユーザーとALB間はHTTPS (TLS) で暗号化 (レイヤー1)。
- ECSタスクとデータベース (RDSなど) 間も、可能であればTLS接続を使用します。RDSではSSL接続がサポートされています。アプリケーションのデータベース接続設定でSSLを有効にし、必要であればサーバー証明書を検証するようにします。
- ECSタスクとS3間も、HTTPS (TLS) で通信します。VPCエンドポイントを使用する場合も通信は暗号化されます。
- AWSサービス間の通信は、多くの場合、AWSバックボーンネットワーク内で自動的に暗号化されていますが、明示的にTLS接続を使用することが推奨されます。
データの種類や機密性レベルに応じて、適切なアクセス制御と暗号化戦略を選択し、実装することが求められます。
8. レイヤー7: 監視、監査、運用体制 - 継続的なセキュリティ維持
セキュリティ対策は、一度設定したら終わりではありません。新たな脅威の出現、システムの変更、設定の形骸化などに対応するため、継続的な監視、監査、そしてインシデント発生時に迅速に対応できる運用体制が不可欠です。AWSはこのための強力なサービス群を提供しています。
8.1. ログ収集と分析
何が起きているかを把握するための基本はログです。様々なソースからのログを一元的に収集し、分析できる体制を整えます。
-
収集すべき主要なログ:
- ALB アクセスログ: (レイヤー3で解説) 誰が、いつ、何にアクセスしたかの記録。S3に保存。
- WAF ログ: (レイヤー2で解説) WAFが検知・ブロックしたリクエストの詳細。CloudWatch Logs, S3, Kinesis Data Firehose に出力可能。
- VPC フローログ: VPC内のネットワークインターフェース (ENI) を通過するIPトラフィックの情報(送信元/先IP, ポート, 許可/拒否など)。セキュリティグループやNACLで拒否された通信の調査、予期せぬ通信の発見に役立つ。CloudWatch Logs または S3 に出力可能。
- CloudTrail ログ: (重要) AWSアカウント内で行われたほぼ全てのAPI操作の記録。「誰が」「いつ」「どのリソースに」「何をしたか」が記録されるため、監査証跡 として非常に重要。不正操作の発見、設定変更の追跡、インシデント調査に不可欠。デフォルトで有効だが、全てのイベントを記録し、長期保存するための証跡 (Trail) を設定し、S3に保存することが推奨される。ログファイルの整合性検証を有効にすると、ログの改ざんも検知できる。
-
ECS タスクログ (アプリケーションログ): コンテナ内で動作するアプリケーションが出力するログ。
awslogs
ログドライバーを使用して CloudWatch Logs に集約するのが一般的。アプリケーションエラーの調査、セキュリティイベント(ログイン失敗など)の記録。 - Route 53 DNS クエリログ: (オプション) Route 53に対するDNSクエリの記録。不正なドメインへのアクセス試行などを調査できる。CloudWatch Logs に出力可能。
-
OS/システムログ (EC2起動タイプの場合):
/var/log/messages
,/var/log/secure
などのシステムログ。CloudWatch Agentを使ってCloudWatch Logsに収集。
-
ログの集約と分析基盤:
- CloudWatch Logs: 多くのAWSサービスログのデフォルトの集約先。ロググループとログストリームで管理。
- CloudWatch Logs Insights: CloudWatch Logs内のログを対話的に検索・分析するための強力なクエリ言語を提供。
- Amazon OpenSearch Service (旧 Elasticsearch Service): 大規模なログデータをリアルタイムで検索、分析、可視化するためのマネージドサービス。Kibanaと連携してダッシュボードを作成できる。
- Amazon Athena: S3に保存されたログ(ALBアクセスログ、CloudTrailログなど)を直接SQLでクエリできる。サーバーレスで手軽に始められる。
- SIEM (Security Information and Event Management) ツール: Splunk, Datadog, Sumo LogicなどのサードパーティSIEMツールと連携し、より高度な相関分析、脅威インテリジェンス連携、アラートルール設定を行うことも多い。
8.2. モニタリングとアラート
ログ分析と並行して、システムの健全性や異常を示すメトリクスを監視し、問題が発生した場合に迅速に検知して通知する仕組みが必要です。
- CloudWatch Metrics: CPU使用率、メモリ使用率、ネットワークトラフィック、ディスクI/O、ALBのリクエスト数、レイテンシ、HTTPエラーカウント (4xx, 5xx)、ECSサービスの実行中タスク数、ヘルスチェックステータスなど、多くのAWSリソースが様々なメトリクスをCloudWatchに自動的に送信します。アプリケーション固有のカスタムメトリクスを送信することも可能です。
-
CloudWatch Alarms: メトリクスにしきい値を設定し、そのしきい値を超えたり下回ったりした場合にアラーム状態となり、通知(SNSトピック経由でメール、Slackなどへ通知)やアクション(EC2 Auto Scalingアクションのトリガーなど)を実行できます。
-
設定すべきアラームの例:
- ECSタスクのCPU/メモリ使用率が高すぎる/低すぎる
- ALBのHTTP 5xxエラー(サーバーエラー)の割合が急増
- ALBの異常なホスト数 (UnHealthyHostCount) が増加
- ALBのレイテンシ(応答時間)が悪化
- WAFでブロックされたリクエスト数が急増
- 特定のログパターン(例: "ERROR", "FATAL", "Login Failed")がCloudWatch Logsで検出された場合 (Metric Filtersを使用)
- CloudTrailログで特定の危険なAPIコール(例: IAMユーザーの作成、セキュリティグループの変更)が検出された場合 (Metric Filtersを使用)
- GuardDutyの検出結果 (後述) の深刻度が高い場合
-
設定すべきアラームの例:
-
ヘルスチェック:
-
ALBヘルスチェック: ALBは定期的にターゲットグループ内のECSタスクにヘルスチェックリクエストを送り、正常に応答するかを確認します。異常なタスクは自動的に切り離され、新しい正常なタスクに置き換えられます(ECSサービスの機能と連携)。アプリケーションが正常に動作しているかを判断するための専用のヘルスチェックエンドポイント (
/health
など)を用意することが推奨されます。 - ECSタスクヘルスチェック: ECSサービスも、タスクが正常に動作しているかをDockerヘルスチェックなどを用いて確認できます。
-
ALBヘルスチェック: ALBは定期的にターゲットグループ内のECSタスクにヘルスチェックリクエストを送り、正常に応答するかを確認します。異常なタスクは自動的に切り離され、新しい正常なタスクに置き換えられます(ECSサービスの機能と連携)。アプリケーションが正常に動作しているかを判断するための専用のヘルスチェックエンドポイント (
8.3. 脅威検知
既知の攻撃パターンだけでなく、未知の脅威や異常なアクティビティを早期に発見するための仕組みも重要です。
-
AWS GuardDuty:
- 機械学習と脅威インテリジェンス を利用して、AWSアカウントとワークロードにおける悪意のあるアクティビティや不正な動作を 継続的にモニタリング・検出 するマネージドな脅威検知サービスです。
- 有効化が非常に簡単: 数クリックで有効にでき、エージェントのインストールなどは不要です。
- 分析対象: VPCフローログ、CloudTrailログ、DNSログなどを自動的に分析します。
-
検出する脅威の例:
- EC2インスタンスやコンテナからのマルウェア通信、コマンド&コントロール (C2) サーバーとの通信
- ポートスキャン、ブルートフォース攻撃
- 悪意のあるIPアドレスやドメインとの通信
- 通常とは異なる場所や時間からのAWS APIコール、権限昇格の試み
- データ窃取の兆候(大量のS3データダウンロードなど)
- クレデンシャル(アクセスキーなど)の漏洩と悪用
- 検出結果 (Findings): 検出された脅威は「結果 (Finding)」として記録され、深刻度(高・中・低)が付与されます。CloudWatch Events (EventBridge) 経由で通知を受け取り、自動対応(例: 不正なIPアドレスをWAFでブロックするLambda関数を起動)につなげることも可能です。
- ECSランタイムモニタリング: FargateやEC2上のECSワークロードに対して、コンテナ内部での不審なアクティビティ(悪性ファイルの実行、権限昇格など)を検知する機能も提供されています (オプション)。
- GuardDutyは、AWS環境のセキュリティ監視において非常に強力で、有効化することが強く推奨されます。
-
AWS Security Hub:
- AWSアカウント全体の セキュリティ状況とコンプライアンス状況を包括的に表示・管理 するためのサービスです。
- 検出結果の一元管理: GuardDuty, Config, IAM Access Analyzer, Inspector (脆弱性診断サービス), Macie (S3データセキュリティサービス), Firewall Manager, パートナー製品など、様々なソースからのセキュリティ検出結果 (Findings) を集約し、標準化されたフォーマットで表示します。
- コンプライアンスチェック: AWS基礎セキュリティベストプラクティス、CIS AWS Foundations Benchmark、PCI DSSなどのセキュリティ標準に対するコンプライアンス状況を自動的にチェックし、不備のある設定項目を指摘します。
- ダッシュボードとレポート: セキュリティスコアや検出結果の傾向を可視化し、優先順位付けを支援します。
- Security Hubを利用することで、複数のセキュリティサービスのアラートを個別に確認する手間が省け、全体像を把握しやすくなります。
8.4. 設定監査
意図しない設定変更や、セキュリティ基準に違反する設定が行われていないかを継続的にチェックします。
-
AWS Config:
- AWSリソースの 設定変更履歴を記録 し、設定が 定義したルール(Config Rules)に準拠しているかどうかを評価 するサービスです。
- 設定変更の追跡: 「いつ」「誰が」「どのリソースの設定を」「どのように変更したか」を記録します。CloudTrailと似ていますが、Configは設定内容そのもののスナップショットと変更履歴に焦点を当てています。
-
コンプライアンス評価:
- AWSが提供するマネージドルール(例: 「S3バケットのパブリック読み取りアクセスが禁止されているか」「セキュリティグループでSSHポート(22)がAnywhere(0.0.0.0/0)に開かれていないか」「CloudTrailが有効になっているか」など)や、カスタムルール(Lambda関数で定義)を使用して、リソース設定が望ましい状態にあるかを継続的に評価します。
- ルールに違反するリソース(非準拠リソース)を特定し、通知したり、自動修復アクション(LambdaやSystems Manager Automationドキュメントを実行)をトリガーしたりできます。
- Config Rulesを活用することで、セキュリティポリシーの遵守を自動的にチェックし、設定ミスによるリスクを低減できます。Security Hubとも連携し、コンプライアンスチェック結果をSecurity Hubに集約できます。
8.5. アクセス管理 (IAM)
全てのAWSリソースへのアクセスはIAMによって制御されます。IAMの適切な設定と運用は、AWSセキュリティの根幹です。
-
最小権限の原則の徹底: (繰り返しになりますが非常に重要)
- IAMユーザー、グループ、ロールには、業務やアプリケーションの実行に必要な最小限の権限のみを付与します。
- ワイルドカード (
*
) の使用は極力避け、具体的なアクションとリソースを指定します。 - 定期的に権限を見直し、不要になった権限は削除します。
-
IAMユーザー、グループ、ロールの適切な使い分け:
- ルートユーザー: 日常的な操作には絶対に使用せず、MFAを設定し、アクセスキーは作成しません。アカウント管理などの特別なタスクにのみ使用します。
- IAMユーザー: 個々の人間に対して作成します。パスワードポリシーを強化し、MFA (多要素認証) を強制 します。アクセスキーは必要な場合にのみ作成し、定期的にローテーションします。
- IAMグループ: 同じ権限を持つIAMユーザーをまとめるために使用します。権限はユーザーに直接ではなく、グループに付与し、ユーザーをグループに追加することで管理を簡素化します。
- IAMロール: AWSサービス(EC2, ECS, Lambdaなど)や他のAWSアカウント、外部IDプロバイダー(SAML, OIDC)からのアクセスに対して、一時的な認証情報を提供するために使用します。アクセスキーを埋め込む代わりにロールを使用することが強く推奨されます。ECSのタスク実行IAMロール、タスクIAMロールが良い例です。
-
アクセスキーの適切な管理:
- 可能な限りアクセスキーの使用を避け、IAMロールを使用します。
- IAMユーザーのアクセスキーが必要な場合は、コードや設定ファイルに直接埋め込まず、環境変数や認証情報ファイル(
~/.aws/credentials
)などで管理し、バージョン管理システム(Gitなど)にコミットしないようにします。 - 定期的にアクセスキーをローテーション(無効化・削除・新規作成)します。
- 未使用のアクセスキーは削除します。
-
IAM Access Analyzer:
- IAMポリシーを分析し、意図しない外部エンティティ(他のAWSアカウント、IAMユーザー、ロールなど)からのアクセスを許可している可能性のあるリソース(S3バケット、IAMロール、KMSキー、Lambda関数、SQSキューなど)を特定するのに役立ちます。
- 定期的にAccess Analyzerの結果を確認し、不要なアクセス許可を修正することで、セキュリティリスクを低減できます。
8.6. 脆弱性管理
インフラやアプリケーションに存在する脆弱性を継続的に特定し、修正していくプロセスです。
-
定期的な脆弱性診断:
- 外部診断: インターネットからアクセス可能なシステム(ALBのエンドポイントなど)に対して、外部の攻撃者の視点から脆弱性をスキャンします。
- 内部診断: VPC内部から、ECSタスクやその他の内部リソースに対して脆弱性をスキャンします。
- AWS Inspector: EC2インスタンスやコンテナイメージ(ECR連携)に対して、OSの脆弱性やネットワーク到達可能性の問題を自動的にスキャンするサービスです。
- サードパーティの脆弱性スキャンツールも広く利用されています。
- ECRイメージスキャン結果のレビューと対応: (レイヤー4で解説) CI/CDパイプラインでのチェックと、定期的なレビューを行います。
- 依存ライブラリの脆弱性管理: (レイヤー5で解説) Dependabot, Snykなどのツールを活用します。
- 発見された脆弱性への対応: 脆弱性が発見された場合、その深刻度(CVSSスコアなど)に基づいてリスクを評価し、修正の優先順位を決定し、計画的に対応します(パッチ適用、設定変更、コード修正など)。
8.7. インシデント対応
どんなに堅牢な対策を施しても、セキュリティインシデント(不正アクセス、情報漏洩、サービス停止など)が発生する可能性はゼロではありません。発生した場合に、被害を最小限に抑え、迅速に復旧し、原因を究明して再発防止策を講じるための準備が必要です。
-
インシデント対応計画 (IRP - Incident Response Plan) の策定:
- インシデント発生時の役割分担と連絡体制(エスカレーションパス)を明確にします。
- インシデントの検知、分析、封じ込め、根絶、復旧、事後レビューといった各フェーズでの具体的な手順を定義します。
- 必要なツール(ログ分析ツール、フォレンジックツールなど)や連絡先リスト(社内外の関係者、AWSサポートなど)を準備しておきます。
- 法的要件やコンプライアンス要件(報告義務など)を考慮します。
- 定期的な訓練: インシデント対応計画が実際に機能するかを確認するため、机上演習や実践的なシミュレーション訓練を定期的に実施します。
- 証拠保全: インシデント発生時には、原因究明と法的対応のために、関連するログ、設定、ディスクイメージなどの証拠を適切に保全する手順が必要です。CloudTrailログや各種アクセスログが重要な証拠となります。
- AWSサポートの活用: 重大なインシデントが発生した場合は、AWSサポート(特にエンタープライズサポートやShield AdvancedのDRT)に連絡し、支援を求めることも有効です。
9. まとめ: セキュリティはチームで取り組む継続的な活動
ここまで、ブラウザからAWS ECS上のWebサーバーへアクセスする流れに沿って、様々なレイヤーでの重要なセキュリティ設定を、会社で実践されているレベルを意識しながら、網羅的に解説してきました。5万字という目標には届かなかったかもしれませんが、非常に広範な内容をカバーできたかと思います。
最後に、最も重要な点を改めて強調したいと思います。
- 多層防御 (Defense in Depth): 単一の完璧な防御策はありません。ネットワーク境界、ロードバランサー、コンテナ実行環境、アプリケーション、データ、そして運用・監視に至るまで、複数のレイヤーでセキュリティ対策を組み合わせることが不可欠です。一つの層が突破されても、次の層で攻撃を食い止める可能性が高まります。
- 最小権限の原則: あらゆる場面で、ユーザー、ロール、アプリケーション、サービスには、その役割を果たすために必要最小限の権限のみを与えることを徹底してください。これはIAMだけでなく、セキュリティグループ、データベース権限など、全てに適用されるべき原則です。
- 自動化の活用: セキュリティ設定の適用(IaC)、脆弱性スキャン、コンプライアンスチェック、ログ監視、アラート通知、インシデント対応の一部などを自動化することで、ヒューマンエラーを減らし、迅速かつ一貫性のある対応が可能になります。CI/CDパイプラインにセキュリティチェックを組み込む (DevSecOps) ことは特に重要です。
- 継続的な改善: セキュリティは一度設定したら終わりではありません。新しい脅威は常に出現し、システム環境も変化します。定期的な見直し、脆弱性診断、ログ分析、インシデント対応訓練を通じて、セキュリティ対策を継続的に評価し、改善していく必要があります。
- 責任共有モデルの理解: AWSを利用する場合、AWSが責任を持つ範囲(物理インフラ、ハイパーバイザーなど)と、ユーザーが責任を持つ範囲(OS、ミドルウェア、アプリケーション、データ、IAM、ネットワーク設定など)を明確に理解することが重要です。Fargateを使えばユーザーの責任範囲は減りますが、ゼロにはなりません。
- チーム全体での意識: セキュリティは、インフラ担当者やセキュリティ専門家だけのものではありません。開発者、運用担当者、企画担当者など、関わる全てのメンバーがセキュリティ意識を持ち、それぞれの立場で責任を果たすことが重要です(セキュアコーディング、安全な設定、インシデント報告など)。