Back to Checks
azure

Microsoft Entra ID authentication is enabled for PostgreSQL Flexible Server

postgresql_flexible_server_entra_id_authentication_enabled
Service: postgresqlSeverity: medium
OfficialBuilt-inVerified
Categories:identity-access
Resource Type:microsoft.dbforpostgresql/flexibleservers

PostgreSQL Flexible Servers must set authConfig.activeDirectoryAuth to Enabled and keep at least one Microsoft Entra administrator assigned so database sessions inherit centrally governed identities instead of unmanaged PostgreSQL accounts.

Risk

Without Entra ID authentication, stolen local passwords bypass MFA and conditional access, enabling persistent database logins. Missing administrators leaves the feature unusable, blocking security teams from rotating duties and allowing unauthorized access or privilege escalation.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler azure --checks postgresql_flexible_server_entra_id_authentication_enabled

Recommendation

Federate PostgreSQL Flexible Server access through Microsoft Entra ID so MFA, conditional access, and centralized RBAC govern logins. Maintain at least one delegated administrator group and rotate membership through identity governance processes.

Remediation

CLI

az postgres flexible-server update --resource-group <resourceGroupName> --name <serverName> --active-directory-auth Enabled
az postgres flexible-server ad-admin create --resource-group <resourceGroupName> --server-name <serverName> --object-id <objectId> --display-name <displayName> --type User

Terraform

data "azurerm_client_config" "current" {}

resource "azurerm_postgresql_flexible_server" "example" {
  name                = "pg-flex"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  sku_name            = "GP_Standard_D4s_v3"
  administrator_login = "pgadmin"
  administrator_password = "<complexPassword>"
  storage_mb          = 131072
  version             = "16"

  authentication {
    active_directory_auth_enabled = true
    tenant_id                     = data.azurerm_client_config.current.tenant_id
  }
}

resource "azurerm_postgresql_flexible_server_active_directory_administrator" "entra_admin" {
  server_id     = azurerm_postgresql_flexible_server.example.id
  object_id     = var.entra_object_id
  principal_name = var.entra_principal_name
  principal_type = "User"
  tenant_id     = data.azurerm_client_config.current.tenant_id
}

NativeIaC

// Enable Microsoft Entra ID authentication on an existing PostgreSQL Flexible Server
resource server 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' existing = {
  name: '<example_resource_name>'
}

// Update server to enable Entra ID authentication
resource serverUpdate 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' = {
  name: server.name
  location: server.location
  properties: {
    authConfig: {
      activeDirectoryAuth: 'Enabled' // CRITICAL: Enables Entra ID authentication
      tenantId: tenant().tenantId
    }
  }
}

// Add Entra ID administrator
resource entraAdmin 'Microsoft.DBforPostgreSQL/flexibleServers/administrators@2023-12-01-preview' = {
  parent: server
  name: '<objectId>' // CRITICAL: Object ID of the Entra ID principal
  properties: {
    principalName: '<displayName>' // User principal name or group display name
    principalType: 'User' // CRITICAL: Can be 'User', 'Group', or 'ServicePrincipal'
    tenantId: tenant().tenantId
  }
  dependsOn: [
    serverUpdate
  ]
}

Other

1In the Azure Portal, open Azure Database for PostgreSQL flexible server and select the target server.
2Under Security > Authentication, set Microsoft Entra ID authentication (or combined mode) to Enabled and save the change.
3Under Security > Microsoft Entra ID, add at least one administrator (user or group) linked to an Entra object ID and confirm the assignment.

Check Code

from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.postgresql.postgresql_client import (
    postgresql_client,
)


class postgresql_flexible_server_entra_id_authentication_enabled(Check):
    def execute(self) -> Check_Report_Azure:
        findings = []
        for (
            subscription,
            flexible_servers,
        ) in postgresql_client.flexible_servers.items():
            subscription_name = postgresql_client.subscriptions.get(
                subscription, subscription
            )
            for server in flexible_servers:
                report = Check_Report_Azure(metadata=self.metadata(), resource=server)
                report.subscription = subscription
                # Default to FAIL
                report.status = "FAIL"

                # Check if Entra ID authentication is enabled
                # Note: active_directory_auth is already normalized to uppercase in service layer
                if (
                    not server.active_directory_auth
                    or server.active_directory_auth != "ENABLED"
                ):
                    report.status_extended = f"Flexible Postgresql server {server.name} from subscription {subscription_name} ({subscription}) has Microsoft Entra ID authentication disabled"
                else:
                    # Authentication is enabled, now check for admins
                    admin_count = (
                        len(server.entra_id_admins) if server.entra_id_admins else 0
                    )

                    if admin_count == 0:
                        report.status_extended = f"Flexible Postgresql server {server.name} from subscription {subscription_name} ({subscription}) has Microsoft Entra ID authentication enabled but no Entra ID administrators configured"
                    else:
                        report.status = "PASS"
                        admin_text = (
                            "administrator" if admin_count == 1 else "administrators"
                        )
                        report.status_extended = f"Flexible Postgresql server {server.name} from subscription {subscription_name} ({subscription}) has Microsoft Entra ID authentication enabled with {admin_count} {admin_text} configured"
                findings.append(report)

        return findings