たかぎとねこの忘備録

プログラミングに関する忘備録を自分用に残しときます。マサカリ怖い。

Cloud Runで`error: Failed to sign the provided bytes`というエラーが表示された場合の対処法

Cloud RunでKtorアプリを動かしていると、次のエラーログが表示された。

error: Failed to sign the provided bytes

色々調べたらCloud Storageに保管してある画像の署名付きURLの生成時に発生しているようだった。

serverfault.com

stackoverflow.com

なので、サービスアカウントトークン作成者ロールをサービスアカウントに付与してみた。

しかし、結果は変わらずだった。次に、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が有効になっていなかったのが原因だったことがわかった。

有効化してみた。

これによりエラーは消えた。