Google Cloud Platform の VPC サービスコントロールを触ってみた

# Google Cloud Platform のセキュリティサービス
Google Cloud Platform (以降、GCP )もだいぶ閉塞ネットワークのサービスが充実してきました。エンタープライズ向けクラウドサービスにはセキュリティは最重要で、Cloud VPN 、Cloud Interconnect、Private Google Access などセキュリティに対するサービスが既にありました。
~~最近まだBeta版(2019年1月3日時点)ですが、~~Google Cloud NEXT'19にてGAがアナウンスされました[VPC サービスコントロール](https://cloud.google.com/vpc-service-controls/)というセキュリティサービスが利用できるようになりました。この VPC サービスコントロールがどのようなサービスかを試してみました。

## VPC サービスコントロールとは
[公式ドキュメント](https://cloud.google.com/vpc-service-controls/)には、
>VPCサービスコントロールを使用すると、Cloud Storageバケット、Bigtableインスタンス、BigQueryデータセットなどのGoogle Cloud Platformリソースの周囲にセキュリティ境界を定義して、VPC内のデータを制限し、データ漏洩のリスクを軽減できます。VPCサービスコントロールを使用すると、企業はGoogle Cloud Platformの完全に管理されたストレージおよびデータ処理機能を利用するため、機密データを非公開にすることができます。

と書いてあります。Google Cloud Storage や BigQuery は、グローバルサービスですので、通常のセキュリティ制御は、Cloud IAM 、それぞれのサービスのACL を使用し、役割（権限）で制御します。VPCサービスコントロールは公式ドキュメントの説明から、ユーザーが使用しているグローバルサービスの領域を閉塞域にすることができて、セキュリティが格段に上がるようです。
このVPC サービスコントロールを実際に設定し検証してみました。

## 本記事の前提読者
本記事の前提読者は以下のように考えています。

* クラウドサービスで環境構築したことがある。
* GCP で環境構築したことがある。

詳細を説明していないところが多々ありますが、ご容赦ください。


## VPC サービスコントロールの条件
VPC サービスコントロールを使用するのに、以下の条件がありますので注意です。

- 組織のユーザーであること
- VPC サービスコントロール使用に必要な権限を持っているユーザーであること
    - アクセスコンテキストマネージャエディタ以上の役割
    - 組織閲覧者以上の役割

組織のユーザーですので、**G Suite** 、または **Cloud Identity** のユーザーであることが必須です。そして、組織に対する役割を持つ必要があります。
[公式ドキュメント](https://cloud.google.com/vpc-service-controls/docs/access-control)には、アクセスコンテキストマネージャリーダーの役割も含まれていますが、VPC サービスコントロールの設定はできません。画面を閲覧できるだけです。

## VPC サービスコントロールの保護対象サービス
VPC サービスコントロールは、現状は以下の GCP サービスが保護対象です。

* Cloud BigTable
* Cloud Storage (以降、GCS)
* BigQuery
* Cloud Pub/Sub
* Cloud Dataproc
* Stackdriver Logging

alpha版としては以下のサービスが対象です。
* Container Registry
* Cloud Key Management Service
* Cloud Spanner

## VPC サービスコントロールの料金
[料金](https://cloud.google.com/vpc-service-controls/pricing)は無料です。

## VPC サービスコントロール の設定
では、VPC サービスコントロールを設定と検証の設定をしていきます。
  
### 限定公開の Google アクセスON の VPC を作成する
**[限定公開の Google アクセス](https://cloud.google.com/compute/docs/configure-private-google-access?hl=ja)**というと日本語がよくわかりませんが、PrivateIP Google Access という意味らしく、内部IPアドレスで GCP のグローバルサービスにアクセスできるという意味らしいです。本記事では [Private Google Access](https://cloud.google.com/vpc/docs/configure-private-google-access?hl=ja) と記述します。 
先に Private Google Access の VPC を作成します。Subnet 作成時に**限定公開の google アクセス** をONにします。
![2019-01-03_15h14_14.png](https://qiita-image-store.s3.amazonaws.com/0/237667/2b62dbca-487a-3361-1caa-cd053697f706.png)

### Google Compute Engine を作成する
検証するための Google Compute Engine (以降、GCE) を作成します。
先ほどのPrivate Google Access の VPC 上に作成し、外部IPアドレスは外します。外部IPアドレスを外す前に、SSHでログインし、シリアルコンソール接続で入れるようにrootのパスワードを設定します。

### GCS のバケットを作成する
ここでは、検証するための GCS バケットを先に作成しておきます。
バケット名は **vsc-bucket** 、Regionalバケット（東京リージョン）としました。
[アクセスログとストレージログ](https://cloud.google.com/storage/docs/access-logs?hl=ja) を参照し、audit-logの出力設定をしておきます。ここで設定したログバケット名は、**vsc-logs-bucket**としました。

### BigQuery のデータセット、テーブルを作成する
検証するための BigQuery データセットとテーブルを先に作成しておきます。
データセット名を **vsc_ds** として、東京リージョンに作成、テーブル名を **table1** として作成しました。

### 新しい境界を作成する
いよいよ、VPC サービスコントロールを設定します。VPC サービスコントロールの画面は、**ナビゲーションメニュー**から**セキュリティ**の**VPC サービスの管理**をクリックします。このとき、プロジェクトの選択は組織を選択します。
そして、上の**新しい境界**をクリックします。

![2019-01-03_13h46_30.png](https://qiita-image-store.s3.amazonaws.com/0/237667/0483a5c0-72c6-ff7b-aa9b-657464ed40e7.png)

新しい境界の設定画面では以下の設定を行いました。
![vsc.png](https://qiita-image-store.s3.amazonaws.com/0/237667/7278ec2b-89ed-ed2a-a3d1-94a855ae9821.png)

- **境界名**に保護する境界の名称を設定します。
- **境界のタイプ**はデフォルトを設定します。
- **保護するプロジェクト**に対象となるプロジェクトを設定します。今回は vpc-test というプロジェクトを設定しました。
- **保護するサービス**に保護したいサービスを設定します。今回は BigQuery と GCS を設定しました。

そして**保存ボタン**をクリックし、新しい境界の設定を保存します。

### GCS の画面をみると
GCS の画面を見ると、**「VPC Service Controls によってアクセスが拒否されました。」**と表示され、ブラウザが表示されません。当たり前ですが、GCP コンソールはグローバルからのアクセスとなりますので、Private になった GCS のバケットは閲覧できなくなります。
![2019-01-03_15h20_21.png](https://qiita-image-store.s3.amazonaws.com/0/237667/08e92d5c-33d7-12f2-8f15-5969a289add7.png)


### BigQuery の画面をみると
BigQuery の画面を見ても、GCS の画面と同じように**「VPC Service Controls: Request is prohibited by organization's policy.・・・」**と表示され、閲覧できませんし、データセットの作成ができません。
![2019-01-03_15h27_49.png](https://qiita-image-store.s3.amazonaws.com/0/237667/148120d3-8dd9-6b0b-f7e3-b7a8724a4c1f.png)


## GCS の操作検証
VPC サービスコントロールで Private 領域となった GCS を操作してみます。

### Cloud Shell から操作（外側からのアクセス）
アクセスできないとは思いますが、Cloud Shell から操作してみます。gsutil ls コマンドでバケット一覧を表示します。

```
aquiq@cloudshell:~ (vpc-test-221614)$ gsutil ls
AccessDeniedException: 403 Request violates VPC Service Controls.
```

VPC サービスコントロールでアクセスできません。「まあ、そりゃそうだ」の結果です。

### 限定公開の Google アクセス VPC 上の GCE から操作
先に作成しておいたPrivate Google Access の VPC上の GCE から操作します。
外部IPアドレスはありませんので、シリアルコンソールからルートでログインします。（実際は別のユーザー作成推奨）※シリアルコンソール接続は何気にすごいです。
gsutil ls コマンドでバケット一覧を表示します。

```
[root@instance-1 ~]# gsutil ls
gs://vsc-bucket/
gs://vsc-logs-bucket/
```
Private Google Access の VPC 上の GCE からは、作成していたバケットが表示されました。

ちなみに、GCE に外部IPアドレスが設定されていても問題なく、SSH で接続して gsutil ls コマンドの結果を取得できました。

### API から操作
次に、API で操作してみます。VPC サービスコントロールで Private な状態ではどうなるのか興味深いです。
今回は単純に、バケットの情報を取得します。
**※アクセストークン取得等APIの操作につきましては、偉大なる先人達の記事等ご参照ください。**

#### Cloud Shell から実行（外側からアクセス）
以下のコマンドを実行しました。

```
curl -H "Authorization: Bearer {アクセストークン}" https://www.googleapis.com/storage/v1/b/vsc-bucket
```

結果は以下の通り、VPC サービスコントロールが効いて取得できませんでした。

```
{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "vpcServiceControls",
    "message": "Request violates VPC Service Controls."
   }
  ],
  "code": 403,
  "message": "Request violates VPC Service Controls."
 }
}
```

#### 限定公開の Google アクセス VPC 上の GCE から操作
同じコマンドを GCE のシリアルコンソール接続から実行し、結果は以下のように正常に取得できました。

```
{
 "kind": "storage#bucket",
 "id": "vsc-bucket",
 "selfLink": "https://www.googleapis.com/storage/v1/b/vsc-bucket",
 "projectNumber": "939212211709",
 "name": "vsc-bucket",
 "timeCreated": "2019-01-03T06:51:34.749Z",
 "updated": "2019-01-03T09:59:43.103Z",
 "metageneration": "3",
 "iamConfiguration": {
  "bucketPolicyOnly": {
   "enabled": false
  }
 },
 "location": "ASIA-NORTHEAST1",
 "logging": {
  "logBucket": "vsc-logs-bucket",
  "logObjectPrefix": "vsc-bucket"
 },
 "storageClass": "REGIONAL",
 "etag": "CAM="
}
```

Private Google Access のVPC 内からは通常と同じ呼び方でAPIは操作できるということですね。

ちなみに、GCE に外部IPアドレスが設定されていても問題なく、**SSH で接続して APIの結果を取得できました。**


## Cloud Functions からの選択
Cloud Functions は、GCS のバケットの状態をトリガーとすることができます。VPC サービスコントロールの GCS は選択できるか確認しました。
<img src="https://qiita-image-store.s3.amazonaws.com/0/237667/193c0001-5d65-ec31-0efc-f20a996d9ff2.png" width=50%>

予想していたと思いますが無理でした。

## VPC サービスコントロール 本記事のまとめ
本記事で VPC サービスコントロールを検証した結果、わかったことのまとめです。

* VPC サービスコントロールで保護したサービスは、外部から保護されるため、 GCP コンソールからの操作が不可能となる。
* gsutil コマンド、APIは Private Google Access の VPC内から通常通り実行可能である。
* VPC の Private Google Access の On/Off は関係なく、内部IPアドレスから VPC サービスコントロールで保護したサービスにはアクセス可能である。
* Cloud Functions では、VPC サービスコントロールで保護した GCS のバケットをトリガーとすることができない。そもそも、現状はVPC サービスコントロールの対象サービスではない。

# 終わりに
Private Google Access や VPC サービスコントロールを使用することで、エンタープライズで重要課題となるセキュリティ面はクリアされ、今後益々 GCP の活用を期待できます。
VPC サービスコントロールを触ってみる前は、セキュアな閉塞ネットワークを作成することができるという思いしかありませんでした。検証してみて、VPC サービスコントロールで保護したサービスでは、GCP コンソールが使用できないのはネックであると思いましたが、機密情報が保存された、例えば GCS の Coldline だけ別プロジェクトにして、外部から完全に保護するといった使用方法もありだと思いました。
~~前述しましたが、VPC サービスコントロールで保護されたサービスの操作は GCP コンソールを使用できず、使い勝手が悪くなる点が課題であると考えます。効率良いサービス構築手順を考える必要があると考えます。
(Google Cloud 様、なんとかご対応をよろしくお願いいたします。)~~
Access Context Manager のアクセスレベルの設定でGCPコンソールの使用は可能です。ごめんなさい。

# アップデート
記事を追記します。

## 対象サービス
2019年11月現在の対象サービスは(α、βも含め)以下の26サービスになっています。
<img width="517" alt="vpc_service_control_list1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237667/1b9d08df-2a09-b55f-f5e3-7a5d64b5c908.png">
<img width="514" alt="vpc_service_control_list2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237667/d71fbb98-7df7-098b-d90c-15f8bcb7ac42.png">


## GCP コンソールのアクセス
Access Context Manager でIPアドレスを制御して、VPC サービスコントロールの対象にしたサービスの GCP コンソールにアクセスできます。

### GCP コンソールの BigQuery を開く(Access Context Manager 設定前)
VPC サービスコントロールを設定しているのでエラーとなります。
<img width="1431" alt="bq設定前.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237667/dc239f0c-c035-1175-3dbc-1a8e2f8bb36f.png">

### Access Context Manager の設定
Access Context Manager に許可するIP アドレスを設定します。
<img width="1433" alt="AccessContextManager.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237667/c10bb3ea-0b22-8548-f3dc-6a677317466d.png">

### Access Context Manager のアクセスレベルを紐付け
VPC サービスコントロールにAccess Context Manager のアクセスレベルを紐付けます。
<img width="1428" alt="VPCサービスコントロールアクセスレベル.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237667/8d0c33c3-9d9e-6ce2-ad7f-967172939201.png">


### BigQuery のGCP コンソールの BigQuery を開く(Access Context Manager 設定後)
Access Context ManagerでIPアドレスを許可したので、クエリ実行が可能となりました。
<img width="1430" alt="bq設定後.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237667/a1a51fc1-03f7-5921-a8fc-a6886c2fb5c9.png">









# 参考記事
* [VPC サービスコントロール](https://cloud.google.com/vpc-service-controls/)
* [Cloud IAM Roles for Administering VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/access-control)
* [プライベート Google アクセス](https://cloud.google.com/vpc/docs/private-google-access?hl=ja)
* [限定公開 Google アクセスの設定](https://cloud.google.com/compute/docs/configure-private-google-access?hl=ja)