プログラマでありたい

おっさんになっても、プログラマでありつづけたい

AWSのマルチアカウント管理ことはじめ ログインの一元化の設計

 日本のAWSのAPN Ambassadorが集まって作り上げるJapan APN Ambassador Advent Calendar 2020の初日です。佐々木の方からは、最近の関心事項であるマルチアカウント管理の中から、認証(ログイン)の一元化の設計について考えてみましょう。

マルチアカウント管理における認証(ログイン)の一元化の必要性

 AWSを本格的に使い始めるとすぐに直面するのが、利用するAWSアカウントの増大です。AWSのお勧めのプラクティスの一つとして、用途ごとにAWSアカウントを使い分けてリスクを下げるというのがあります。本番環境と開発環境が同居しているより、分離した上で使えるユーザーを役割ごとに限定した方がリスクを下げることができますよね。一方で、プロジェクトごと・環境ごとにAWSアカウントを分離していくとすぐに10や20のアカウントになってしまいます。その時に第一の課題となるのが、IAMユーザーの問題です。

f:id:dkfj:20201201084154p:plain


 AWSアカウントごとにIAMユーザーを作っていくと、ユーザーごとにIAMユーザーのIDとパスワードが10個も20個もできてきます。さらにAWSに携わる人が数十人いたら、数百のオーダーのID管理が必要となります。これを個々のユーザー任せで適切に管理することができるでしょうか?なかなか難しいのが現状で、放っておくと全部同じID・パスワードで運用されるといったことも発生しうるでしょう。そこで、必要になってくるのが認証(ログイン)の一元管理です。

認証の一元化のデザインパターン

認証の一元管理にも、AWSの機能のみで管理するパターンやサードパーティのツールを駆使するパターンなど幾つかあります。代表的なパターンを幾つかみていきましょう。

踏み台AWSアカウントパターン

 一番お手軽なのが踏み台AWSアカウントパターンです。踏み台となるAWSアカウントのみにIAMユーザーを発行し、後はクロスアカウントのスイッチロールでスイッチしていくパターンです。

f:id:dkfj:20201201084212p:plain

 このパターンは、踏み台となる一つのAWSアカウントのみにIAMユーザーを発行し、他のAWSアカウントにはIAMロールのみ発行します。踏み台にログイン後にスイッチロールを利用してそれぞれのAWSアカウントを利用します。スイッチされる側のIAMロールで、スイッチできるIAMユーザーを制限できるので各アカウント側で権限の制御ができるのがポイントです。また、このパターンだとAWS Organizationsで管理外のものでも簡単に利用できるというメリットもあります。ただし、スイッチ先の各アカウントでCLIを利用したい場合は、一工夫が必要となります。
 なお、このパターン名は、私が勝手に名付けているだけです。

サードパーティのIdP(Identity Provider)を利用するパターン

 次に紹介するパターンは、ある意味王道であるサードパーティのIdP(Identity Provider)を利用するパターンです。IdPは認証部分を専用のシステムに委託し、認証した結果を受け取ってAWSアカウントの利用を許可するパターンです。IdPを利用するとAWS側でID/パスワードの管理が不要になります。代表的なIdPとしては、Microsoft Active Directory(AD)やGoogle Workspace(旧G Suite),Okta,OneLoginなどがあります。

f:id:dkfj:20201201085741p:plain

 IdPを利用するパターンも、AWS部分はIAMロールを使います。そのため、踏み台AWSアカウントパターンと構成的には大きく違わないように見えます。しかし、ポイントはAWSアカウント内に一切IDとパスワードを持つ必要がない点にあります。AWSを使うような組織は、AWS以外にも様々なシステムを利用し、ID/パスワードを管理する必要があります。そこにAWSのID管理を統合できるのは大きなメリットです。一方で、踏み台AWSアカウントパターン同様にCLIを利用したい場合は一工夫が必要です。

AWS SSOを利用するパターン

 3つ目のパターンとしては、AWS SSO(AWS Single Sign-On)です。AWS SSOは、その名の通りマルチアカウントでのAWS運用を想定したサービスです。AWS SSO用のログイン画面があり、ログイン後に自身が利用できるAWSアカウントを選択できるようになっています。

f:id:dkfj:20201201091712p:plain

 構成的には、IdPパターンと大きく変わりませんが、メリットは幾つかあります。そのうちの1つが、SSOから利用しているユーザーもCLI(v2)が使えることです。もう一つは、アクセス権限セットという機能を使って、複数アカウントのアクセス権限を一元管理できることです。ただし、SSOの利用はAWS Organizationsが前提となります。それにしても、これいいじゃんってなりますよね。ただ、お勧めの使い方としては別パターンがあるので、SSOのアクセス権限セットを説明の後で紹介したいと思います。

AWS SSOのアクセス権限セット

 先程紹介したどのパターンでも、IAMロールが肝になっているのが解るでしょうか?認証の一元化はできても、どの機能が使えるかという認可の部分については各アカウントに設定されたIAMロールに依存することになります。そのため、個々のアカウントにIAMロールを設定していくという作業が必要になります。AWS OrganizationsとCloudFormation StackSetsを使えばこの辺りの作業もだいぶ楽にはなりますが、一元管理とは少し遠い世界です。
 そこで登場するのがAWS SSOのアクセス権限セットです。アクセス権限セットはユーザーごとのアクセス権限を一元管理する仕組みです。SSOを設定するOrganizationsの管理アカウント(旧マスターアカウント)で定義します。アクセス権限セットと呼ばれるポリシーを作成し、ユーザーがどの権限を利用できるかを紐付けます。管理者の操作としてはこれだけなのですが、アクセス権限セットの良いところは、裏で対象のAWSアカウントの方に、アクセス権限セットと対応するIAMロールを作っているということです。まさしく一元管理!!

