GCEからGCS操作時の権限エラーでサービスアカウントのIAM以外に疑うこと

記事タイトルとURLをコピーする

G-gen の藤岡です。当記事では、Google Cloud (旧称 GCP) の Compute Engine VM から Cloud Storage バケットを操作する時に起きる権限エラーについて、実際のエラー内容からサービスアカウントの IAM 権限以外に疑うこと、その対処法について紹介します。

前提知識

Compute Engine (以下 GCE)は、デフォルトでは PROJECT_NUMBER-compute@developer.gserviceaccount.com のサービスアカウントが設定されます。但し、このサービスアカウントにはプロジェクトレベルで 編集者roles/editor)ロールが付与されており、広範囲な権限を持っているため実運用での利用は好ましくありません。

事象

GCE インスタンスでデフォルトのサービスアカウントをアタッチした状態で Cloud Storage(以下 GCS)を操作すると、バケットやオブジェクトの閲覧はできても、アップロードや削除ができませんでした。

# バケットの表示:可
fujioka@instance:~$ gcloud storage ls
gs://test-bucket/
fujioka@instance:~$ 
  
# ファイルのアップロード:不可
fujioka@instance:~$ gcloud storage cp test.txt gs://test-bucket/
Copying file://test.txt to gs://test-bucket/test.txt
ERROR: User [012345-compute@developer.gserviceaccount.com] does not have permission to access b instance [test-bucket] (or it may not exist): Access denied.
  Completed files 1/1 | 0B                                                          
fujioka@instance:~$ 

デフォルトのサービスアカウントには編集者ロールが付与されています。バケットから確認しても、編集者ロールが継承され、ストレージ管理者roles/storage.admin)、が設定されており、サービスアカウントの IAM 権限としては問題ありません。

バケットの権限

この時、Cloud Logging にはエラーログは出力されていませんでした。

原因

今回は、サービスアカウントの IAM は編集者ロールのため GCS バケットにオブジェクトのアップロードが出来るはずですが、アクセススコープが読み取りしか許可をしていないため、制約の厳しいアクセススコープが優先され生じた権限エラーでした。

詳しく見ていきます。

GCE インスタンスから Google Cloud APIs へのアクセス制御方法には以下の 2 つがあります。

  • サービスアカウントの IAM
  • アクセススコープ

サービスアカウントとアクセススコープについての詳細は以下の記事をご参照ください。

blog.g-gen.co.jp blog.g-gen.co.jp

全てデフォルトでインスタンスを作成すると、 API と ID の管理 で、サービスアカウントと Cloud API アクセススコープは以下のように設定されます。

インスタンスの詳細画面

