microsoft / Microsoft365DSC

Manages, configures, extracts and monitors Microsoft 365 tenant configurations
https://aka.ms/M365DSC
MIT License
1.54k stars 477 forks source link

[New-M365DeltaReport] AADRoleDefinition-Global Secure Access Administrator and some EXO Roles have issues with the descriptions #5058

Open jadamones opened 3 days ago

jadamones commented 3 days ago

Description of the issue

When running a delta report between two configurations from the same tenant, these two resources keep identifying themselves as a drift. I'm really confused as to why this is the case and I've done a fresh export of both resources as well. I'm totally mystified about this. Does anyone have tips on how to resolve it?

image

Microsoft 365 DSC Version

1.24.904.1

Which workloads are affected

Azure Active Directory (Entra ID), Intune

The DSC configuration

IntuneDeviceConfigurationPlatformScriptWindows "IntuneDeviceConfigurationPlatformScriptWindows-Enable Long Paths"
    {
        ApplicationId         = $ApplicationId;
        Assignments           = @(
            MSFT_DeviceManagementConfigurationPolicyAssignments{
                deviceAndAppManagementAssignmentFilterType = 'none'
                groupDisplayName = 'All devices'
                dataType = '#microsoft.graph.allDevicesAssignmentTarget'
            }
        );
        CertificateThumbprint = $Thumbprint;
        Description           = "New-ItemProperty -Path `"HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem`" -Name `"LongPathsEnabled`" -Value 1 -PropertyType DWORD -Force
#Enables long paths";
        DisplayName           = "Enable Long Paths";
        EnforceSignatureCheck = $False;
        Ensure                = "Present";
        FileName              = "longpaths.ps1";
        Id                    = "12ef00fd-19cc-4236-9b71-7d6b50235609";
        RoleScopeTagIds       = @("0");
        RunAs32Bit            = $True;
        RunAsAccount          = "system";
        ScriptContent         = "TmV3LUl0ZW1Qcm9wZXJ0eSAtUGF0aCAiSEtMTTpcU1lTVEVNXEN1cnJlbnRDb250cm9sU2V0XENvbnRyb2xcRmlsZVN5c3RlbSIgLU5hbWUgIkxvbmdQYXRoc0VuYWJsZWQiIC1WYWx1ZSAxIC1Qcm9wZXJ0eVR5cGUgRFdPUkQgLUZvcmNl";
        TenantId              = $TenantId;
    }
    AADRoleDefinition "AADRoleDefinition-Global Secure Access Administrator"
    {
        ApplicationId         = $ApplicationId;
        CertificateThumbprint = $Thumbprint;
        Description           = "Create and manage all aspects of Global Secure Internet Access and Microsoft Global Secure Private Access, including managing access to public and private endpoints.";
        DisplayName           = "Global Secure Access Administrator";
        Ensure                = "Present";
        Id                    = "ac434307-12b9-4fa1-a708-88bf58caabc1";
        IsEnabled             = $True;
        ResourceScopes        = @("/");
        RolePermissions       = @("microsoft.azure.supportTickets/allEntities/allTasks","microsoft.directory/applicationPolicies/standard/read","microsoft.directory/applications/applicationProxy/read","microsoft.directory/applications/owners/read","microsoft.directory/applications/policies/read","microsoft.directory/applications/standard/read","microsoft.directory/auditLogs/allProperties/read","microsoft.directory/conditionalAccessPolicies/standard/read","microsoft.directory/connectorGroups/allProperties/read","microsoft.directory/connectors/allProperties/read","microsoft.directory/crossTenantAccessPolicy/default/standard/read","microsoft.directory/crossTenantAccessPolicy/partners/standard/read","microsoft.directory/crossTenantAccessPolicy/standard/read","microsoft.directory/namedLocations/standard/read","microsoft.directory/signInReports/allProperties/read","microsoft.networkAccess/allEntities/allProperties/allTasks","microsoft.office365.messageCenter/messages/read","microsoft.office365.serviceHealth/allEntities/allTasks","microsoft.office365.supportTickets/allEntities/allTasks","microsoft.office365.webPortal/allEntities/standard/read");
        TemplateId            = "ac434307-12b9-4fa1-a708-88bf58caabc1";
        TenantId              = $TenantId;
        Version               = "1";
    }

Verbose logs showing the problem

No response

Environment Information + PowerShell Version

No response

ricmestre commented 3 days ago

Most likely it's a problem with line endings, blueprints are always exported as Windows (CRLF) but in the tenant you might have those settings that appear as drifts with either MacOS (CR) or Un*x (LF) line endings and they won't be clearly visible.

My advice is to try to remove the current values on those settings, save the policy and then change them again with whatever value it appears in the blueprint as-is so that it copies the correct line endings.

jadamones commented 2 days ago

