How to convert Conditional Access "system.collections" values into friendly name upon running Get-AzureADMSConditionalAccessPolicy

Benard Mwanza 1,006 Reputation points
2022-03-02T07:10:03.85+00:00

I'm currently working on PowerShell script to retrieve Conditional access policies configurations. The information is required in a csv file to help management with auditing requests. As of current upon running Get-AzureADMSConditionalAccessPolicy cmdlet, the only data that i can grab and save to a csv file is: Id, display name and state. Conditions and controls comes in an obfuscated format of "system.collections" which cannot be understood.

PS C:\Windows\system32> Get-AzureADMSConditionalAccessPolicy  
  
  
Id              : a77d724e-b9f9-452d-b1f0-d041142413a0  
DisplayName     : Block_Office365_Apps_Access_In_Android_Devices  
State           : enabled  
Conditions      : class ConditionalAccessConditionSet {  
                    Applications: class ConditionalAccessApplicationCondition {  
                    IncludeApplications: System.Collections.Generic.List`1[System.String]  
                    ExcludeApplications: System.Collections.Generic.List`1[System.String]  
                    IncludeUserActions: System.Collections.Generic.List`1[System.String]  
                    IncludeProtectionLevels:  
                  }  
  
                    Users: class ConditionalAccessUserCondition {  
                    IncludeUsers: System.Collections.Generic.List`1[System.String]  
                    ExcludeUsers: System.Collections.Generic.List`1[System.String]  
                    IncludeGroups: System.Collections.Generic.List`1[System.String]  
                    ExcludeGroups: System.Collections.Generic.List`1[System.String]  
                    IncludeRoles: System.Collections.Generic.List`1[System.String]  
                    ExcludeRoles: System.Collections.Generic.List`1[System.String]  
                  }  
  
                    Platforms: class ConditionalAccessPlatformCondition {  
                    IncludePlatforms: System.Collections.Generic.List`1[Microsoft.Open.MSGraph.Model.ConditionalAccessDevicePlatforms]  
                    ExcludePlatforms: System.Collections.Generic.List`1[Microsoft.Open.MSGraph.Model.ConditionalAccessDevicePlatforms]  
                  }  
  
                    Locations:  
                    SignInRiskLevels: System.Collections.Generic.List`1[Microsoft.Open.MSGraph.Model.ConditionalAccessRiskLevel]  
                    ClientAppTypes: System.Collections.Generic.List`1[Microsoft.Open.MSGraph.Model.ConditionalAccessClientApp]  
                  }  
  
GrantControls   : class ConditionalAccessGrantControls {  
                    _Operator: OR  
                    BuiltInControls: System.Collections.Generic.List`1[Microsoft.Open.MSGraph.Model.ConditionalAccessGrantControl]  
                    CustomAuthenticationFactors: System.Collections.Generic.List`1[System.String]  
                    TermsOfUse: System.Collections.Generic.List`1[System.String]  
                  }  
  
SessionControls :  

Condition section includes information about: applications, users, platforms, locations which is required to be retrieved

My script so far: Get-AzureADMSConditionalAccessPolicy | Select-Object -Property DisplayName, Id, State | Export-Csv -Path C:\CAccessResults.csv -NoTypeInformation

On further research, it looks like by running ((Get-AzureADMSConditionalAccessPolicy).Conditions).Applications can display

PS C:\Windows\system32> ((Get-AzureADMSConditionalAccessPolicy).Conditions).Applications  
  
IncludeApplications ExcludeApplications IncludeUserActions IncludeProtectionLevels  
------------------- ------------------- ------------------ -----------------------  
{Office365}         {}                  {}  

and the same applies for users, platforms, locations and grantcontrols.

PS C:\Windows\system32> ((Get-AzureADMSConditionalAccessPolicy).Conditions).users  
  
  
IncludeUsers  : {350a541a-02f0-4759-b729-70922997e819}  
ExcludeUsers  : {}  
IncludeGroups : {}  
ExcludeGroups : {}  
IncludeRoles  : {}  
ExcludeRoles  : {}  

PS C:\Windows\system32> ((Get-AzureADMSConditionalAccessPolicy).Conditions).users  
  
  
IncludeUsers  : {350a541a-02f0-4759-b729-70922997e819}  
ExcludeUsers  : {}  
IncludeGroups : {}  
ExcludeGroups : {}  
IncludeRoles  : {}  
ExcludeRoles  : {}  

The user querry returns GUID.

My goal is to have this friendly readable information queried and stored in the csv file. How can that be implemented?

My script so far:

$allpolicies = Get-AzureADMSConditionalAccessPolicy   
  
$allpolicies | ForEach-Object{  
  
    $policyID = $_.Id  
    $policydisplayname = $_.DisplayName  
    $policystate = $_.State  
    $applications = ($_.Conditions).Applications.IncludeApplications  
    $includedusers = ($_.Conditions).Users.IncludeUsers  
    $includedgroups = ($_.Conditions).Users.IncludeGroups  
    $includedlocation = ($_.Conditions).Locations.includelocations  
  
  
    New-object -typename PSobject -property @{  
  
        ID = $policyID  
        DisplayName = $policydisplayname  
        Policy_State = $policystate  
        Includedapps =  $applications  
        Users_Applied_The_Policy = $includedusers  
        Groups_Applied_The_Policy = $includedgroups  
        Locations_Applied_The_Policy = $includedlocation  
  
  
    }  
  
} | Sort-Object ID, DisplayName, Policy_State, Includedapps, Users_Applied_Policy, Groups_Applied_Policy, Locations_Applied | Export-Csv -Path C:\CAccessResults3.csv -NoTypeInformation  

CSV output:
179742-conditionalaccesscsv.png

Running the script using powershell without saving the output in csv
179713-conditionaaccesscoreps.png

Is there a way to output the values for Includedapps, Users_Applied_Policy, Groups_Applied_Policy, Locations_Applied in a readable format and have them separated in each row.

Windows for business | Windows Server | User experience | PowerShell
Microsoft Security | Microsoft Entra | Microsoft Entra ID
0 comments No comments
{count} votes

Answer accepted by question author
  1. Clément BETACORNE 2,496 Reputation points
    2022-03-03T15:29:38.563+00:00

    Hello,

    You try to add a join at this part in your script :

    $allpolicies = Get-AzureADMSConditionalAccessPolicy   
          
     $allpolicies | ForEach-Object{  
          
         $policyID = $_.Id  
         $policydisplayname = $_.DisplayName  
         $policystate = $_.State  
         $applications = ($_.Conditions).Applications.IncludeApplications -join ' '  
         $includedusers = ($_.Conditions).Users.IncludeUsers -join ' '  
         $includedgroups = ($_.Conditions).Users.IncludeGroups -join ' '  
         $includedlocation = ($_.Conditions).Locations.includelocations -join ' '  
          
          
         New-object -typename PSobject -property @{  
          
             ID = $policyID  
             DisplayName = $policydisplayname  
             Policy_State = $policystate  
             Includedapps =  $applications  
             Users_Applied_The_Policy = $includedusers  
             Groups_Applied_The_Policy = $includedgroups  
             Locations_Applied_The_Policy = $includedlocation  
          
          
         }  
          
     }  
    

    I've tested it with the export and you have something like that :
    179765-image.png

    2 people found this answer helpful.

3 additional answers

Sort by: Most helpful
  1. Clément BETACORNE 2,496 Reputation points
    2022-03-03T09:49:02.72+00:00

    Hello,

    You should use the DCToolBox module with the New-DCConditionalAccessPolicyDesignReport cmdlet :
    https://danielchronlund.com/2020/11/09/dctoolbox-powershell-module-for-microsoft-365-security-conditional-access-automation-and-more/

    Regards,

    0 comments No comments

  2. Rich Matheisen 48,026 Reputation points
    2022-03-03T21:04:12.837+00:00

    CSV files aren't really geared towards representing structured data. You can place all of the values in a list into one column if you provide for a delimiter within the data that 1) doesn't exist in any data in the column, and 2) isn't the same delimiter used to separate the columns.

    [PSCustomObject]@{
        Includedapps = ($applications -join ';')
    }
    
    # OR without the need for the intermediate variable "$applications"
    
    [PSCustomObject]@{
        Includedapps = ($_.Conditions.Applications.IncludeApplications -join ';')
    }
    
    # THEN
    Export-CSV some-file-name.csv -NoTypeInformation -Delimiter ',' # Note: the comma is the default delimiter. 
                                                                    #       I just used it here to contrast with the semi-colon separator
                                                                    #       used within the column data
    
    0 comments No comments

  3. Siva-kumar-selvaraj 15,731 Reputation points Volunteer Moderator
    2022-04-04T06:11:29.04+00:00

    You could use Get-AzureADUser -ObjectId 7ccb8dc7-c694-42d7-8242-bd5cf7d5a9f2 | Select UserPrincipalName to get UserPrincipalName of given user's Object ID as shown below:

    189604-image.png

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.