Cloud SQL REST API connection refused when authenticating with service accounts

We’re getting connection refused errors when trying to authenticate to Cloud SQL REST API using service accounts. The API calls work fine from our local development machines but fail when deployed to Cloud Run services.

The service account has Cloud SQL Client role assigned, but we suspect there’s more to service account roles configuration. Network configuration might also be blocking API endpoint access - our Cloud Run services are in a VPC.


GET /sql/v1beta4/projects/{project}/instances/{instance}
Authorization: Bearer {service_account_token}
Error: Connection refused (errno 111)

This is blocking our automated database provisioning workflows. What permissions or network settings are we missing?

Your connection refused error points to a network routing issue compounded by incomplete IAM configuration. Since it works locally but fails from Cloud Run, this is definitely VPC-related with some IAM gaps. Let me address all three problem areas.

Service account roles: Cloud SQL Client role alone is insufficient for REST API operations. You need these specific permissions for your service account:


Required roles:
- roles/cloudsql.client (for Cloud SQL Proxy connections)
- roles/cloudsql.viewer (for API read operations like instances.get)
- roles/iam.serviceAccountTokenCreator (if generating tokens programmatically)

Create a custom role combining these permissions, or assign all three roles to your service account. The key permission for REST API access is cloudsql.instances.get which isn’t in Cloud SQL Client role. Grant this explicitly:

  --member=serviceAccount:{sa-email} \
  --role=roles/cloudsql.viewer``

**Network configuration**: Your Cloud Run service in VPC cannot reach Google APIs without proper routing. Enable Private Google Access on your VPC subnet:

```gcloud compute networks subnets update {subnet} \
  --region={region} \
  --enable-private-ip-google-access``

This allows private IP addresses in your subnet to reach Google APIs (including Cloud SQL REST API) through Google's private network. Additionally, configure your VPC connector egress settings. Edit your Cloud Run service:

egress-settings: all-traffic vpc-connector: {connector-name}


The "all-traffic" setting routes both private and public traffic through the VPC connector, ensuring API calls use the VPC network with Private Google Access.

**API endpoint access verification**: After fixing network routing, test connectivity from Cloud Run. Deploy a test service that attempts to reach the Cloud SQL API endpoint:

curl -H “Authorization: Bearer $(gcloud auth print-access-token)”
https://sqladmin.googleapis.com/sql/v1beta4/projects/{project}/instances


If this returns data, your network routing works. If you still get connection refused, check these additional items:

1. Firewall rules: Ensure no VPC firewall rules block egress to 199.36.153.8/30 (Google API range)
2. Cloud Run service identity: Verify the service account is properly attached to Cloud Run (not just granted IAM roles)
3. Token generation: If generating tokens in code, ensure proper scopes: https://www.googleapis.com/auth/sqlservice.admin

The connection refused error specifically (not timeout) suggests routing is completely blocked. Private Google Access is your primary fix. Once enabled, API calls should succeed within seconds. Monitor Cloud Run logs for any subsequent 401/403 errors which would indicate IAM permission gaps rather than network issues.

Connection refused usually means network-level blocking, not authentication failure. If it was auth, you’d get 401 or 403. Check if your VPC has Private Google Access enabled - Cloud Run needs this to reach Google APIs when using VPC connector.

Yes, without Private Google Access, your VPC can’t route to Google APIs (199.36.153.8/30 range). Enable it on your subnet. Also verify your service account token is being generated correctly - use gcloud auth print-access-token to test. The Cloud SQL Client role alone might not be enough; you may need cloudsql.instances.get permission specifically for API calls.