Cloud API アクセススコープが デフォルトのアクセス権を許可 になっている時は、GCS に対して読み取り専用のアクセス権(https://www.googleapis.com/auth/devstorage.read_only)が与えられます。この時、サービスアカウントの IAM とアクセススコープのうち、制約が厳しい方が優先されます。今回のエラー原因は、このアクセススコープが デフォルトのアクセス権を許可 の設定だったためです。

GCS 以外にもアクセススコープは以下のようなサービスの制御が可能です。

API ごとのアクセススコープ

gcloud compute instances create で GCE インスタンスを作成した場合もデフォルトではコンソールと同様のアクセススコープ設定となるため注意が必要です。

エラー文の違い

アクセススコープ起因とサービスアカウントの IAM 起因のそれぞれの権限エラーでは、エラーの表示に以下のような違いがあります。

# アクセススコープ起因
fujioka@instance:~$ gcloud storage cp test.txt gs://test-bucket/
Copying file://test.txt to gs://test-bucket/test.txt
ERROR: User [012345-compute@developer.gserviceaccount.com] does not have permission to access b instance [test-bucket] (or it may not exist): Access denied.
  Completed files 1/1 | 0B                                                          
fujioka@instance:~$ 
  
# サービスアカウントの IAM 起因
fujioka@instance:~$ gcloud storage cp test.txt gs://test-bucket/
Copying file://test.txt to gs://test-bucket/test.txt
⠹ERROR: User [test@012345.iam.gserviceaccount.com] does not have permission to access b instance [test-bucket] (or it may not exist): test-59@012345.iam.gserviceaccount.com does not have storage.objects.create access to the Google Cloud Storage object. Permission 'storage.objects.create' denied on resource (or it may not exist).
  Completed files 1/1 | 0B      
fujioka@instance:~$ 

サービスアカウントの IAM 権限が不足している時には、具体的に不足している権限(ここでは storage.objects.create)がエラー文に含まれています。

対処

アクセススコープの変更

アクセススコープは、以下の 3 種類から選べます。

  • デフォルトのアクセス権を許可
  • すべての Cloud API に完全アクセス権を許可
  • API ごとにアクセス権を設定

アクセススコープの種類

アクセススコープは、すべての Cloud API に完全アクセス権を許可https://www.googleapis.com/auth/cloud-platformにし、アクセス制御はサービスアカウントの IAM で行うことが推奨されています。 アクセススコープで GCE インスタンスのアクセス制御をすることはレガシーな方法です。

今回は、デフォルトのサービスアカウントのままアクセススコープを すべての Cloud API に完全アクセス権を許可 に変更することで権限エラーは解消されました。

手動で作成したサービスアカウントをアタッチ

実運用では前述の通り、デフォルトのサービスアカウントの利用は推奨されていません。 そのため、ベストプラクティスはサービスアカウントを作成し、最小権限の原則に従い適切な IAM 権限を付与したサービスアカウントを GCE インスタンスにアタッチすることです。

この時、手動で作成したサービスアカウントに変更すると、以下のようにアクセススコープが選択できなくなります。

アクセススコープが選択不可になる

ユーザーアカウントの使用

方法論としてユーザーアカウントを使うことで今回のエラーは回避できますが、「アクセススコープの変更」と「手動で作成したサービスアカウントをアタッチ」を行う方が好ましいです。ここでは参考までに記載します。

デフォルトでは、GCE インスタンス上で gcloud CLI を使う際、アプリケーションのデフォルト認証情報(ADC)を使ってサービスアカウントの認証情報とアクセススコープに従いアクセス制御を行います。

GCE インスタンスの設定を確認すると、以下のようにデフォルトのサービスアカウントが設定されていることがわかります。この状態では、アクセススコープの変更をしていないため、gcloud storage cp~ でエラーとなります。

# アカウントの確認
fujioka@instance:~$ gcloud config list 
[core]
account = 012345-compute@developer.gserviceaccount.com
disable_usage_reporting = True
project = 012345
  
Your active configuration is: [default]
fujioka@instance:~$
  
# ファイルのアップロード:不可
fujioka@instance:~$ gcloud storage cp test.txt gs://test-bucket/
Copying file://test.txt to gs://test-bucket/test.txt
ERROR: User [012345-compute@developer.gserviceaccount.com] does not have permission to access b instance [test-bucket] (or it may not exist): Access denied.
  Completed files 1/1 | 0B                                                          
fujioka@instance:~$ 

ここで、適切な権限を持ったユーザーアカウントに切り替えると、gcloud CLI の実行はユーザーアカウントになるため、gcloud storage cp~ が問題なく実行できます。

# ユーザーアカウントを使う
fujioka@instance:~$ gcloud auth login 

You are running on a Google Compute Engine virtual machine.
It is recommended that you use service accounts for authentication.
  
~
  
You are now logged in as [fujioka@g-gen.co.jp].
Your current project is [012345].  You can change this setting by running:
  $ gcloud config set project PROJECT_ID
fujioka@instance:~$ 
  
# アカウントの確認
fujioka@instance:~$ gcloud config list 
[core]
account = fujioka@g-gen.co.jp
disable_usage_reporting = True
project = 012345
  
Your active configuration is: [default]
fujioka@instance:~$
  
# ファイルのアップロード:可
fujioka@instance:~$ gcloud storage cp test.txt gs://test-bucket/
Copying file://test.txt to gs://test-bucket/test.txt
  Completed files 1/1 | 0B                                                          
fujioka@instance:~$ 

藤岡 里美 (記事一覧)

クラウドソリューション部

数年前までチキン売ったりドレスショップで働いてました!2022年9月 G-gen にジョイン。ハイキューの映画を4回は見に行きたい。

Google Cloud All Certifications Engineer / Google Cloud Partner Top Engineer 2024