Cloud Runで`error: Failed to sign the provided bytes`というエラーが表示された場合の対処法
Cloud RunでKtorアプリを動かしていると、次のエラーログが表示された。
error: Failed to sign the provided bytes
色々調べたらCloud Storageに保管してある画像の署名付きURLの生成時に発生しているようだった。
なので、サービスアカウントトークン作成者ロールをサービスアカウントに付与してみた。
しかし、結果は変わらずだった。次に、signUrl()
の呼び出し時のオプションを変えてみた。
変える前の書き方。
override suspend fun find(blobName: String): FileObject? { val bucket = storage.get(bucketName) val blob = bucket.get(blobName) val url = blob.signUrl( 15, TimeUnit.MINUTES, Storage.SignUrlOption.withV4Signature() ) ... }
変えた後の書き方。
override suspend fun find(blobName: String): FileObject? { val bucket = storage.get(bucketName) val blob = bucket.get(blobName) var credentialsToSign = storage.options.credentials if (credentialsToSign is UserCredentials) { credentialsToSign = ImpersonatedCredentials.create( credentialsToSign as GoogleCredentials, "service-account-id@project-name.iam.gserviceaccount.com", Collections.emptyList(), Collections.emptyList(), 3600 ) } val url = blob.signUrl( 15, TimeUnit.MINUTES, Storage.SignUrlOption.httpMethod(HttpMethod.PUT), Storage.SignUrlOption.withExtHeaders(mapOf("Content-Type" to "application/octet-stream")), Storage.SignUrlOption.withV4Signature(), Storage.SignUrlOption.signWith(credentialsToSign as ServiceAccountSigner) Storage.SignUrlOption.withV4Signature() ) ... }
しかし、結果は変わらず。このメッセージだけじゃ具体的に何が原因なのかわからなかったので、とりあえず例外処理を外して、実際のエラーの内容を確認してみることにした。
すると次のようなログが出力された。
Caused by: java.io.IOException: Error code 403 trying to sign provided bytes: IAM Service Account Credentials API has not been used in project xxxxxxxxxxxx before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/iamcredentials.googleapis.com/overview?project=xxxxxxxxxxxx then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
つまり、IAM Service Account Credentials API
が有効になっていなかったのが原因だったことがわかった。
有効化してみた。
これによりエラーは消えた。