Microsoft Defender for Cloud · Azure Database for MySQL
Enforce SSL connection should be enabled for MySQL database servers
Written and reviewed by Emnode · Last reviewed
What does the recommendation "Enforce SSL connection should be enabled for MySQL database servers" check?
Flags any Azure Database for MySQL single server whose 'sslEnforcement' property is set to Disabled, which lets clients connect over plaintext TCP without TLS. The check reads the server-level setting on the Microsoft.DBforMySQL/servers resource only. It does not apply to the newer flexible server, where the equivalent control is the 'require_secure_transport' server parameter, and it does not inspect the negotiated TLS version, the minimum TLS version setting, or whether individual client applications actually present a certificate. It confirms only that the server will refuse unencrypted connections, not how strong the cipher is once a session is established. To harden the cipher itself you would separately raise the minimumTlsVersion setting, which this control does not cover.
Why does "Enforce SSL connection should be enabled for MySQL database servers" matter?
With enforcement off, a MySQL single server happily accepts unencrypted sessions, so credentials, query parameters and result sets cross the network in clear text. Anyone positioned on the path, a compromised host in the same VNet, a misconfigured peering, or an on-premises hop, can read or alter that traffic in a classic man in the middle attack. For a database holding customer or regulated data this is both a breach exposure and a direct compliance failure: PCI DSS, HIPAA and most data protection regimes treat encryption in transit as mandatory, so a single disabled flag can fail an audit and stall a release. Enabling enforcement is a low-risk change that closes the gap without touching application logic, only the connection string.
How do I fix "Enforce SSL connection should be enabled for MySQL database servers"?
- Turn enforcement on at the server level: az mysql server update --resource-group <rg> --name <server> --ssl-enforcement Enabled. Note that on single server the 'require_secure_transport' parameter has no effect, so the --ssl-enforcement flag is the correct control.
- In Bicep or ARM set sslEnforcement to 'Enabled' on the Microsoft.DBforMySQL/servers resource (API 2017-12-01), and update any client connection strings to supply the Microsoft RSA root CA so applications keep connecting after the change.
- Assign the built-in policy so new servers stay compliant. Look the definition up by display name rather than hardcoding a GUID: pid=$(az policy definition list --query "[?displayName=='Enforce SSL connection should be enabled for MySQL database servers'].name" -o tsv); az policy assignment create --name enforce-mysql-ssl --policy "$pid" --scope /subscriptions/<sub-id>.
Remediation script · bash
# 1. Lock the wire and the network on a production PostgreSQL flexible server.
RG=db-prod-rg
SRV=ordersprod-pg
# Enforce encrypted connections (dynamic, no restart needed).
az postgres flexible-server parameter set \
--resource-group "$RG" --server-name "$SRV" \
--source user-override \
--name require_secure_transport --value ON
# Pin the minimum TLS version.
az postgres flexible-server parameter set \
--resource-group "$RG" --server-name "$SRV" \
--source user-override \
--name ssl_min_protocol_version --value TLSv1.2
# Disable public network access.
az postgres flexible-server update \
--resource-group "$RG" --name "$SRV" \
--public-access Disabled
# 2. Turn on the pgaudit trail and connection throttling.
for p in "pgaudit.log=role,ddl,misc" \
"pgaudit.log_client=ON" \
"pgaudit.log_level=log" \
"pgaudit.log_statement=on" \
"pgaudit.log_statement_once=on" \
"connection_throttle.enable=on"; do
az postgres flexible-server parameter set \
--resource-group "$RG" --server-name "$SRV" \
--source user-override \
--name "${p%%=*}" --value "${p#*=}"
done
# 3. Provision a Microsoft Entra administrator and disable password sign-in.
az postgres flexible-server ad-admin create \
--resource-group "$RG" --server-name "$SRV" \
--display-name "dba-team" \
--object-id "$(az ad group show --group dba-team --query id -o tsv)" \
--type Group
az postgres flexible-server update \
--resource-group "$RG" --name "$SRV" \
--microsoft-entra-auth Enabled --password-auth Disabled
# 4. Ratchet it shut: deny any future PostgreSQL flexible server with public access.
# Look the built-in policy up by its EXACT display name, never paste a guessed GUID.
PID=$(az policy definition list \
--query "[?displayName=='Public network access should be disabled for PostgreSQL flexible servers'].name" \
-o tsv)
az policy assignment create \
--name deny-public-pg-flex \
--policy "$PID" \
--params '{"effect":{"value":"Deny"}}' \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" Full walkthrough (console steps, edge cases and verification) in the lesson Harden Azure MySQL and PostgreSQL.
Is "Enforce SSL connection should be enabled for MySQL database servers" a false positive?
Because single server is on a retirement path, the long-term fix is to migrate to flexible server, where TLS is enforced by default. A single server already scheduled for migration may still flag here until it is decommissioned; that is expected, and the right response is to finish the migration rather than to re-secure a server you are about to retire. There is no legitimate steady-state reason to leave enforcement disabled on a live single server.
More Azure Database for MySQL controls
- (Enable if required) MySQL servers should use customer-managed keys to encrypt data at rest
- Azure Database for MySQL should have a Microsoft Entra administrator provisioned
- Geo-redundant backup should be enabled for Azure Database for MySQL
- Private endpoint should be enabled for MySQL servers
- Public network access should be disabled for MySQL servers