Zoomed Image

Azure License Import

Software Asset Management Guide
Importing Licenses

Azure License Import

Microsoft cloud subscriptions — Microsoft 365, Dynamics 365, Power BI, Teams Phone and the rest — are not bought as files you can import. They live in your Entra tenant, they change whenever someone joins or leaves, and a spreadsheet of them is out of date the day you export it. The Azure License Import reads them directly from Microsoft Graph and keeps them current, including who holds each licence.

Unlike the other imports in this chapter, this one is not a file you paste in. It is a scheduled integration that runs against your tenant.

What the Import Creates

Created From Notes
A parent licence per subscription SKU subscribedSkus in Graph Seats come from the enabled unit count
A child licence per licensable service plan The service plans inside each SKU Only where the plan maps to a catalog product — see Child Licences
A per-user allocation per assigned licence The assignedLicenses on each user Written to the licence's Assigned Users, not to a device

Licences are created as Software License assets (CategoryID = 10) with the Supplier set to Microsoft Corporation and the licence class set to Enterprise Agreement. The subscription identifier is stored as the serial number, which is what the import matches on when it runs again — so a licence is updated in place rather than duplicated, and a seat count change is picked up on the next run.

Prerequisites

Run the Entra ID integration first. This is the one that catches people out. Per-user allocation matches each Azure user to a Custodian record on the Entra object ID, and that ID is only populated by the Entra ID (Azure Active Directory) integration. If Custodians have never been synchronised, licences import correctly but no allocations are created and no error is raised — the join simply finds nothing.

To check before you start:

select count(*) from Custodian where Spare9 is not null and Spare9 <> ''

If that returns zero, run Azure Active Directory Integration first. See Azure – Direct Integration.

Grant the Graph permissions. The integration only ever issues GETs, so read-only application permissions are sufficient:

Permission Needed For
Organization.Read.All Reading the subscription and seat counts
User.Read.All Reading which user holds which licence

Both are application permissions and need admin consent. A missing scope shows up as a 403 on the fetch rather than a failure to authenticate, because the token request itself succeeds.

Populate the Software Catalog. As with every import in this chapter, licences attach to catalog entries that already exist. See Preparing the Catalog.

Running the Import

Run Azure Licensing Integration from the Integrations list. It runs in two halves:

  1. Get Data from Azure — authenticates and fetches the subscriptions, their service plans, and the per-user assignments, paging through the results
  2. Process Imported Data — everything else: create licences, recognise them, create and link child licences, allocate to users, and remove allocations that have gone away

The second half can be run on its own. That is useful when you want to reprocess the last fetch after changing recognition rules, without going back to Microsoft for data that has not changed.

Licence Names

Microsoft's API returns identifiers, not names. Left alone, your licence register would read SPE_E3, AAD_PREMIUM and MCOEV.

xAssets ships the published Microsoft product names as Software License Recognition rules, so those become Microsoft 365 E3, Microsoft Entra ID P1 and Microsoft Teams Phone Standard. Around 600 SKUs are covered out of the box.

Where Microsoft has not published a name — usually a very new or add-on SKU — the raw identifier is shown unchanged. That is deliberate: an identifier you can look up is more useful than a guess. If you want to name one yourself, add or edit a rule under Software License Recognition and set the Display Name; your value is preserved when the shipped list is next refreshed.

Suppressing Licences You Do Not Care About

A Microsoft tenant typically carries a long tail of free trials, viral sign-ups and internal service SKUs — Power Automate Free, Microsoft Fabric (Free), various preview products. They are real subscriptions, but they are not licences anyone manages, and they clutter the register.

To suppress one, add a Software License Recognition rule matching its identifier and set the Software Title to Ignore. The licence is still imported and still visible if you go looking, but it is marked as ignored and drops out of the day-to-day licence list.

Child Licences

A Microsoft 365 E3 subscription is not one product. It contains dozens of service plans — Exchange Online, SharePoint, Teams, the Office desktop apps and more — and it is those, not the suite, that people actually install.

The import creates a child licence for a service plan only where a recognition rule maps it to a real catalog product. Without that rule the plan is ignored, which keeps a tenant with hundreds of service plans from producing hundreds of unusable licence records.

Two rules keep the counting honest:

  • A child is only created where the service plan maps to a catalog entry that exists
  • A child is not created where its parent SKU already maps to the same product, so a single installation is never counted against both the suite and its component

Children are linked to their parent so the relationship is visible from either record.

Per-User Allocation

Microsoft cloud licences are assigned to people, not machines, and the import reflects that. Allocations are written to the licence's Assigned Users, showing who holds each seat.

This matters for compliance because a per-user licence is consumed once per named person regardless of how many devices they use. A user with a laptop, a desktop and a virtual machine consumes one M365 seat, not three.

Each allocation records when it was first seen, when it was last seen, and when it was last confirmed by an import. Those dates drive the License Allocations Needing Review report, which surfaces seats held by people who have left and manual allocations nobody has reconfirmed. The staleness threshold is the AllocationStaleDays setting, 180 days by default.

Allocations you make by hand are never removed by the import. When a licence is unassigned in Microsoft 365 the corresponding allocation disappears on the next run, but manual allocations are left alone — the import only tidies up what it created.

Verifying the Import

After the first run:

  1. Check the licence count on Licensing → Licenses. It should match the number of subscriptions in your tenant.
  2. Open a licence and confirm the seat count matches the Microsoft 365 admin centre.
  3. Open Assigned Users on a licence you know is widely used, and confirm real people are listed.
  4. Recalculate the licensing position (Licensing → Calculate Licensing Position) — licences do not affect compliance until you do.
  5. Check the Licensing Position for the products you expect to be covered.

Troubleshooting

Symptom Cause
Licences import but no users are assigned The Entra ID integration has not run, so Custodians have no Entra object ID to match on. See Prerequisites.
403 from Microsoft during the fetch A Graph permission is missing or has not been consented. The token is granted regardless, so this appears part-way through rather than at logon.
Licence names show as raw identifiers No recognition rule matches. Expected for very new SKUs; add a rule with a Display Name if you want one.
A licence appears twice Its serial number changed at source. The import matches on the subscription identifier, so a genuinely new subscription is a new licence.
Seat counts look wrong The count is the enabled unit count from Microsoft, which includes seats you have bought but not assigned. Compare against the admin centre rather than against your user count.
A user holds a licence in Microsoft 365 but not in xAssets Their Azure account has no matching Custodian — commonly a guest, a service account, or someone who joined since the last Entra sync.