お勧めのデザインパターン IdP + AWS SSO

 アクセス権限セットとCLI対応の2点でAWS SSOがお勧めです。一方で、いろいろな現場でSSOを紹介しても、やっぱり既存のIdPを使いたいというケースが多いです。やっぱりIDの二重管理は嫌ですもんね。そんな時にお勧めがIdP + AWS SSOというパターンです

f:id:dkfj:20201201093752p:plain

 構成としては、ユーザーはIdPでまず認証します。認証後にAWS SSOのポータル画面に移動します。そして、任意のAWSアカウントに移動するというパターンです。画面遷移が一つ増えるという手間が増えますが、このパターンには大きなメリットがあります

  • ID管理をAWS以外も含めて一元化できる
  • 認証(IdP)と認可(アクセス権限)を明示的に分離できる
  • AWS SSOの機能が100%利用できる
  • 今後AWS SSOの機能が増えてもグヌヌとならない

まとめ

 AWSのマルチアカウント管理については、踏み台AWSアカウントあたりから始める人が多いのではと思います。コストも掛からないので、それで充分な場合も多いです。一方で大規模になると辛くなるということもあります。そんな際の参考になれればなと思います。
 じつはこの辺の話をAWSの薄い本Ⅲとしてまとめようと思いつつ、はや半年が過ぎました。1行もかけていません。年内に執筆在庫を一層して、年初あたりから取りかかれればと思っておりますので、生暖かい目で見守ってください。また、AWS SSOを使う上では、Organizationsが必須となります。請求代行使っててOrganizations使えないよという方は、Organizations対応の支払い代行とかしているところを検討するといいんじゃないかなと思います。(ステマ)
 今回は論理設計の話が中心だったので、もう少し具体的な話を今後紹介していきます。乞うご期待!!

www.nri-net.com


booth.pm

booth.pm

S3のマイナー機能の四天王候補の一つであるS3 オブジェクトロックの機能について

 Amazon S3の正式名称は、Amazon Simple Storage Serviceです。Simpleを辞書で紐解くと、次のような言葉が出てきます。

1. 易しい、難しくない
2. 簡素な、簡略した、シンプルな
3. 質素な、地味な、豪華でない
4. 単一の、一つだけで構成される
5. 単純な、複雑でない
6. 〔人が〕気取らない、控えめな、見えを張らない
7. 〈軽蔑的〉〔知的レベルが〕単純な、ばかな
8. 〈軽蔑的〉教養がない、無知な
9. 〔人が〕素朴な、洗練されていない
10. 〔人が〕真面目な、誠実な、うそをつかない
11. 普通の、いつもの、ありふれた
12. 基本の、初歩の
13. ささいな、重要でない、つまらない
14. 《植物》単一の◆【対】compound
15. 《化学》〔化合物が〕単純な
16. 《言語学》〔文構造が〕単純な

引用元 英辞郎 on the Web

 AWSの認定試験を受けていると、普段あまり使わないような機能がどんどん出てきて、Simpleってなんだろうと哲学的な気分になります。昔、大阪でインド人がやっているカレー屋で辛そうに食べていたら、インド人に「辛くない〜、辛くな〜い」と励まされた事も思い出されます。シンプルなのかシンプルじゃないのか、辛いのか辛くないかは、人それぞれということですね。

 前置きが長くなりましたが、今回のテーマは、数あるS3の機能の中で一般的な機能要件ではまず使うことがないオブジェクトロックの機能についてです。

S3のオブジェクトロックの概要とそのニーズ

 S3のオブジェクトロックは、雑な言い方をすると指定されていると何があっても変更したり消せなくする機能です。モードによりますが、管理者であっても消せなくなります。何故、そのような機能が求められるのかというと、コンプライアンス対応です。業種・業界によっては、一定期間データを保持し続けないといけないとルールで定められているものがあります。ルールの多くは、データの完全性を求めていて、期間中のデータ変更や削除を防がないといけません。そんな時に、どうしたらいいでしょうか?
 ぱっと思いつくのは、データにアクセスできる場所と人を限定することです。しかし、その場合は期間中のそのデータへのアクセス履歴とともに、データにアクセスできる人の行動履歴を残し続けないといけません。また、履歴データ自体も改ざんされていないことを証明することが必要です。結構、大変ですよね。そこで登場するのがS3のオブジェクトロックの機能です。これはAWSによって、期間中は一切変更・削除できないということを保証する機能です。利用者は、対象データが確かにその設定がされていることだけ確認するだけで良くなります。格段に楽になりますよね。

S3のオブジェクトロックの機能

 S3 オブジェクトロックは、リテンションモードリーガルホールドの2つを利用できます。どちらか一方を利用することも、両方を利用することも可能です。まずここからして、オブジェクトロックが解らなくなります。順を追って説明します。

