I'm working on a program that will run on Google Cloud Run and has files stored in Google Cloud storage.
The problem I'm experiencing happens when attempting to generate a signed URL to download a file from Cloud storage that is usually private. On my local machine it works fine, but when running in Cloud Run it does not.
Locally I am using a service account that has the Storage Object Admin
role assigned to it. I load the permissions using an environment variable called GOOGLE_APPLICATION_CREDENTIALS
with in its value the absolute path to the key .json file I downloaded from the cloud console.
On Cloud Run, I granted the same role to the service account that the service runs as. However, when I attempt to sign anything on there, I get an exception:
java.io.IOException: Error code 403 trying to sign provided bytes: The caller does not have permission
In my code I don't explicitly select any service account since the SDK documentation makes me believe this is done automatically. In Cloud Run I do not have a GOOGLE_APPLICATION_CREDENTIALS
variable set because I thought this was also done automatically.
What confuses me is that the application running in Cloud Run can still upload files to Cloud Storage fine, so this makes me think it does have some form of credentials from somewhere.
What am I doing wrong?
TL;DR: Make sure the service account has the
iam.serviceAccounts.signBlob
permission.After further investigating the method I used to acquire credentials on Cloud Run:
I read the javadoc for
ComputeEngineCredentials
:After this I read the javadoc for
sign(byte[])
(emphasis mine):As such, I created a new role with just the
iam.serviceAccounts.signBlob
permission and assigned it to the service account that my Cloud Run configuration uses. After this, the issue immediately went away (no need to redeploy)