From 66110cf376a5a718b9f777d283aa8e6afb25e687 Mon Sep 17 00:00:00 2001 From: Kyle Pope Date: Mon, 6 Oct 2025 15:47:00 +0800 Subject: [PATCH] expanded directory and added 365 group copy scripts --- Cloud/Microsoft365/IAM/Copy-User365Groups.ps1 | 12 ++ .../Microsoft365/IAM/Copy-User365GroupsV2.ps1 | 90 +++++++++++++ .../Microsoft365/IAM/Copy-User365GroupsV3.ps1 | 121 ++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 Cloud/Microsoft365/IAM/Copy-User365Groups.ps1 create mode 100644 Cloud/Microsoft365/IAM/Copy-User365GroupsV2.ps1 create mode 100644 Cloud/Microsoft365/IAM/Copy-User365GroupsV3.ps1 diff --git a/Cloud/Microsoft365/IAM/Copy-User365Groups.ps1 b/Cloud/Microsoft365/IAM/Copy-User365Groups.ps1 new file mode 100644 index 0000000..0efde3e --- /dev/null +++ b/Cloud/Microsoft365/IAM/Copy-User365Groups.ps1 @@ -0,0 +1,12 @@ +# input the users email address you want to copy from +$source = "user1@domain.com.au" + +# input the users email address you want to paste the groups to +$destination = "user2@domain.com.au" + +Connect-ExchangeOnline + +$dn = (Get-EXOMailbox $source).DistinguishedName + +Get-EXORecipient -Filter "Members -eq '$dn'" -RecipientTypeDetails GroupMailbox | ForEach-Object { Add-UnifiedGroupLinks $_.Name -LinkType Member -Links $destination } +Get-EXORecipient -Filter "Members -eq '$dn'" -RecipientTypeDetails MailUniversalDistributionGroup | ForEach-Object { Add-DistributionGroupMember $_.Name -Member $destination } diff --git a/Cloud/Microsoft365/IAM/Copy-User365GroupsV2.ps1 b/Cloud/Microsoft365/IAM/Copy-User365GroupsV2.ps1 new file mode 100644 index 0000000..893b733 --- /dev/null +++ b/Cloud/Microsoft365/IAM/Copy-User365GroupsV2.ps1 @@ -0,0 +1,90 @@ +# Define log directory and file +$logDir = "C:\Logs" +$logFile = "$logDir\Copy365GroupMemberships.log" + +# Create the log directory if it doesn't exist +if (-not (Test-Path -Path $logDir)) { + New-Item -ItemType Directory -Path $logDir | Out-Null + Write-Host "Created log directory: $logDir" +} + +# Function to write logs +function Write-Log { + param ( + [string]$Message + ) + $timestamp = Get-Date -Format "dd-MM-yyyy HH:mm:ss" + $logMessage = "$timestamp - $Message" + Add-Content -Path $logFile -Value $logMessage + Write-Host $logMessage +} + +# Start logging +Write-Log "INFO: Starting group membership copy process..." + +# Input the user's email address you want to copy from +$source = "user1@domain.com.au" + +# Input the user's email address you want to paste the groups to +$destination = "user2@domain.com.au" + +# Connect to Exchange Online +try { + Connect-ExchangeOnline -ErrorAction Stop + Write-Log "INFO: Successfully connected to Exchange Online." +} catch { + Write-Log "ERROR: Failed to connect to Exchange Online. Error: $_" + exit +} + +# Get the DistinguishedName of the source user +try { + $dn = (Get-EXOMailbox $source -ErrorAction Stop).DistinguishedName + Write-Log "INFO: Retrieved DistinguishedName for source user: $source" +} catch { + Write-Log "ERROR: Failed to retrieve DistinguishedName for source user: $source. Error: $_" + exit +} + +# Copy group memberships for GroupMailbox +try { + $groupMailboxes = Get-EXORecipient -Filter "Members -eq '$dn'" -RecipientTypeDetails GroupMailbox -ErrorAction Stop + Write-Log "INFO: Found $($groupMailboxes.Count) GroupMailbox memberships for source user: $source" + foreach ($group in $groupMailboxes) { + try { + Add-UnifiedGroupLinks -Identity $group.Name -LinkType Member -Links $destination -ErrorAction Stop + Write-Log "INFO: Successfully added $destination to GroupMailbox: $($group.Name)" + } catch { + Write-Log "ERROR: Failed to add $destination to GroupMailbox: $($group.Name). Error: $_" + } + } +} catch { + Write-Log "ERROR: Failed to retrieve GroupMailbox memberships for source user: $source. Error: $_" +} + +# Copy group memberships for MailUniversalDistributionGroup +try { + $distributionGroups = Get-EXORecipient -Filter "Members -eq '$dn'" -RecipientTypeDetails MailUniversalDistributionGroup -ErrorAction Stop + Write-Log "INFO: Found $($distributionGroups.Count) Distribution Group memberships for source user: $source" + foreach ($group in $distributionGroups) { + try { + Add-DistributionGroupMember -Identity $group.Name -Member $destination -ErrorAction Stop + Write-Log "INFO: Successfully added $destination to Distribution Group: $($group.Name)" + } catch { + Write-Log "ERROR: Failed to add $destination to Distribution Group: $($group.Name). Error: $_" + } + } +} catch { + Write-Log "ERROR: Failed to retrieve Distribution Group memberships for source user: $source. Error: $_" +} + +# Disconnect from Exchange Online +try { + Disconnect-ExchangeOnline -Confirm:$false -ErrorAction Stop + Write-Log "INFO: Successfully disconnected from Exchange Online." +} catch { + Write-Log "ERROR: Failed to disconnect from Exchange Online. Error: $_" +} + +# End logging +Write-Log "INFO: Group membership copy process completed." \ No newline at end of file diff --git a/Cloud/Microsoft365/IAM/Copy-User365GroupsV3.ps1 b/Cloud/Microsoft365/IAM/Copy-User365GroupsV3.ps1 new file mode 100644 index 0000000..87734f4 --- /dev/null +++ b/Cloud/Microsoft365/IAM/Copy-User365GroupsV3.ps1 @@ -0,0 +1,121 @@ +<# +.SYNOPSIS + Copies group memberships from one user to another in Microsoft 365 with detailed logging. +.DESCRIPTION + This script connects to Exchange Online and copies all group memberships (both Microsoft 365 Groups and Distribution Lists) + from a source user to a destination user, with comprehensive logging. +.NOTES + File Name : Copy-365GroupMembershipsV3.ps1 + Prerequisite : ExchangeOnlineManagement PowerShell module +#> + +# Input parameters +$source = "user1@domain.com.au" +$destination = "user2@domain.com.au" + +# Logging configuration +$logFolder = "C:\Logs\365UserCopy" +$logDate = Get-Date -Format "ddMMyyyy_HHmm" +$logFile = "$logFolder\365UserGroupCopy_$logDate.log" + +# Create log directory if it doesn't exist +if (-not (Test-Path $logFolder)) { + New-Item -ItemType Directory -Path $logFolder -Force | Out-Null +} + +# Function for consistent logging +function Write-Log { + param ( + [string]$Message, + [string]$Level = "INFO" + ) + + $timestamp = Get-Date -Format "dd-MM-yyyy HH:mm:ss" + $logEntry = "[$timestamp] [$Level] $Message" + Write-Output $logEntry | Out-File -FilePath $logFile -Append -Encoding utf8 + + # Also display to console + switch ($Level) { + "ERROR" { Write-Host $logEntry -ForegroundColor Red } + "WARNING" { Write-Host $logEntry -ForegroundColor Yellow } + "SUCCESS" { Write-Host $logEntry -ForegroundColor Green } + default { Write-Host $logEntry } + } +} + +try { + # Start logging + Write-Log "Script started" + Write-Log "Source user: $source" + Write-Log "Destination user: $destination" + + # Connect to Exchange Online + Write-Log "Connecting to Exchange Online..." + Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop + Write-Log "Successfully connected to Exchange Online" + + # Get source user details + Write-Log "Retrieving source user information..." + $sourceMailbox = Get-EXOMailbox $source -ErrorAction Stop + if (-not $sourceMailbox) { + throw "Source user $source not found" + } + $dn = $sourceMailbox.DistinguishedName + Write-Log "Source user found: $($sourceMailbox.PrimarySmtpAddress) (DN: $dn)" + + # Process Microsoft 365 Groups + Write-Log "Processing Microsoft 365 Groups..." + $o365Groups = Get-EXORecipient -Filter "Members -eq '$dn'" -RecipientTypeDetails GroupMailbox -ErrorAction Stop + Write-Log "Found $($o365Groups.Count) Microsoft 365 Groups for source user" + + foreach ($group in $o365Groups) { + try { + Write-Log "Adding $destination to group: $($group.Name) ($($group.PrimarySmtpAddress))" + Add-UnifiedGroupLinks -Identity $group.Name -LinkType Member -Links $destination -ErrorAction Stop + Write-Log -Level "SUCCESS" "Successfully added $destination to Microsoft 365 Group: $($group.Name)" + } + catch { + Write-Log -Level "ERROR" "Failed to add $destination to Microsoft 365 Group $($group.Name): $_" + } + } + + # Process Distribution Groups + Write-Log "Processing Distribution Groups..." + $distGroups = Get-EXORecipient -Filter "Members -eq '$dn'" -RecipientTypeDetails MailUniversalDistributionGroup -ErrorAction Stop + Write-Log "Found $($distGroups.Count) Distribution Groups for source user" + + foreach ($group in $distGroups) { + try { + Write-Log "Adding $destination to distribution group: $($group.Name) ($($group.PrimarySmtpAddress))" + Add-DistributionGroupMember -Identity $group.Name -Member $destination -ErrorAction Stop + Write-Log -Level "SUCCESS" "Successfully added $destination to Distribution Group: $($group.Name)" + } + catch { + Write-Log -Level "ERROR" "Failed to add $destination to Distribution Group $($group.Name): $_" + } + } + + # Summary report + Write-Log "Processing complete" + Write-Log "SUMMARY:" + Write-Log " Microsoft 365 Groups processed: $($o365Groups.Count)" + Write-Log " Distribution Groups processed: $($distGroups.Count)" +} +catch { + Write-Log -Level "ERROR" "Script encountered an error: $_" + Write-Log -Level "ERROR" "Error details: $($_.ScriptStackTrace)" +} +finally { + # Disconnect from Exchange Online + try { + Write-Log "Disconnecting from Exchange Online..." + Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue + Write-Log "Disconnected from Exchange Online" + } + catch { + Write-Log -Level "WARNING" "Failed to properly disconnect from Exchange Online: $_" + } + + Write-Log "Script completed" + Write-Log "Log file saved to: $logFile" +} \ No newline at end of file