Wednesday, February 8, 2023
Hi All,
Yesterday the new Version of the AZ PowerShell Module 9.4.0 has been released to PowerShell Gallery.
Az 9.4.0
Azure PowerShell release notes
Show Installed AZ Module and what's available in the PowerShell Gallery
Get-InstalledModule AZ
Find-Module AZ
To uninstall all the old Modules and install the new Modules i have written a PowerShell Script that is published at my GitHub Repo.
#Run Script directly from GitHub
$ScriptFromGitHub = Invoke-WebRequest "https://raw.githubusercontent.com/BohrenAn/GitHub_PowerShellScripts/main/Azure/Cleanup-AZModules.ps1"
Invoke-Expression $($ScriptFromGitHub.Content)
The AZ Module is just a Wrapper Module for all AZ* Modules
Get-InstalledModule AZ*
Regards
Andres Bohren
Hi All,
I've stumbled accross the new Microsoft 365 Defender Role-based access control (RBAC). It is still in Preview but i gave it a go.For now you can create the RBAC Roles only in the M365 Defender Portal. But Graph Integration is at least on the Roadmap.
Centrally manage permissions with the Microsoft 365 Defender role-based access control (RBAC) model
Microsoft 365 Defender role-based access control (RBAC)
Let's create a custom role
Give it a Name and some Discription if you like
Select one of the Categories
Select the Permissions you need or want
Add an assignment
Give it a name and select the Identities
The summary page
Sucessfully created the RBAC Role
That's how it looks like in the Portal
I guess because of the "Security data basics (read)" Permissions i could access a lot of Information.
For just Microsoft 365 Defender for Office 365 / Exchang Online Protection Quarantine it's better to use the "Email and Collaboration Roles"
And assign just the Quarantine Permission
That's much better if you just want someone to manage the Quarantine
Regards
Andres Bohren
Hi All,
While checking the Devices in my M365 Tenant i was stumbled over the Stale Devices.
The List shows Devices that have an acivity more than 6 Months ago
Let's check if we can get that Information with Microsoft.Graph PowerShell
Connect-MgGraph -Scopes Directory.ReadWrite.All, Directory.AccessAsUser.All
Get-MgDevice
Now we need to get the Devices that are older than six Months
$Devices = Get-MgDevice
$Devices | where {$_.ApproximateLastSignInDateTime -lt (Get-Date).AddMonths(-6)}
We can format that a little better
$Devices | where {$_.ApproximateLastSignInDateTime -lt (Get-Date).AddMonths(-6)} | ft DisplayName,AccountEnabled,OperatingSystem,OperatingSystemVersion,ProfileType,IsManaged,IsCompliant,OnPremisesSyncEnabled,ApproximateLastSignInDateTime
Let's remove these Devices
$StaleDevices = $Devices | where {$_.ApproximateLastSignInDateTime -lt (Get-Date).AddMonths(-6)}
Foreach ($StaleDevice in $StaleDevices)
{
Write-Host "DisplayName: $($StaleDevice.DisplayName) ApproximateLastSignInDateTime: $($StaleDevice.ApproximateLastSignInDateTime)"
$DeviceId = $StaleDevice.Id
Write-Host "Delete Id: $DeviceId" -ForegroundColor Yellow
Remove-MgDevice -DeviceId $DeviceId
}
These Devices have now been gone
Regards
Andres Bohren
Sunday, February 5, 2023
Hi All,
Just a few days ago Microsoft has released PowerToys v0.67.0. As always, there are a plenty of news.
PowerToysRelease v0.67.0
Regards
Andres Bohren
Friday, February 3, 2023
Hi All,
I had the "pleasure" again this week to Document the Azure AD Policies.
Making several Screenshots in the Azure AD Portal seemed not the best way.
MSGraph: List Conditional Access policies
You need the Permission: Policy.Read.All
https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies
While using the JSON could be one way. It's not very good if you have to Document it in a Word Document right.
I tried to use the Microsoft.Graph PowerShell Module
Import-Module Microsoft.Graph.Identity.SignIns
Connect-MgGraph -Scopes Policy.Read.All
$CAP = Get-MgIdentityConditionalAccessPolicy
$CAP
As you can see the Conditions, GrantControls and SessionControls are dedicated Objects
$CAP[1] | fl
If we dig down the Conditions more Objects appear
$CAP[1].Conditions | fl
And again one more Layer down in Applications we can find the Values
$CAP[1].Conditions.Applications | fl
Grant Controls are very staight forward
$CAP[1].GrantControls | fl
The Session Control has again multiple Objects to dig down
$CAP[1].SessionControls | fl
I came up with the Idea of using the Layers as Labels with "_" and the Expression to get the Values
$CAP[1] | select Id, DisplayName, State, `
@{Label = "Conditions_Applications_ExcludeApplications"; Expression = { $_.Conditions.Applications.ExcludeApplications}}, `
@{Label = "Conditions_Applications_IncludeApplications"; Expression = { $_.Conditions.Applications.IncludeApplications}}, `
@{Label = "Conditions_Applications_IncludeAuthenticationContextClassReferences"; Expression = { $_.Conditions.Applications.IncludeAuthenticationContextClassReferences}}, `
@{Label = "Conditions_Applications_IncludeUserActions"; Expression = { $_.Conditions.Applications.IncludeUserActions}}, `
@{Label = "Conditions_Applications_AdditionalProperties"; Expression = { $_.Conditions.Applications.AdditionalProperties}}, `
@{Label = "Conditions_ClientAppTypes"; Expression = { $_.Conditions.ClientAppTypes}}, `
@{Label = "Conditions_ClientApplications_ExcludeServicePrincipals"; Expression = { $_.Conditions.ClientApplications.ExcludeServicePrincipals}}, `
@{Label = "Conditions_ClientApplications_IncludeServicePrincipals"; Expression = { $_.Conditions.ClientApplications.IncludeServicePrincipals}}, `
@{Label = "Conditions_Devices_DeviceFilter_Mode"; Expression = { $_.Conditions.Devices.DeviceFilter.Mode}}, `
@{Label = "Conditions_Devices_DeviceFilter_Rule"; Expression = { $_.Conditions.Devices.DeviceFilter.Rule}}, `
@{Label = "Conditions_Devices_DeviceFilter_AdditionalProperties"; Expression = { $_.Conditions.Devices.DeviceFilter.AdditionalProperties}}, `
@{Label = "Conditions_Locations_ExcludeLocations"; Expression = { $_.Conditions.Locations.ExcludeLocations}}, `
@{Label = "Conditions_Locations_IncludeLocations"; Expression = { $_.Conditions.Locations.IncludeLocations}}, `
@{Label = "Conditions_Platforms_ExcludePlatforms"; Expression = { $_.Conditions.Platforms.ExcludePlatforms}}, `
@{Label = "Conditions_Platforms_IncludePlatforms"; Expression = { $_.Conditions.Platforms.IncludePlatforms}}, `
@{Label = "Conditions_Platforms_AdditionalProperties"; Expression = { $_.Conditions.Platforms.AdditionalProperties}}, `
@{Label = "Conditions_ServicePrincipalRiskLevels"; Expression = { $_.Conditions.ServicePrincipalRiskLevels}}, `
@{Label = "Conditions_SignInRiskLevels"; Expression = { $_.Conditions.SignInRiskLevels}}, `
@{Label = "Conditions_UserRiskLevels"; Expression = { $_.Conditions.UserRiskLevels}}, `
@{Label = "Conditions_users_ExcludeGroups"; Expression = { $_.Conditions.Users.ExcludeGroups}}, `
@{Label = "Conditions_users_ExcludeRoles"; Expression = { $_.Conditions.Users.ExcludeRoles}}, `
@{Label = "Conditions_users_ExcludeUsers"; Expression = { $_.Conditions.Users.ExcludeUsers}}, `
@{Label = "Conditions_users_IncludeGroups"; Expression = { $_.Conditions.Users.IncludeGroups}}, `
@{Label = "Conditions_users_IncludeRoles"; Expression = { $_.Conditions.Users.IncludeRoles}}, `
@{Label = "Conditions_users_IncludeUsers"; Expression = { $_.Conditions.Users.IncludeUsers}}, `
@{Label = "Conditions_users_AdditionalProperties"; Expression = { $_.Conditions.Users.AdditionalProperties}}, `
@{Label = "Conditions_AdditionalProperties"; Expression = { $_.Conditions.AdditionalProperties}}, `
@{Label = "SessionControls_ApplicationEnforcedRestrictions_IsEnabled"; Expression = { $_.SessionControls.ApplicationEnforcedRestrictions.IsEnabled}}, `
@{Label = "SessionControls_ApplicationEnforcedRestrictions_AdditionalProperties"; Expression = { $_.SessionControls.ApplicationEnforcedRestrictions.AdditionalProperties}}, `
@{Label = "SessionControls_CloudAppSecurity_CloudAppSecurityType"; Expression = { $_.SessionControls.CloudAppSecurity.CloudAppSecurityType}}, `
@{Label = "SessionControls_CloudAppSecurity_IsEnabled"; Expression = { $_.SessionControls.CloudAppSecurity.IsEnabled}}, `
@{Label = "SessionControls_CloudAppSecurity_AdditionalProperties"; Expression = { $_.SessionControls.CloudAppSecurity.AdditionalProperties}}, `
@{Label = "SessionControls_DisableResilienceDefaults"; Expression = { $_.SessionControls.DisableResilienceDefaults}}, `
@{Label = "SessionControls_PersistentBrowser_IsEnabled"; Expression = { $_.SessionControls.PersistentBrowser.IsEnabled}}, `
@{Label = "SessionControls_PersistentBrowser_Mode"; Expression = { $_.SessionControls.PersistentBrowser.Mode}}, `
@{Label = "SessionControls_PersistentBrowser_AdditionalProperties"; Expression = { $_.SessionControls.PersistentBrowser.AdditionalProperties}}, `
@{Label = "SessionControls_SignInFrequency_AuthenticationType"; Expression = { $_.SessionControls.SignInFrequency.AuthenticationType}}, `
@{Label = "SessionControls_SignInFrequency_FrequencyInterval"; Expression = { $_.SessionControls.SignInFrequency.FrequencyInterval}}, `
@{Label = "SessionControls_SignInFrequency_IsEnabled"; Expression = { $_.SessionControls.SignInFrequency.IsEnabled}}, `
@{Label = "SessionControls_SignInFrequency_Type"; Expression = { $_.SessionControls.SignInFrequency.Type}}, `
@{Label = "SessionControls_SignInFrequency_Value"; Expression = { $_.SessionControls.SignInFrequency.Value}}, `
@{Label = "SessionControls_SignInFrequency_AdditionalProperties"; Expression = { $_.SessionControls.SignInFrequency.AdditionalProperties}}, `
@{Label = "SessionControls_AdditionalProperties"; Expression = { $_.SessionControls.AdditionalProperties}}, `
@{Label = "GrantControls_BuiltInControls"; Expression = { $_.GrantControls.BuiltInControls}}, `
@{Label = "GrantControls_Operator"; Expression = { $_.GrantControls.Operator}}, `
@{Label = "GrantControls_CustomAuthenticationFactors"; Expression = { $_.GrantControls.CustomAuthenticationFactors}}, `
@{Label = "GrantControls_TermsOfUse"; Expression = { $_.GrantControls.TermsOfUse}}

Looks better, but still does not solve the Problem of:
- Applications are displayed with the ID (No reference what Application is used)
- User/Group/Roles are displayed with the ObjectID (DisplayName would help here)
Update 05.02.2023
Some People mentioned "DCToolbox"
So i'll gave it a Shot
Find-Module DCToolbox
Install-Module DCToolbox
List all the Commands of the Module
Get-Command -Module DCToolbox
For the Export of the Conditional Access Policies you need an Azure AD Application with a ClientSecret.
In Addition you need another Module:
Install-Module ImportExcel
New-DCConditionalAccessPolicyDesignReport -ClientID <ClientID> -ClientSecret <ClientSecret>
I was finnaly able to Export to Excel
Took me a while to figure out the needet Permissions.
- Agreement.Read.All
- Application.Read.All
- Directory.Read.All
- Group.Read.All
- Policy.Read.All
- Policy.ReadWrite.ConditionalAccess
- User.Read
- user.Read.All
It's a wide Excel Sheet with Columns up to "Y"
It did resolve the Excluded Users but with no Delimiter.
Included Roles where mostly not resolved and also no Delimiter
Another suggestion was
Needs to run in the C:\Scripts Folder due Output is hardcoded that way (can be fixed easy)
Still uses the AzureAD Commandlet's that will be depreciated in Summer 2023
Resolves Names of Users, Roles (sometimes) and Network Locations.
How do you document the Conditional Access Policies?
Regards
Andres Bohren
Wednesday, February 1, 2023
Hi All,
Just a few Hours ago, Microsoft has released the MicrosoftTeams PowerShell Module 4.9.3 to the PowerShell Gallery.
MicrosoftTeams 4.9.3
Microsoft Teams PowerShell Release Notes
Check installed Module and what's available in the PowerShell Gallery
Get-InstalledModule MicrosoftTeams -AllVersions
Find-Module MicrosoftTeams
Uninstall the old Module and install the newest Module
Uninstall-Module MicrosoftTeams
Uninstall-Module MicrosoftTeams
Install-Module MicrosoftTeams
I've already blogged how to set up Azure AD App and Certificate Authentication for Microsoft Teams
Microsoft Teams PowerShell Module 4.7.1-Preview with AzureAD App and Certificate Authentication
How to connect with the Certificate Parameter
$AppID = "93b64305-ea5b-41f2-be0f-a2235fb91480" #DemoTeamsPS
$TenantId = "icewolfch.onmicrosoft.com"
$PFXPassword = ConvertTo-SecureString -String "SecretPFXPassword" -Force -AsPlainText
$PFX = Get-PfxData -FilePath "C:\GIT_WorkingDir\O365Powershell3.pfx" -Password $PFXPassword
$Certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$Certificate = $PFX.EndEntityCertificates[0]
Import-Module MicrosoftTeams
Connect-MicrosoftTeams -ApplicationId $AppID -TenantId $TenantId -Certificate $Certificate
Regards
Andres Bohren
Hi All,
When i started the PowerShell 7 yesterday, it told me that there is a new Version v7.3.2 available.
v7.3.2 Release of PowerShell
I have downloaded the x64 *.msi and these are the Screenshots from the Installation.
I always enable "Enable PowerShell remoting" wich is not enabled by default.
Get-Host
Regards
Andres Bohren
Tuesday, January 31, 2023
Hi All,
Just a few Hours ago, Microsoft has released Microsoft.Graph PowerShell Module 1.21.0.
Microsoft.Graph 1.21.0
https://www.powershellgallery.com/packages/Microsoft.Graph/1.21.0
Let's check the installed Version and what's available on the PowerShell Gallery
Get-InstalledModule Microsoft.Graph
Find-Module Microsoft.Graph
To install the newest Version of the PowerShell Modules and also uninstalling the old Versions, you can use my GitHub Script. It takes a while until all Modules are installed. Wait until "Cleanup finished" is shown.
#Run Script directly from GitHub
$ScriptFromGitHub = Invoke-WebRequest "https://raw.githubusercontent.com/BohrenAn/GitHub_PowerShellScripts/main/ExchangeOnline/GraphAPI/Cleanup-GraphModules.ps1"
Invoke-Expression $($ScriptFromGitHub.Content)
To list the Modules you can use the following Command
Get-Module Microsoft.Graph* -ListAvailable
Regards
Andres Bohren
Monday, January 30, 2023
Hi All,
If you still use "Exchange Online PowerShell with MFA" aka "ExchangeOnline_V1" PowerShell Module - it is time to Upgrade.
Instead of using the ExchangeOnlineManagement V2 i recommend to use the V3 Module wich is GA since a few Months.
ExchangeOnlineManagement 3.1.0
The old PowerShell Module still can be downloaded in the "Classic Exchange Admin Center"
That's the Link on the Desktop
Here's the Info Message you receive when using this PowerShell
Regards
Andres Bohren
Hi All,
Just a few days after its last release, Microsoft has released another Version of the MSIdentityTools PowerShell Module to the Powershell Gallery.
MSIdentityTools 2.0.37
Check what Version of the Module is installed and what's available in the PowerShell Gallery
Get-InstalledModule MSIdentityTools
Find-Module MSIdentityTools
Uninstall the old version of the PowerShell Module and install the newest one
Uninstall-Module MSIdentityTools
Install-Module MSIdentityTools
Get-InstalledModule MSIdentityTools
To see what commands are available use the following command
Get-Command -Module MSIdentityTools
Get Exchange Online Endpoints
Get-MsIdO365Endpoints | where {$_.serviceArea -eq "Exchange"}
Regards
Andres Bohren