Azure resources that participate in service-to-service communications can authenticate their peers with client certificates, in a mutual TLS handshake. Disabling that mechanism leaves the endpoint relying on weaker controls, such as passwords or network position alone, to establish trust between the two parties.
Several Azure services let workloads authenticate their peers with client certificates over TLS, establishing mutual trust between the two ends of the connection. Unlike a shared password, a certificate cannot be forged or replayed by a man-in-the-middle, and its private key never leaves the holder, which makes it considerably harder to steal.
This rule targets resources used for internal, machine-to-machine traffic, where mTLS is the industry-standard authentication mechanism. Externally-facing endpoints handling browser or mobile traffic are out of scope, since certificate-based authentication is impractical there.
Disabling client certificate authentication on an internal resource, or selecting an authentication mode that does not require a certificate, removes the mutual-trust guarantee. The endpoint must then rely on weaker controls, such as passwords or network reachability, to decide whether the caller is legitimate.
Certificates also support precise incident response. Compromised certificates can be revoked individually, and an issuing certificate authority can be revoked to invalidate every certificate it produced. Authentication mechanisms that do not rely on certificates do not offer that level of traceability and containment.
Without client certificate authentication, an attacker who learns a shared password or reaches the endpoint over the network can impersonate the legitimate caller. Depending on what the affected resource handles, this exposes data flowing through the endpoint, the credentials it stores, or any downstream system it integrates with.
Recovery is also harder. A password leak typically forces a rotation across every caller that knows it, whereas certificate-based authentication scopes the blast radius to a single revoked credential and preserves an audit trail of which certificate was used.
Set clientCertEnabled to true and clientCertMode to Required on the
Microsoft.Web/sites (or Microsoft.Web/sites/slots) resource.
The following code disables client certificate authentication on an Azure resource, leaving the endpoint to rely on weaker controls such as passwords, or on no peer authentication at all.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Web/sites",
"apiVersion": "2022-03-01",
"name": "internal-api",
"properties": {
"publicNetworkAccess": "Disabled",
"clientCertEnabled": true,
"clientCertMode": "Optional"
}
}
]
}
resource internalApi 'Microsoft.Web/sites@2022-03-01' = {
name: 'internal-api'
properties: {
publicNetworkAccess: 'Disabled'
clientCertEnabled: true
clientCertMode: 'Optional' // Noncompliant
}
}
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Web/sites",
"apiVersion": "2022-03-01",
"name": "internal-api",
"properties": {
"publicNetworkAccess": "Disabled",
"clientCertEnabled": true,
"clientCertMode": "Required"
}
}
]
}
resource internalApi 'Microsoft.Web/sites@2022-03-01' = {
name: 'internal-api'
properties: {
publicNetworkAccess: 'Disabled'
clientCertEnabled: true
clientCertMode: 'Required'
}
}
Set tls.clientCertEnabled to true on the Microsoft.SignalRService/signalR or
Microsoft.SignalRService/webPubSub resource.
The following code disables client certificate authentication on an Azure resource, leaving the endpoint to rely on weaker controls such as passwords, or on no peer authentication at all.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.SignalRService/webPubSub",
"apiVersion": "2021-10-01",
"name": "internal-bus",
"properties": {
"publicNetworkAccess": "Disabled",
"tls": {
"clientCertEnabled": false
}
}
}
]
}
resource internalBus 'Microsoft.SignalRService/webPubSub@2021-10-01' = {
name: 'internal-bus'
properties: {
publicNetworkAccess: 'Disabled'
tls: {
clientCertEnabled: false // Noncompliant
}
}
}
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.SignalRService/webPubSub",
"apiVersion": "2021-10-01",
"name": "internal-bus",
"properties": {
"publicNetworkAccess": "Disabled",
"tls": {
"clientCertEnabled": true
}
}
}
]
}
resource internalBus 'Microsoft.SignalRService/webPubSub@2021-10-01' = {
name: 'internal-bus'
properties: {
publicNetworkAccess: 'Disabled'
tls: {
clientCertEnabled: true
}
}
}
Set configuration.ingress.clientCertificateMode to require on the Microsoft.App/containerApps resource.
The following code disables client certificate authentication on an Azure resource, leaving the endpoint to rely on weaker controls such as passwords, or on no peer authentication at all.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.App/containerApps",
"apiVersion": "2022-10-01",
"name": "internal-worker",
"properties": {
"configuration": {
"ingress": {
"external": false,
"clientCertificateMode": "accept"
}
}
}
}
]
}
resource internalWorker 'Microsoft.App/containerApps@2022-10-01' = {
name: 'internal-worker'
properties: {
configuration: {
ingress: {
external: false
clientCertificateMode: 'accept' // Noncompliant
}
}
}
}
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.App/containerApps",
"apiVersion": "2022-10-01",
"name": "internal-worker",
"properties": {
"configuration": {
"ingress": {
"external": false,
"clientCertificateMode": "require"
}
}
}
}
]
}
resource internalWorker 'Microsoft.App/containerApps@2022-10-01' = {
name: 'internal-worker'
properties: {
configuration: {
ingress: {
external: false
clientCertificateMode: 'require'
}
}
}
}
Set negotiateClientCertificate to true on the
Microsoft.ApiManagement/service/gateways/hostnameConfigurations resource.
The following code disables client certificate authentication on an Azure resource, leaving the endpoint to rely on weaker controls such as passwords, or on no peer authentication at all.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.ApiManagement/service/gateways/hostnameConfigurations",
"apiVersion": "2022-11-01",
"name": "service/gateway/m2m-host",
"properties": {
"negotiateClientCertificate": false
}
}
]
}
resource m2mHost 'Microsoft.ApiManagement/service/gateways/hostnameConfigurations@2022-11-01' = {
name: 'm2m-host'
properties: {
negotiateClientCertificate: false // Noncompliant
}
}
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.ApiManagement/service/gateways/hostnameConfigurations",
"apiVersion": "2022-11-01",
"name": "service/gateway/m2m-host",
"properties": {
"negotiateClientCertificate": true
}
}
]
}
resource m2mHost 'Microsoft.ApiManagement/service/gateways/hostnameConfigurations@2022-11-01' = {
name: 'm2m-host'
properties: {
negotiateClientCertificate: true
}
}
Data Factory linked services of type Web or HttpServer, and pipeline WebActivity / WebHook
activities, call external endpoints from the integration runtime. The authenticationType field selects how the runtime authenticates to
the remote endpoint, and any value other than ClientCertificate disables certificate-based authentication.
The following code disables client certificate authentication on an Azure resource, leaving the endpoint to rely on weaker controls such as passwords, or on no peer authentication at all.
A linked service authenticating with a basic password:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.DataFactory/factories/linkedservices",
"apiVersion": "2018-06-01",
"name": "factories/example",
"properties": {
"type": "Web",
"typeProperties": {
"authenticationType": "Basic"
}
}
}
]
}
resource example 'Microsoft.DataFactory/factories/linkedservices@2018-06-01' = {
name: 'example'
properties: {
type: 'Web'
typeProperties: {
authenticationType: 'Basic' // Noncompliant
}
}
}
A pipeline WebActivity authenticating with a basic password:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.DataFactory/factories/pipelines",
"apiVersion": "2018-06-01",
"name": "factories/example",
"properties": {
"activities": [
{
"name": "CallEndpoint",
"type": "WebActivity",
"typeProperties": {
"url": "https://example.com",
"method": "POST",
"authenticationType": "Basic"
}
}
]
}
}
]
}
resource example 'Microsoft.DataFactory/factories/pipelines@2018-06-01' = {
name: 'example'
properties: {
activities: [
{
name: 'CallEndpoint'
type: 'WebActivity'
typeProperties: {
url: 'https://example.com'
method: 'POST'
authenticationType: 'Basic' // Noncompliant
}
}
]
}
}
A linked service authenticating with a client certificate:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.DataFactory/factories/linkedservices",
"apiVersion": "2018-06-01",
"name": "example",
"properties": {
"type": "Web",
"typeProperties": {
"authenticationType": "ClientCertificate"
}
}
}
]
}
resource example 'Microsoft.DataFactory/factories/linkedservices@2018-06-01' = {
name: 'example'
properties: {
type: 'Web'
typeProperties: {
authenticationType: 'ClientCertificate'
}
}
}
A pipeline WebActivity authenticating with a client certificate:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.DataFactory/factories/pipelines",
"apiVersion": "2018-06-01",
"name": "example",
"properties": {
"activities": [
{
"name": "CallEndpoint",
"type": "WebActivity",
"typeProperties": {
"url": "https://example.com",
"method": "POST",
"authenticationType": "ClientCertificate"
}
}
]
}
}
]
}
resource example 'Microsoft.DataFactory/factories/pipelines@2018-06-01' = {
name: 'example'
properties: {
activities: [
{
name: 'CallEndpoint'
type: 'WebActivity'
typeProperties: {
url: 'https://example.com'
method: 'POST'
authenticationType: 'ClientCertificate'
}
}
]
}
}
A Container Registry token can authenticate clients with either certificates or passwords. Defining only passwords leaves the registry without a certificate-based credential, so clients fall back to shared secrets that are easier to steal and harder to revoke individually.
The following code disables client certificate authentication on an Azure resource, leaving the endpoint to rely on weaker controls such as passwords, or on no peer authentication at all.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.ContainerRegistry/registries/tokens",
"apiVersion": "2022-12-01",
"name": "registries/example",
"properties": {
"credentials": {
"passwords": [
{
"name": "password1"
}
]
}
}
}
]
}
resource example 'Microsoft.ContainerRegistry/registries/tokens@2022-12-01' = {
name: 'example'
properties: {
credentials: {
passwords: [ // Noncompliant
{
name: 'password1'
}
]
}
}
}
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.ContainerRegistry/registries/tokens",
"apiVersion": "2022-12-01",
"name": "example",
"properties": {
"credentials": {
"certificates": [
{
"name": "certificate1",
"encodedPemCertificate": "[base64-encoded certificate]"
}
]
}
}
}
]
}
resource example 'Microsoft.ContainerRegistry/registries/tokens@2022-12-01' = {
name: 'example'
properties: {
credentials: {
certificates: [
{
name: 'certificate1'
encodedPemCertificate: '[base64-encoded certificate]'
}
]
}
}
}
The same pattern of providing a list of accepted client certificates also applies to two other Azure resources that the rule flags. On
Microsoft.DocumentDB/cassandraClusters, populate clientCertificates with the operator certificates that should be allowed to
connect. On Microsoft.ServiceFabric/clusters, populate clientCertificateCommonNames or
clientCertificateThumbprints with the same intent. In both cases, leaving the list empty (or omitting it) leaves the resource without
certificate-based authentication.