リテンションモードの2つのモード

 リテンションとは、保持とか維持するという意味です。オブジェクトを保護しますよという機能ですね。リテンションモードは2つのモードを提供しています。

  • ガバナンスモード
  • コンプライアンスモード

 ガバナンスモードは、特別なアクセス許可を持つユーザー以外は、オブジェクトのバージョンの上書きや削除、ロック設定を変更することはできません。つまり、限定したユーザーだけは変更・削除できるということです。続いて、コンプライアンスモードは、AWSアカウントのルートユーザーを含めて、指定期間中は対象のオブジェクトのバージョンを上書きまたは削除、ロック設定の変更をすることはできません。結構強烈な機能ですね。

保持期間

 リテンションモードには、保持期間が設定されます。これはバケット単位で○○日までというような設定ではなく、オブジェクト単位に何日保持するかというような指定です。例えば、ルールで1年間保持しないといけないのであれば、365日と指定します。

リーガルホールド

 オブジェクトロックは、リテンションモードとは別にリーガルホールドというオブジェクトを保護する仕組みがあります。リテンションモードとの違いは、保持期間がないという点です。削除するためには、リーガルホールドの適用を解除する必要があり、s3:PutObjectLegalHold を持つユーザーがその設定をできます。つまりS3のFullAccessをもっていると、リーガルホールド対象のオブジェクトは直接は消せないけど、ひと手間掛けると消せるということになります。リテンションモードよりは少し弱い保護となります。

リテンションモードとリーガルホールドの組み合わせ

 さて、ここからが地獄です。リテンションモードとリーガルホールドは何故か排他の設定ではなく組み合わせることができます。設定のパターンとしては、以下のパターンが可能です。

  • オブジェクトロックなし(デフォルトの状態)
  • リテンションモードのガバナンスモード
  • リテンションモードのコンプライアンスモード
  • リーガルホールド
  • リーガルホールドかつリテンションモードのガバナンスモード
  • リーガルホールドかつリテンションモードのコンプライアンスモード

 AWSの認定試験でここまで問われることは無いと信じています。ただ、オブジェクトロック機能がリテンションモードとリーガルホールドの2つの機能があることと、それの違いを理解していないと混乱するでしょう。事実、試験のたびにどうだったかなぁと頭を悩まします。

オブジェクトロックを利用する方法

 オブジェクトロックの概要はだいたい理解できたかと思います。それでは、実際にどう設定すればいいのでしょうか?たぶんこの記事を読んでいる人の9割8分3厘は実際に設定することがないと思いますので、詳細は省きます。下記の2点が必要という事を覚えておいてください。

  • バケット設定でオブジェクトロックの有効化
  • オブジェクト単位で保持期間やリーガルホールドの設定

 バケット設定でオブジェクトロックを有効化して、その後にオブジェクト単位で設定していくという流れです。注意点としては、バケット設定で有効化するには新規作成のバケットのみで指定できるという点です。既存のバケットに対しては、サポートにお願いすると有効化してくれそうな雰囲気ですが、試したことはないです。またオブジェクトロックを利用する場合は、バージョニング設定が必須となります。

f:id:dkfj:20201019015129p:plain

デフォルトの保持設定

 先程、バケットでオブジェクトロックを有効化されても、オブジェクト単位で指定する必要があると説明しました。いやいや、それは面倒くさいという人のために、デフォルトの保持期間が設定可能です。なお、画面コンソールから指定できるのは、リテンションモードのみです。

f:id:dkfj:20201019022006p:plain

オブジェクトロックされたファイルの消し方

 最後にオブジェクトロックされたファイルの消し方をまとめておきましょう

  • リテンションモードのガバナンスモード

  保持期間明けまで待ってから削除
  特別なアクセス許可を持つユーザーでガバナンスモードを解除してからオブジェクトを削除

  • リテンションモードのコンプライアンスモード

  保持期間明けまで待ってから削除

  • リーガルホールド

  IAMで権限を持つユーザーでリーガルホールドを解除してからオブジェクトを削除

 リテンションモードとリーガルホールドは併用できるので、その場合はそれぞれの条件を満たす必要があります。こうやってみると、リテンションモードのコンプライアンスモードの制約の大きさが解りますね。退職前にコンプライアンスモードの設定で保持期間をこっそり10年とか指定するのは、テロに等しいのでやめましょうね。

まとめ

 S3のマイナー機能の四天王候補の一つであるオブジェクトロック機能です。機能を知ると、よく考えられているなぁと感心します。ただ、ここまで求められる要件がでてくるのは、ごく一部の業界のみで大半の人は使わずに終わるのではないかなぁと思います。そんな業界に飛び込んだあなたは、ラッキーと思ってドヤ顔で使いましょう。私は、残りの四天王の3つを探す旅にでることとします


AWSのロードバランサ、CLB, ALB, NLBの機能差まとめ

いい加減に12冠にならないとなぁということで、スキマ時間にちょっとづつ勉強しています。隙間時間だと、前回勉強したところの続きに戻るまでに隙間時間が過ぎてしまう辛みがありますが、皆さんいかがお過ごしでしょうか?

 私にとっての最鬼門のAWS認定アドバンスドネットワーク専門知識の試験範囲の確認のために公式トレーニングの試験対策を見ています。AWSの試験で一番わからないのが、どのサービスが対象範囲なのかという点だと思います。これを受けることにより、ここを勉強すればよいのだというのがはっきりするのでお勧めです。
