Back to Checks
azure

Cosmos DB account uses private endpoint connections

cosmosdb_account_use_private_endpoints
Service: cosmosdbSeverity: high
OfficialBuilt-inVerified
Categories:internet-exposedtrust-boundaries
Resource Type:microsoft.documentdb/databaseaccounts

Azure Cosmos DB accounts are assessed for private endpoint connections that keep data-plane traffic on private IPs within authorized virtual networks.

Risk

Without private endpoints, access may use public endpoints or broad IP rules, enabling:

  • interception and credential replay
  • unauthorized queries and data exfiltration
  • lateral movement via exposed paths

This degrades confidentiality and can impact availability under abusive traffic.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler azure --checks cosmosdb_account_use_private_endpoints

Recommendation

Adopt Azure Private Link for Cosmos DB:

  • Create private endpoints for required subresources
  • Link a private DNS zone so clients resolve to private IPs
  • Set PublicNetworkAccess=Disabled; keep tight firewall rules
  • Allow only needed VNets/subnets; apply NSGs
  • Enforce least privilege and monitor access patterns

Remediation

CLI

az network private-endpoint create --name <example_resource_name> --resource-group <example_resource_name> --vnet-name <example_resource_name> --subnet <example_resource_name> --private-connection-resource-id /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<example_resource_name>/providers/Microsoft.DocumentDB/databaseAccounts/<example_resource_name> --group-ids Sql --connection-name <example_resource_name>

Terraform

# Create a Private Endpoint to a Cosmos DB account (adds a private endpoint connection)
resource "azurerm_private_endpoint" "<example_resource_name>" {
  name                = "<example_resource_name>"
  location            = "<location>"
  resource_group_name = "<example_resource_name>"
  subnet_id           = "<example_subnet_id>"

  private_service_connection {
    name                           = "<example_resource_name>"
    private_connection_resource_id = "<example_cosmosdb_account_id>" # CRITICAL: Cosmos DB account ID
    subresource_names              = ["Sql"]                           # CRITICAL: targets Cosmos DB subresource to create the connection
  }
}

NativeIaC

// Create a Private Endpoint to a Cosmos DB account (adds a private endpoint connection)
resource pe 'Microsoft.Network/privateEndpoints@2025-05-01' = {
  name: '<example_resource_name>'
  location: resourceGroup().location
  properties: {
    subnet: { id: '<example_subnet_id>' }
    privateLinkServiceConnections: [
      {
        name: 'conn'
        properties: {
          privateLinkServiceId: '<example_cosmosdb_account_id>' // CRITICAL: attaches PE to the Cosmos DB account
          groupIds: ['Sql'] // CRITICAL: targets Cosmos DB NoSQL subresource so the connection is created
        }
      }
    ]
  }
}

Other

1In Azure Portal, open your Cosmos DB account
2Go to Networking > Private access
3Click + Private endpoint
4Resource type: Microsoft.AzureCosmosDB/databaseAccounts; Resource: select your account; Target subresource: Sql
5Select your Virtual network and Subnet
6Click Review + create, then Create
7Verify the private endpoint connection appears under Networking > Private access

Check Code

from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.cosmosdb.cosmosdb_client import cosmosdb_client


class cosmosdb_account_use_private_endpoints(Check):
    def execute(self) -> Check_Report_Azure:
        findings = []
        for subscription, accounts in cosmosdb_client.accounts.items():
            subscription_name = cosmosdb_client.subscriptions.get(
                subscription, subscription
            )
            for account in accounts:
                report = Check_Report_Azure(metadata=self.metadata(), resource=account)
                report.subscription = subscription
                report.status = "FAIL"
                report.status_extended = f"CosmosDB account {account.name} from subscription {subscription_name} ({subscription}) is not using private endpoints connections"
                if account.private_endpoint_connections:
                    report.status = "PASS"
                    report.status_extended = f"CosmosDB account {account.name} from subscription {subscription_name} ({subscription}) is using private endpoints connections"
                findings.append(report)

        return findings