So I resolved the intune policy by removing the end line of the description starting at the comment but the Global Secure Access definition continues to give me issues. I've replaced the blueprint with the export and compared them again but it's still the same issue. This is a built-in role so I can't change the description on the tenant. Hmm...

jadamones commented 2 days ago

When I open a new export of this role definition in notepad, this is what it looks like. This is actually happening on all of my tenant configurations. It looks like the default description on this role in Entra is malformed..

image

jadamones commented 2 days ago

I seem to have the same issue with this role too. Seems to be an issue with the single quotes in the description.

image

EXORoleGroup "EXORoleGroup-ComplianceAdmins_-549003957"
    {
        ApplicationId         = $ApplicationId;
        CertificateThumbprint = $Thumbprint;
        Description           = "Membership in this role group is synchronized across services and managed centrally. This role group is not manageable through Microsoft Exchange or Unified Compliance Center(UCC). By default, this group is not assigned any roles. However, it will be a member of the ‘Records Management’ and ‘Compliance Management’ role groups in Exchange and ‘Conmpliance Administrator’ role group in UCC. It will inherit the rights of these groups.";
        Ensure                = "Present";
        Name                  = "ComplianceAdmins_-549003957";
        Roles                 = @();
        TenantId              = $TenantId;
    }
jadamones commented 2 days ago

For the sake of completeness, I'm seeing this issue in a few places. The "blueprint" source is actually compiled in ADO and is generated as an artifact and the destination file is a full export of the production tenant, so we periodically run deltas against these. Also not sure why the comments on the Transport Rules are an issue. When we run a Test-DSCConfiguration against the same source, we only get a error on the ComplianceAdmins-549003957 (not on the global secure access admin, or any of these phantom comments on the transport rules). So I'm extra confused...

image

jadamones commented 2 days ago

ok.. In VSCode where the code that creates the source file is, it is encoded in UTF-8; however, the destination file that it is comparing against is encoded in UTF-16 LE BOM. I'm assuming this has something to do with it. I've tried converting the source file to Unicode but doesn't make a difference. Do I have any options to get these two files seeing the same thing? Everything is being written in VSCode on Windows 11.

jadamones commented 2 days ago

Last update for the evening, I've worked around this by excluding the comments and descriptions properties since I don't really need them in the reports. I'm still curious if there is a notion of what the issue is.

FabienTschanz commented 2 days ago

Don't really know if the issue lies in the UTF-16 LE BOM format instead of UTF-8, but the single quotes you mentioned seem exactly like the ones Microsoft Word uses when I write a single quote (though Swiss German). Any chance that was the case for this description?

The NNBSP that was mentioned earlier is the "Narrow No-Break Space". Not visible to the eye, but certainly different from a regular space in terms of text. If that's a default role, then I guess you can't change the description, right? Then that's most likely staying like this, unfortunately.

Any chance that the comments in the EXOTransportRules are not "empty", but contain a space or a line break or something like that?

jadamones commented 1 day ago

Hey @FabienTschanz ,

Thanks for the response. I will check the comments on the transport rules but the only issue at this point is that since adding AADRoleDefinition and EXORoleGroup resources to my repo for these tenants, the Test-DSCConfiguration is in fact failing on "EXORoleGroup-ComplianceAdmins_-549003957" and "AADRoleDefinition-Global Secure Access Administrator". These are both built-in roles and I can't change the way that the descriptions were written so it's just constantly failing on these two. This is happening with every tenant for the Global Secure Access Administrator.

I'm just not sure how to get the code in the repo to match the encoding of the export or descriptions in the actual tenants so that it doesn't throw this. If I compare two exports, it's not an issue. It only becomes an issue when I compare the code in the ADO repo to the export. I've tried changing the encoding on both files to match but that doesn't seem to make a difference. Is there a way to prevent Test-DSCConfiguration from evaluating those two resources or at least the descriptions without removing the entire resource which would then cause a drift in a blueprint evaluatation?

Here is a log example:

