GCP Cloud IAM Conditionsを試す

#はじめに
2020/2/28にGAになったCloud IAM Conditionを試してみたいと思います。
AWSのIAMは以前からリソース名やタグ、Source IPでの認可設定のConditionを記載できてましたが、GCPのCloud IAMにもCloud IAM Conditionという名称で同様の機能が追加になりました。
認可設定を付与する際の条件が設定できます。

https://cloud.google.com/iam/docs/release-notes#February_28_2020

#何が出来るのか
https://cloud.google.com/iam/docs/conditions-overview
現在、Conditionとして記載できるのは、大きく分けて時刻とリソースの2つになります。

時刻(request.time)
リソース(resource)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/ef5bd3be-eaf7-172a-6eaa-e98ba0580317.png)


##マニュアルに記載がある設定例
- GCEインスタンス名などのリソース名やタイプを指定した制限(resource.name, resource.type)

```
指定されたプレフィックス文字列で始まる名前のリソースへのアクセスのみを許可します。
resource.name.startsWith("projects/_/buckets/exampleco-site-assets-")
```

- 一時的なアクセスのみ許可(request.time)

```
指定された有効期限まで一時的にアクセスを許可します：
request.time < timestamp("2021-01-01T00:00:00Z")
```

- 送信元IPアドレス制限(IAP TCPトンネリング用)

```
destination.ip == "14.0.0.1"
```

##評価する際に使える機能
- 複数の条件をAND(&&)やOR(||)で評価可能
- 関数による複雑な条件の記載(request.path.startsWithなど)

##参考、演算子の定義など
https://cloud.google.com/iam/docs/conditions-attribute-reference

#よくありそうなケース試してみる

##VPC外のGCPサービスの実行する際の送信元IPを制限する
こちらは、IAM Conditionsではなく、VPC Service ControlとAccess Context Managerの組み合わせで、送信元を任意とVPCと任意のサブネットに制限できます。
https://qiita.com/atsumjp/items/096d101ba60f16b94349

##特定のインスタンスを指定した認可設定
AWSでのタグを指定した制限はできない。現状、Cloud IAM Conditionのリソース制限は、タイプ/サービス/名前でのみ可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/bae6cce8-e025-70cd-5d90-747a5c731aab.png)

ということで、インスタンス名がinstanceから始まるリソースに対してのみssh可能になるようなCloud IAM Condition設定してみます。
今回は、サービスアカウントを作成し、そのサービスアカウントのIAM RoleでConditionを設定します。

最終的な構成は以下になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/626c06af-22ff-4ed0-008e-3783587338f9.png)

condition-testというサービスアカウントを作成し、ユーザから使用できるようにbindingを追加します。

```
$ gcloud iam service-accounts add-iam-policy-binding condition-test@<Project ID>.iam.gserviceaccount.com --member=user:atsum@uimoz.com --role=roles/iam.serviceAccountTokenCreator
Updated IAM policy for serviceAccount [condition-test@<Project ID>.iam.gserviceaccount.com].
bindings:
- members:
  - user:atsum@uimoz.com
  role: roles/iam.serviceAccountTokenCreator
etag: BwWgT6Y9U_o=
version: 1
```

作成したサービスアカウントにIAMロールを追加します。
sshするために、compute adminを付与し、Cloud IAM ConditionでInstanceから始まるように設定します。

```
resource.name.startsWith("projects/<Project ID>/zones/asia-northeast1-b/instances/instance")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/6c74f045-1e3b-7853-8772-979d989f897b.png)


また、compute.project.getはプロジェクトに対して必要なパーミッションになるため、Custom RoleでCondtionによる制限なしで設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/f4f2aaf9-899e-cbaf-fcfe-ba8ac4e0b02d.png)

compute.project.getがプロジェクトに対して許可されていないと、任意のインスタンスにsshする権限がっても、以下のようなエラーになります。

```
$ gcloud compute ssh  instance-3 --zone asia-northeast1-b --impersonate-service-account=condition-test@<Project ID>.iam.gserviceaccount.com
WARNING: This command is using service account impersonation. All API calls will be executed as [condition-test@<Project ID>.iam.gserviceaccount.com].
ERROR: (gcloud.compute.ssh) Could not fetch resource:
 - Required 'compute.projects.get' permission for 'projects/<Project ID>'
```

テストの用にinstanceから始まる名称の仮想マシンとvmから始まる名称の仮想マシンを作成します。ssh可能なようにFirewallの設定をします。
gcloudコマンドでimpersonate-service-accountオプションで作成したサービスアカウントを指定します。
vmから始まるインスタンスにSSHしてみます。Conditionの制限が効いてSSHに失敗します。

```
$ gcloud compute ssh  vm-5 --zone asia-northeast1-b --impersonate-service-account=condition-test@<Project ID>.iam.gserviceaccount.com
WARNING: This command is using service account impersonation. All API calls will be executed as [condition-test@<Project ID>.iam.gserviceaccount.com].
ERROR: (gcloud.compute.ssh) Could not fetch resource:
 - Required 'compute.instances.get' permission for 'projects/<Project ID>/zones/asia-northeast1-b/instances/vm-5'
```

instanceから始まるインスタンスにSSHしてみます。こちらは成功します。

```
$ gcloud compute ssh  instance-3 --zone asia-northeast1-b --impersonate-service-account=condition-test@<Project ID>.iam.gserviceaccount.com
WARNING: This command is using service account impersonation. All API calls will be executed as [condition-test@<Project ID>.iam.gserviceaccount.com].
Linux instance-3 4.9.0-12-amd64 #1 SMP Debian 4.9.210-1 (2020-01-20) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Mar  8 06:06:53 2020 from 35.201.224.212
```

##AWSのSTSのような一時的セキュリティ認証情報を付与する仕組みを考える

request.timeのConditionで認可される時間を指定します。

```
Condition on "Compute Admin" role
{
    "expression": "resource.name.startsWith(\"projects/<Project ID>/zones/asia-northeast1-b/instances/instance\") &&\nrequest.time < timestamp(\"2020-03-08T07:07:39.696Z\")",
    "title": "instance name",
    "description": ""
}
Use GCP APIs to manage IAM conditions.
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/977f0786-ee61-bdf9-0e93-5e48bc970c70.png)

指定した時間が経過するとsshが失敗します。

```
$ date;gcloud compute ssh  instance-3 --zone asia-northeast1-b --impersonate-service-account=condition-test@<Project ID>.iam.gserviceaccount.com
Sun Mar  8 16:09:32 +09 2020
WARNING: This command is using service account impersonation. All API calls will be executed as [condition-test@<Project ID>.iam.gserviceaccount.com].
ERROR: (gcloud.compute.ssh) Could not fetch resource:
 - Required 'compute.instances.get' permission for 'projects/<Project ID>/zones/asia-northeast1-b/instances/instance-3'
```

上記仕組みをCloud Functionsから更新する仕組みを作ろうと思いましたが、時間がなくなったのでまた次回。

#投稿内容は私個人の意見であり、所属企業・部門見解を代表するものではありません。