安全なAmazon S3バケットの構築(AWS)
Josh Stella
2020年9月8日
0 分で読めます編集者注
このブログ記事は、もともとfugue.coに掲載されていました。Fugueは2022年にSnykの一員となり、Snyk IaCの重要な構成要素となっています。
Amazon Web Services(AWS)上のAmazon S3セキュリティについては、報道機関や技術系の出版物で数多く取り上げられてきました。しかし、その多くは単純化されすぎており、実務にはあまり役立ちません。Amazon S3は非常に使いやすいクラウドサービスですが、S3リソースを適切に保護するのは決して簡単ではありません。そのことを、多くの組織が身をもって知っています。
この記事と、Amazon S3をテーマにした2回のCloud Security Masterclassセッションでは、S3セキュリティを理解するための実践的なアプローチをご紹介します。具体的なS3のユースケースをどう保護すべきかを考え、ニーズに合った安全なS3バケットを構築できるようになります。
報道記事だけを参考にすると、S3バケットを安全にするために必要なのは「Block Public Access」だけだと思ってしまうかもしれません。この設定を正しく行うことは重要です(設定に問題がある場合にAWSが警告するようになったのも大切な進歩です)。ただし、それだけでは誤った安心感につながるおそれがあります。
Amazon S3セキュリティの階層
Amazon S3セキュリティにはいくつかの階層があり、重要度はそれぞれ異なります。
アクセス制御ポイント(ACL)
Identity and Access Management(IAM)ポリシー
バケットポリシー
Block Public Access
アクセスポイント
暗号化
まず理解しておきたいのは、IAMポリシー、暗号化、バケットポリシーです。ただし、これらのポリシーの詳細に入る前に、ポリシーの基本的な考え方と、AWSのアクションおよびリソースとの関係を理解しておくことが重要です。ACLについては、歴史的な経緯で残っているものであり、ほとんどの場合AWSも使用を推奨していないため、ここでは扱いません。
IAMポリシー
AWSには、プリンシパル、アクション、リソースがあります。もちろんAWSにはほかにもさまざまなエンティティがありますが、安全なS3バケットを設計するうえで理解しておくべきなのはこの3つです。
プリンシパルは、人間やマシンなどの主体です。認証情報を使ってアクションやリソースに対するリクエストを行うエンティティを指します。
アクションは、クラウド上で操作を行うために使用するAPIエンドポイントです。AWSの各サービスには一連のアクションがあり、S3ではListBucketsやGetObjectなどが該当します。
リソースは、AWSサービス内の個別のインスタンスやオブジェクトです。たとえば、S3バケットやオブジェクト、EC2インスタンスなどです。
プリンシパルがリソースに対してアクション(たとえばS3バケットの内容一覧の取得)を実行するには、処理の各段階で許可するポリシーが必要です。どの段階であっても拒否されれば、リソースに対するアクションは失敗します。AWSでは、すべてのプリンシパルによるすべてのアクションとリソースへのアクセスを、デフォルトで拒否します。
図で説明しましょう。

プリンシパルとアクションの間、そしてアクションとリソースの間に、それぞれ縦線があるのがわかりますか?この線を「拒否の壁」と呼びましょう。安全なS3バケットを構築するには、プリンシパルに必要なアクションに対してのみ、かつ適切なリソースに対してのみ、この壁に穴を開ける必要があります。
AWSユーザーやリソース(IAMロールが関連付けられたEC2インスタンスなど)のようなAWSプリンシパルには、IAMを使ってアクションとリソースへのアクセスを許可できます。以下は、アカウント内のすべてのS3バケットに対して複数のアクションを許可するIAMポリシーの例です。
図と同じように、このポリシーにはアクションとリソースのセクションがあります。ポリシーで定義した3つのGetアクションに対して、プリンシパルとアクションの間にある拒否の壁に穴を開け、それをリソース内のすべてのS3バケットに適用している点に注目してください。

