GCP SQL No Private Ip Remediation
Triage and Remediation
- Remediation
Remediation
Using Console
To allow public (external) access to a Cloud SQL for PostgreSQL instance in GCP using the Console, you need to add a public IP (you can keep the private IP as well if needed).
Step-by-step in GCP Console
-
Go to Cloud SQL
- In the Google Cloud Console, go to:
Navigation menu → Databases → SQL - Click on your PostgreSQL instance.
- In the Google Cloud Console, go to:
-
Open the Connections settings
- In the instance page, click the Edit button at the top.
- In the left or central tabs, find and click Connections.
-
Enable Public IP
- Scroll to the Connectivity or IP addresses section.
- Under Public IP, check Assign a public IP address (or Add network / Add public IP depending on UI version).
- The Console will show that a public IP will be assigned on save.
-
Configure Authorized Networks (Firewall for DB)
- Still under Public IP, find Authorized networks.
- Click Add Network.
- Enter:
- Name: A label for the client/network (e.g.,
office-networkordev-laptop). - Network: The IP or CIDR that should be allowed (e.g.,
203.0.113.10/32for a single IP).
- Name: A label for the client/network (e.g.,
- Repeat for all client IPs that need access.
- Avoid
0.0.0.0/0unless this is a controlled test environment and you fully understand the risk.
-
Save changes
- Scroll down and click Save.
- Wait for the instance to finish updating (status changes back to RUNNABLE).
-
Get the public IP and connect
- In the instance Overview page, under Connect to this instance or Instance IP addresses, note the Public IP address.
- Use this host in your PostgreSQL client connection string:
- Host: the public IP
- Port: default
5432unless you changed it - User/password / database as configured.
-
(Optional) Keep or remove Private IP
- If you no longer want private-only access:
- Go back to Edit → Connections.
- Under Private IP, uncheck / remove private IP assignment (if your design allows).
- Save again.
- If you no longer want private-only access:
This remediates the configuration from “private-only” to “private + public” (or public-only) access using the GCP Console.
Using CLI
To remediate “PostgreSQL Instance IP Assignment Set To Private” in GCP (i.e., enable a public IPv4 address) via gcloud, do the following:
1. Make sure you have the right project and auth
# Authenticate
gcloud auth login
# Set the correct project
gcloud config set project YOUR_PROJECT_ID
2. Check current IP configuration of the instance
gcloud sql instances describe INSTANCE_NAME \
--format="get(ipAddresses)"
Confirm it only has PRIVATE and no PRIMARY / PUBLIC IPv4.
3. (Optional but recommended) Define authorized networks
Decide which client IPs should be allowed to connect to the public IP.
Example: allow only one office IP and one VPN IP:
AUTHORIZED_NETWORKS="Office=203.0.113.5/32,VPN=198.51.100.10/32"
4. Enable public IPv4 on the instance
Use gcloud sql instances patch with --assign-ip. You can optionally add authorized networks at the same time.
gcloud sql instances patch INSTANCE_NAME \
--assign-ip \
--authorized-networks="${AUTHORIZED_NETWORKS}"
Notes:
--assign-ipadds a public IPv4 address (keeps private IP if already enabled).- If you don’t want to set authorized networks now, just omit the flag and add them later.
5. Verify that a public IP was assigned
gcloud sql instances describe INSTANCE_NAME \
--format="json(ipAddresses)"
You should now see an entry like:
"ipAddresses": [
{
"type": "PRIMARY",
"ipAddress": "X.X.X.X"
},
{
"type": "PRIVATE",
"ipAddress": "10.x.x.x"
}
]
6. (Optional) Adjust or add authorized networks later
To update the allowed IP ranges:
gcloud sql instances patch INSTANCE_NAME \
--authorized-networks="Office=203.0.113.5/32,VPN=198.51.100.10/32,Home=203.0.113.20/32"
This overwrites the existing list with the one you provide.
These commands will change the instance from “private-only” to having a public IPv4 endpoint while retaining the private IP if it was already configured.
Using Python
Below is how to change a Cloud SQL for PostgreSQL instance so it has a public IP (in addition to or instead of private IP) using Python.
1. Prerequisites
-
Cloud SQL Admin API must be enabled:
-
Authentication:
- Use a service account with the
roles/cloudsql.adminrole. - Set
GOOGLE_APPLICATION_CREDENTIALSto point to its JSON key, or run this from an environment with default credentials (e.g., Cloud Shell, Cloud Run with attached service account).
- Use a service account with the
-
Install libraries:
pip install google-api-python-client google-auth google-auth-httplib2
2. Python code to add a public IP
This example:
- Adds a public IP to an existing PostgreSQL instance.
- Keeps existing private IP settings intact (if any).
- Optionally restricts access with
authorizedNetworks.
Replace:
PROJECT_IDwith your project IDINSTANCE_NAMEwith your Cloud SQL instance nameNETWORK_CIDRwith your allowed CIDR (or removeauthorizedNetworksblock if not needed)
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google.oauth2 import service_account
import time
# ---- CONFIGURE THESE ----
PROJECT_ID = "your-gcp-project-id"
INSTANCE_NAME = "your-postgres-instance-name"
SERVICE_ACCOUNT_KEY = "path/to/service-account.json" # or use default creds
NETWORK_CIDR = "203.0.113.0/24" # example; change to your IP/CIDR
# -------------------------
def wait_for_operation(service, project, operation_name):
while True:
op = service.operations().get(
project=project,
operation=operation_name
).execute()
if op.get("status") == "DONE":
if "error" in op:
raise RuntimeError(f"Operation error: {op['error']}")
break
time.sleep(5)
def main():
# Use service account; or use google.auth.default() if running on GCP
creds = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_KEY,
scopes=["https://www.googleapis.com/auth/cloud-platform"],
)
service = build("sqladmin", "v1beta4", credentials=creds, cache_discovery=False)
try:
# Get current instance config
instance = service.instances().get(
project=PROJECT_ID,
instance=INSTANCE_NAME
).execute()
settings = instance.get("settings", {})
ip_config = settings.get("ipConfiguration", {})
# Ensure public IP is enabled
ip_config["ipv4Enabled"] = True
# OPTIONAL: restrict access with authorized networks
# If you already have authorizedNetworks, append instead of overwrite.
ip_config["authorizedNetworks"] = [
{
"name": "allowed-office-network",
"value": NETWORK_CIDR,
}
]
settings["ipConfiguration"] = ip_config
body = {
"settings": settings
}
# Patch instance
op = service.instances().patch(
project=PROJECT_ID,
instance=INSTANCE_NAME,
body=body
).execute()
print(f"Patch operation started: {op['name']}")
wait_for_operation(service, PROJECT_ID, op["name"])
print("Instance updated. Public IP should now be assigned/enabled.")
except HttpError as e:
print(f"API error: {e}")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()
3. Notes / Variations
-
Keep both private and public IP:
The code above leaves any existingprivateNetworkandpscConfiguntouched; it just enablesipv4Enabled. That gives you dual (private + public) connectivity. -
Remove public IP later (if needed): Set
ip_config["ipv4Enabled"] = Falseand patch again. -
No network restriction: If you omit
authorizedNetworks, any IP can attempt to connect (still needs DB auth). For better security, always defineauthorizedNetworks.
This is the standard remediation path if your security policy requires a publicly reachable PostgreSQL Cloud SQL instance instead of only private IP.
Using Terraform
resource "google_sql_database_instance" "POSTGRES_INSTANCE" {
name = "POSTGRES_INSTANCE_NAME" # replace with your instance name
database_version = "POSTGRES_14" # replace with your required version
region = "GCP_REGION" # replace with the region (e.g. us-central1)
settings {
tier = "DB_TIER" # e.g. db-custom-2-7680
ip_configuration {
# Disable public IP
ipv4_enabled = false
# Attach to a VPC for private IP
private_network = google_compute_network.VPC.self_link
# or use: "projects/PROJECT_ID/global/networks/VPC_NETWORK_NAME"
}
}
}
resource "google_compute_network" "VPC" {
name = "VPC_NETWORK_NAME" # replace or reference existing VPC
}
resource "google_compute_global_address" "SQL_PRIVATE_SERVICE_RANGE" {
name = "SQL_PRIVATE_SERVICE_RANGE_NAME" # replace with a unique name
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 16
network = google_compute_network.VPC.id
}
resource "google_service_networking_connection" "SQL_VPC_PEERING" {
network = google_compute_network.VPC.id
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [google_compute_global_address.SQL_PRIVATE_SERVICE_RANGE.name]
}
Changing an existing Cloud SQL instance from public IP to private IP (private_network plus ipv4_enabled = false) can force replacement of the instance, which may cause downtime; review the terraform plan carefully before applying.
For verification, terraform plan should show the google_sql_database_instance gaining settings.ip_configuration.private_network and ipv4_enabled = false, and (for an existing public-only instance) it may show the instance being replaced along with creation of the networking/peering resources if they are new.