ExpressRoute Direct port with no circuit on it
An ExpressRoute Direct port with no circuit provisioned on it.
Why it happens
An ExpressRoute Direct port is a physical port reserved for one customer and billed by the month whether or not a circuit is provisioned on it: roughly $6,000 to $8,500 a month for 10 Gbps, $50,000 to $80,000 for 100 Gbps, and up to $160,000 for 400 Gbps. Ports are commonly procured months ahead of the circuits that will use them, so a delayed or cancelled project leaves one billing for nothing. The rate depends on the billing type as well as the bandwidth: an unlimited-data port costs around twelve times a metered one. Releasing a port is not something this agent will do, because there is a physical cross-connect and a carrier contract behind it and it cannot be undone by provisioning another, so the check reports the cost and leaves the decision to a human.
Paste this into Resource Graph Explorer in the Azure portal.
resources
| where type =~ 'microsoft.network/expressrouteports'
// 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')
// A MEASURED zero. An absent array means the payload never reported the circuits, which is not the
// same as there being none, so it is excluded rather than treated as unused.
| where isnotnull(properties.circuits) and array_length(properties.circuits) == 0
// billingType decides which meter applies, and the two differ by about twelve times.
| extend portBilling = tostring(properties.billingType)
| project name, resourceGroup, location,
bandwidthGbps = toint(properties.bandwidthInGbps),
billingType = portBilling,
peeringLocation = tostring(properties.peeringLocation),
environment = cfopEnvAn ExpressRoute Direct port is a physical port reserved for one customer and billed by the month whether or not a circuit is provisioned on it: roughly $6,000 to $8,500 for 10 Gbps, $50,000 to $80,000 for 100 Gbps, and up to $160,000 for 400 Gbps. Ports are often procured months before the circuits that will use them, so a delayed project leaves one billing for nothing. Pricing this is unusually easy to get wrong. The meters sit under the product name 'ExpressRoute Direct' while the service is called 'ExpressRoute', whose rows are gateway meters only. The unit of measure is 1/Month rather than the 1 Hour used almost everywhere else in Azure, so the usual multiplication by 730 would overstate a port by three orders of magnitude. 'Port Unlimited 10 Gbps Port' is a different product from 'Port 10 Gbps Port' at about twelve times the price, and which one applies is decided by the port's billingType. Most circuit meters under the same product are published at $0.00. And Metro ports are metered separately, so the check reports one without a figure rather than quoting the standard rate. This is a structural test, so what it returns is what the check reports.
Applies to microsoft.network/expressrouteportsWhat the agent does about it
An ExpressRoute Direct port with no circuit provisioned on it.
It will not fix this one
It reports this and takes no action. A check only earns the right to change something once the action behind it can re-read live state before it fires and knows the way back.