Restricting database public access: the basics
What does a database open to the internet actually look like in Azure?
A managed database is one of the highest-value targets in an Azure subscription, because it usually holds the data the rest of the estate is built around. Exposure shows up in a few distinct shapes rather than one setting, and each Azure database service expresses it slightly differently. Azure SQL Database has a public network access toggle: when it is set to Enabled, the server answers on its public endpoint and lets through anything that matches an IP or virtual-network firewall rule. Azure Database for PostgreSQL has the same idea: a server deployed with public access can be reached on its public endpoint, gated only by firewall rules. Azure Cosmos DB defaults to accepting traffic from all networks unless you define firewall rules or disable public access outright. Each is its own Defender for Cloud recommendation, but the underlying risk is identical: a database that more of the internet can reach than you meant.
Microsoft Defender for Cloud turns each of these into its own recommendation, which is why one data-heavy subscription can fail several database checks at once. 'Public network access on Azure SQL Database should be disabled', 'Public network access should be disabled for PostgreSQL servers' and 'Azure Cosmos DB accounts should have firewall rules' read as three separate problems on the report, but they are one job: stop databases from being reachable on a public endpoint, and route the legitimate traffic through a private endpoint or a known, named set of trusted networks instead.
Most of this exposure is drift, not intent. A SQL server created before private endpoints were standard, a PostgreSQL server spun up with public access for a quick connection test, a Cosmos DB account that nobody ever put firewall rules on. A firewall rule of 0.0.0.0 to 255.255.255.255, or the 'Allow access from Azure services' checkbox left ticked, quietly turns a database into an internet-facing one. The work is to find every database that is reachable more widely than intended, decide which genuinely need a public path, scope those down to named networks, and move the rest behind a private endpoint.
In this lesson you will learn how Azure's managed databases express public reachability, how SQL Database, PostgreSQL and Cosmos DB each differ in the detail, how to find every over-exposed database in a subscription, and how to lock them down without breaking the applications that legitimately connect to them. The Controls this lesson covers section lists every Defender for Cloud recommendation in this capability, each linking to a deep page with the exact check and a copy-and-paste fix.
The firewall rule that let the whole internet in
One of the most common ways an Azure database ends up exposed is a single firewall rule with a start address of 0.0.0.0 and an end address of 255.255.255.255, added during a connectivity test and never removed. It reads like a narrow allow-list entry, but it permits every address on the internet. The 'Allow access from Azure services' option has caused similar surprises: it opens the database to traffic from any Azure tenant, not just your own, which means another customer's compromised workload can reach your endpoint. Setting public network access to Disabled sidesteps both, because firewall rules stop being evaluated at all and only private-endpoint connections are accepted.
Finding database exposure across a subscription
Sam is the security lead at a scale-up preparing for its first ISO 27001 audit. Defender for Cloud shows database findings spread across several SQL servers, a couple of PostgreSQL servers and a Cosmos DB account in two subscriptions that pre-date the team's current guardrails.
Rather than work the findings one by one, Sam starts by listing which SQL servers still have public network access enabled, so the databases that are reachable on a public endpoint can be separated from the ones already behind a private endpoint before anything changes.
Start by listing the SQL servers that still answer on their public endpoint. These are the widest-open doors.
A production server holding customer records and answering on a public endpoint is the highest-value target in this group. Fix these before the staging servers.
How Defender for Cloud decides a database is exposeddeep dive
Each service exposes the same idea through a slightly different property. Azure SQL Database and Azure Database for PostgreSQL both have a 'publicNetworkAccess' setting: when it is Enabled, the server answers on its public endpoint and lets through any connection that matches an IP or virtual-network firewall rule, so the firewall rules are the only thing between the internet and the database. When it is Disabled, the public endpoint stops answering entirely, firewall rules are no longer evaluated, and the only path in is a private endpoint inside your virtual network. Azure Cosmos DB is assessed differently: the 'Azure Cosmos DB accounts should have firewall rules' recommendation is satisfied when the account has at least one IP rule with the virtual-network filter enabled, or when public network access is disabled outright, so an account that accepts traffic from all networks fails the check.
Two settings quietly widen exposure on SQL and PostgreSQL servers. A firewall rule from 0.0.0.0 to 255.255.255.255 allows the entire internet despite looking like a narrow entry, and the 'Allow Azure services and resources to access this server' option admits traffic from any Azure tenant, not only yours. On Cosmos DB, the equivalent trap is the 0.0.0.0 IP rule, which Microsoft treats as 'accept connections from Azure datacentres' and which the 'should not allow traffic from all Azure data centers' recommendation flags separately.
Defender for Cloud evaluates these against the Microsoft Cloud Security Benchmark on a periodic cycle, so a fix does not flip the recommendation to Healthy instantly. The control-plane change itself is immediate, but the posture catches up on the next assessment. The strongest position combines the per-server setting with an Azure Policy backstop: a deny policy on 'publicNetworkAccess' for SQL and PostgreSQL means no new server can be created on a public endpoint, which is the difference between checking nothing is exposed today and guaranteeing nothing can be exposed tomorrow.
What is the impact of leaving a database public?
The direct impact is data exposure at the most sensitive point in the estate. A database reachable on its public endpoint is discoverable by automated scanners and exposed to credential-stuffing, brute-force and exploitation of any unpatched engine vulnerability. Unlike a single leaked file, a compromised database often means the whole dataset: every customer record, every transaction, every secret stored in a row. The overwhelming majority of these incidents are accidents: a public-access toggle left Enabled, a 0.0.0.0 firewall rule from a test, an 'allow Azure services' box nobody unticked.
The second-order impact is blast radius. Every database answering on a public endpoint is attack surface that has to be defended continuously, and it sits right next to the data you most need to protect. Moving databases behind private endpoints shrinks that surface to traffic that originates inside your own virtual network, which is the traffic you can actually reason about, monitor and contain.
On the compliance side, every modern framework, ISO 27001, SOC 2, HIPAA, PCI DSS and the UK and EU data-protection regimes, expects evidence that data stores are not directly reachable from the public internet and that access is restricted to known networks. A passing set of database recommendations across every subscription, with public network access disabled and private endpoints in place, is one of the most defensible artefacts you can hand an auditor.
How do you lock databases down safely?
Work the capability as one loop rather than chasing individual findings. The order matters: find out how each database is actually connected to before you start closing public endpoints, so you do not cut off a live application that has no private path yet.
1. Inventory every database by exposure
List the SQL and PostgreSQL servers with public network access enabled, and the Cosmos DB accounts without firewall rules or with an open 0.0.0.0 rule. Treat this inventory as the source of truth, not the Defender finding count, because the three services express the same risk differently and one subscription can trigger several recommendations at once.
2. Map how each database is reached before you close anything
For each database, confirm how the applications that use it connect today. A database whose clients already run inside the virtual network can move behind a private endpoint with no disruption. A database reached over the public endpoint needs its clients re-pointed to a private endpoint, or a tightly scoped firewall rule, before you disable public access, or the application breaks.
3. Close the public endpoints, highest impact first
For SQL and PostgreSQL, create a private endpoint, then set public network access to Disabled. For Cosmos DB, add firewall rules scoped to your virtual network or disable public access outright, and remove any 0.0.0.0 rule. Prioritise production databases that hold sensitive data over empty ones. Remember that on SQL and PostgreSQL, disabling public access stops firewall rules being evaluated, so the private endpoint must already be in place.
4. Ratchet it shut with Azure Policy
Assign deny policies so no new SQL or PostgreSQL server can be created with public network access enabled, and audit Cosmos DB accounts for firewall rules. Back this with a private-endpoint requirement for the regulated workloads that need it, so the safe configuration is enforced rather than merely encouraged.
# Close the highest-impact database exposure first: production servers on a public endpoint.
# Make sure a private endpoint is in place BEFORE disabling public access,
# otherwise in-VNet clients lose their path in.
# Azure SQL Database server
az sql server update --name custrecords-prod --resource-group data-prod \
--set publicNetworkAccess=Disabled
# Azure Database for PostgreSQL flexible server
az postgres flexible-server update --name billing-prod --resource-group data-prod \
--public-access Disabled
# Azure Cosmos DB: scope to the VNet and drop the open Azure-datacentres rule
az cosmosdb update --name sandbox-cosmos --resource-group data-prod \
--ip-range-filter "" --public-network-access Disabled
# Ratchet it shut: deny any future SQL server that allows public network access.
az policy assignment create \
--name deny-sql-public-access \
--policy 1b8ca024-1d5c-4dec-8995-b1a932b41780 \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" Quick quiz
Question 1 of 5Defender for Cloud shows public-access findings across an Azure SQL server, a PostgreSQL server and a Cosmos DB account. What is the most efficient way to think about them?
You scored
0 / 5
Keep learning
Go deeper on how each Azure database service expresses public reachability and how to route the legitimate traffic privately.
- Azure SQL Database connectivity settings How the public network access toggle and private endpoints work together on Azure SQL Database.
- Disable public access for Azure Database for PostgreSQL How to disable the public endpoint and what happens to firewall rules when you do.
- Configure an IP firewall for Azure Cosmos DB How to scope a Cosmos DB account to trusted networks and avoid the open 0.0.0.0 rule.
You can now treat Azure database exposure as one capability rather than a scatter of findings across SQL, PostgreSQL and Cosmos DB: inventory what is reachable on a public endpoint or lacks firewall rules, map how each database is reached before you close anything, move the production stores behind private endpoints highest-impact first, and ratchet the estate shut with Azure Policy. The Controls this lesson covers section below links every recommendation in this group to its deep page and fix.
Back to the library