この例を含め、多くの場合、リソースのセクションは「*」となっています。これは、そのアクションの対象となるすべてのリソースを意味します。すべてのポリシーを評価する際に、バケットポリシーなどを使って許可するリソースを絞り込めるため、これは有効な方法です。
リソース名などの詳細をどこに定義するかを決める際に重要なのは、IAMポリシーの増殖を避けることです。ポリシーの管理が、コストとリスクの両方を生む原因になるためです。そのため、IAMポリシーに特定のリソース識別子を埋め込むのは、同じポリシーのコピーが多数必要になるため、一般的には望ましくありません。次に、S3バケットポリシーを使ってバケット単位でリソースへのアクセスを制限します。こうすれば、このポリシーをユーザーやプロセスに適用しても、すべてのS3バケットへのアクセスを許可せずに済みます。
可能な場合はAWS管理ポリシーを使うことをおすすめします。アカウントにはすでに700種類以上のポリシーがあり、AWSが管理してくれるためです。目的に完全に合うものが見つからなくても、質の高いIAMポリシーを手作業で作成する際の参考として活用する価値があります。
バケットポリシー
これで、アカウント内のすべてのS3バケットに対して複数のGetアクションを許可するIAMポリシーができました。ただし、実際には、作業中のアプリケーションに必要なS3バケットだけに対象を絞りたいでしょう。いくつか方法はありますが、最後の防御線として、すべてのS3バケットにバケットポリシーを設定することをおすすめします。
バケットポリシーは個々のバケットに適用されるAWSポリシーで、IAMポリシーで許可される可能性のあるリクエストを拒否するのに役立ちます。この例では、バケット「foo」が、特定の2つのVPCネットワークから開始されたアクションのみを受け入れるようにします。そのためのポリシーをAWSサポートポータルから見てみましょう。
このポリシーでは、ステートメントの冒頭で、すべてのプリンシパルによるすべてのS3アクションを拒否しています。その後の条件で、拒否の対象を、2つのVpcE識別子および2つのCIDRブロックと一致しないVPCエンドポイントに絞り込んでいます。つまり、指定されたVPCエンドポイントを経由し、指定されたCIDRブロック内からアクセスするプリンシパルだけが、S3アクションを実行できます。
これらを図に組み合わせ、このポリシーをバケット「foo」に適用し、別のVPCエンドポイントとCIDRブロックを指定した別のバケットポリシーも設定すると、次のようになります。

青いユーザーはvpce-1111111エンドポイントを持つVPC経由でアクセスしています。一方、赤いユーザーはvpce-3333333エンドポイント経由です。fooのバケットポリシーは、青いユーザーと同じIAMポリシーを使っていても、許可されていないVPCエンドポイントからアクセスしている赤いユーザーを拒否します。
これらすべてのポリシーは、一括して評価されると考えることができます。拒否が1つでもあれば、リクエストは拒否されます。そのため、ユースケースやアーキテクチャに応じて、AllowとDenyのステートメントをどこに配置するかを決められます。
Block Public Access
AWSのBlock Public Access機能を有効にすればS3の侵害を防げると考えている方をよく見かけます。これは優れた機能です。適切な場合は利用すべきですが、アクセスを遮断する仕組みは想像とはかなり異なります。機能を有効にしただけで安全だと考えてはいけません。
AWSのドキュメントには、次のように記載されています。
「非パブリックとみなされるには、バケットポリシーが、以下の1つ以上について固定値(ワイルドカードを含まない値)のみを使ってアクセスを許可する必要があります。
aws:SourceIpを使用した、クラスレスドメイン間ルーティング(CIDR)の範囲。…」
ドキュメントにはさらに詳しい説明があります(ぜひお読みください)が、この記述だけでも、パブリックアクセスを含むCIDRブロックの一覧が、この機能における「パブリック」に該当しない場合があることがわかります。CIDRブロックはインターネット上の広大な範囲を表すこともあるため、何百万ものIPアドレスに公開された「非パブリック」バケットを、安全だと思い込んでしまうおそれがあります。各S3バケットのポリシーは、可能な限り対象を絞り込むのが賢明です。
暗号化について
S3バケットを暗号化する場合は、KMSキーまたはユーザー管理キーを使うことが重要です。これらの方法では、S3バケットから復号済みのデータを取得するために、攻撃者が追加のサービスやデータにもアクセスする必要があるためです。最も基本的な形式のサーバー側暗号化を有効にしただけでは、S3サービス内で保存データが暗号化されるだけです。GetObject権限を持つプリンシパルは、オブジェクトを復号した状態で受け取れます。
保存データのすべてを暗号化するという規制要件がある場合は、これで要件を満たせるでしょう。しかし、実際のセキュリティ態勢への影響はほとんどありません。
ほかにも、できることはあります…
この記事では、AWSにおけるS3セキュリティの機能や階層をすべて取り上げたわけではありません。Cloud Security MasterclassのS3セキュリティシリーズでは、その一部を解説しています。この記事から1つだけ覚えていただくとすれば、S3セキュリティを理解するにはAWSのポリシーを本当に理解する必要があり、定型的なサンプルに頼るだけでは十分ではないということです。
追記: S3バケットでは、アクセスログとオブジェクトレベルのログを有効にし、バージョニングを設定することもおすすめします。アクセスログとオブジェクトレベルのログを有効にすると、バケット内で何が起きたかを確認できます。バージョニングを設定すれば、誰かにアクセスされて必要なオブジェクトを変更または削除された場合に、以前のバージョンに戻せます。
S3セキュリティについて、さらに詳しく取り上げてほしいテーマがあれば、ぜひご連絡ください。掘り下げて解説します。
開発者のために設計されたIaCセキュリティ
Snykは、統合されたポリシー・アズ・コードエンジンにより、SDLCからクラウドでの実行時までInfrastructure as Codeを保護します。すべてのチームが安全に開発、デプロイ、運用できるよう支援します。


