IAMとかサービスとかのはなし

ふらーっとRe: Post覗いてたら、やっぱり、というか以外と、なのか、IAM周りと権限付与、そしてsts周りってやっぱりうまく把握しきれていない人って結構いるんですね。

まあくそわかりにくいので、しょうがないですが。どうもこんにちは、Infrabbitです。

IAMやPassRoleなんかはクラスメソッド千葉さんの「IAMはお面のようなもの。」の記事を読めばなんとなくつかめるんじゃないかと思うんですが、問題はSTSのAssumeRole。これがインスタンスとかIAMユーザーですとかならするっと頭に入ると思うんですよ。でもAssumeする先って別にそれだけじゃないんですね。

「何をPassRoleする先として信用するか」なので、別に人やモノである必要もなく、この信頼先ってようするになんでもいいけどなんかのオブジェクト。なんですよ。そもそもインスタンスプロファイルだってAssumeRoleの一環ですし。インスタンスにRoleを直接取り付けてるわけじゃあないんですよ、見かけ上そう見えるでしょうけど。

つまり、AWSの「サービス」という概念に対して行われるのがサービスリンクロールとかサービスロールとかいうやつになりますし、「STSにアクセスが許された権限持った何か」だったら別に勝手に作ったアプリケーションでも問題ないし、Bash上でコマンド叩いてセッションもらったら別に「Bash上の操作」という概念にだって当然与えられるわけです。まあそれやってるのがAWS CLIってわけなんですが。もちろん、外部のサービスだっていいし、ちゃんとお作法守ってくれるなら伝書鳩の足に括り付けてある伝言メッセージでも構いません(RFC 1149)。たぶんパケットが往復してる間にタイムアウトしますけど。

まあなんというか、Credentialsに慣れた人ほどRoleがわからなくなりやすいのかもしれないですね。あれはもうなんかID/Passくらいに思えたんでしょうね。実際のところ、CredentialsもID/Passではなく、Roleへのアクセス手段でしかないのですが、まあ見かけ上ID/Passに見えるのでしょうがないですね。

なので、Role自体はただのお面テンプレートでしかありません。Roleがいっぱいあるからセキュリティ的に問題、なんじゃなくて、Roleがいっぱいあったとしても誰にもRole渡さない仕組みだったら別にかまやしません。管理できてるかどうか、が争点ならセキュリティ的にまずいかもしれませんが、Roleがいっぱいあるから問題、なんじゃなくてそれはいっぱいあるRoleを管理できていないから問題、なのであって、その解消過程で管理できる程度までRole減らそうね、という話が出てきたりはしますが、普通に本末転倒の部類の話です。

IAMは非常に強力な認証認可メカニズムなので、条件式がきちんとかける分、厳密に最小原則でやると結構地獄を見ます。わかっててもあれだけある権限を厳密に最小原則で付与するのってむつかしいですしね。アプリがある程度配慮してくれれば別ですが、その場の勢い的なノリで作られたマイクロサービスなんて目も当てられません。基本設計ってとても大事。

うちでよくやる手としては、ざかーっとおおまかにはアスタリスクリソースで許可出してしまって、こうなったらまずいよな、ってのを想定してそっちをふさぐ、というパターンですが、それでも想定外からに対して弱くなるので痛しかゆしですし、セキュリティガーっていうセキュリティが何かもよくわかってないけどとりあえず言ってみる系な関係者がいるとまあ使えない手です。

Roleが認可のテンプレート、実際の誰に何を与えるかを決定づけているのがAssumeRoleに当たるところで、ここが認可の実態といえるかと。Credentialsなんかは認証の要素であって認可要素じゃねぇ、ってとこがきちんと理解できれば、Roleの話題にCredentialsの話を持ち込むのがいかにナンセンスなのか、ということが見えてきます。

じゃあIAMの認証要素って何なんだよ、って話ですが、そりゃまあIAMユーザーだのCredentialsだのIdentity Centerだのってのが認証要素に当たりますね。でもこいつら認可には一切手出し口出しできません。

ユーザーなんかだとデフォルトでもらってるRoleがありますが、このRoleに権限をあれやこれやぶち込むのがいかにナンセンスか、というのもなんとなくわかってくるんじゃないでしょうか。ここにリテラル突っ込むって要するにくっそダサい。ぶっちゃけここの権限なんてゴミでもViewOnlyでも構わんのです。ログインできりゃそれでいいんだから。そのあと何かしたいならRole切り替えていけばいいのです。

ユーザー単位で権限を考える、のではなく、やりたいことに対して「権限持っていいのはだれ/なにか?」で考える、という感じですね。IAMは基本原則としてデフォルトDenyなので、明示Allowを与えない限り実行できません。

ぶっちゃけ、最小原則で行くならエラー出たら都度与えますね!がたぶんかなり正確になるんですよね。開発の方々がすっごい嫌がりそうですけど。まあそのへんを大雑把に解決するためにあるのがPermission Boundaryということになります。

こちらは大雑把に言ってしまえば、「絶対やってほしくないこと」リストに当たります。なので、基本的にDenyリストですね。IAMユーザーに個々人のIAMの各変更権限だとかM2Aの設定権限だとかCredentialsの発行権限だとかを与えたいときに、でもCreateUserとかは与えたくねぇわ。しゃーねー羅列するか。

というのは基本くそめんどくさいうえにRoleがバカみたいに長くなります。まあTerraformで書くんで実はそんなに気にならないんですが、ドキュメントにしたときにJSON見せたらそっ閉じされます。

