AWSやGCPを利用する際によく対面するセキュリティ対応について各クラウドでのソリューションを比較しながら、サービスや方針についてまとめました。
この記事の範囲
- 主に、Webサービス/アプリ開発でのクラウド利用におけるセキュリティについての話がメインです
- PCI DSS とか ISMS とかの難しい話はしません(というかできないよ\(^o^)/)
パブリッククラウドにおけるセキュリティ
パブリッククラウドにおいて、まず最初に押さえるべきは「責任分担モデル」です。簡単にいうと、**クラウドサービス自体の運用に関しての責任はクラウドプロバイダが持つ。クラウドサービスの利用の仕方に関する責任は自分たちで持つ。**ってやつです。
これは大体どのプロバイダも一緒なので、覚えておくといいと思います。
引用: https://aws.amazon.com/jp/compliance/shared-responsibility-model/
どっちに責任があるのかを明確にするのも大事なのですが、自分が一番大事にしたいのは、有事の際に一番困るのは**"自分たちのサービスを利用してくれるユーザー"**ってことです。だからこそ、可用性と共にセキュリティは重要だと考えています。
また、パブリッククラウドのセキュリティに対する考え方は各プロバイダでホワイトペーパーが出てるので一読しておくのをおすすめします。
セキュリティ設計・実装パターン比較
IAM(Identity and Access Management) 権限
IAMは、ここを避けては通れないほどAWS/GCPともにめちゃくちゃ重要な概念です。できることはほぼ同じなのですが、用語とコンセプトがやや違うため混乱します。
たとえば、「IAMポリシー」という用語を取ってみても、AWSだと単純に権限を定義するドキュメントで、GCPだと役割とメンバーのバインディングリストだったりします。
AWSからGCPにスイッチする人向けに、権限管理についての比較表があるので抜粋します。
引用:https://cloud.google.com/docs/compare/aws/management?hl=ja用語の差異以外にも、「バージョニングの有無」なども気になるポイントです。
権限の継承
AWSにおけるIAM権限の継承は、IAMグループにIAMユーザをアタッチすることで、グループの権限をユーザに継承することができます。継承の仕組みとしてはわかりやすくシンプルですね。
GCPでは「リソース階層を使用したアクセス制御」が可能です。これはAWS同様「権限が継承される」仕組みなのですが、スコープが大きく違います。
AWSの場合、同じアカウントに閉じられていますが、GCPの場合、GCPプロジェクトの上位リソース(組織やフォルダ)から権限を継承させることができます。
引用:https://cloudplatform-jp.googleblog.com/2016/04/iam.html
このメリットは、「権限の一元管理ができる」ことと、「権限管理のライフサイクルがプロジェクトに依存しない」ことだと思います。
権限管理には棚卸しがつきものなので、こういった一括で設定できような仕組みがあるのは助かります。
詳細は、GCPのリソース階層を参照してください。
リソースごとの権限管理
AWSでは、リソースに一意の名前(Amazonリソースネーム)があるので、リソース単位で細かく権限管理することが可能です。
それに比べ、GCPではリソースレベルで制限できるものが決まっています。
権限管理ができるリソースとして具体的には、Big Query (Table)、PubSub (Topic)、Cloud Storage (Bucket)、Compute Engine(VM Instance、disk、image)があります。
この思想については、「リソース階層を使用したアクセス制御」のベストプラクティスに以下のように述べられています。
リソースレベルではなく、組織レベルまたはプロジェクトレベルでポリシーを設定してください。新しいリソースが追加されたとき、それらが親リソースからポリシーを自動的に継承すると便利です。たとえば、新しい仮想マシンが自動スケーリングによってプロジェクトに追加されたときに、それらが自動的にプロジェクトのポリシーを継承するようにします。
引用:https://cloud.google.com/iam/docs/resource-hierarchy-access-control?hl=ja
IAMベストプラクティス
同じIAMでも、クラウドによって異なるものだということがわかります。なので、それぞれのベストプラクティスに乗っ取る形がおすすめです。
- AWS IAM のベストプラクティス
- GCP IAM ベスト プラクティス ガイドを公開
Bastion(踏み台)サーバーについて
Bastionサーバーとは、外から接続できないサーバーに対して、メンテなどの目的でSSH/RDPするための"踏み台"として利用するサーバーです。
Bastionサーバーは上げたり落としたりなども検討する必要があるし、セキュリティ的にも気をつかうリソースです。
Bastionサーバーに関しては、3段階でアプローチするとよいと考えています。
- SSH/RDPでの接続ができないアーキテクチャの検討
- Bastionサーバーを立てない
- Bastionサーバーを立てる
SSH/RDPでの接続ができないアーキテクチャを検討する
そもそもBastionサーバーどころか、SSH/RDPが必要なのかどうかから検討するのがおすすめです。おそらく、小さいアプリなどに限られると思いますが、アプリケーションやインフラの要件に合うのであれば、sshできないマネージドサービス(AWS lambda, Cloud Functions, GooleAppEngine StandardEnvironmentなど)を使うなど検討してみましょう。
つまり、「SSHでのアクセスを許容する設定がない」サービスを使うことでオペミスすらできない状態を作ることができます。
Bastionサーバーを立てない
AWS/GCPともにBastionサーバーを立てずに、SSHできる仕組みがあります。
AWSだと、「AWS Systems Manager Session Manager」の利用が考えられます。Pluginを利用すれば、CLIを使ってローカルのMacから接続することもできます。
また、接続して実行するコマンドが決まっている場合は、「AWS Systems Manager Run Command」がおすすめです。
GCPの場合は、「Cloud Identity-Aware Proxy(IAP)」が利用できます。TCP転送にCloudIAPを利用することで実現可能です。アナウンスはこの記事でドキュメントはこちらです。ただ、Cloud IAPはアプリケーションへのアクセスを制御するものなので、社内向けツールなどにアクセス制限ありきのサービスに使われるケースが多いと感じます。
Bastionサーバーを立てる
Bastionサーバーを立てる方法は、Webに事例がいくつもありますが、一応公式として良さそうなものを載せておきますので参考に構築してください。
IAMでSSHアクセスを認証する
IAMを使ってSSHアクセスを管理する方法もあります。どちらかというとパブリックなインスタンス向けですが、知っておくと便利に使えます。
AWSでは、「EC2 Instance Connect」が使えます。このサービスは、テンポラリな公開鍵をインスタンス(メタデータ)に登録し、その鍵を使ってSSH接続の認証をするものです。毎回秘密鍵/公開鍵は作り直しになりますが、それらを意識することはほぼ無いので、安全に接続することが可能です。
GCPでは、「OSログイン」を使います。OSログインはIAMを使用してインスタンスへのSSHアクセスを管理できるサービスです。OSログインは、IAM権限で許可するだけでなく、プロジェクトまたはインスタンスへのメタデータ(enable-oslogin=TRUE)の登録により利用可能になります。
Web Application Firewall
XSSやSQLiへの防御策としての役割です。
AWSでは、「AWS WAF」が利用できます。AWS WAFはサードパーティのルール(F5 Web Application CVE Signatures For AWS WAFなど)も適用できたりします。
安いとはいい難いですが、社内でガッツリとWAFを運用できる人材が確保できないなら導入検討の余地はあります。
GCPでは、Cloud Armor(DoSやウェブ攻撃からの防御)の追加機能としてルールが登録できるようになる予定ですが、一般的に利用できるようになる時期は未定です。
サードパーティーのソリューションを利用したり、デプロイ前にSecurity Scannerをかけるなど運用でカバーする必要があります。
DDoS対策
分散型サービス拒否(DDoS)攻撃対策 を見ていきます。それぞれL4レイヤー(一部L7)での防御がメインになり、いわゆるSynフラッドやUDPリフレクション からの防御です。
AWSでは、「AWS Shield Standard / Advanced」が利用できます。Advancedは、Standardに加えサポートが手厚く、例えば実際にDDoS攻撃があった場合の「スケーリングへのDDoSコスト保護」など攻撃を受けたときの保険として有効です。
GCPに関しては、特にサービスというわけではなく Global HTTP(S) Load Balancer にBuilt-inされています。またGAE/SEも同様にL4レイヤーでの防御されます。Googleのサービスを守るDDoS対策と聞けば、その凄さは想像に難くないですね。
以下、GCP中の人の記事から引用します。
GCP の Global HTTP(S) LB はネットワークのエッジに存在し、GCP のデータセンタにたどり着くこともなく DDoS 攻撃をエッジでブロックします。なお、この DDoS 対策機能は Google の Search、YouTube や Gmail などにも使用されており、万全な守備となっているかと思います。
また、各社それぞれホワイトペーパー(pdf)がありますので、そちらも参照してください。
脆弱性スキャン
ディストリビューションに対する脆弱性スキャン
AWSだと、「Amazon Inspector」を使います。これは評価ターゲットに対して評価テンプレートを適用し、結果を可視化することができます。
例えば、EC2インスタンス(評価ターゲット)に対して、CVEの脆弱性を検知するための評価テンプレートを適用し、インスタンスの脆弱性を可視化することができます。
しかし、現時点では評価ターゲットはEC2インスタンスのみでコンテナには対応していません。
GCPでは、Google Container Registryの機能のひとつとしてContainer Analysisがあります。Debian、Ubuntu、Alpine、Red Hat Enterprise Linux と CentOSに対するCVEの脆弱性をスキャンをすることができます。
しかし、名前からも分かる通りComputeEngineには対応していません。AWSとは逆にインスタンスに対する脆弱性スキャンの仕組みはありません。
Webアプリケーションに対する脆弱性スキャン
AWSだと、AWS WAFを利用し、ワークロードにおいてルールベースでの防御を実現することは可能ですが、事前にスキャンを実行するようなサービスは現時点ではありません。
GCPでは、Cloud Web Security Scannerを使って、脆弱性を事前にスキャンすることが可能です。
ただし、対象はComputeEngine,AppEngine,GKEになり、対応する脆弱性はXSS、Flashインジェクション、混合コンテンツ(http/https)、安全でないJavaScriptライブラリの使用に限られます。
VPC ネットワークアクセスコントロール
AWSにおける一般的なネットワーク設計の入門資料としては下記資料が参考になります。
Network ACL + Security Group での制御するのが基本で、Subnet構成やRoutingを工夫したりすることで実装します。
GCPはデフォルトでグローバルなネットワークが使えることがポイントですが、アクセスコントロール関しては、グローバルもローカルを特に意識せずVCPファイアウォールルール で制御します。 またファイアウォールルールは GAE/SEにも存在しますが、VPCのものとは別なので注意が必要です。
VPCファイアウォールルールで特徴的なのは、暗黙のルールが存在することです。何も設定しないと、上り(inbound)は全て拒否、下り(outbound)は全て許可になっています。また、常に許可/拒否されるルールとして、「TCP ポート 25(SMTP)での下りトラフィック は拒否」だったり、「DHCP, NTP, メタデータサーバー (169.254.169.254) は許可」だったり、暗黙のルールは厳密に制限したい場合には注意が必要です。
秘匿情報の管理
APIシークレットなどをどのように保存するかについて考えます。
SOPSなどを使って暗号化してリポジトリに含める方法もありますが、できればクラウドのサービスでなんとかしたいですよね。
AWSだと、AWS Systems Manager パラメータストアのSecure Stringを利用するケースが多いと思います。似たようなサービスで、ライフサイクル管理が必要であればAWS シークレットマネージャーもあります。一般的には前者を利用することが多いと思いますが、DBのパスワードを定期的に変更したいような監査的なワークロードがある場合は後者を利用します。
一方、GCPでは現時点では便利に使えるサービスというものはありません。
KMS + Cloud Storageがよくあるパターンだと思いますが、そこらへんをまるっとやってくれるOSS(berglas)をGCPが提供していたりします。
まとめ
いろいろと見てきましたが、それぞれ特徴があっておもしろいですね。
個人的にクラウドにおけるセキュリティへの意識は、以下3つに集約されるのかなと思っています。
1.トレードオフを意識する
全部やれるにこしたことはないですが、コスト(実装、運用、リソース使用量)をきちんと検討したうえで、トレードオフがあることを意識しましょう。
2.守らなくて良いように設計する
開けなくて良い穴は開けない。やらなくていいことはやらない。たとえば、Bastionサーバーの必要是非など。オペミスできないように設計することも検討しましょう。
3.クラウドらしさを忘れずに
クラウドらしい使い方として、マネージド・サービスを積極的に利用したり、調達コストを低く保ち、自動化を推進していきましょう。
最後に
セキュリティは、納期ドリブン開発のときは放置されることも多々あるかと思いますが、手軽にやれることもたくさんあるので、できるだけ後回しにしないようにすることが大切だと考えています。
セキュアな環境を継続的に保つためにクラウドっぽく自動化し、より安全なサービスを提供できるといいですね。
この記事が、みなさんの勘所になれば幸いです
最後に、セキュリティ云々の前に「ログはとにかく取っておく」のを忘れずに!