MyPSFunctions.AAD.ps1
<#
=========================================================================== Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.196 Created on: 10/26/2023 7:04 PM Created by: John@MyPSFunctions.com Organization: MyPSFunctions Filename: MyPSFunctions.AAD.psm1 ------------------------------------------------------------------------- Module Name: MyPSFunctions.AAD =========================================================================== #> #region MSOLService #################################################### ################ MSOL Service ####################### ################################################### Function Generate-MSOLServicePrincipalReport { [CmdletBinding()] param () $ServicePrincipals = Get-MsolServicePrincipal -All $Table = $Null $Table = @() foreach ($ServicePrincipal in $ServicePrincipals) { $ServicePrincipal_Address = $Null $ServicePrincipal_Address = $ServicePrincipal.addresses.Address $Addresses = $Null $Addresses = $ServicePrincipal_Address -join ";" $DisplayName = $Null $DisplayName = $ServicePrincipal.DisplayName $AppPrincipalId = $Null $AppPrincipalId = $ServicePrincipal.AppPrincipalId $ObjectId = $Null $ObjectId = $ServicePrincipal.ObjectId $ServicePrincipal_ServicePrincipalNames = $Null $ServicePrincipalNames = $Null $ServicePrincipal_ServicePrincipalNames = $ServicePrincipal.ServicePrincipalNames $ServicePrincipalNames = $ServicePrincipal_ServicePrincipalNames -join ";" $TrustedForDelegation = $Null $TrustedForDelegation = $ServicePrincipal.TrustedForDelegation $Table += New-object PSobject -Property ([Ordered] @{ DisplayName = $DisplayName; AppPrincipalId = $AppPrincipalId; ObjectId = $ObjectId; Addresses = $Addresses; ServicePrincipalNames = $ServicePrincipalNames; TrustedForDelegation = $TrustedForDelegation; }) } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFile = ".\MSOL_ServicesPrincipales_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFile -TableName "MSOLServicePrincipals" -Title "MSOL Service Principals" -TitleBold -WorksheetName "MSOLServicePrincipals" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFile" } Function Check-MSOLUserMFAEnrolledDevices { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UPN ) $User = Get-MSolUser -UserPrincipalName $UPN $User.StrongAuthenticationMethods | Ft MethodType, IsDefault } Function Generate-MSOLMFAEnrollmentStatusReport { [CmdletBinding()] param () $MSOLUsers = Get-MsolUser -All [Int]$i = 1 $Table = $Null $Table = @() $Count = ($MSOLUsers | Measure).count ForEach ($MSOLUser in $MSOLUsers) { $DisplayName = $Null $DisplayName = $MSOLUser.DisplayName $UserPrincipalName = $Null $UserPrincipalName = $MSOLUser.UserPrincipalName $StrongAuthenticationMethods = $Null $StrongAuthenticationMethods = $MSOLUser.StrongAuthenticationMethods.methodType -join "," Write-Log -Level Warning -Message "Analyzing User: --- $i/$Count" $Table += New-object PSobject -Property ([Ordered] @{ DisplayName = $DisplayName; UserPrincipalName = $UserPrincipalName; StrongAuthenticationMethods = $StrongAuthenticationMethods; }) $i++ } $Table | ft } Function Export-MSOLAllLicensedUsers { [CmdletBinding()] param () # Backup all MSOLUsers $MSOLUsers = Get-MsolUser -All # Backup all Licensed Users $MSOLUsers_Licensed = $MSOLUsers | where { $_.IsLicensed -eq "True" } # Generate Table for licensed Users #Initiate the Hash Table [Int]$i = 1 $Table = $Null $Table = @() $Count = ($MSOLUsers_Licensed | Measure).count ForEach ($MSOLUser_Licensed in $MSOLUsers_Licensed) { $DisplayName = $Null $DisplayName = $MSOLUser_Licensed.DisplayName $signinName = $Null $signinName = $MSOLUser_Licensed.signinName $Title = $Null $Title = $MSOLUser_Licensed.Title $Department = $Null $Department = $MSOLUser_Licensed.Department $Office = $Null $Office = $MSOLUser_Licensed.Office $City = $Null $City = $MSOLUser_Licensed.City $Country = $Null $Country = $MSOLUser_Licensed.Country $islicensed = $Null $islicensed = $MSOLUser_Licensed.islicensed $lastDirsynctime = $Null $lastDirsynctime = $MSOLUser_Licensed.lastDirsynctime $licenses = $Null $licenses = $MSOLUser_Licensed.licenses.AccountSkuId -join ";" Write-Log -Level Warning -message "The script is analyzing $DisplayName ($signinName)….. --- $i/$Count" $Table += New-object PSobject -Property ([Ordered] @{ DisplayName = $DisplayName; UserName = $signinName; Title = $Title; Department = $Department; Office = $Office; City = $City; Country = $Country; islicensed = $islicensed; lastDirsynctime = $lastDirsynctime; licenses = $licenses; }) $i++ } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFilexlsx = ".\Report_Licensed_Users_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFilexlsx -TableName "LicensedUsers" -Title "Licensed Users" -TitleBold -WorksheetName "LicensedUsers" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFilexlsx" } #endregion #region AAD #################################################### ################ Azure AD ########################### ################################################### Function Get-AADUserGroupMembership { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UPN ) $AADGroups = Get-AzureADUser -SearchString $UPN | Get-AzureADUserMembership [Int]$i = 1 $Table = $Null $Table = @() $Count = ($AADGroups | Measure).count ForEach ($AADGroup in $AADGroups) { $DisplayName = $Null $ObjectType = $Null $MailEnabled = $Null $SecurityEnabled = $Null $Mail = $Null $DirSyncEnabled = $Null $GroupMailenabled = $Null $RecipientTypeDetails = $Null $GroupMailenabled = $Null $DisplayName = $AADGroup.DisplayName $ObjectType = $AADGroup.ObjectType $MailEnabled = $AADGroup.MailEnabled $SecurityEnabled = $AADGroup.SecurityEnabled $DirSyncEnabled = $AADGroup.DirSyncEnabled $Mail = $AADGroup.Mail If ($MailEnabled) { $GroupMailenabled = Get-Recipient $Mail $RecipientTypeDetails = $GroupMailenabled.RecipientTypeDetails } $Table += New-object PSobject -Property ([Ordered] @{ DisplayName = $DisplayName; ObjectType = $ObjectType; MailEnabled = $MailEnabled; GroupType = $RecipientTypeDetails; SecurityEnabled = $SecurityEnabled; DirSyncEnabled = $DirSyncEnabled; Mail = $Mail; }) } $Table | ft } Function Check-AADO365GroupCreationSettings { [CmdletBinding()] param () $GroupUnifiedSetttings = (Get-AzureADDirectorySetting | where { $_.DisplayName -eq "Group.Unified" }).values $GroupCreationAllowedGroupId = ($GroupUnifiedSetttings | where { $_.Name -eq "GroupCreationAllowedGroupId" }).Value $EnableGroupCreation = ($GroupUnifiedSetttings | where { $_.Name -eq "EnableGroupCreation" }).Value $AADGroupName = (Get-AzureADGroup -ObjectId $GroupCreationAllowedGroupId).DisplayName Write-Host "Allowed Office 365 Group Creation Name is: " -NoNewline; Write-host "$AADGroupName" -ForegroundColor Yellow Write-Host "Office 365 Group creation is enabled: " -NoNewline; Write-host "$EnableGroupCreation" -ForegroundColor Yellow } Function Block-AADOffice365GroupCreation { [CmdletBinding()] param ( [Parameter(Mandatory = $false, Position = 1)] [String]$AADGroupName ) if ($AADGroupName) { # Check if group exist $FoundAADGroup = Get-AzureADGroup -SearchString $AADGroupName if (!$FoundAADGroup) { # Create Group if does not exist $NewADGroup = New-AzureADGroup -DisplayName $AADGroupName -MailNickName $AADGroupName -MailEnabled $False -SecurityEnabled $True $AADGroupObjectID = $NewADGroup.objectid } } Else { # Check if group exist $FoundAADGroup = Get-AzureADGroup -SearchString GroupCreationAllowedGroup if (!$FoundAADGroup) { # Create Group if does not exist $NewADGroup = New-AzureADGroup -DisplayName GroupCreationAllowedGroup -MailNickName GroupCreationAllowedGroup -MailEnabled $False -SecurityEnabled $True $AADGroupObjectID = $NewADGroup.objectid If ($NewADGroup) { Write-Host "The Following Azure AD Group has been created: GroupCreationAllowedGroup" } } Else { $AADGroupObjectID = $FoundAADGroup.objectid } } # Update Settings $AllowGroupCreation = "False" $settingsObjectID = (Get-AzureADDirectorySetting | Where-object -Property Displayname -Value "Group.Unified" -EQ).id if (!$settingsObjectID) { $template = Get-AzureADDirectorySettingTemplate | Where-object { $_.displayname -eq "group.unified" } $settingsCopy = $template.CreateDirectorySetting() New-AzureADDirectorySetting -DirectorySetting $settingsCopy $settingsObjectID = (Get-AzureADDirectorySetting | Where-object -Property Displayname -Value "Group.Unified" -EQ).id } $settingsCopy = Get-AzureADDirectorySetting -Id $settingsObjectID $settingsCopy["EnableGroupCreation"] = $AllowGroupCreation if ($GroupName) { $settingsCopy["GroupCreationAllowedGroupId"] = $AADGroupObjectID } else { $settingsCopy["GroupCreationAllowedGroupId"] = $GroupName } Set-AzureADDirectorySetting -Id $settingsObjectID -DirectorySetting $settingsCopy Check-O365GroupCreationSettings } Function Validate-AADCloudOnlyAllOffice365Admins { [CmdletBinding()] param () $Table = $Null $Table = @() #List of Admins Roles $AzureADRoles = $Null Try { $AzureADRoles = Get-AzureADDirectoryRole $Status = "Success" } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Host "Failed to Find the Azure AD Directory Roles" -ForegroundColor Red Write-Host "Failed to run the following CMDLet: $CMDLet" Write-Host "Failed with Error:$ErrorMessage" $Status = "Failed" } #Analyzing AAD Role members Foreach ($AzureADRole in $AzureADRoles) { $AzureADRole_ObjectID = $Null $AzureADRole_ObjectID = $AzureADRole.ObjectID $AzureADRole_DisplayName = $Null $AzureADRole_DisplayName = $AzureADRole.DisplayName $AzureADRoleMembers = $Null Try { $AzureADRoleMembers = Get-AzureADDirectoryRoleMember -objectID $AzureADRole_ObjectID foreach ($AzureADRoleMember in $AzureADRoleMembers) { $AzureADRoleMember_DisplayName = $Null $AzureADRoleMember_DisplayName = $AzureADRoleMember.DisplayName $AzureADRoleMember_UserPrincipalName = $Null $AzureADRoleMember_UserPrincipalName = $AzureADRoleMember.UserPrincipalName $AzureADRoleMember_DirSyncEnabled = $Null $AzureADRoleMember_DirSyncEnabled = $AzureADRoleMember.DirSyncEnabled $AzureADRoleMember_ImmutableId = $Null $AzureADRoleMember_ImmutableId = $AzureADRoleMember.ImmutableId $AzureADRoleMember_LastDirSyncTime = $Null $AzureADRoleMember_LastDirSyncTime = $AzureADRoleMember.LastDirSyncTime $AzureADRoleMember_UserType = $Null $AzureADRoleMember_UserType = $AzureADRoleMember.UserType $CloudOnly = "No" # Check if the user is Cloud Only If (($AzureADRoleMember_DirSyncEnabled -eq $Null) -and ($AzureADRoleMember_ImmutableId -eq $Null) -and ($AzureADRoleMember_LastDirSyncTime -eq $Null)) { $CloudOnly = "Yes" } $Table += New-object PSobject -Property ([Ordered] @{ AzureADRole = $AzureADRole_DisplayName; DisplayName = $AzureADRoleMember_DisplayName; UserPrincipalName = $AzureADRoleMember_UserPrincipalName; UserType = $AzureADRoleMember_UserType; DirSyncEnabled = $AzureADRoleMember_DirSyncEnabled; ImmutableId = $AzureADRoleMember_ImmutableId; LastDirSyncTime = $AzureADRoleMember_LastDirSyncTime; CloudOnly = $CloudOnly; Status = "Member found" }) } } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Host "Failed to get member of the role $AzureADRole_DisplayName" -ForegroundColor Red Write-Host "Failed to run the following CMDLet: $CMDLet" -ForegroundColor Red Write-Host "Failed with Error:$ErrorMessage" -ForegroundColor Red $Table += New-object PSobject -Property ([Ordered] @{ AzureADRole = "Failed to get member"; DisplayName = "Failed to get member"; UserPrincipalName = "Failed to get member"; DirSyncEnabled = "Failed to get member"; ImmutableId = "Failed to get member"; LastDirSyncTime = "Failed to get member"; CloudOnly = "Failed to get member"; Status = "Failed to get member"; }) } } Return $Table } Function Generate-AADRegisteredDevicesReport { Try { $AllAADUsers = Get-AzureADUser -All:$True $AADUsers = $AllAADUsers | Where { ($_.Mail -ne $Null) -and ($_.UserType -eq "Member") } $Status = "Successful" } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to Find All Azure AD users" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" $Status = "Failed" } If ($Status -eq "Successful") { #Initiate the Hash Table [Int]$i = 1 $Table = $Null $Table = @() $Count = ($AADUsers | Measure).count ForEach ($AADUser in $AADUsers) { $UserPrincipalName = $Null $UserPrincipalName = $AADUser.UserPrincipalName $ObjectId = $Null $ObjectId = $AADUser.ObjectId $DisplayName = $Null $DisplayName = $AADUser.DisplayName $Mail = $Null $Mail = $AADUser.Mail $UserType = $Null $UserType = $AADUser.UserType Write-Log -Level Warning -message "The script is analyzing $DisplayName ($UserPrincipalName)….. --- $i/$Count" #Get Registered Device Try { $RegisteredDevices = $Null $RegisteredDevices = Get-AzureADUserRegisteredDevice -All:$true -ObjectId $ObjectId $StatusDevices = "Successful" } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to Find All Registered Devices" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" $StatusDevices = "Failed" } If ($StatusDevices -eq "Successful") { ForEach ($RegisteredDevice in $RegisteredDevices) { $DeviceObjectType = $Null $DeviceObjectType = $RegisteredDevice.ObjectType $ApproximateLastLogonTimeStamp = $Null $ApproximateLastLogonTimeStamp = $RegisteredDevice.ApproximateLastLogonTimeStamp $DeviceDeviceId = $Null $DeviceDeviceId = $RegisteredDevice.DeviceId $DeviceOSVersion = $Null $DeviceOSVersion = $RegisteredDevice.DeviceOSVersion $DeviceOSType = $Null $DeviceOSType = $RegisteredDevice.DeviceOSType $DeviceTrustType = $Null $DeviceTrustType = $RegisteredDevice.DeviceTrustType $DeviceDisplayName = $Null $DeviceDisplayName = $RegisteredDevice.DisplayName $DeviceProfileType = $Null $DeviceProfileType = $RegisteredDevice.ProfileType $Table += New-object PSobject -Property ([Ordered] @{ DisplayName = $DisplayName; UserPrincipalName = $UserPrincipalName; ObjectId = $ObjectId; Mail = $Mail; UserType = $UserType; DeviceDisplayName = $DeviceDisplayName; DeviceObjectType = $DeviceObjectType; DeviceOSType = $DeviceOSType; DeviceOSVersion = $DeviceOSVersion; DeviceTrustType = $DeviceTrustType; DeviceProfileType = $DeviceProfileType; }) } } $i++ } } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFilexlsx = ".\Report_AADRegistedDevices_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFilexlsx -TableName "AADRegisteredDevices" -Title "AAD Registered Devices" -TitleBold -WorksheetName "AADRegisteredDevices" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFilexlsx" } Function Generate-AADServicePrincipalsReport { [CmdletBinding()] param () Try { # Retreive list of Service Principal $AllServicePrincipals = Get-AzureADServicePrincipal -All:$true #Initiate the Hash Table $Table = $Null $Table = @() Foreach ($ServicePrincipal in $AllServicePrincipals) { $ServicePrincipal_ObjectID = $Null $ServicePrincipal_ObjectID = $ServicePrincipal.ObjectID $ServicePrincipal_AppRoleAssignmentRequired = $Null $ServicePrincipal_AppRoleAssignmentRequired = $ServicePrincipal.AppRoleAssignmentRequired $ServicePrincipal_ObjectType = $Null $ServicePrincipal_ObjectType = $ServicePrincipal.ObjectType $ServicePrincipal_ServicePrincipalType = $Null $ServicePrincipal_ServicePrincipalType = $ServicePrincipal.ServicePrincipalType $ServicePrincipal_AccountEnabled = $Null $ServicePrincipal_AccountEnabled = $ServicePrincipal.AccountEnabled $ServicePrincipal_ReplyUrls = $Null $ServicePrincipal_ReplyUrls = $ServicePrincipal.ReplyUrls $ServicePrincipal_ReplyUrls = $ServicePrincipal_ReplyUrls -join ";" $ServicePrincipal_AppDisplayName = $Null $ServicePrincipal_AppDisplayName = $ServicePrincipal.AppDisplayName $ServicePrincipal_Oauth2Permissions = $Null $ServicePrincipal_Oauth2Permissions = $ServicePrincipal.Oauth2Permissions.Value $ServicePrincipal_Oauth2Permissions = $ServicePrincipal_Oauth2Permissions -join ";" $ServicePrincipalRoleAssignments = Get-AzureADServiceAppRoleAssignment -ObjectId $ServicePrincipal_ObjectID Foreach ($ServicePrincipalRoleAssignment in $ServicePrincipalRoleAssignments) { $ServicePrincipalRoleAssignment_CreationTime = $Null $ServicePrincipalRoleAssignment_CreationTime = $ServicePrincipalRoleAssignment.CreationTimestamp $ServicePrincipalRoleAssignment_PrincipalDisplayName = $Null $ServicePrincipalRoleAssignment_PrincipalDisplayName = $ServicePrincipalRoleAssignment.PrincipalDisplayName $ServicePrincipalRoleAssignment_PrincipalID = $Null $ServicePrincipalRoleAssignment_PrincipalID = $ServicePrincipalRoleAssignment.PrincipalID $ServicePrincipalRoleAssignment_PrincipalType = $Null $ServicePrincipalRoleAssignment_PrincipalType = $ServicePrincipalRoleAssignment.PrincipalType Try { $AADObject = $Null $AADObject = Get-AzureADObjectByObjectId -ObjectIds $ServicePrincipalRoleAssignment_PrincipalID $ServicePrincipalRoleAssignment_PrincipalUPN = $Null $ServicePrincipalRoleAssignment_PrincipalUPN = $AADObject.USerPrincipalName } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to Find Service Principal UPN" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" $ServicePrincipalRoleAssignment_PrincipalUPN = "Failed to Find forObjectID: $ServicePrincipalRoleAssignment_PrincipalID " } $Table += New-object PSobject -Property ([Ordered] @{ ServicePrincipal_AppDisplayName = $ServicePrincipal_AppDisplayName; ServicePrincipal_ObjectID = $ServicePrincipal_ObjectID; ServicePrincipal_ObjectType = $ServicePrincipal_ObjectType; ServicePrincipal_ServicePrincipalType = $ServicePrincipal_ServicePrincipalType; ServicePrincipal_AccountEnabled = $ServicePrincipal_AccountEnabled; ServicePrincipal_AppRoleAssignmentRequired = $ServicePrincipal_AppRoleAssignmentRequired; ServicePrincipal_ReplyUrls = $ServicePrincipal_ReplyUrls; ServicePrincipal_Oauth2Permissions = $ServicePrincipal_Oauth2Permissions; ServicePrincipalRoleAssignment_CreationTime = $ServicePrincipalRoleAssignment_CreationTime; ServicePrincipalRoleAssignment_PrincipalDisplayName = $ServicePrincipalRoleAssignment_PrincipalDisplayName; ServicePrincipalRoleAssignment_PrincipalUPN = $ServicePrincipalRoleAssignment_PrincipalUPN; ServicePrincipalRoleAssignment_PrincipalID = $ServicePrincipalRoleAssignment_PrincipalID; ServicePrincipalRoleAssignment_PrincipalType = $ServicePrincipalRoleAssignment_PrincipalType; }) } } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFilexlsx = ".\AzureADServicePrincipals_Report_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFilexlsx -TableName "AADServicePrincipals" -Title "AAD Service Principals" -TitleBold -WorksheetName "AADServicePrincipals" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFilexlsx" } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to Find Azure AD Service Principals" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" Exit } } Function Get-AADUserMembership { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$EmailAddress ) # Find User DN $DN = (Get-Mailbox $EmailAddress).DistinguishedName # Find Mailbox FullAccess Write-Log -Level Warning -Message "Check for FullAccess permission on all Mailboxes:" $AllMailboxes = Get-Mailbox -ResultSize Unlimited $AllMailboxes | Get-MailboxPermission -User $EmailAddress | ft Identity, User, Trustee, AccessControlType, AccessRights # Find Mailbox SendAs Write-Log -Level Warning -Message "Check for SendAs permission on all Mailboxes:" $AllMailboxes | Get-RecipientPermission -Trustee $EmailAddress | ft Identity, Trustee, AccessControlType, AccessRights # Find Mailbox SendOnBehalf Write-Log -Level Warning -Message "Check for SendOnBehalf permission on all Mailboxes:" $AllMailboxes | Where { $_.GrantSendOnBehalfTo -match "'$EmailAddress'" } | ft DisplayName,PrimarySMTPAddress # Find DG managedBy Write-Log -Level Warning -Message "Check for FullAccess permission on all DGs:" Get-DistributionGroup -Filter "ManagedBy -eq '$DN'" } Function Validate-AADUserMembership { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [string]$UPN, [Parameter(Mandatory = $true, Position = 2)] [string]$GroupName ) $AADUser = Get-AzureADUser -Filter "userPrincipalName eq '$UPN'" $AADUser_DisplayName = $AADUser.DisplayName $AADUser_ObjectID = $AADUser.ObjectID $AADGroup = Get-AzureADGroup -Filter "DisplayName eq '$($Name)'" $AADGroupID = $AADGroup.ObjectID $GroupMembership = Get-AzureADUserMembership -ObjectId $AADUser_ObjectID # check if member: $FoundGroupMembershipCount = (($GroupMembership | where { $_.ObjectId -like $AADGroupID }) | Measure).count If ($FoundGroupMembershipCount -eq 1) { Write-Log -Level Warning -Message "The user $AADUser_DisplayName ($UPN) is member of $GroupName" } Else { Write-Log -Level Error -Message "The user $AADUser_DisplayName ($UPN) is NOT member of $GroupName" } } Function Get-AADGroupMember { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$Name ) $AADGroup = $Null $AADGroupID = $Null $AADGroup = Get-AzureADGroup -Filter "DisplayName eq '$($Name)'" $AADGroupID = $AADGroup.ObjectID Write-Host "Search for the Member of the following group:$Name ($AADGroupID) " Get-AzureADGroupMember -ObjectId $AADGroupID -All $true } Function Compare-AADGroupMembershipOfTwoGroups { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [string]$GroupName1, [Parameter(Mandatory = $true, Position = 2)] [string]$GroupName2 ) [Int]$i = 1 $Table = $Null $Table = @() $AADGroup1 = Get-AzureADGroup -SearchString $groupName1 $AADGroup1_ObjectID = $AADGroup1.ObjectID $AADGroup1Members = Get-AzureADGroupMember -ObjectId $AADGroup1_ObjectID -All:$True $AADGroup2 = Get-AzureADGroup -SearchString $GroupName2 $AADGroup2_ObjectID = $AADGroup2.ObjectID $Count = ($AADGroup1Members | Measure).count foreach ($AADGroup1Member in $AADGroup1Members) { $UserprincipalName = $Null $UserprincipalName = $AADGroup1Member.UserprincipalName Write-Log -Level Warning -message "The script is analyzing $UserprincipalName….. --- $i/$Count" $AADUserMembership = $Null $AADUserMembership = Get-AzureADUserMembership -ObjectId $UserprincipalName $MembershipFound = $Null $MembershipFound = $AADUserMembership | where{ $_.ObjectID -eq $AADGroup2_ObjectID } if ($MembershipFound) { $Found = $True } Else { $Found = $False } $Table += New-object PSobject -Property ([Ordered] @{ UserprincipalName = $UserprincipalName; Members = $Found; }) $i++ } Return $Table } Function HardMatch-AADDuplicateCloudAccount { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$OnpremiseUPN, [Parameter(Mandatory = $true, Position = 2)] [String]$CloudUPN ) Read-Host "Please validate you are connect to Azure AD powershell module" #Retreive AAD users Info Write-Log -Level INFO -message "The Hard Match need to happens between to AD connect Sync cycle, please find the next:" Check-ADConnectLastSync Read-Host "Pause to check Last and Next AD Connect Sync" Try { Write-Log -Level INFO -message "Retreiving AAD information about $OnpremiseUPN & $CloudUPN from AAD" $Cloud_AADUser = Get-azureaduser -SearchString $CloudUPN $Onpremise_AADUser = Get-azureaduser -SearchString $OnpremiseUPN Write-Log -Level warning -message "Retreived AAD information about $OnpremiseUPN & $CloudUPN from AAD" } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line Write-Log -Level Error -message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -message "Failed with Error:$ErrorMessage" Write-Log -Level Error -message "Failed to retreive AAD Users information" Exit } # Variable $OnpremiseObjectID = $Onpremise_AADUser.Objectid $OnpremiseImmutableID = $Onpremise_AADUser.immutableID $CloudObjectID = $Cloud_AADUser.Objectid Write-Log -Level INFO -message "$CloudUPN has the following ObjectID: $CloudObjectID" Write-Log -Level INFO -message "$OnpremiseUPN has the following ObjectID: $OnpremiseObjectID" Write-Log -Level INFO -message "$OnpremiseUPN has the following immutableID: $OnpremiseImmutableID" Read-Host "Pause after collecting required data - Continue to permanent deleted Onpremise Account $OnpremiseUPN" # Delete OnpremiseAccount Try { Write-Log -Level INFO -message "Removing $OnpremiseUPN from AAD" Remove-AzureADUser -ObjectId $OnpremiseObjectID Sleep 10 Remove-AzureADMSDeletedDirectoryObject -Id $OnpremiseObjectID Sleep 10 Write-Log -Level warning -message "Removed $OnpremiseUPN from AAD" } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line Write-Log -Level Error -message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -message "Failed with Error:$ErrorMessage" Write-Log -Level Error -message "Failed to remove $OnpremiseUPN from AAD" Exit } #Update ImmutableID Try { Write-Log -Level INFO -message "updating ImmutableID for $OnpremiseUPN" Set-AzureADUser -ObjectId $CloudObjectID -ImmutableId $OnpremiseImmutableID Write-Log -Level warning -message "updated ImmutableID for $OnpremiseUPN" } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line Write-Log -Level Error -message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -message "Failed with Error:$ErrorMessage" Write-Log -Level Error -message "Failed to update ImmutableID for $OnpremiseUPN" } Sleep 10 # Set immutableID Try { Write-Log -Level INFO -message "Update Cloud User UPN ($CloudUPN) to $OnpremiseUPN" Set-AzureADUser -ObjectId $CloudObjectID -UserPrincipalName $OnpremiseUPN Write-Log -Level warning -message "Updated Cloud User UPN ($CloudUPN) to $OnpremiseUPN" } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line Write-Log -Level Error -message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -message "Failed with Error:$ErrorMessage" Write-Log -Level Error -message "Failed to Update Cloud User UPN ($CloudUPN) to $OnpremiseUPN" } # Display Immutable ID: $AADUserAfter = Get-azureaduser -SearchString $OnpremiseUPN $AADUser_ObjectID = $AADUserAfter.Objectid $AADUser_ImmutableID = $AADUserAfter.immutableID Write-Log -Level warning -message "The Onpremise User: UPN:$OnpremiseUPN - ObjectID: $OnpremiseObjectID - ImmutableID: $OnpremiseImmutableID" Write-Log -Level warning -message "The Cloud User: UPN:$OnpremiseUPN (old UPN: $CloudUPN) - ObjectID: $AADUser_ObjectID - ImmutableID: $AADUser_ImmutableID" } Function Find-AADApplication { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$Name ) Get-AzureADApplication -All:$True | where { $_.DisplayName -like "*$Name*" } | select DisplayName, ReplyUrls, ObjectId, AppId } Function Update-ADDynamicGroupMember { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$Name ) $AzureADGroup = Get-AzureADGroup -SearchString $Name $AzureADGroupID = $AzureADGroup.ObjectId Get-AzureADMSGroup -Id $AzureADGroupID | select DisplayName, MembershipRuleProcessingState, GroupTypes, MembershipRule Write-Host "The Function will paused the Rule Processing" -ForegroundColor Red Set-AzureADMSGroup -Id $AzureADGroupID -MembershipRuleProcessingState "Paused" Get-AzureADMSGroup -Id $AzureADGroupID | select DisplayName, MembershipRuleProcessingState Write-Host "The Function will paused the Rule Processing" -ForegroundColor Green Set-AzureADMSGroup -Id $AzureADGroupID -MembershipRuleProcessingState "On" Get-AzureADMSGroup -Id $AzureADGroupID | select DisplayName, MembershipRuleProcessingState Write-Host "Wait 15 min for Azure AD to process the Rule Membership of this Group" -ForegroundColor Yellow } Function Update-ADUserPasswordNeverExpires { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UPN, [Parameter(Position = 2)] [switch]$Enable, [Parameter(Position = 3)] [switch]$Disable ) # Check Status before : $BeforePasswordNeverExpires = $Null $BeforePasswordNeverExpires = Get-AzureADUser -ObjectId $UPN | Select-Object UserprincipalName, @{ N = "PasswordNeverExpires"; E = { $_.PasswordPolicies -contains "DisablePasswordExpiration" } } Write-Host "Password Never Expires settings for " -NoNewline; Write-Host "$UPN " -ForegroundColor Red -NoNewline; Write-Host "(After):" -ForegroundColor Green $BeforePasswordNeverExpires | ft If ($Enable) { Set-AzureADUser -ObjectId $UPN -PasswordPolicies DisablePasswordExpiration } If ($Disable) { Set-AzureADUser -ObjectId $UPN -PasswordPolicies None } # Check Status After: $AfterPasswordNeverExpires = $Null $AfterPasswordNeverExpires = Get-AzureADUser -ObjectId $UPN | Select-Object UserprincipalName, @{ N = "PasswordNeverExpires"; E = { $_.PasswordPolicies -contains "DisablePasswordExpiration" } } Write-Host "Password Never Expires settings for " -NoNewline; Write-Host "$UPN " -ForegroundColor Red -NoNewline; Write-Host "(After):" -ForegroundColor Yellow $AfterPasswordNeverExpires | ft } Function Get-AADUserDirectReport { param ( [Parameter(Mandatory = $true, Position = 1)] [string]$Identity ) #Search for Azure AD Connect $AzureADUser = Get-AzureADUser -SearchString $Identity | select -First 1 $ObjectID = $Null $ObjectID = $AzureADUser.ObjectID $DisplayName = $Null $DisplayName = $AzureADUser.DisplayName $UPN = $Null $UPN = $AzureADUser.UserPrincipalName Write-Host "The script found user with: DisplayName: $DisplayName and with UPN: $UPN - ObjectID: $ObjectID" # Check User Direct Report $DirectReport = $Null $DirectReport = Get-AzureADUserDirectReport -ObjectId $ObjectID $DirectReport | Ft DisplayName, UserPrincipalName, ObjectID } Function Get-AADGroupMembersDetails { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$GroupName ) $AAGroup = Get-AzureADGroup -SearchString $GroupName $AADGroup_ObjectID = $AAGroup.ObjectID $AADGroupMembers = Get-AzureADGroupMember -ObjectId $AADGroup_ObjectID -All:$true [Int]$i = 1 $Table = $Null $Table = @() $Count = ($AADGroupMembers | Measure).count ForEach ($AADGroupMember in $AADGroupMembers) { $UserPrincipalName = $Null $UserPrincipalName = $AADGroupMember.UserPrincipalName $DisplayName = $Null $DisplayName = $AADGroupMember.DisplayName $Recipient = $Null $Recipient = Get-Recipient $UserPrincipalName Write-Log -Level Warning -message "The script is analyzing $DisplayName ($UserPrincipalName)….. --- $i/$Count" $City = $Recipient.City $Department = $Recipient.Department $FirstName = $Null $FirstName = $Recipient.FirstName $LastName = $Null $LastName = $Recipient.LastName $Office = $Null $Office = $Recipient.Office $Title = $Null $Title = $Recipient.Title $CustomAttribute5 = $Null $CustomAttribute5 = $Recipient.CustomAttribute5 $CustomAttribute7 = $Null $CustomAttribute7 = $Recipient.CustomAttribute7 $CustomAttribute13 = $Null $CustomAttribute13 = $Recipient.CustomAttribute13 $CustomAttribute14 = $Null $CustomAttribute14 = $Recipient.CustomAttribute14 $CustomAttribute15 = $Null $CustomAttribute15 = $Recipient.CustomAttribute15 $Table += New-object PSobject -Property ([Ordered] @{ FirstName = $FirstName; LastName = $LastName; UserPrincipalName = $UserPrincipalName; Department = $Department; City = $City; Office = $Office; Title = $Title; CustomAttribute5 = $CustomAttribute5; CustomAttribute7 = $CustomAttribute7; CustomAttribute13 = $CustomAttribute13; CustomAttribute14 = $CustomAttribute14; CustomAttribute15 = $CustomAttribute15; }) $i++ } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFilexlsx = ".\Report_Users_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFilexlsx -TableName "Users" -Title "Users" -TitleBold -WorksheetName "Users" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFilexlsx" } Function Add-AADUserToAADGroup { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$GroupName, [Parameter(Mandatory = $true, Position = 2)] [String]$UserEmailAddress ) $AADGroup = Get-AzureADGroup -SearchString $GroupName $AADGroup = $AADGroup | where { $_.DisplayName -eq $GroupName } $AADGroup_ObjectID = $AADGroup.ObjectID $AADUser = Get-AzureADUser -Filter "userPrincipalName eq '$UserEmailAddress'" $AADUser_DisplayName = $AADUser.DisplayName $AADUser_ObjectID = $AADUser.ObjectID Try { Add-AzureADGroupMember -ObjectId $AADGroup_ObjectID -RefObjectId $AADUser_ObjectID $Status = "Success" } Catch { $ErrorMessage = $Error[0].Exception.Message If ($ErrorMessage -like "*members*") { $Status = "Failed - already members" } Else { $Status = "Failed - $ErrorMessage " } } $OutPutMessage = $null $OutPutMessage = @() $OutPutMessage += New-object PSobject -Property ([Ordered] @{ EmailAddress = $UserEmailAddress; Group = $GroupName; Action = "Add"; Status = $Status; }) Return $OutPutMessage } Function Add-AADUserToAADGroupCSV { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [string]$GroupName, [Parameter(Mandatory = $true, Position = 2)] [String]$CSVFile ) Read-Host "Expected CSV Column:EmailAddress" $Users = Import-Csv $CSVFile $Count = ($Users | Measure).count [Int]$i = 1 $Table = $Null $Table = @() Foreach ($User in $Users) { $UserEmailAddress = $Null $UserEmailAddress = $User.EmailAddress Write-Host "User $UserEmailAddress will be added to Group $GroupName --- $i/$Count" $UserOutput = $Null $UserOutput = @() $UserOutput = Add-AADUserToAADGroup -GroupName $GroupName -UserEmailAddress $UserEmailAddress If ($UserOutput.Status -like "*Failed*") { $Color = "Red" } Else { $Color = "Green" } Write-Host "Script try to add: $UserEmailAddress to $GroupName - Status: " -NoNewline; write-host $UserOutput.Status -ForegroundColor $Color $Table += New-object PSobject -Property ([Ordered] @{ GroupName = $GroupName; UserName = $UserEmailAddress; Action = $UserOutput.Action; Status = $UserOutput.Status; }) $i++ } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFilexlsx = ".\Report_Users_Added_To_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFilexlsx -TableName "AddedUsers" -Title "Added Users" -TitleBold -WorksheetName "AddedUsers" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFilexlsx" } Function Remove-AADUserToAADGroup { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$GroupName, [Parameter(Mandatory = $true, Position = 2)] [String]$UserEmailAddress ) $AADGroup = Get-AzureADGroup -SearchString $GroupName $AADGroup = $AADGroup | where { $_.DisplayName -eq $GroupName } $AADGroup_ObjectID = $AADGroup.ObjectID $AADUser = Get-AzureADUser -Filter "userPrincipalName eq '$UserEmailAddress'" $AADUser_DisplayName = $AADUser.DisplayName $AADUser_ObjectID = $AADUser.ObjectID Try { Remove-AzureADGroupMember -ObjectId $AADGroup_ObjectID -MemberId $AADUser_ObjectID $Status = "Success" } Catch { $ErrorMessage = $Error[0].Exception.Message If ($ErrorMessage -like "*Request_ResourceNotFound*") { $Status = "Failed - Not member" } Else { $Status = "Failed - $ErrorMessage " } } $OutPutMessage = $null $OutPutMessage = @() $OutPutMessage += New-object PSobject -Property ([Ordered] @{ EmailAddress = $UserEmailAddress; Group = $GroupName; Action = "Remove"; Status = $Status; }) Return $OutPutMessage } Function Remove-AADUserToAADGroupCSV { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [string]$GroupName, [Parameter(Mandatory = $true, Position = 2)] [String]$CSVFile ) Read-Host "Expected CSV Column: EmailAddress" $Users = Import-Csv $CSVFile $Count = ($Users | Measure).count [Int]$i = 1 $Table = $Null $Table = @() Foreach ($User in $Users) { $UserEmailAddress = $Null $UserEmailAddress = $User.EmailAddress Write-Host "User $UserEmailAddress will be removed to Group $GroupName --- $i/$Count" $UserOutput = $Null $UserOutput = @() $UserOutput = Remove-AADUserToAADGroup -GroupName $GroupName -UserEmailAddress $UserEmailAddress If ($UserOutput.Status -like "*Failed*") { $Color = "Red" } Else { $Color = "Green" } Write-Host "Script try to remove: $UserEmailAddress to $GroupName - Status: " -NoNewline; write-host $UserOutput.Status -ForegroundColor $Color $Table += New-object PSobject -Property ([Ordered] @{ GroupName = $GroupName; UserName = $UserEmailAddress; Action = $UserOutput.Action; Status = $UserOutput.Status; }) $i++ } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFilexlsx = ".\Report_Users_Removed_To_" + $GroupName + "_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFilexlsx -TableName "RemovedUsers" -Title "Removed Users" -TitleBold -WorksheetName "RemovedUsers" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFilexlsx" } Function Add-AADUsersToAADGroupFromCSV { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$GroupName, [Parameter(Mandatory = $true, Position = 2)] [String]$CSVfile ) Read-Host "Expected CSV Column: PrimaryEmailAddress" $Users = Import-Csv $CSVfile Foreach ($User in $Users) { $Primary = $Null $Primary = $User.PrimaryEmailAddress $Recipient = Get-recipient $Primary $WindowsLiveID = $Null $WindowsLiveID = $Recipient.WindowsLiveID Add-AADUserToAADGroup -GroupName $GroupName -UserEmailAddress $WindowsLiveID } } Function Export-AADGroupMembers { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$SourceGroupName ) $SourceAADGroup = Get-AzureADGroup -SearchString $SourceGroupName $SourceGroupID = $SourceAADGroup.ObjectID $SourceGroupMembers = Get-AzureADGroupMember -ObjectId $SourceGroupID -All:$True $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $SourceGroupMembersFile = ".\Report_Members_Of_" + $SourceGroupName + "_" + $DateFull + ".xlsx" $SourceGroupMembers | select DisplayName, UserPrincipalName | Export-Excel $SourceGroupMembersFile -TableName "MemberOf" -Title "MemberOf" -TitleBold -WorksheetName "MemberOf" -TableStyle Medium9 -AutoSize -AutoFilter Write-Host "Generate the following Report: $SourceGroupMembersFile" } Function Get-AADUserPasswordNeverExpires { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [string]$UPN ) $PasswordNeverExpires = $Null $PasswordNeverExpires = Get-AzureADUser -ObjectId $UPN | Select-Object UserprincipalName, @{ N = "PasswordNeverExpires"; E = { $_.PasswordPolicies -contains "DisablePasswordExpiration" } } $PasswordNeverExpires | ft } Function Revoke-AADToken { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [string]$UPN ) $User = Get-AzureADUser -ObjectId $UPN $DisplayName = $User.DisplayName $ObjectID = $User.ObjectID Write-Host "the script find the user: $DisplayName (UPN:$UPN) with the following ObjectID: $ObjectID" Read-Host "Are you sure you want to revoke all Azure Tokens of $DisplayName? Press Any Key to continue or CTRL+C to Cancel" Revoke-AzureADUserAllRefreshToken -ObjectId $ObjectID Write-Host "The script Revoke the Token for $UPN " } Function Disable-AADAccount { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [string]$UPN ) # Find User Try { $User = Get-AzureADUser -ObjectId $UPN $DisplayName = $User.DisplayName $ObjectID = $User.ObjectID Write-Host "The script find the user: $DisplayName (UPN:$UPN) with the following ObjectID: $ObjectID" -ForegroundColor Green Read-Host "Are you sure you want to Disable the AAD Account & revoke all Azure Tokens of $DisplayName? Press Any Key to continue or CTRL+C to Cancel" } Catch { $ErrorMessage = $Error[0].Exception.Message; Write-Host "Failed with Error:$ErrorMessage" -ForegroundColor Red } # Disable AAD Account Try { Set-AzureADUser -ObjectId $UPN -AccountEnabled $false Write-Host "The script disabled AAD Account $UPN" -ForegroundColor green } Catch { $ErrorMessage = $Error[0].Exception.Message; Write-Host "Failed with Error:$ErrorMessage" -ForegroundColor Red } # Revoke AAD Tokens Try { Revoke-AzureADUserAllRefreshToken -ObjectId $ObjectID Write-Host "The script revoke all tokens for $UPN" -ForegroundColor Green } Catch { $ErrorMessage = $Error[0].Exception.Message; Write-Host "Failed with Error:$ErrorMessage" -ForegroundColor Red } } Function Report-AADLicenseM365E3Group { [CmdletBinding()] param () Try { # Get All users who has M365E3 licenses $AllLicensedAADUsersCount = $Null $AllAzureADUsers = $Null $AllLicensedAADUsers = Get-AzureADUser -All: $True | where { $_.AssignedLicenses.Skuid -eq "05e9a617-0261-4cee-bb44-138d3ef5d965" } $AllLicensedAADUsersCount = ($AllLicensedAADUsers | Measure).count Write-Log -Level info -Message "AAD Users Found: $AllLicensedAADUsersCount" # Collect members of SG-ICTD-LIC-M365 Baseline $Members_Of_SG_ICTD_LIC_M365_Baseline = Get-AzureADGroupMember -All:$True -ObjectId "3c7418ca-5e15-495d-95ec-203c996e3551" $Members_Of_SG_ICTD_LIC_M365_BaselineCount = ($Members_Of_SG_ICTD_LIC_M365_Baseline | Measure).count Write-Log -Level info -Message "Members Of SG_ICTD_LIC_M365_Baseline Found: $Members_Of_SG_ICTD_LIC_M365_BaselineCount" # Collect members of SG-ICTD-LIC-M365 Baseline No MyAnalitics $Members_Of_SG_ICTD_LIC_M365_Baseline_No_MyAnalitics = Get-AzureADGroupMember -All:$True -ObjectId "0c17c388-60c2-401e-b624-98ad10e10084" $Members_Of_SG_ICTD_LIC_M365_Baseline_No_MyAnaliticsCount = ($Members_Of_SG_ICTD_LIC_M365_Baseline_No_MyAnalitics | Measure).count Write-Log -Level info -Message "Members Of SG_ICTD_LIC_M365_Baseline_No_MyAnalitics Found: $Members_Of_SG_ICTD_LIC_M365_Baseline_No_MyAnaliticsCount" # Collect members of SG-ICTD-M365 Rooms $Members_Of_SG_ICTD_LIC_M365_Rooms = Get-AzureADGroupMember -All:$True -ObjectId "1eb5c497-be2e-4413-9ed4-1da20e9e58ac" $Members_Of_SG_ICTD_LIC_M365_RoomsCount = ($Members_Of_SG_ICTD_LIC_M365_Rooms | Measure).count Write-Log -Level info -Message "Members Of SG_ICTD_LIC_M365_Rooms Found: $Members_Of_SG_ICTD_LIC_M365_RoomsCount" } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to collect information about all Azure AD Users" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" Exit } [Int]$i = 1 $Table = $Null $Table = @() foreach ($LicensedAADUser in $AllLicensedAADUsers) { $UPN = $Null $UPN = $LicensedAADUser.UserPrincipalName Write-Log -Level Warning -message "The script is analyzing $UPN….. --- $i/$AllLicensedAADUsersCount" # Check if the user is licensed for E1: If ($LicensedAADUser.AssignedLicenses.Skuid -eq "18181a46-0d4e-45cd-891e-60aabd171b4e") { $LicensedOffice365E1 = $True } Else { $LicensedOffice365E1 = $False } # Check member of SG_ICTD_LIC_M365_Baseline Try { $Member_Of_SG_ICTD_LIC_M365_Baseline = $false $M365_BaselineFounds = $Null $M365_BaselineCount = $Null $M365_BaselineFounds = $Members_Of_SG_ICTD_LIC_M365_Baseline | where { $_.UserPrincipalName -eq $UPN } $M365_BaselineCount = ($M365_BaselineFounds | Measure).count If ($M365_BaselineCount -ge 1) { Write-Log -Level Warning -Message "$UPN is member of SG_ICTD_LIC_M365_Baseline" $Member_Of_SG_ICTD_LIC_M365_Baseline = $True } } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to Get Member" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" $Member_Of_SG_ICTD_LIC_M365_Baseline = "Failed - $ErrorMessage" } # Check member of SG_ICTD_LIC_M365_Baseline_No_MyAnalitics Try { $Member_Of_SG_ICTD_LIC_M365_Baseline_No_MyAnalitics = $false $M365_Baseline_No_MyAnaliticsFounds = $Null $M365_Baseline_No_MyAnaliticsCount = $Null $M365_Baseline_No_MyAnaliticsFounds = $Members_Of_SG_ICTD_LIC_M365_Baseline_No_MyAnalitics | where { $_.UserPrincipalName -eq $UPN } $M365_Baseline_No_MyAnaliticsCount = ($M365_Baseline_No_MyAnaliticsFounds | Measure).count If ($M365_Baseline_No_MyAnaliticsCount -ge 1) { Write-Log -Level Warning -Message "$UPN is member of SG_ICTD_LIC_M365_Baseline_No_MyAnalitics" $Member_Of_SG_ICTD_LIC_M365_Baseline_No_MyAnalitics = $True } } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to Get Member" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" $Member_Of_SG_ICTD_LIC_M365_Baseline_No_MyAnalitics = "Failed - $ErrorMessage" } # Check member of SG_ICTD_LIC_M365_Rooms Try { $Member_Of_SG_ICTD_LIC_M365_Rooms = $false $M365_RoomsFounds = $Null $M365_RoomsCount = $Null $M365_RoomsFounds = $Members_Of_SG_ICTD_LIC_M365_Rooms | where { $_.UserPrincipalName -eq $UPN } $M365_RoomsCount = ($M365_RoomsFounds | Measure).count If ($M365_RoomsCount -ge 1) { Write-Log -Level Warning -Message "$UPN is member of SG_ICTD_LIC_M365_Baseline" $Member_Of_SG_ICTD_LIC_M365_Rooms = $True } } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to Get Member" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" $Member_Of_SG_ICTD_LIC_M365_Rooms = "Failed - $ErrorMessage" } $Table += New-object PSobject -Property ([Ordered] @{ UPN = $UPN; Member_Of_SG_ICTD_LIC_M365_Baseline = $Member_Of_SG_ICTD_LIC_M365_Baseline; Member_Of_SG_ICTD_LIC_M365_Baseline_No_MyAnalitics = $Member_Of_SG_ICTD_LIC_M365_Baseline_No_MyAnalitics; Member_Of_SG_ICTD_LIC_M365_Rooms = $Member_Of_SG_ICTD_LIC_M365_Rooms; LicensedOffice365E1 = $LicensedOffice365E1; }) $i++ } # Generate a Table based check if user are members of any Baseline Group $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFilexlsx = ".\Report_Licensed_Users_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFilexlsx -TableName "LicensedUsers" -Title "Licensed Users" -TitleBold -WorksheetName "LicensedUsers" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFilexlsx" } Function Collect-AADLicensedUsersDetails_fromGroup { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$GroupName ) # Find GroupID Try { Write-Log -Level Info -Message "Searching for group with Name: $GroupName" $GroupNames = $Null $GroupNames = Get-AzureADGroup -SearchString $GroupName $GroupID = $Null $GroupID = ($GroupNames | where { $_.DisplayName -eq $GroupName }).ObjectId Write-Log -Level warning -Message "Find the group with Name: $GroupName (ObjectID: $GroupID)" # Retrieve Group Members Try { Write-Log -Level Info -Message "Retrieving Group member of $GroupName (ObjectID: $GroupID)" $GroupMembers = $Null $GroupMembers = Get-AzureADGroupMember -ObjectId $GroupID -All $True $GroupMembersCount = ($GroupMembers | Measure).count Write-Log -Level info -Message "Number of Group member of $GroupName (ObjectID: $GroupID): $GroupMembersCount" #Initiate the Hash Table [Int]$i = 1 $Table = $Null $Table = @() } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to find AAD Group with the following Name : $GroupName" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" } # format Data Foreach ($GroupMember in $GroupMembers) { #Clear Variable $Mail = $Null $DisplayName = $Null $JobTitle = $Null $Country = $Null $Department = $Null $City = $Null $CompanyName = $Null $UsageLocation = $Null $UserPrincipalName = $Null $PERNR = $Null $StaffLevel = $Null $StaffCategory = $Null $IndexNumber = $Null $DutyStationCountryName = $Null $UserType = $Null # Set variable $Mail = $GroupMember.Mail $DisplayName = $GroupMember.DisplayName $JobTitle = $GroupMember.JobTitle $Country = $GroupMember.Country $Department = $GroupMember.Department $City = $GroupMember.City $CompanyName = $GroupMember.CompanyName $UsageLocation = $GroupMember.UsageLocation $UserPrincipalName = $GroupMember.UserPrincipalName # Write-Log -Level Warning -message "The script is analyzing $DisplayName ($UserPrincipalName) ….. --- $i/$Count" $Table += New-object PSobject -Property ([Ordered] @{ DisplayName = $DisplayName; Mail = $Mail; UserPrincipalName = $UserPrincipalName; UserType = $UserType; JobTitle = $JobTitle; Department = $Department; StaffLevel = $StaffLevel; StaffCategory = $StaffCategory; IndexNumber = $IndexNumber; CompanyName = $CompanyName; City = $City; Country = $Country; DutyStationCountryName = $DutyStationCountryName; UsageLocation = $UsageLocation; PERNR = $PERNR; }) $i++ } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFile = ".\LicensedUsersDetailed_fromGroup_" + $GroupName + "_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFile -TableName "LicensedUsers" -Title "Licensed Users" -TitleBold -WorksheetName "LicensedUsers" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFile" } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to find AAD Group with the following Name : $GroupName" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" } } Function Check-AADLicenseForUser { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UserPrincipalName ) $AssignedLicenses = $Null $AssignedLicenses = @() $AzureADUser = Get-AzureADUser -ObjectId $UserPrincipalName $LicenseSkuId = $AzureADUser.AssignedLicenses.SkuId $AllSKUs = Get-AzureADSubscribedSku # Skuid -eq SkuPartNumber Foreach ($LicenseFound in $LicenseSkuId) { foreach ($Sku in $AllSKUs) { $SkuID = $Sku.SkuID if ($SkuID -eq $LicenseFound) { $SkuPartNumber = $Sku.SkuPartNumber $License = $Sku | select SkuID, SkuPartNumber $AssignedLicenses += $License } } } Return $AssignedLicenses } Function Add-AADLicenseToUser { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UserPrincipalName, [Parameter(Mandatory = $true, Position = 1)] [String]$SKUPartName, [Parameter(Mandatory = $true, Position = 1)] [String]$UsageLocation ) Set-AzureADUser -ObjectId $UserPrincipalName -UsageLocation $UsageLocation # Create the objects we'll need to add and remove licenses $license = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicense $licenses = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicenses # Find the SkuID of the license we want to add - in this example we'll use the O365_BUSINESS_PREMIUM license $license.SkuId = (Get-AzureADSubscribedSku | Where-Object -Property SkuPartNumber -Value $SKUPartName -EQ).SkuID # Set the Office license as the license we want to add in the $licenses object $licenses.AddLicenses = $license # Call the Set-AzureADUserLicense cmdlet to set the license. Set-AzureADUserLicense -ObjectId $UserPrincipalName -AssignedLicenses $licenses } Function Remove-AADLicenseToUser { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UserPrincipalName, [Parameter(Mandatory = $true, Position = 2)] [String]$SkuPartName ) $Licenses.AddLicenses = @() $Licenses.RemoveLicenses = (Get-AzureADSubscribedSku | Where-Object -Property SkuPartNumber -Value $SkuPartName -EQ).SkuID Set-AzureADUserLicense -ObjectId $UserPrincipalName -AssignedLicenses $licenses } Function Generate-AADLicensesSKUsTable { $Table = $Null $Table = @() $SKUs = Get-AzureADSubscribedSku [int]$i = 0 ForEach ($SKU in $SKUs) { #$MaxLicence =$null $MaxLicence = $SKU.PrepaidUnits.Enabled #$LicenceUsed = $null $LicenceUsed = $SKU.ConsumedUnits #$Name = $Null $Name = $SKU.SkuPartNumber $RemainingLicence = $MaxLicence - $LicenceUsed $Table += New-object PSobject -Property ([Ordered] @{ DisplayName = $Name; MaxLicence = $MaxLicence; LicenceUsed = $LicenceUsed; RemainingLicence = $RemainingLicence; }) $i++ } $Table } #endregion #region ADConnect #################################################### ################ AD Connect ########################## ################################################### Function Start-AADConnectSync { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$Server, [Switch]$Full, [Parameter(HelpMessage = 'To be use if your Current User does NOT have permission to open a Remote PS session')] [String]$AlternateID ) Write-Log warning -Message "Establishing a Remote PSSession to $Server" If ($AlternateID) { $ADConnectCredential = Get-Credential -Credential $AlternateID $ADConnectPSSession = New-PSSession -ComputerName $Server -Credential $ADConnectCredential -ErrorVariable ADConnectPSSessionErrorVariable -ErrorAction SilentlyContinue } Else { $ADConnectPSSession = New-PSSession -ComputerName $Server -ErrorVariable ADConnectPSSessionErrorVariable -ErrorAction SilentlyContinue } If ($ADConnectPSSessionErrorVariable) { Write-Log Error -Message "Fail to create the PSSession to $Server" } Else { Write-Log Info -Message "Succesfully create the PSSession to $Server" If ($Full) { Invoke-Command -Session $ADConnectPSSession -ScriptBlock { Start-ADSyncSyncCycle -PolicyType initial } -ErrorVariable ADConnectErrorVariable -ErrorAction SilentlyContinue If ($ADConnectErrorVariable) { If ($ADConnectErrorVariable -like "*busy*") { Write-Log warning -Message "Sync already running" } Else { Write-Log Error -Message "Failed to run AD ConnectFull Sync" Write-Log Error -Message "Failed with Error:" $ADConnectErrorVariable } } Else { Write-Log Info -Message "The Full Sync is running" } } Else { Invoke-Command -Session $ADConnectPSSession -ScriptBlock { Start-ADSyncSyncCycle -PolicyType Delta } -ErrorVariable ErrorVariable -ErrorAction SilentlyContinue If ($ErrorVariable) { If ($ErrorVariable -like "*busy*") { Write-Log Error -Message "Sync already running" } Else { Write-Log Error -Message "Failed to run AD Connect Delta Sync" Write-Log Error -Message "Failed with Error:" $ErrorVariable } } Else { Write-Log Info -Message "Delta Sync is running" } } } } Function Check-AADConnectLastSync { $AzureAdTenantDetails = Get-AzureADTenantDetail | select CompanyLastDirSyncTime $Time = $AzureAdTenantDetails.CompanyLastDirSyncTime $NextTime = $Time.Addminutes(30) $ToTimeZoneObj = [system.timezoneinfo]::GetSystemTimeZones() | Where-Object { $_.id -eq "Eastern Standard Time" } $TargetZoneTime = [system.timezoneinfo]::ConvertTime($Time, $ToTimeZoneObj) $NextTargetZoneTime = [system.timezoneinfo]::ConvertTime($NextTime, $ToTimeZoneObj) Write-host "The Last Synchronization was : " -NoNewline; Write-host "$TargetZoneTime" -ForegroundColor Green Write-host "The Next Synchronization will be at : " -NoNewline; Write-host "$NextTargetZoneTime" -ForegroundColor Yellow } Function Check-AADUserLastSync { param ( [Parameter(Mandatory = $true, Position = 1)] [string]$UserName ) $AzureADUserLastSync = Get-AzureADUser -ObjectId $UserName | Select DisplayName, Mail, MailNickName, LastDirSyncTime $AzureADUserLastSync } #endregion |