Exam Readiness: AWS Certified Advanced Networking - Specialty (Digital)

 その中で、AWSのロードバランサであるELB(CLB, ALB, NLB)のまとめ表があったので紹介しておきます。

3種類のELBの違いを1枚の図でまとめる

 みなさん、3種類のELB(CLB, ALB, NLB)の違いを説明できますでしょうか?CLBはTCPとHTTP,HTTPSが使えて、ALBはHTTP,HTTPSだけでNLBはとか頭の中を駆け巡ると思います。その辺を一枚の表にしておけばもう悩みません。常々作ろうと思いつつ、既にまとめてあったので紹介させて貰います。どん!!

f:id:dkfj:20201013115235p:plain

※2020年10月13日 11:55追記 
優しいマサカリが飛んできたので、図を修正しています。NLBも2019年1月よりTLS Terminationが出来るようになっています。Container Supportについてはもう少し補足が必要なので、Container Native Supportに変更の上で、下に補足を書いています。

 図の項目名で、一部分かりづらいものがあるので補足しておきます。

Protcol

 どのプロトコルを受け付けるかですね。NLBはレイヤー4のサービスなのでTCPのみです。ALBはレイヤー7でHTTP,HTTPSの他にHTTP/2も受け付けます。CLBはそういえばSSLも受け付けましたね。UDPについては言及なしの世界線です。

SSL offloading

 SSLオフロードは、TLSまたはSSLの通信を紐解いて後ろに平文の通信で流すという機能です。現実的にはSSLはもう使わないのでTLS offloadingというのが正しいのでしょうね。CLBとALBがもともと対応していましたが、NLBも対応しました。つまりこの観点では、どれを使っても大丈夫。これがないと、個々のWebサーバーに直接SSLの証明書をそれぞれ入れないといけないので不便です。試験問題だと逆に、Webサーバからアプリケーションサーバ間の通信も暗号化したままにしたいというのがあるので、頭のひねりどころですよ

IP as target

 これは言葉にすると解りづらいのですが、ターゲットグループにIPを指定できるかという事です。一般的にはインスタンスを指定すると思いますが、ALBとNLBはローカルIPアドレスを指定できます。これ使うと、VPNやダイレクトコネクト先の(嬉しいかどうかしりませんが)オンプレサーバを指定するといったことも可能です。オンプレに対して使うかどうかは別として、設計の幅が広がるのは確かです。リバースプロキシ立ててたけどっていうのを、NLBやALBで代替できるケースも多数あるでしょうね。

Path-based routhing, host-base routing

パスベースのルーティングというのは、example.com/imageやexample.com/contentsなどドメインの後の/以下の部分を判断して振り分けるという機能です。ホストベースのルーティングは、app.example.comやimage.example.comといったようにサブドメイン部分を判断して振り分けるということです。これが出来るのは、ALBだけです。そもそもCLBはELBとターゲットは1対1の紐付けしかできません。ALBは、1対多の紐付けができます。便利ですねぇ~。その気になれば、複数のシステムでALBを共有してコスト削減できますが、システム同士が密結合になるので止めた方がよいですね。

Static IP

 パスベース・ホストベースのルーティングができるのがALBの売りですが、このStatic IPの機能がNLBの売りの一つです。このStatic IPはロードバランサーに固定のIPアドレスを設定できます。ALBやCLBはURLベースでしたが、NLBは固定のIPを指定できます。これが利点になることが多いです。IPを固定したいという用途がある時に、前にNLBを置くことにより解決することができます。

WebSockets

 WebSocketsはシンプルに対応しているかどうかですね。ALBとNLBが対応しています。

Container Support

 Container Support。これは、ECS等に対応している「仮想マシンでのホップなしにコンテナネイティブなルーティングができる」かという点です。細かくケース別にわけると長くなるので、別途まとめようと思いますが、ALBとNLBが対応しています。単純なルーティングだけであればCLBでも一応使えます。

まとめ

 AWSはCLB, ALB ,NLBと3種類もロードバランサがあって解らんよという方もいると思います。まずは、この表で頭の中を整理してみるのも良いのではないでしょうか。ただ実質CLBはリタイアしていく運命のサービスですから、ALBとNLBだけ覚えれば充分です。WebサイトのロードバランスにALB、それ以外の用途はNLBとなることが多いです。原則のALB覚えて、それに対応できないケースを解決しているNLBになります。NLBの構成図を見ると、なるほどなぁとなることが多いです。一度、目を通してみると良いですよ

AWSのS3のバージョニングとライフサイクルの組み合わせについて

 S3を使っていて、初見でイマイチ腑に落ちないのが、バージョニングです。このバージョニング機能は、その名の通りオブジェクトの履歴管理を行いオブジェクトが更新されるたびに新たな履歴として追加していきます。これが腑に落ちないとなるのは、何ででしょうか?順番に説明していきます。

f:id:dkfj:20201005080025p:plain

バージョニングとライフサイクルの機能解説

 まずはS3のバージョニングとライフサイクルの機能の概要を見ていきましょう。どちらも考え方としては、非常にシンプルです。