まあなので、IAM:*で与えちゃって、PermissionBaundaryでCreateUserを殺(Deny)す、といったことをやったりします。要するに重ね合わせ、ユニオンファイルシステムですね(違。

最近はCloudTrailから権限組んだりもできるのでだいぶ楽になってきた感はありますが、それでもまあIAM周りはやっぱり鬼門なんでしょうね。とはいえ、AWSにしろGCPにしろAzureにしろ、認証認可は基盤の中の一番根っこに当たる部分なので、ここがわかってなかったら上っ面のサービスをいくらうまく使えてもどっかで転びます。特にインフラ屋がここわかってない、というのはふう、なんとか今回の案件のミスは致命傷で済んだぜ。という事態を容易に引き起こします。

ま、Identity Center使ってるならSCPも使えるので、さらにごちゃつきさ加減は加速するわけですが。

何が言いたいかというと、アプリ作るときはインフラも呼んでください。アプリの人の権限設計はアプリの中の話であって、その外側の権限設計とは分離しています。まして分散で設計とかされた日には、あっちのアプリはDynamoDB使うけどこっちのアプリはRedis使っててこっちのはRDSに放り込んで、こっちのはSQSからパイプラインで流してて。。。。

 

みたいなのが開発が始まって中盤くらいになってインフラに図面が下りてきて何このぐっちゃぐちゃな世界。え、これでもう作ってる? バカなの? 死ぬの? なんてことも起こります。起きてほしくないですが。とりあえず全員一回Dynamoに放り込んでからAirflowでもなんでもいいからパイプライン通せばいいじゃない。なんでもかんでも最短距離行くのが最適解とは限らんよ。局所的には最適解だけど大局的に最適解じゃないケースなんていくらでもあるでしょ、世の中。

だって世のおかーさん方、コスト的最適解は大阪のスーパー玉手や東京のアキダイかもしんないけど、愛知在住のおかーさんコスト最適解だからって行くか? いかないよな。移動代だって大量に買えばコスト最適解なんだからどこかに損益分岐があるわけで、移動代かかるから損、じゃないんだよ。正しくはコスト以外の要因で行かないんだよ。賞味期限だったり、時間パフォーマンスだったり、それらはコスト、という局所的最適解ではなくて、全体俯瞰した結果、複数の要因を満たせないから大局的最適解ではない、という話なんですね。そして、それと同じことなんです。部分的最適解の積み上げが必ずしも大局的最適解ではない、ということを理解しておかなくてはならない。まあ普通に部分的最適解が全部は積みあがらない、という話でもあるんですが。全部積みあがるなら大局的最適解も一致するはずです。

要するに全体俯瞰できるSIerがいりゃあこんなことは起きないんですが、全体俯瞰できてAWSの権限設計がきちんと頭入ってて全員の調整ができるプレーヤーってそんじょそこらにそうそうは転がっていません。わりとエースプレイヤーです、そんなん。クラスメソッドさんとことか、サーバーワークスさんとことか行けばいますが、そこらの昔からの付き合いでねぇ。。。みたいなSIerにはまずいません。

だからと言ってそれらのトップ集団とこに頼め、というてるのではなくて、チームでやりゃあいいんですよ。わからんとこはサポートしてもらえばいいじゃない。しますよ、AWSの話なんだから。アプリがあっちこっちと使いたいのはわかるし、使いやすいのを使いたがるのもわかるけど、シンプルにしたほうがいいよ、とか一緒に悩む脳みそくらいは貸せますよ、という話。

個人的にはインフラって基本的に全体俯瞰することが仕事の一部だと思っているので、とりあえずざらっと見るときに俯瞰します。いきなり細かいこと言うこともありますが、それも全体俯瞰の地盤の上で言う、というのが基本になってきます。これが割と重要な話でもあり、この「俯瞰する」ために僕らはAWSの内部構造まで知りたがるんです。ディープダイブとか見まくるのも、趣味じゃなくて地盤をどこまで強固にするか、俯瞰するときの精度をどこまで高めるか、という点でやっていることです。

なのでハードウェアの進化も追っかけていますし、クラウドサービスも追っかけます。死ぬほど地味なのにつらいです。

AWSとかが公表していないサービスの内部構造は、「自分だったらどう作るか、どう成立させるか」で想定し、推定し、AWSが出している「制約事項」が自分の想定する構造の場合同じように発生するかどうかを推論し、仮定し、時には実際に構築し、その上で「おおむね似たような作り方をしているに違いない」という不確実な確信を得て、ようやくぼくらは「(たぶんこういう仕組みだと思うので)こうしたほうがいい」という言葉につなげるのです。

たとえその結論が、「ドキュメントにこうすべきだ」と書かれているものと同一になったとしても、「(ドキュメントに書いてあったから)こうしたほうがいい」という言葉とは重みが違う、と思っています。そして、そこに価値を見出してくれる人と仕事をしたいなぁ、と思ったりするのです。

だいたい「ドキュメントに書いてあるから」じゃねぇよ。疑ってかかろうよ。ドキュメントがほんとかどうか試して、確かめる、くらいは最低でもやるべきだと思うんだよなぁ。少なくとも、作るシステムの肝になってる部分に関してはそれくらいやっても罰は当たらんと思うんですよね。

そんなことを年末にぼんやり考えていたら、投稿するのを忘れていて新年になりました。

あけましておめでとうございます。