In the past I written and presented on the topic of user licensing in D365FO, the methodology used has not really changed since October 2019 when Microsoft released their new ‘privilege based licensing’. Recently though I was contacted about some interesting behavior on how D365FO was reporting particular licenses. I did a deeper dive into why this was and wanted to share my findings.
The scenario sent to me was around the ‘View error execution log of overhead calculation’ privilege, which has one object assigned to it the CamRuleErrorLog menu item display with a grant and the Read level:
When you look at the ‘View Permissions’ report for this privilege, it is listed as requiring a ‘Team Member’ license. But if we look in AOT at this object both the ‘MaintainUserLicense’ and ‘ViewUserLicense’ settings are listed as requiring an Enterprise/Operations level license:
This of course goes against the current licensing methodology I have written about before, where if you have Read access to an object whatever license is in the ‘ViewUserLicense’ parameter setting is what is required for the user. So what is going on?
Technical Deep Dive
The form that is executed when going to the ‘View Permissions’ report in D365FO is the SysSecRelatedObjects form and the field is the AggregateLicense:
If we look at the code to populate this field, we can see there is a call to an external Microsoft DLL called Microsoft.Dynamics.AX.Security.Management.UI. The data used to populate this field comes from the DialogService class and PopulateRelatedSecurityObjectsTable method:
We can find this DLL in our webroot directory and then use a free tool called dotPeek to decompile the DLL and be able to see the contents, if we use this we can see that the license is calculated in a separate call to the RelatedObjectDataLicenseProcessor (located in the Microsoft.Dynamics.AX.Security.Management DLL):
The RelatedObjectDataLicenseProcessor then calls a LicenseProcessor -> ComputeLicenseWithPrivilege method:
The LicenseProcessor then calls a MenuItemLicenseProperties -> ComputeForGrant method:
And finally we find the root cause, this code performs the following steps:
- Looks to see if the access granted to the menu item is at a ‘Read’ level
- If so, it looks to see if a feature flight called ‘DisabledReadGrantTeamMembersLicense’ is disabled (or does not exist) and also checks to see if the ViewUserLicense Parameter is Operations (UserLicenseType = 4) or Activity (UserLicenseType = 7)
- If both of these boolean checks are true, then the ViewUserLicense parameter for this menu item is overridden to be a Team Member license (UserLicenseType = 6)
- If either of these boolean checks are false, then the original ViewUserLicense parameter on the menu item is returned
If we look at a 10.0.32 version of this DLL, we can see this additional feature flight code is not there:
Which means this change happened at some point between 10.0.32 -> 10.0.35.
Note: The code above relies on the UserLicenseType enum value which has the following values:
I was unable to find any reference to the flighted feature ‘DisableReadGrantTeamMembersLicense’ in the SysFlighting table or any currently flighted featured. Because this feature flag is a negative (you have to enable the feature flag for it to ‘disable’ this functionality) this means that by default, all clients have this new licensing logic being performed.
If I go and actually insert this feature in the SysFlighting table:
And then restart the AOS by executing an iisreset command, when we go back in to the View Permissions report for the same privilege we can see that D365FO is now reporting the privilege as requiring an Operations license like would be expected previously.
I have now updated the licensing decision Visio diagram to include this additional logic:
How Big is the Impact of This Licensing Change?
If I look at the metadata of all menu items and I look at those where the ViewUserLicense is either Activity or Operations level license we can see there are 680+ objects that meet those requirements. Any role, duty, or privilege where these objects are assigned could potentially cause the licensing issue addressed in this blog post.
Looking in Microsoft D365FO Release Notes
I was unable to find any mention of this licensing change in any of the recent release notes from Microsoft, if anyone has anything mentioning this licensing change, please feel free to reach out: https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/fin-ops/get-started/whats-new-changed
I initially found this change in the 10.0.35 release of D365FO, I am still working to see when this change was first implemented, but looking at how this change was performed my guess is that Microsoft expects this to be part of the default licensing methodology going forward.