GCP Service Accountを理解する

https://cloud.google.com/iam/docs/understanding-service-accounts?hl=ja

サービスアカウントは個人ではなくアプリケーションやVMに属する特別なアカウント。サービスアカウントは0以上のサービスアカウントのキーペアを持ち、Googleの認証に使用する。
サービスアカウントを使用する時、以下の点を明確にしておく必要がある。
- どのリソースにアクセスできるようにすべきか
- どのパーミッションが必要か
- どこでそのコードは実行されるのか。（GCP or オンプレなど）

![sa-flowchart.png](https://qiita-image-store.s3.amazonaws.com/0/95399/722ebd38-0399-8a4e-0644-d7f73f242b84.png)

サービスアカウントの特徴の一つとして、サービスアカウントをリソースやIdentityとして扱うことができる。
- サービスアカウントをIdentityとして扱う時、リソースにアクセスするためのロールをサービスアカウントに与えることができる。
- サービスアカウントををリソースとして扱う時、サービスカウントにアクセスするためのパーミッションをユーザに与えることができる。Owner,Editor,Viewer, Service Account Actorロールをユーザに付与できる。

# サービスアカウントにアクセスを付与する
サービスアカウントにリソースへのアクセスを付与するのは個人のIdentityに付与するのと似ている。例えば、アプリケーションがGCE上で動作しており、アプリケーションに対してGCS上にオブジェクトを作成だけ行えるようにしたい場合、このアプリケーションのためにサービスアカウントを作成し、Storage Object Creatorのロールを付与すればよい。
![sa-storage.png](https://qiita-image-store.s3.amazonaws.com/0/95399/6bcfde90-577f-32d8-dba4-f976d83f0885.png)

#　サービスアカウントの振る舞い
例えば長期間のジョブを実行する場合で、そのジョブを起動する権限をあなたの同僚が持っている場合。その同僚が会社を去るときに実行したジョブがterminateして欲しくない。
これ解決する手段としてサービスアカウントにジョブの起動と停止をする権限を与える。以下のステップでそれを実現できる。
- サービスカウントを作成し、Service Account Actorロールをあなたの同僚に与える。ジョブの起動を行いたい同僚に対してこのロールを与える。このときのサービスアカウントはリソースとして振る舞う。
- Service Account Actorロールがアサインされた同僚はサービスアカウントとしてジョブを起動できる。このときのサービスアカウントはIdentityとして振る舞う。
![sa-identity-resource.png](https://qiita-image-store.s3.amazonaws.com/0/95399/9ab00935-6d98-3b05-1f9a-f9dd72119254.png)

Service Account Actorを付与されたユーザは、サービスアカウントがアクセス可能なリソースにアクセスすることができる。

# GCPへデータをマイグレーション
別のクラウドやオンプレからGCPへデータをマイグレーションしたい場合、サービスアカウントキーを作成し、ダウンロードする。そしてこのキーを使用してGCPのAPIをコールすれば、GCPへデータをマイグレーションすることができる。

# サービスアカウントをトラック
サービスアカウントをたくさん作成すると、そのうち、どのサービスが何の目的で利用しているか分からなくなるかもしれない。そんなときは、サービスアカウントのdisplay名は追加情報として便利である。
何の目的のためのサービスアカウントなのかdisplay名に記載しておけば、何の目的なのか分かる。
既に存在するサービスアカウント名に対してserviceAcounts.update()を使用してdisplay名を修正することができる。

# サービスアカウントに最小限の権限を与える
サービスアカウントには最低限の権限を与えるべきである。ユーザにサービスアカウントの権限を与えることは、そのユーザはサービスアカウントがアクセスできる全てのリソースにアクセスすることが可能になるからである。そのため、サービスアカウントの権限は慎重に設定するべきである。

# サービスアカウント Keyの管理
2種類のサービスアカウントキーがある。
- GCP-managed keys. このキーはAppEngineやComputeEngineなどのサービスで使用されるキーであり、ダウンロードはできない。Googleが鍵を管理し、自動的にそれらをほぼ毎週ローテーションする。 
- User-managed keys. このキーはユーザが作成、ダウンロードが可能で、ユーザが管理する。

User-manage keysを管理するには例えば以下のこと考慮する必要がある。
- 鍵の保管場所
- 鍵の配布
- 鍵の失効
- 鍵のローテーション 
- 鍵を認証されてないユーザから保護する
- 鍵の復旧

鍵のセキュリティを改善するために
- IAM service account APIを使用して、自動でサービスアカウントキーをローテートさせる。新しいキーを作成し、アプリが利用している鍵を古い鍵から新しい鍵に変更することにより、鍵をローテートすることができる。serviceAccount.keys.create()とserviceAccount.keys.delete()を使用して自動でローテーションすることができる。
- serviceAccount.keys.list()を使用して、サービスアカウントとキーを検査することができる。 

# Compute Engineでサービスアカウントを使用する
ComputeEngineのインスタンスは他のGCPリソースにアクセスできる権限を持ったサービスアカウントで実行する必要がある。

- 同じProject内で異なるサービスカウントでVMSを作成。どのサービスアカウントがVMを作成することができるかは慎重に考慮する必要がある。なぜならVMを作成した後は、VMのサービスアカウントを変更することはできないため。
- IAM role（どのサービスへアクセスできるか）をサービスアカウントへ与える。この利点は、インスタンスを作り変えることなく、VMのサービスアカウントのパーミッションを修正することができる点である。
- インスタンスのACLはサービスアカウント次第であり、実行中のインスタンスが使用しているサービスアカウントの削除を避ける。もしサービスアカウントを削除してしまった場合、インスタンスは処理の起動に失敗する。

# ベスト・プラクティス
- Service Account Actorsのユーザはサービスアカウントがアクセスすることができるリソースにアクセスすることができるため、誰にServiceAccountActor roleを与えるかは慎重にしないといけない。
- サービスアカウントはゴール達成に向けて必要最低限の権限のみ与えるべきである。
- サービス毎にサービスアカウントを作成すべきである
- サービスアカウントの用途をトラックできるようdisplay nameを使用するべきである。
- サービスアカウント名の命名規則を定義するべきである
- user-managed service account keysの自動ローテーション処理を実装するべきである
- 鍵のローテーションにはIAM service account APIを利用すべきである。
- serviceAccount.keys.list()をやLogページを使用してサービスアカウントと鍵を監査すべきである。
- 実行中のインスタンスが使用しているサービスアカウントは削除してはいけない