S3のバージョニングの機能

 S3のバージョニングを有効にすると、オブジェクトの更新履歴を保持します。保存期間・世代数はバージョニング機能で指定できないので、永遠に保持し続けます。まず、ここが最初の?となるポイントです。保存期間・世代数の指定方法を無しに、どうやって制限するのと思うのではないでしょうか?AWSは、そこをライフサイクルという別の機能でカバーしています。

S3のライフサイクル機能

 S3のライフサイクルを使うと、ルールに従ってストレージクラスの変更とオブジェクトの削除ができます。また、対象は「現行バージョン」と「以前のバージョン」をそれぞれ指定可能です。ここで、「以前のバージョン」を指定することによりバージョニングを有効にした場合のオブジェクトの管理ができます。バージョニング設定はオン・オフしかできなくて、過去バージョンを管理するのがライフサイクルという別の機能というのがAWSらしい設計思想です。
 では、実際にライフサイクルの画面をみて確認してみましょう。ファイルの削除は「有効期限」の設定画面で失効の設定を行うことによりできます。バージョニングによる過去の履歴ファイルを消したい場合は、「以前のバージョン」をチェックの上で、○○日以前のオブジェクトを消すか設定します。

f:id:dkfj:20201005090950p:plain

 この時点で、また疑問が出てくると思います。バージョニングとライフサイクルの組み合わせで、例えば何世代残すという設定はできないのでしょうか?答えとしては、S3の機能だけではできません。S3のバージョニング機能とライフサイクルのファイル削除機能でできるのは、過去の更新履歴を残し続けること、一定期間が過ぎたオブジェクトを消すことの、シンプルな2点のみです。

f:id:dkfj:20201007132938p:plain

ユースケース別にS3のバージョニング機能の適合性を考える

 S3のバージョニング機能とライフサイクル機能を抑えたうえで、じゃぁどういったパターンで使うのかという話になります。よく聞かれるケースを3つほど紹介してみます。

ケース1 Gitのようなタグやブランチで管理したい

 無理!!

素直にGit系のサービスを使ってください。AWSだったらCodeCommit

ケース2 バケット内の全てのファイルを、1世代前のオブジェクトに戻したい

 出来るけど、たぶんやりたい事と違う動きになる

スクリプトを組んで、全部のオブジェクトを1世代前に戻すことは可能です。でも、S3の世代の概念は、オブジェクトごとです。そのため1世代前のファイルが3日前に更新されたものもあれば、1年前ということもありえます。そんな状態で1世代前に戻しても意味がないです。

ケース3 バケット内の全てのファイルを、特定日付のオブジェクトに戻したい

 出来なくはないけど、自分で実装が必要

オブジェクトごとに履歴があって日付の情報もあるので、一つづつのオブジェクトに対して調べてバージョン指定で戻すということで実現ができます。ただし、対象ファイルが多いと手作業で出来るものではないので、何らかのプログラムが必要になります。何が事があってからでは厳しいので、そういったことが必要であれば事前に作って検証しておきましょう。

まとめ

 S3のバージョニングとライフサイクルの話でした。AWSらしくそれぞれの機能はシンプルです。その特性を使ってどうするかというは、料理人の腕次第です。個人的には、バックアップと特定日での戻しに関して言うと、S3と連携する専用のバックアップソフトを使うことをお勧めです。また、静的Webサイトに多いリリース前に戻したいという要件は、複数のバケットを使ったBlue/Greenデプロイを使うのがいいんじゃないかなと思っています。現場からは以上です。

AdministratorAccess権限を持ったIAMユーザーでも閲覧できないS3バケットの消し方

 AWSのS3のマネジメントコンソールを見ていると、アクセスタイプで絞り込むことができることに気が付きます。絞り込みの条件として、「公開」や「オブジェクトは公開可能」など5種類あり、その中の一つに「エラー」というものがあります。今日は、このエラーというバケットが何者なのかというのと、それを無理やり消すための豆知識をお伝えします。

エラーが表示されるS3バケットは何者なのか?

 まずこのエラーと表示されるS3バケットが何者なのかという話からです。これは、S3のバケット一覧・詳細を表示しようとしているIAMユーザーもしくはIAMロールの権限とバケットポリシーの組み合わせで表示する権限がない場合に発生します。バケットポリシーも考慮するので、たとえ制限のないAdministratorAccessの権限を持っている利用者でも発生する場合があります。

 ちょっとイメージが付きにくいと思うので、具体的な例で紹介します。
手元にあった表示できないS3のバケットです。
f:id:dkfj:20201001001236p:plain


 バケットを選択の上で、概要を見ようにもAccessDenyになっています。
f:id:dkfj:20201001001345p:plain

 このバケットのバケットポリシーがどうなっているかを見てみましょう。
特定のVPCエンドポイント経由からのアクセス以外はすべて拒否するようにしています。

