Skip to main content
emnode
Compliance Medium severity MCSB PA-7

Microsoft Defender for Cloud · Azure API Management

API Management subscriptions shouldn't be scoped to all APIs

Written and reviewed by Emnode · Last reviewed

What does the recommendation "API Management subscriptions shouldn't be scoped to all APIs" check?

Audits each subscription on an Azure API Management instance and flags any whose 'scope' field is set to '/apis', the all-APIs scope, rather than to a single product ('/products/{id}') or a single API ('/apis/{id}'). A subscription scoped to all APIs hands its key holder access to every API the instance publishes. It does not inspect the built-in all-access subscription that the platform creates for administrators, it does not check whether 'subscriptionRequired' is enabled on a product or API, and it does not verify the key is actually being used, so a flagged but dormant subscription still counts. It only evaluates the breadth of the scope, not who holds the key.

Why does "API Management subscriptions shouldn't be scoped to all APIs" matter?

An all-APIs subscription key is a single credential that unlocks the entire gateway, so it breaks least privilege in exactly the place an API platform should enforce it. If that key leaks (committed to a repository, baked into a mobile app, captured from a log), an attacker reaches every backend the instance fronts, not just the one API a partner was meant to consume. It also defeats per-product governance: policies attached at the product scope, such as rate limits, quotas and IP filters, are not applied to requests that arrive on an all-APIs or all-access subscription, so the controls you configured silently do nothing. The business consequence is an oversized blast radius and an audit finding that one revoked key would have to take down every integration at once.

How do I fix "API Management subscriptions shouldn't be scoped to all APIs"?

  1. Identify the offending subscriptions: in the API Management instance under Subscriptions, find any whose scope reads 'All APIs', then recreate the access each consumer actually needs as a product-scoped or single-API subscription. In an ARM or Bicep deployment of 'Microsoft.ApiManagement/service/subscriptions', set 'properties.scope' to '/products/{productId}' or '/apis/{apiId}' instead of '/apis', and require a subscription on that product or API.
  2. Migrate consumers onto the new keys, then suspend (state 'suspended') and later delete the all-APIs subscription so the broad key stops working. There is no stable 'az apim' command for subscription scope, so make the change through the portal, the REST API ('PUT .../subscriptions/{sid}' with the narrowed scope), or your IaC template.
  3. Assign the built-in audit policy at your management group or subscription so new all-APIs subscriptions are caught automatically. Look the definition up by name rather than hardcoding its id: pid=$(az policy definition list --query "[?displayName=='API Management subscriptions should not be scoped to all APIs'].name" -o tsv); az policy assignment create --name apim-sub-scope-audit --policy "$pid" --scope <scope>.

Remediation script · bash

# 1. Enable the Defender for APIs plan on the subscription so onboarded APIs are inspected.
az security pricing create --name Api --tier Standard

# 2. Disable the deprecated direct management endpoint (retired 15 March 2025).
#    'customProperties' on the service controls this gateway behaviour.
az apim update --name apim-prod --resource-group rg-platform \
  --set 'properties.customProperties."Microsoft.WindowsAzure.ApiManagement.Gateway.ManagementEndpoint"=false'

# 3. Re-enable backend certificate chain and name validation on a backend that
#    had it switched off. There is no native 'az apim backend' TLS flag, so PUT
#    the documented 'tls' block via the management API (api-version 2024-05-01).
sub=$(az account show --query id -o tsv)
az rest --method put \
  --uri "https://management.azure.com/subscriptions/$sub/resourceGroups/rg-platform/providers/Microsoft.ApiManagement/service/apim-prod/backends/payments-backend?api-version=2024-05-01" \
  --body '{"properties":{"url":"https://payments.internal/","protocol":"http","tls":{"validateCertificateChain":true,"validateCertificateName":true}}}'

# 4. Ratchet it shut: audit any instance whose management endpoint stays enabled.
#    Look the built-in policy up by display name; never hardcode a definition GUID.
pid=$(az policy definition list \
  --query "[?displayName=='API Management direct management endpoint should not be enabled'].name" -o tsv)
az policy assignment create \
  --name audit-apim-mgmt-endpoint \
  --policy "$pid" \
  --scope "/subscriptions/$sub"

Full walkthrough (console steps, edge cases and verification) in the lesson Harden Azure API Management.

Is "API Management subscriptions shouldn't be scoped to all APIs" a false positive?

A deliberately broad subscription reserved for a trusted internal integration test harness or an API gateway monitor that must exercise every published API will flag, because the control measures scope breadth, not intent. If that key is held only by a controlled, non-public workload and rotated regularly, exempt the resource through an Azure Policy exemption rather than narrowing the scope, and document why the all-APIs grant is justified.