Cloud SQL instances exposed on a public IPv4 address
What does ZopNight detect here?
Cloud SQL instances with ipv4Enabled set true are flagged critical by ZopNight rule RC-136: the database endpoint is reachable from the internet, one authorized-networks mistake away from exposure. Detection is proven: the discoverer records the flag in both polarities from instance settings and abstains only when enrichment is missing.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-136 |
| Category | compliance |
| Severity | critical |
| Metric | none — pure configuration read |
| Source | cloudsql_public.go |
Where it applies
A database endpoint on the public internet
Enabling public IP on a Cloud SQL instance gives the database a routable IPv4 address that answers connection attempts from anywhere. The engine’s authentication still stands between an attacker and the data, but that is the only thing standing, and it is now doing so against internet-scale credential stuffing rather than against traffic that first had to get inside a VPC. ZopNight rates the finding critical because the difference between those two positions is the difference between defense in depth and a single password.
Authorized networks are a thinner shield than they look
The standard justification is “we restrict authorized networks.” In practice those lists
accumulate: an office CIDR that later gets reassigned, a contractor’s home IP added during a
crunch, a 0.0.0.0/0 entry left from debugging. Each entry is a standing grant that
nobody re-reviews, and any future edit can widen it silently. A private-IP instance has no
equivalent failure mode. No list exists whose drift exposes it to the internet.
Proven from ipv4Enabled, both ways
Detection here is proven, not inferred. The discoverer reads
settings.ipConfiguration.ipv4Enabled off the instance’s settings proto and writes the
public-access marker as an explicit true or false, in both polarities, on every enrichment. The
rule fires only on the explicit true and abstains when the marker is absent, so an instance
the discoverer never enriched cannot be flagged. The reads ride
cloudsql.instances.list under roles/cloudsql.viewer, with the bulk sweep under
roles/cloudasset.viewer; the finding is informational and nothing modifies the instance.
List every public instance in a project
gcloud sql instances list \ --filter="settings.ipConfiguration.ipv4Enabled=true" \ --format="table(name,region,ipAddresses[].ipAddress)"The migration order that avoids breaking clients
Removing the public IP is a hard cutover for anything still using it, so migrate in order: set up a private services connection in the VPC and enable private IP alongside the public one; repoint every consumer at the private address; give developers Cloud SQL Auth Proxy for local access instead of an authorized-network hole; then, with connection logs quiet on the public address, disable it. The instance keeps running throughout; only the last step changes what the internet can see, and by then nothing legitimate is arriving that way.