My app is using Datastore as it's main DB, and for whatever reason, we just started getting:
google.api_core.exceptions.PermissionDenied: 403 Received http2 header with status: 403
errors, specifically on our Hetzner VM instances.
What I tried so far:
- Tried writing into the database from local environment using the same service account key - works fine
- Tried changing service account key - Got the same error. Both service accounts I tried have Owner permissions and Cloud Datastore Owner permissions
More detailed error is the following:
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.PERMISSION_DENIED
details = "Received http2 header with status: 403"
debug_error_string = "UNKNOWN:Error received from peer {created_time:"2024-03-24T16:48:16.893337907+00:00", grpc_status:7, grpc_message:"Received http2 header with status: 403"}
What can I try next?
As this usually goes, I solved the problem literally 30mins after asking the question.
The Problem
Google has blocked some of the Hetzners IP addresses for some reason. As for the reason why, my best guess after looking around is that someone did something malicious and they just blocked the whole IP range.
How We Diagnosed the Problem
I've stumbled upon some reddit posts which suggested checking whether you could ping either
www.google.comorwww.googleapis.comI logged in to the server in question and got 403 when trying to ping
https://www.googleapis.com/oauth2/v1/certswith the following command:curl --ipv4 https://www.googleapis.com/oauth2/v1/certsIn my case, response was the following:
I've tried the same on another server that wasn't impacted and got the following response (which should be the same you get when opening link directly in the browser):
The Solution
Go to Hetzner and just replace your IP, everything started working normally after that. Just keep in mind that Hetzner likes to assign the identical IP if you immediately delete and reassign.
In order to avoid that, first just detach the old IP, create new one, and after creating delete the old one.
Hope this will save someone else hours of pulling hair and debugging.