日頃当然のように利用しているAWS VPCを、整理の意味も兼ねて改めて考え直してみたい。
なおタイトルにIssueとついているのは『イシューからはじめよ――知的生産の「シンプルな本質」』を読んでいて感化されたため。
考えながら書いているので、冗長になるのはお許し願いたい。
そもそも論
そもそもVPCを用意しないといけないのはなぜか。この疑問を考えるにあたっては、比較したほうがわかりやすかろうということで、VPCが無い場合とある場合でどう違うのかを比較して考えてみる。
VPCがあるとなにが良いのだろうか。もしくは、ないとどうなるのだろうか。
- 外部からの(または、外部への)通信を制限できる
- もしVPCがなくて、全部パブリックIPをつけたEC2をポン置きしないといけないとすると(EC2-Classicはそれに近かったのかもしれない)、インターネット上からのアタックがそのまま叩きつけられる。セキュリティ的に大変恐ろしい状況だ。
- その点、VPCのPrivateネットワークにEC2を配置すれば、通信経路は大いに限定できる。最小権限の原則も守りやすい。ちょっとくらいミドルウェアの更新が遅れても、通信が届かないなら安心である。もちろんアップデートが滞っているのは良いことではないのだが、必要となったら即アップデート、なんてことは、かなり頑張ってImmutableにしていないと厳しいことが多いだろう。
- また逆に、内部からの不要な通信が外部に飛んでしまうことも防げる。
- 開発中のアプリケーションに馬鹿馬鹿しいバグはつきものだ。しかもそれが事前にわからない。だがネットワーク的にガードされているとなればかなり安心できる。
- 内部でもあやまった通信を制限しやすい
- Product用のリソースとDevelop用のリソースも同じネットワークにいる状況は、ホラー映画よりも恐ろしい。うっかり開発中のアプリのバグによって本番用データベースのデータを破壊してしまったら地獄である。サービスの継続性にまで関わる。
- その点、Product用のVPCとDevelop用のVPCを分けると、開発中のミスがエンドユーザにまで及ぶなんて悲劇をネットワーク的に防ぐことができる(完全ではないが)。
- ネットワークが区切られていなくても、iptablesを使えばポートも接続元も制限できるわけだが、その管理はひたすら手間だ。個々のノードごとに管理しないといけない方式は、数が多いと管理が困難極まる。それに、たった一つの仕組みで守ると、その一つの仕組みがミスっていたらインシデントに繋がる。
- iptablesはうっかり設定ミスをすると通信ができなくなる危険な代物なので、作業中は神経が削れる、という問題もある。リスクを軽減する方法もあるけれどもAnsibleなどの自動化ツールと組み合わせるのは結構辛そうな気がしている。
- ネットワークが区切られていなくても、iptablesを使えばポートも接続元も制限できるわけだが、その管理はひたすら手間だ。個々のノードごとに管理しないといけない方式は、数が多いと管理が困難極まる。それに、たった一つの仕組みで守ると、その一つの仕組みがミスっていたらインシデントに繋がる。
- 通信の監視とロギングが容易
- Private IPアドレスが使える
まあ大体ここに書いてある通りではあるのだが、VPCのメリットは概ねセキュリティの維持にあると言ってよさそうだ(IPアドレスなど、当てはまらないものも若干あるが)。データ破壊などを防ぐことで「可用性」を、不要な通信をシャットアウトすることで「機密性」を、それによって間接的に「完全性」を得られるわけだ。
つまりVPCのポイントとは?
してみると、VPC構築の本質的な価値も同様に考えていい。3要素のうち特に可用性、機密性がポイントだろう。
可用性を維持できるようMultiAZを採用したり、通信ログを監視したり(間接的な繋がりだが)する。
そしてまた、通信権限を必要最小限にとどめるために、サブネットを切ったり、SecurityGroupを細かく設定したり、NATゲートウェイやVPCエンドポイントなどの外部接続のための仕組みを用意したり(これがないと全部Publicにおかざるを得ないわけだから、これも通信権限を限定するための補助的な仕組みと言っていい。事実、ノードを全部Public Subnetに置いて通信も公開ネットワークをどんどこ飛び回っていいなら、NATゲートウェイもVPCエンドポイントも必要ない)する。
その設計はセキュリティ確保に寄与するか?
それがVPC設計のキモと言っていいだろう。
もちろん、サブネットで確保したアドレス範囲が狭すぎて必要なノードが配置できない、なんてのは困るから、セキュリティしか考慮する点がないわけではないのだが。