{
    "Version": "2012-10-17",
    "Id": "Policy1415115909152",
    "Statement": [
        {
            "Sid": "Access-to-specific-VPCE-only",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::tmp-test1234/*",
                "arn:aws:s3:::tmp-test1234"
            ],
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpce": "vpce-xxxxxxxx"
                }
            }
        }
    ]
}

 極めて機密性が高いデータや個人情報を含むものについては、IAMのアクセス権のコントロールのみならずバケット側でも制御することは必須となります。その際の選択肢として、そのデータを活用するシステムが格納されている特定のVPCからのみ制御はよくあるんじゃないでしょうか。

 そして、ここからが本題です。こういった制御はVPCエンドポイントのID等を指定します。そのエンドポイントが消してしまったり、指定の仕方がを間違えた場合はどうなるのでしょうか?答えは、誰も見えない消せないバケットの誕生です。ということで、そうならないように気をつけましょう!!

AdministratorAccess権限を持ったユーザーでも消せないバケットの消し方

 気をつけましょうで終われれば、世の中システム障害や謝罪会見は発生しません。気をつけても現実には起こりうるので、その時の対処法です。AdministratorAccess権限を持ってしても消せないのは、バケットポリシーによって制限されているからです。解決策としては、そのバケットポリシーを消せばいいのです。ということで、AdministratorAccess権限を持ったIAMユーザーで、バケットポリシーを表示してみましょう。

f:id:dkfj:20201001002202p:plain

 はい。無慈悲にも何も表示されませんし、保存・削除ボタンも押せません。では、どうしたらいいのか?実は、ルートユーザーであれば、どんな状態でもバケットポリシーの編集だけは出来るのです。

f:id:dkfj:20201001002441p:plain

 ということで解決策としては、ルートユーザーでバケットポリシーを削除するです。なお、ルートユーザーでもバケットポリシー以外の部分はすべてAccess Denyのエラーがでて、表示することができません。

 その他の解決策としては、AWSのサポートに問い合わせてみるというのもあるかと思います。過去、どうやったのか忘れたのですが、どうやっても消せないバケットが出来たこともあったような気がします。その時にサポートに聞いた記憶があるので。(遠い昔の話で、全く覚えていないですが)

まとめ

 結論としては、シンプルです。AdministratorAccess権限を持ったIAMユーザーでも消せないS3バケットを作ってしまったら、ルートユーザーでバケットポリシーを消しましょう。ちゃんちゃん

AWSのEC2 インスタンスメタデータサービスのv1(IMDSv1) とv2 (IMDSv2) の違いと効果

 SecurityHubにIMDSv2にしろよと警告が出るようになった今日この頃です。そこで、そもそもIMDSv2って何という疑問があるので、簡単に解説してみます。IMDSv2は、インスタンスメタデータサービス Version 2です。iPhone 3Gの前は無印のiPhone(初代)ですが、version 2ということはversion 1があります。v2 (IMDSv2) が出てきた経緯と、その動作の違い等についての豆知識です。

インスタンスメタデータとは?

 インスタンスメタデータとはインスタンスに関する情報(データ)で、実行中のインスタンスからcURLなどのツールからリンクローカルアドレス(http://169.254.169.254)を呼び出すことで取得できます。取得できる情報とては、インスタンスIDや自身のIPアドレス、所属するセキュリティグループなどです。インスタンスの中で実行するプログラムあるいはAWSの各種サービスが、この情報を使って何らかの処理をする時に利用します。

 v1とv2の違いは、取得の仕方です。

v1は次のように単純にURLを叩くだけで取得できます。

curl http://169.254.169.254/latest/meta-data/

v2は、リクエストのヘッダーに有効期限などを元にしたトークンを埋め込む必要があります。

TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/

Capital Oneを襲ったSSRF攻撃とインスタンスメタデータ

 それでは何故v2は、わざわざトークンを埋め込んで取得しにくくしているのでしょう?その背景を知るために、Capital Oneを襲ったSSRF攻撃の事件を紹介します。事件の概要を簡単に説明すると、攻撃者はWAFの脆弱性を利用してIAM Roleが設定されているインスタンスにServer Side Request Forgery(SSRF)攻撃を仕掛け、インスタンスメタデータを利用してIAMのクレデンシャル情報を取得しました。そのクレデンシャルを利用して、S3にアクセスして大量のデータを盗んだという事件です。

f:id:dkfj:20190812151512p:plain

Capital Oneの個人情報流出事件に思うこと - プログラマでありたい

 この事件には幾つかポイントがあるのですが、そのうちの一つがインスタンスメタデータを通じてIAMロールの一時的なアクセスキー・シークレット(クレデンシャル)が取得され、それを悪用された事にあります。

f:id:dkfj:20200930094358p:plain

 インスタンスメタデータからクレデンシャルを取得できる事自体は、インスタンスメタデータサービスの仕様なのでそれ自体は問題ありません。問題は、そのデータが簡単に取得できるので、SSRF攻撃を受けた時に悪用されやすいという点です。その改善としてv2が出てました。v2がもともと計画していたのか、Capital Oneを受けて作ったのかは不明です。ただGCPのメタデータの取得はv2的な動きで、AWSもそうして欲しいという話は以前からありました。

インスタンスに対してv1・v2を指定して設定する

 インスタンスメタデータサービスのバージョンの指定は、インスタンス起動時に指定できます。v2が出た当初は、CLIでの起動のみ指定可能ですが、今だとマネジメントコンソールからでも指定できるようになっています。インスタンスの詳細設定の高度な詳細(どんな日本語だよ)のMetadata Versionで指定できます。デフォルトはv1とv2の両方を使えるもので、v2のみ使えるものも指定できます。また、Metadata accessibleで、メタデータ自体にアクセスできないようにすることもできます。

f:id:dkfj:20200930095414p:plain

v1とv2の挙動の確認

 それでは、実際にv1とv2の設定をしたインスタンスで、それぞれの挙動を確認してみましょう。まずは、v1設定のインスタンスです。

単純なcurlコマンドでの取得

$ curl http://169.254.169.254/latest/meta-data/ami-id/
ami-0ce107ae7af2e92b5

 成功しますね。
次にv2に対応したトークン埋め込みでの取得

$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` && curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/ami-id/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 56 100 56 0 0 11200 0 --:--:-- --:--:-- --:--:-- 11200

Trying 169.254.169.254...

TCP_NODELAY set

Connected to 169.254.169.254 (169.254.169.254) port 80 (#0)

> GET /latest/meta-data/ami-id/ HTTP/1.1
> Host: 169.254.169.254
> User-Agent: curl/7.61.1
> Accept: */*
> X-aws-ec2-metadata-token: AQAAAMVnM-DonAFD57_6PRycSd7L-6KgnwwOK2i352oj2ir7dYa85g==
>

HTTP 1.0, assume close after body

< HTTP/1.0 200 OK< Accept-Ranges: bytes< Content-Length: 21< Content-Type: text/plain< Date: Tue, 29 Sep 2020 15:32:45 GMT< Last-Modified: Tue, 29 Sep 2020 15:03:15 GMT< X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 21600< Connection: close< Server: EC2ws<

Closing connection 0

 見え方が違うけど、成功しています。
v1,v2のどちらのコマンドでも取得できることが確認できました。

次にv2設定のインスタンスで、v1で取得する際に利用する単純なcurlコマンドでの取得してみます。

$ curl http://169.254.169.254/latest/meta-data/ami-id/
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>401 - Unauthorized</title>
 </head>
 <body>
  <h1>401 - Unauthorized</h1>
 </body>
</html>

 401 Unauthorizedで権限がないためにエラーがでています。
ということで、v2に設定しているとトークンを埋め込まないと取得できないことが解りました。

 v1からv2に変更する場合、AWSの機能・サービスで呼ぶ出しているところは影響ないですが、自前でメタデータを取得するプログラム・コマンドを作っている場合は変更が必要です。

v2 (IMDSv2) を設定した場合のセキュリティ的な効果は?

 それでは、v2 (IMDSv2) を設定するとセキュリティ的にどういった効果があるのでしょうか?AWSやクラスメソッド臼田さんのブログにある通り、幾つかの効果があります。

  • 誤って設定された Web アプリケーションファイアウォールからの保護
  • 誤って設定されたリバースプロキシからの保護
  • SSRF 脆弱性からの保護
  • 誤って設定されたレイヤ3ファイアウォール、NAT 機器からの保護

 v2を使うと何故防げるのかというと、ヘッダーを検証するようになっているのでX-Forwarded-Forが入っているとトークンを発行しないなどの幾つかの仕様がはいっているためです。詳しくはブログを確認してください。

aws.amazon.com

dev.classmethod.jp

実際、どれくらいの効果があるのか?

 それでは、v2 (IMDSv2) にした場合にどれくらいの効果があるのでしょうか?これはSSRF等の防止策ではなく緩和策と認識しています。つまり単純な攻撃からの被害を防げるけど、もっと本気を出した攻撃は防げません。このあたりは徳丸さんが詳細指摘しています。

blog.tokumaru.org

 対策として大事なのは、設計レベルでそれぞれのサービスに防御を盛り込むことだと思います。例えば、インスタンスに付与するIAMロールには最小権限に絞るとか、取得される先のS3バケットはバケットポリシーで接続元を絞り込むなどがあります。このあたりは、過去にまとめています。

blog.takuros.net

 今後作るインスタンスについては、v2 (IMDSv2) にすべきだと思います。またIAMポリシーで、IMDSv2を強制するということもできます。ただし、その設定をしていれば安心という代物ではないということはしっかり認識しておきましょう。それぞれのレイヤーで、出来うる限りの設計・防御をしていくという観点をもっていきましょう。でもIAMとかAWSのセキュリティサービスが解らんという方は、お勧めの本がありますよというステマで終わらせて頂きます。現場からは以上です!!

booth.pm

booth.pm

ファイルストレージ・ブロックストレージ・オブジェクトストレージの違いと、AWSのストレージサービスとのマッピング

 こんにちは。仕事でAWSの構築し、プライベートでAWSの研究と技術書の執筆をし、Amazonで本を売っているAmazon依存症疑惑のある佐々木(@dkfj)です。
 AWS使い始めてまず悩むことのベスト10の一つが、ストレージサービスの選び方です。AWSにはS3やEBSの他に、EFSやFSxなど多種多様なストレージサービスがあります。今回は、ストレージサービスの種類から、AWSのサービスの使い分けを説明したいと思います。

ストレージサービスの種別

 一口にストレージといっても、用途に応じて幾つか分類できます。代表的なのが、ファイルストレージ・ブロックストレージ・オブジェクトストレージです。まずは、この3つの違いをみてみましょう。

ブロックストレージ

 まず一番イメージしにくいのが、このブロックストレージ。ブロックストレージは、ものすごくザックリいうとハードディスクのようなもので、ブロックと呼ばれる論理単位でのアクセスします。ハードディスクは物理的な単位に制約されますが、クラウドのブロックストレージはバックエンドのストレージを論理的にまとめて好きな単位に切り売りしてくれます。人間が直接扱うというより、OSとかが使う低レイヤーなストレージになります。

ファイルストレージ

 次にファイルストレージとは何かです。こちらはいわゆるファイルサーバーのようなイメージです。ユーザーは、ストレージ上のデータを個々のファイル単位で扱います。OSを介して見えるのがファイルストレージですし、それをネットワーク越しに利用するのがNAS(ネットワーク・アタッチト・ストレージ )です。

オブジェクトストレージ

 最後にオブジェクトストレージです。字義的には、データをオブジェクト単位で扱うストレージです。これだと、ファイル単位で扱うファイルストレージと何が違うのだという気がしますが、その通りです。ディレクトリ構造で管理するファイルストレージと違い、オブジェクトストレージはオブジェクトを一意に識別するIDと、それを管理するメタデータで構成されています。さらにS3のようにアクセスするためのAPIが提供されているケースもあります。というか、オブジェクトストレージの概念と実装は、S3の存在が大きいんですね。知らなかった。

ストレージ種別のまとめ

 ブロックストレージ⇒ファイルストレージ⇒オブジェクトストレージとレイヤーが上がってくるイメージですかね。この辺りRedHatさんが上手くまとめています。流石、ストレージ会社の側面がありますね。

www.redhat.com

ストレージ種別とAWSのサービスのマッピング

 ストレージ種別の概要がザックリ解ったところで、AWSのサービスをマッピングしてみましょう。

ストレージ種別 サービス名 概要
オブジェクトストレージ S3 AWSが誇るオブジェクトストレージ
オブジェクトストレージ Glacier S3のストレージクラスの一部に取り込まれたアーカイブ用ストレージ
ブロックストレージ EBS 不揮発性のストレージ
ブロックストレージ EC2のインスタンスストア 揮発性のストレージ
ファイルストレージ EFS NASみたいに複数のインスタンスからマウントできる
ファイルストレージ FSx for Windowsとfor Lustreの2種類があるよ

ファイルストレージの使い分け

 オブジェクトストレージは2種類ありますが、Glacierはアーカイブ用と用途と機能がはっきりしているので使い分けに悩みません。またブロックストレージも永続化&使いまわししたければEBSで、インスタンスストアはローカルで高速なI/O処理に利用すると、これも使い分け方がはっきりしています。一番悩むのが、ファイルストレージだと思います。ファイルストレージには、EFSとFSx for WindowsとFSx for Lustreがあります。ここをどう使い分けたらよいのか難しいので、個人的な見解含みでザックリと分けたいと思います。

EFS

 まずEFSは、Linux向けのファイルシステムとして考えましょう。何故ならば、Windowsの素のドライバーでは、未だEFSをサポートしていないからです。EFSはNFSv4プロトコル経由でのアクセスを前提としていますが、Windowsは今のところNFSv4に対応していません。利用したい場合は、サードパーティ製のドライバを使うという手がありますが、それであれば次で紹介するFSx for Windowsを使ったほうが良いです。
 それ以外の特徴として、参照系のアクセスに強く書き込み性能は高くないという点があります。『何千もの Amazon EC2 インスタンスに対して大規模な並列共有アクセスを提供するように設計されている』と豪語されているのですが、一方でWrite Manyなシステムには向いていません。あと、EBSに比べるとRead・Writeとも性能はそこまで高くないです。更にスループットモードがバーストとがあり、バーストモードはサイズによって基本性能が変わります。使い所として悩みますが、CMSの共有ストレージとしてのコンテンツの置き場に使いやすいのも事実です。その際は、CloudFront等と併用してキャッシュを上手く使いましょう。

FSx for Windows

 EFSがWindowsに使えないとすると、じゃぁどうすんのという時に出てくるのがこのFSx for Windowsです。FSxは、FとSが大文字でxが小文字というこだわりのネーミングですが、そもそも何の略称か解りません。FSxにはfor Windowsとfor Lustreの2種類があり、アーキテクチャ・機能・用途も大きく違っています。for Windowsは名前の通りWindows用のサービスで、フルマネージドなWindowsのファイルサーバとして使えます。ということで、Windowsでファイルストレージが必要になった場合は、FSx for Windowsを使いましょう。

www.slideshare.net

FSx for Lustre

 最後のファイルストレージがFSx for Lustreです。Lustreは、フルマネージドな分散ファイルシステムで、S3とシームレスに統合できるファイルストレージです。個々の単語の意味を理解できても、つなげると解らなくなってしまいます。まずS3とのシームレスな統合というのは何かというと、ファイルシステム作成時にS3のバケットと関連付けできます。そして、S3上のファイルをインデックスし、あたかも自前のファイルのようにみせます。初回アクセス時はS3から取得するので遅いのですが、2回目以降はキャッシュしているので高速です。なんとなくStorage Gatewayのキャッシュ型ボリュームの挙動と似ていますね。主な用途は、高速なデータアクセスが必要なハイパフォーマンス・コンピューティングや機械学習とのことです。

www.slideshare.net

まとめ

 AWSのサービスはいろいろあって悩むと思います。悩んだ時は、一度基本に立ち返ってどのレイヤーに対応したサービスなのかを確認するといいのかもしれません。


See Also

blog.takuros.net

blog.takuros.net