Azure waste

Front Door Premium without a Premium-only feature configured

A Front Door profile on Premium whose attached WAF policies define no managed rule sets, so the Premium base fee buys nothing Standard does not already provide.
The agent tells you how to fix it
Why it happens

Front Door Premium costs $330 per profile per month against $35 for Standard, a $295 difference that buys exactly three things Microsoft lists as unavailable on Standard: managed WAF rule sets, bot protection, and Private Link to origin. Custom WAF rules are free on both tiers. Microsoft's own upgrade procedure explains why this is common: upgrading copies the WAF policies and then tells you to "enable managed WAF rules manually for the new premium WAF policy copies after upgrading", so a team that clicked Upgrade and stopped is paying Premium for the rules it already had. Bot protection is itself a managed rule set, so an empty managedRuleSets array rules out both of the capabilities the agent can see.

Paste this into Resource Graph Explorer in the Azure portal.

resources
| where type =~ 'microsoft.cdn/profiles'
// Scope below matches CloudFinOpsPro policy DEFAULTS: exclusions.protectTag, environment.tagKeys,
// environment.allowedTagValues, and allowUntagged false so an untagged resource counts as production.
// If your policy.yaml differs, edit the three lines below or this will disagree with your own agent.
| where tolower(tostring(coalesce(tags['cfop:protect'], ''))) !in ('true', 'yes', '1')
| extend cfopEnv = tolower(trim(' ', tostring(coalesce(tags['Environment'], tags['environment'], tags['env'], ''))))
| where cfopEnv in ('dev', 'development', 'test', 'qa', 'sandbox', 'nonprod', 'non-prod', 'staging')
| where tostring(sku.name) =~ 'Premium_AzureFrontDoor'
| project profileId = tolower(id), name, resourceGroup, location, sku = tostring(sku.name)
// INNER, so a Premium profile with NO WAF policy never reaches the result. That is the
// decline the agent makes first: Private Link to origin is the third Premium-only
// capability and the one neither this query nor the agent can see, so a profile that
// bought no WAF at all is the likeliest to be on Premium for a reason we cannot observe.
| join kind=inner (
    resources
    | where type =~ 'microsoft.network/frontdoorwebapplicationfirewallpolicies'
    | extend managedSets = array_length(properties.managedRules.managedRuleSets)
    // A policy names the profile it protects as <profile-id>/securityPolicies/<name>,
    // so the parent is that id cut at the child segment. split() is case sensitive,
    // which is why the id is lowercased first.
    | mv-expand link = properties.securityPolicyLinks
    | extend profileId = tostring(split(tolower(tostring(link.id)), '/securitypolicies/')[0])
    | summarize policiesAttached = dcount(id), withManagedRuleSets = countif(managedSets > 0) by profileId
  ) on profileId
| where withManagedRuleSets == 0
| project name, resourceGroup, location, sku, policiesAttached
| order by name asc

Each row is a Front Door profile on Premium whose attached WAF policies define no managed rule sets, so the Premium base fee is buying nothing Standard does not already give you: $330 a month against $35, a $295 difference. Premium buys exactly three things Standard cannot do - managed WAF rule sets, bot protection, and Private Link to origin - and custom WAF rules are free on both tiers. A Premium profile with NO WAF policy attached is deliberately absent from these results rather than missing by accident: Private Link to origin is the one Premium capability neither this query nor the agent can see, so a profile that bought no WAF at all is the likeliest to be on Premium for a reason that is real and invisible here. The join is an inner one for exactly that reason. One difference from the agent, stated rather than hidden: this counts entries in managedRuleSets, while the agent additionally requires each entry to name a non-empty ruleSetType. They differ only for a malformed rule set that names no type. Bot protection needs no separate test because it IS a managed rule set, so an empty list rules out both capabilities the agent can observe. A row here is not something the agent can fix for you: Microsoft does not support downgrading a profile from Premium to Standard, so the remedy is building a new Standard profile and migrating onto it, which is why this check recommends and never acts.

Applies to microsoft.cdn/profiles
What the agent does about it

A Front Door profile on Premium whose attached WAF policies define no managed rule sets, so the Premium base fee buys nothing Standard does not already provide.

It will not fix this one

It finds it and tells you what to change. The change itself is yours to make, because it is not one the agent should make on your behalf.