<M365DSCEvent>
    <ConfigurationDrift Source="MSFT_AADRoleDefinition" TenantId="xxxxxxxxxx">
        <ParametersNotInDesiredState>
            <Param Name="Description"><CurrentValue>Create and manage all aspects of Global Secure Internet Access and Microsoft Global Secure Private Access, including managing access to public and private endpoints.</CurrentValue><DesiredValue>Create and manage all aspects of Global Secure Internet Access and Microsoft Global Secure Private Access, including managing access to public and private endpoints.</DesiredValue></Param>
        </ParametersNotInDesiredState>
    </ConfigurationDrift>
    <DesiredValues>
        <Param Name ="DisplayName">Global Secure Access Administrator</Param>
        <Param Name ="Description">Create and manage all aspects of Global Secure Internet Access and Microsoft Global Secure Private Access, including managing access to public and private endpoints.</Param>
        <Param Name ="ResourceScopes">/</Param>
        <Param Name ="IsEnabled">True</Param>
        <Param Name ="RolePermissions">microsoft.azure.supportTickets/allEntities/allTasks microsoft.directory/applicationPolicies/standard/read microsoft.directory/applications/applicationProxy/read microsoft.directory/applications/owners/read microsoft.directory/applications/policies/read microsoft.directory/applications/standard/read microsoft.directory/auditLogs/allProperties/read microsoft.directory/conditionalAccessPolicies/standard/read microsoft.directory/connectorGroups/allProperties/read microsoft.directory/connectors/allProperties/read microsoft.directory/crossTenantAccessPolicy/default/standard/read microsoft.directory/crossTenantAccessPolicy/partners/standard/read microsoft.directory/crossTenantAccessPolicy/standard/read microsoft.directory/namedLocations/standard/read microsoft.directory/signInReports/allProperties/read microsoft.networkAccess/allEntities/allProperties/allTasks microsoft.office365.messageCenter/messages/read microsoft.office365.serviceHealth/allEntities/allTasks microsoft.office365.supportTickets/allEntities/allTasks microsoft.office365.webPortal/allEntities/standard/read</Param>
        <Param Name ="Version">1</Param>
        <Param Name ="Ensure">Present</Param>
        <Param Name ="ApplicationId">xxxxxxxxxx</Param>
        <Param Name ="TenantId">xxxxxxx</Param>
        <Param Name ="CertificateThumbprint">xxxxxxxx</Param>
        <Param Name ="Verbose">True</Param>
    </DesiredValues>
    <CurrentValues>
        <Param Name ="ApplicationSecret">$null</Param>
        <Param Name ="Id">xxxxxxxxx</Param>
        <Param Name ="ApplicationId">xxxxxxxx</Param>
        <Param Name ="CertificateThumbprint">xxxxxx</Param>
        <Param Name ="AccessTokens">$null</Param>
        <Param Name ="ResourceScopes">/</Param>
        <Param Name ="RolePermissions">microsoft.azure.supportTickets/allEntities/allTasks microsoft.directory/applicationPolicies/standard/read microsoft.directory/applications/applicationProxy/read microsoft.directory/applications/owners/read microsoft.directory/applications/policies/read microsoft.directory/applications/standard/read microsoft.directory/auditLogs/allProperties/read microsoft.directory/conditionalAccessPolicies/standard/read microsoft.directory/connectorGroups/allProperties/read microsoft.directory/connectors/allProperties/read microsoft.directory/crossTenantAccessPolicy/default/standard/read microsoft.directory/crossTenantAccessPolicy/partners/standard/read microsoft.directory/crossTenantAccessPolicy/standard/read microsoft.directory/namedLocations/standard/read microsoft.directory/signInReports/allProperties/read microsoft.networkAccess/allEntities/allProperties/allTasks microsoft.office365.messageCenter/messages/read microsoft.office365.serviceHealth/allEntities/allTasks microsoft.office365.supportTickets/allEntities/allTasks microsoft.office365.webPortal/allEntities/standard/read</Param>
        <Param Name ="Managedidentity">False</Param>
        <Param Name ="Credential">$null</Param>
        <Param Name ="DisplayName">Global Secure Access Administrator</Param>
        <Param Name ="Ensure">Present</Param>
        <Param Name ="Description">Create and manage all aspects of Global Secure Internet Access and Microsoft Global Secure Private Access, including managing access to public and private endpoints.</Param>
        <Param Name ="Version">1</Param>
        <Param Name ="IsEnabled">True</Param>
        <Param Name ="TenantId">xxxxxxx/Param>
        <Param Name ="TemplateId">xxxxxxxx</Param>
    </CurrentValues>
</M365DSCEvent>
FabienTschanz commented 1 day ago

What is the ADO repository (sorry, dumb question)? I exported the description for the Global Secure Access Administrator and converted that to json to see if there are any fancy characters, but it doesn't seem like. So, is the code in the ADO repository the one that is "faulty"?

ricmestre commented 1 day ago

Most likely AzureDevOps, please note that is very likely that the files in these repos get to be converted to Un*x line endings and it might screw things around. For this reason I always set git config --global core.autocrlf false so that the file is stored in the repo with whatever line ending I decide which is always Windows CRLF.

jadamones commented 1 day ago

@FabienTschanz yeah, sorry ADO = Azure DevOps.

@ricmestre I will give this a try. Will I need to recreate the files in the repo, or will this update on the next PR for that particular file?

ricmestre commented 1 day ago

should not be required but even better is to just add a .gitattributes at the root of the repo with the contents below.

# Enforce crlf line endings
* text=crlf