こんにちは、SREチームの成田です。 2019年も残りわずかといったところですが、今年行ったインフラ改善の一つでAWSセキュリティグループの整理を行いました。 その結果、不要なセキュリティグループを減らし、ルールもシンプルな状態にできたのでその時の話をしたいと思います。
キラメックスでは、TechAcademyやTechAcademyマガジンをAWSで運用しています。 AWSを使用する際に必ずと言っていいほど使用するのが、インスタンスに対してのステートフルファイアウォールであるセキュリティグループですが、セキュリティグループ便利ですよね。 ただ、セキュリティグループは適切に運用しないと、どんどんルールが膨れ上がっていき、散らかりがちになりやすいものだと思います。 セキュリティグループが散らかっていると、セキュリティインシデントやネットワーク障害の温床になるので整理された状態に保ちたいところです。
キラメックスのセキュリティグループも、度重なる変更によりルールが複雑になっていたり使用していないものがあったりと、管理コストが高い状態でした。 そこで不要なセキュリティグループの断捨離をした後、新たにセキュリティグループを再設計して整理を行いました。
不要なセキュリティグループの削除
使用していないセキュリティグループが複数存在していたのでまずはそれらを削除します。
使用していないセキュリティグループを洗い出すのにはこちらを参考にさせていただきました。
【Tips】使用していないセキュリティグループを洗い出したい!!! | Developers.IO
今回はEC2やRDSのようにENIに紐付いているセキュリティグループの他に、Auto Scalingで使用しているセキュリティグループも洗い出したかったのですが、問題なく洗い出しを行うことができました。 洗い出した結果、セキュリティグループ全体の半数近くが使用されていないことがわかり、それらを削除することでだいぶ見通しがよくなりました。 定期的な見直しは大事ですね。
セキュリティグループの設計
不要なセキュリティグループを削除して見通しが良くなりましたが、そのままだとまた数年後には同じような状況になってしまうので、なるべくきれいな状態に保てるようにセキュリティグループを設計し直します。
当時の状態
当時のセキュリティグループの状態としては、インスタンスごとにセキュリティグループを作成しているような状態でした。 例えば、インスタンスAにはセキュリティグループA、インスタンスBにはセキュリティグループBがアタッチされている、といったイメージです。
これだと、新しくインスタンスを作成するたびにセキュリティグループが増えていきますし、インスタンスを削除したときにセキュリティグループを消し忘れた場合、不要なセキュリティグループとして残り続けてしまいます。
また、VPC内通信(例えばEC2 <-> RDSといったもの)のルールもIPアドレスベースのルールで記述されていたので、ルール数が増える原因となっていました。
改善策
インスタンスが増減したとしても不要なセキュリティグループを出さないようにするにはどうしたらよいかを考えた結果、再利用性が高いセキュリティグループの設計を目指すことにしました。
特定のインスタンスに対してのセキュリティグループではなく、HTTPやSSHなどの用途ごとにセキュリティグループ作成して、インスタンスが必要なルールを持つセキュリティグループを選択してアタッチする、といった具合です。
例えば、以下のようなインバウンドルールを持ったセキュリティグループを作成したとします。
セキュリティグループ | ソース | ポート | プロトコル |
---|---|---|---|
セキュリティグループA | 0.0.0.0/0 | 80 | HTTP |
セキュリティグループB | 12.34.56.789/32 | 22 | SSH |
この時、インスタンスAでパブリックなHTTPと特定IPからのSSHを受けたい場合は、セキュリティグループAとBをアタッチします。 対して、インスタンスBでパブリックなHTTPのみを受けたい場合はセキュリティグループAのみをアタッチします。
このように用途ごとにセキュリティグループを作成することで再利用性を高めることができ、不要なセキュリティグループが生じることを防ぐことが期待できます。
また、VPC内のインスタンスにデフォルトでアタッチするセキュリティグループを作成し、VPC内通信を許可する場合はインバウンド設定のソースにそのセキュリティグループを指定したセキュリティグループを作成することで、IPアドレスベースのルールからの脱却を目指しました。 インバウンド設定のソースにセキュリティグループを指定すると、ソースに指定したセキュリティグループがアタッチされているインスタンスからの通信を許可するという意味になるので、VPC内通信のルールをシンプルにすることができます。
以下の例ですと、セキュリティグループCはセキュリティグループDがアタッチされているインスタンスからポート3000番の通信を許可する、という意味になります。
セキュリティグループ | ソース | ポート | プロトコル |
---|---|---|---|
セキュリティグループC | セキュリティグループD | 3000 | TCP |
セキュリティグループの変更作業
セキュリティグループの変更は、
- 旧セキュリティグループがアタッチされているところに新セキュリティグループをアタッチ
- 旧セキュリティグループをデタッチ
の2段階で行いました。 変更対象は、EC2インスタンス、Auto Scaling、ALB、RDS、Elasticacheなどになります。
旧セキュリティグループのデタッチについては、1つ旧セキュリティグループをデタッチしたら関連する通信の疎通を都度確認するという地道なものでしたが、無停止で行うことが出来ました。
RDSやElasticacheのセキュリティグループ変更について、事前にステージング環境で無停止で行えることは確認済みでしたが、実際に本番環境へ適応するのはちょっと怖かったです。 (考えてみればRDSもElasticacheもEC2が基盤なので無停止でできるはずなんですけどね。)
まとめ
ということで、セキュリティグループの改善をした結果、セキュリティグループ数とルール数ともに半分以下に減らすことができました。 改善してから1ヶ月ほど経過しましたが、特に問題なく運用できています。
とはいえ定期的な見直しは必要そうな気はしているので、1年後にどのような状況になっているのか楽しみです。