[GCP] VPC Service Controls と Cloud Identity-Aware Proxy の相性が悪い件について

# これはなんですか

- VPC Service Controls (VPC SC)とCloud Identity-Aware Proxy (Cloud IAP)を併用した際に罠にハマったのでメモしておきます。


# このメモの主張

- VPC Service Controls はVPC NetworkへのIP制限を行わない。Firewallで頑張れ。
- 外部IPを非公開にしているシステムからの接続を許可したい場合はCloud IAPを使う。ただし、Cloud IAMレベルでのアクセス制御になるので、IP制限は少し工夫が必要。

# 詳細

とある案件でセキュリティ要件を満たすためにVPC Service ControlsとCloud IAPを使ってシステムを構築した。

## 要件

高いセキュリティが求められるシステムのため、以下のようなセキュリティ要件がある。

- 社内ネットワーウからの接続のみ許可
- GCPリソースへのアクセスはCloud IAMで認証

一方でデプロイにはCircle CIの利用を検討している。

## 構成

GCE/BQ/Storageを使ったETLの仕組みを組んでいる。

- VPC Service Controls のサービス境界を設定する
    - BigQuery、Cloud Storageを境界内に含める
    - アクセスレベルでお客様拠点IPからの接続を許可
- VPC ネットワークを構成
    - Cloud NATを構成
    - FirewallルールはCloud IAPの外部IP(`35.235.240.0/20`)からの22番ポートへの接続のみ許可
- GCEのVMインスタンスを作成する
    - 外部IPは持たない
    - Cloud IAPでトンネル接続を行う
        - `gcloud compute ssh --tunnel-through-iap` で接続 ([ドキュメント](https://cloud.google.com/sdk/gcloud/reference/compute/ssh))
- VMインスタンスへのアプリケーションデプロイはCircleCIで行う想定
    - サービスアカウントおよびキーを発行し、役割を設定する

## 何がおきたか

- BQ、Storageへの接続は想定通りIP制限できた。
- VMインスタンスは、**ソースIPに関係なく**SSH接続できてしまった。

つまり、要件を満たしていない。

## なぜそうなったか

先に書いた通り、VPC Service Controls はVPC NetworkのIP制御を行わないため。

## どうするか

SaaSのCircle CIを使う場合、セキュリティ要件を完全に満たす設計は不可。理由は、CircleCIが外部IPリストを公開していないため([公式のQA](https://support.circleci.com/hc/ja/articles/115014372807-IP-%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AE%E3%83%9B%E3%83%AF%E3%82%A4%E3%83%88%E3%83%AA%E3%82%B9%E3%83%88%E7%99%BB%E9%8C%B2-))。Circle CIが必須の場合、次善の策は次の2案:

- Cloud IAPで頑張る。
    - VMインスタンスへのアクセスはCloud IAMの制御に倒す。
    - Cloud IAMのconditionsでAccess Context Managerのアクセスレベルを当てることでIP制御を行う。
- FirewallでIP制御を行いつつ、CircleCI向けにCloud IAPの穴を残す。
    - サービスアカウントを発行し、適切な権限を付与した上でCloudIAP経由での接続を行う。
    - Cloud IAMでサービスアカウントにのみCloud IAP経由の接続を許可するように権限設定を行う。

Cloud IAMで最小権限を意識している限りでは前者のほうが良いように思う。

# まとめ

- VPC Service Controls はマネージドサービスのセキュリティレイヤを増やすサービスで、Cloud IAMとは別にIPやデバイスレベルでのアクセス制御ができるようになる。
- Cloud IAPはCloud IAMレベルの認証でTCP転送(SSH接続性)を提供するため、IPによる制御とは相性が悪い。
- とはいえ、IPに閉じたサービスを組む場合Cloud IAPとCloud IAMで頑張るのが今の所はベターと思われる
    - Firewallで全て頑張る方法もあるが、External IPができてしまうのでそっちのリスクと天秤をかけることになる。
    - Cloud IAPを使う方がSaaSへの対応も容易と思われるため、こちらを採用したい。

# 参考

## VPC Service Controls

VPC Service Controls の概要
https://cloud.google.com/vpc-service-controls/docs/overview

サービス境界の作成(英語)
https://cloud.google.com/vpc-service-controls/docs/create-service-perimeters

## Cloud Identity-Aware Proxy

TCP 転送の概要
https://cloud.google.com/iap/docs/tcp-forwarding-overview?hl=ja

TCP 転送に Cloud IAP を使用する
https://cloud.google.com/iap/docs/using-tcp-forwarding?hl=ja

gcloud compute ssh
https://cloud.google.com/sdk/gcloud/reference/compute/ssh

## Cloud IAM

Cloud IAM Conditions の概要
https://cloud.google.com/iam/docs/conditions-overview?hl=ja#request_attributes

アクセスレベル式の例 を参照。アクセスレベルについては以下を参照。
https://cloud.google.com/access-context-manager/docs/overview?hl=ja#access-levels

## VMのセキュリティについて

Configuring secure remote access for Compute Engine VMs? | Google Cloud Blog
https://cloud.google.com/blog/products/identity-security/configuring-secure-remote-access-for-compute-engine-vms

- External IPは使わない
- Cloud IAPを使う
- VPC Service Controls の Google限定公開アクセスを設定する
    - Cloud NAT建てる場合はいらないけど、セキュリティの壁は薄くなるはず