🤧

Workload IdentityでGoogle Coud Storageの署名付きURLを発行する

2021/06/10に公開

やること

google-cloud-ruby で、Workload Identityを使用した認証を行う場合に、 Google Cloud Storageの 署名付きURLの発行が行い得ない問題を解消するものである

発生している問題

前提

  • workload identityによって接続されるサービスアカウントを ワークロードサービスアカウント とする
  • 筆者の環境では、GKEのnode上に存在するRuby on Railsにワークロードサービスアカウントが接続される
  • ワークロードサービスアカウントに対する権限の設定は問題がない。 (使用するStorage bucketに対して roles/storage.objectAdmin)

署名付きURLの発行を試みる

storage = Google::Cloud::Storage.new
storage.bucket('任意のバケット名', skip_lookup: true).file('バケットに存在するファイル名', skip_lookup: true).signed_url(method: 'GET', expires: 300)

=> Google::Cloud::Storage::SignedUrlUnavailable (Service account credentials 'issuer (client_email)' is missing. To generate service account credentials see https://cloud.google.com/iam/docs/service-accounts)

Google::Cloud::Storage::SignedUrlUnavailable によって怒られる

一方でファイル情報は取得できる

念の為、権限が正しそうかを確認する

storage = Google::Cloud::Storage.new
storage.bucket('任意のバケット名', skip_lookup: true).file('バケットに存在するファイル名')

=> #<Google::Cloud::Storage::File:0x00005624a9833208 @service=Google::Cloud::Storage::Service(project_id), @gapi=#<Google::Apis::StorageV1::Object:0x00005624a9887740 @bucket="hogehoge", @content_type="image/jpeg", @id="hogehoge/sample.jpeg/000", @kind="storage#object", ....>

OK

なぜか

一部、妄想も含まれてるかもなので参考程度に...

  • (workload identityを通じて)環境に適用されるサービスアカウントの資格情報は、色々省略された情報しか保持されていない
  • 多くのAPIを使用する場合には問題がないが、 Google Cloud Storageの署名付きURLの発行に必要な資格情報が含まれないケースが有る

参考

https://stackoverflow.com/questions/50549176/google-cloud-storage-500-internal-server-error-googlecloudstoragesignedur

解決するには

1. ワークロードサービスアカウントの資格情報を直接所持させる

pod内にワークロードサービスアカウントの資格情報を保有させるというやり方。鍵の管理やサービスアカウントの資格情報は10年で切れるという点で、あまりお薦めはできない。

2. Cloud IAMCredentials signBlob によって署名を作成して使用する

今回はこの方法を取る。署名を行う際に、直接APIを叩いて署名を実行するというやり方である。

署名付きのURLを発行するときに、 サービスアカウントの識別子(Issuer)を使用するが、環境に適用されるサービスアカウントの場合は取得できない。Issuerを環境に設定されているサービスアカウントとは別に設定した上で、署名付きURLを発行するときに指定する必要がある。しかし、google-cloud-rubyにはIssuer だけ を外から流し込む事はできないので、署名ロジックも一緒に以下の様に変更する。

サービスアカウントへの権限を追加

このやり方の場合、ワークロードサービスアカウントに roles/iam.serviceAccountTokenCreator の権限が必要となるため付与する

署名付きURLの発行方法を変更する

https://googleapis.dev/ruby/google-cloud-storage/v1.27.0/Google/Cloud/Storage/Bucket.html#signed_url-instance_method

ここの Using Cloud IAMCredentials signBlob to create the signature によるやり方で、 issuerとしてワークロードサービスアカウントを指定すればOK

参考

https://github.com/googleapis/google-cloud-ruby/issues/6268

Discussion