Encryption in transit: the basics
What does an Azure service that accepts a plaintext connection actually expose?
Encryption in transit means every connection to a service is wrapped in TLS, so nothing it sends or receives crosses the network as plaintext. The failure shows up in a handful of distinct shapes rather than one setting. An Azure Cache for Redis can have its non-SSL port 6379 left enabled, so a client can connect without TLS at all. A web app on App Service can accept plain HTTP instead of redirecting to HTTPS. A Function App can do the same on the endpoints that trigger it. Each is its own Defender for Cloud recommendation, but the underlying risk is identical: a service that answers an unencrypted request, and therefore exposes whatever travels over it to anyone able to observe the path.
Microsoft Defender for Cloud turns each of these into its own recommendation, all mapped to the same Microsoft Cloud Security Benchmark control, DP-3, encrypt sensitive data in transit. 'Redis Cache should allow access only via SSL', 'Web Application should only be accessible over HTTPS' and 'Function App should only be accessible over HTTPS' read as three unrelated findings on three different service types, but they are one job: make sure nothing in the estate will speak plaintext on the wire. A subscription running a cache, a couple of web apps and a few functions can fail several of these at once.
Most of this exposure is drift, not intent. A Redis cache created from a template that never set 'enableNonSslPort' to false, a web app deployed before 'HTTPS only' was switched on, a function whose host config never enforced a redirect. The work is to find every service in the estate that will accept an unencrypted connection, turn the plaintext door off, set a sane minimum TLS version so old, weak protocol versions cannot be negotiated either, and then make the safe state the only state a new resource can be created in.
In this lesson you will learn how Azure services express whether they accept an unencrypted connection, how to find every service in a subscription that still will, and how to enforce TLS everywhere without breaking the few clients that have not yet been updated. 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 downgrade nobody noticed
The danger with encryption in transit is rarely that an attacker breaks TLS; it is that the service quietly offered a way around it. A cache that leaves its non-SSL port open, or an app that still answers plain HTTP, gives an attacker on the path a downgrade to plaintext without breaking anything. This is why 'HTTPS only' redirects are not enough on their own: a redirect still sends the first request over HTTP, so the only fully safe posture is to refuse the unencrypted connection outright and pair it with HSTS. Azure now defaults new Redis caches to a minimum TLS of 1.2 and new web apps toward HTTPS, but every resource created before those defaults still needs to be checked and closed explicitly.
Finding plaintext-capable services across a subscription
Sam is the security lead at a scale-up preparing for its first ISO 27001 audit. Defender for Cloud shows encryption-in-transit findings spread across a Redis cache, a couple of web apps and several functions, all in a subscription that pre-dates the team's current guardrails.
Rather than work the findings one by one, Sam starts by listing which web apps still accept plain HTTP, so the genuinely live services can be separated from drift before anything changes.
Start by listing the web apps that do not have 'HTTPS only' enabled. These are the ones still answering plain HTTP.
A web app that both answers plain HTTP and handles sensitive data is the highest-value target in this group. Fix these before the low-risk marketing sites.
How Defender for Cloud decides a service will speak plaintextdeep dive
Each recommendation resolves to one property on the resource. For Azure Cache for Redis it is 'enableNonSslPort': when it is true, the cache listens on the unencrypted port 6379 alongside the TLS port 6380, so a client can connect with no encryption at all. For a web app or a Function App it is 'httpsOnly': when it is false, the service answers plain HTTP and does not redirect to HTTPS, so the request, and anything in it, crosses the network as plaintext. A companion setting, 'minTlsVersion' on the site config and 'minimumTlsVersion' on Redis, governs how weak a TLS version the service will still negotiate, so a resource can be HTTPS only yet still accept a downgraded TLS 1.0 handshake if that floor is left low.
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. This matters when you are gathering audit evidence against a deadline.
The strongest position combines the resource setting with an Azure Policy backstop. Microsoft ships built-in deny and audit policies, 'Web Application should only be accessible over HTTPS', 'Function apps should only be accessible over HTTPS' and the Redis SSL enforcement policy, all grouped under MCSB DP-3. Assigning them means no individual resource can be created in the plaintext-capable state again. Turning those policies on is the difference between checking that nothing speaks plaintext today and guaranteeing that nothing can be created to speak it tomorrow.
What is the impact of leaving plaintext connections open?
The direct impact is interception. Anything that crosses an unencrypted connection, a Redis AUTH password or a session token, a login posted over plain HTTP, an API key in a header, can be read by anyone able to observe the path: a compromised network device, a malicious Wi-Fi hotspot, a misconfigured proxy. A stolen credential is worse than a single leaked record, because it can be replayed: an attacker who reads a Redis password or a session token off the wire gains whatever access it grants until it is rotated or expires.
The second-order impact is the downgrade. A service that merely redirects HTTP to HTTPS still sends that first request in plaintext, and a service with a low minimum TLS version can be pushed onto a weak, breakable protocol version by an attacker on the path. Refusing the unencrypted connection outright, closing the non-SSL port and setting a modern TLS floor, removes the downgrade path entirely, which is why enforcement beats redirection.
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 in transit is encrypted. PCI DSS is explicit about it for cardholder data, and HIPAA treats transmission security as an addressable safeguard. A passing set of encryption-in-transit recommendations across every subscription is the cheapest and most defensible artefact you can hand an auditor.
How do you enforce TLS safely?
Work the capability as one loop rather than chasing individual findings. The order matters: find and update the clients that still connect over plaintext before you close the door, so you do not drop a live connection.
1. Inventory every plaintext-capable service
List the Redis caches with the non-SSL port enabled, the web apps and functions without 'HTTPS only', and any resource sitting below a TLS 1.2 floor. Treat this inventory as the source of truth, not the Defender finding count, because the same capability spans several different resource types.
2. Find the clients that still use plaintext
Before closing the non-SSL Redis port, confirm no application still connects on 6379, and update any that do to the TLS port 6380. Before raising the TLS floor, check that no old client pins TLS 1.0 or 1.1. This is the only step that can break a live service, so do it first.
3. Close the plaintext doors, highest impact first
Disable the non-SSL Redis port, set every web app and Function App to HTTPS only, and set a minimum TLS version of 1.2 across the board. Prioritise the services carrying credentials and sensitive payloads over low-risk internal ones. Each change is a single command per resource and takes effect immediately.
4. Ratchet it shut with Azure Policy
Assign the built-in deny policies so no new web app, function or cache can be created that accepts an unencrypted connection, and pair 'HTTPS only' with HSTS on the apps so browsers refuse to downgrade. Back this with audit policies for the minimum TLS version, so the safe configuration is enforced rather than merely encouraged.
# Close the highest-impact plaintext doors first: the Redis non-SSL port,
# then HTTPS-only + a modern TLS floor on every web app.
# Redis: disable the non-SSL port 6379 and require TLS 1.2 (clients use 6380).
for cache in $(az redis list --query "[?enableNonSslPort].name" -o tsv); do
rg=$(az redis list --query "[?name=='$cache'].resourceGroup" -o tsv)
az redis update --name "$cache" --resource-group "$rg" \
--set enableNonSslPort=false minimumTlsVersion=1.2
echo "$cache: non-SSL port disabled, min TLS 1.2"
done
# Web apps: enforce HTTPS only and raise the TLS floor.
for app in $(az webapp list --query "[?httpsOnly==\`false\`].name" -o tsv); do
rg=$(az webapp list --query "[?name=='$app'].resourceGroup" -o tsv)
az webapp update --name "$app" --resource-group "$rg" --https-only true
az webapp config set --name "$app" --resource-group "$rg" --min-tls-version 1.2
echo "$app: HTTPS only, min TLS 1.2"
done
# Functions follow the same pattern with az functionapp update --set httpsOnly=true.
# Ratchet it shut: assign the built-in deny policy for web apps over HTTPS only.
az policy assignment create \
--name require-https-webapp \
--policy a4af4a39-4135-47fb-b175-47fbdf85311d \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" Quick quiz
Question 1 of 5Defender for Cloud shows findings for a Redis cache, two web apps and several functions, all about encryption in transit. What is the most efficient way to think about them?
You scored
0 / 5
Keep learning
Go deeper on how each Azure service expresses whether it will accept an unencrypted connection, across the settings in this capability.
- Azure Cache for Redis TLS configuration settings How to disable the non-SSL port and set the minimum TLS version on a cache.
- Enforce HTTPS for Azure App Service How 'HTTPS only' works on web apps and functions, and why it pairs with HSTS.
- Azure security control: Data Protection (DP-3) The Microsoft Cloud Security Benchmark control these recommendations map to: encrypt sensitive data in transit.
You can now treat encryption in transit as one capability rather than a scatter of findings across different service types: inventory every service that will accept an unencrypted connection, update any plaintext clients first, close the non-SSL ports and HTTP endpoints highest-impact first with a TLS 1.2 floor, 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