Last active
January 30, 2025 20:03
-
-
Save jschlackman/d44ef32de2062506fe0838a01704091d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Searches for and updates Jira users in preparation for SSO by changing their login name to match their email address. | |
.DESCRIPTION | |
Uses the Jira Server API (via the JiraPS module) to bulk update the usernames of selected Jira users so that their login name matches their email address, allowing them to be correctly logged in via SSO mechanisms such as SAML. | |
Author: James Schlackman | |
Last Modified: January 29 2025 | |
.PARAMETER ServerUri | |
Jira server to connect to. | |
.PARAMETER UserFilter | |
User search filter. Uses the same syntax as searches within the user management section of Jira. | |
.PARAMETER ConfirmChanges | |
Confirm update to each individual user. When not specified, batch process all users selected for update without additional confirmation. | |
.PARAMETER SkipAuthenticatedUser | |
Set to false to include the user account used to authenticate to the API in any batch change. | |
When true (default), the user account used to authenticate to the API will be excluded from any change operations to prevent the login token from being expired. | |
.NOTES | |
Information on documentation for the JiraPS module can be found at https://atlassianps.org/docs/JiraPS/ | |
#> | |
#Requires -Modules JiraPS | |
Param( | |
[Parameter(Mandatory)] [String] $ServerUri, | |
[Parameter(Mandatory)] [String] $UserFilter, | |
[Parameter()] [Switch] $ConfirmChanges, | |
[Parameter()] [Bool] $SkipAuthenticatedUser = $true | |
) | |
Import-Module JiraPS | |
Function Connect-JiraServer { | |
Param( | |
[Parameter(Mandatory=$true)] [string]$ServerUri | |
) | |
# Clean up server parameter | |
$ServerUri = $ServerUri.Trim().TrimEnd('/').ToLower() | |
# Default to https:// if protocol not specified | |
If ($ServerUri -notmatch '^http(s)?:\/\/') { | |
$ServerUri = 'https://{0}' -f $ServerUri | |
} | |
# Check for a current connection | |
$currentServer = Get-JiraServerInfo -ErrorAction SilentlyContinue | |
# If already connected to the correct server, return immediately | |
If ($currentServer.BaseURL -eq $ServerUri) { | |
Write-Host ($currentServer | Out-String) | |
Return $currentServer | |
} Else { | |
# Set the server Uri | |
Set-JiraConfigServer -Server $ServerUri | |
# Get new credentials | |
Do { | |
$newCred = $null | |
$newCred = Get-Credential | |
# Test provided credentials | |
If ($newCred) { | |
$serverInfo = Get-JiraServerInfo -Credential $newCred | |
} Else { | |
$serverInfo = $null | |
} | |
} Until (![bool]$newCred -or $serverInfo) | |
# If we got server info successfully, start a session with those credentials | |
If ($serverInfo) { | |
New-JiraSession -Credential $newCred | |
Write-Host "`nConnection established." -ForegroundColor Green | |
Write-Host ($serverInfo | Out-String) | |
Return $serverInfo | |
} Else { | |
Return $null | |
} | |
} | |
} | |
# Attempt to connect to the server and process users | |
If (Connect-JiraServer -ServerUri $ServerUri) { | |
If (!$SkipAuthenticatedUser) { | |
Write-Warning 'Authenticated user is NOT being skipped during updates. If credentials are modified during batch update, all subsequent API operations will fail.' | |
} | |
Write-Host 'Finding users that match ' -NoNewline | |
Write-Host $UserFilter -ForegroundColor Cyan -NoNewline | |
Write-Host '...' | |
$candidateUsers = @() | |
$startAt = 0 | |
# Fetch user details in batches of 1000 until the number returned is less than the maximum (indicating no more users to fetch) | |
do { | |
$apiResult = Get-JiraUser -UserName $UserFilter -MaxResults 1000 -Skip $startAt | |
$candidateUsers += $apiResult | |
$startAt += 1000 | |
} until (@($apiResult).Count -lt 1000) | |
# Now process any returned users | |
If ($candidateUsers) { | |
Write-Host ('Matching users: {0}' -f @($candidateUsers).Count) | |
Write-Host 'Review grid output and select users to update.' | |
# Show grid for selection | |
$changeUsers = $candidateUsers| Select Name,DisplayName,EmailAddress,Active,@{Name='Groups';Expression={($_.Groups -join ', ')}} | Out-GridView -Title 'Select Jira users to update' -OutputMode Multiple | |
If ($SkipAuthenticatedUser) { | |
$changeUsers = $changeUsers | Where-Object -Property Name -ne (Get-JiraSession).Username | |
} | |
Write-Host ('Users selected for update: {0}' -f @($changeUsers).Count) | |
$jobActivity = 'Updating users...' | |
# Process selected users | |
For ($changeIndex = 0; $changeIndex -lt @($changeUsers).Count; $changeIndex++ ) { | |
$changeUser = @($changeUsers)[$changeIndex] | |
# Post job progress | |
Write-Progress -Activity $jobActivity -CurrentOperation $changeUser.Name -PercentComplete ($changeIndex / @($changeUsers).Count * 100) | |
# Make sure the user confirms the change if required | |
$changeConfirmed = !$ConfirmChanges | |
# If the username and email already match, skip this user | |
If ($changeUser.Name -eq $changeUser.EmailAddress) { | |
Write-Verbose ('Skipping name update for user {0}, login name already matches email.' -f $changeUser.Name) | |
} Else { | |
# If the username does not match, update it | |
$changeDetail = @{name = $changeUser.EmailAddress} | |
# Write a summary of the changes to be submitted and ask for confirmation if required | |
If ($changeConfirmed) { | |
Write-Verbose ('Username for {0} changing from {1} to {2}' -f $changeUser.DisplayName, $changeUser.Name, $changeDetail.name) | |
} Else { | |
Write-Host ("`nUsername for {0} will change from " -f $changeUser.DisplayName) -NoNewline | |
Write-Host $changeUser.Name -ForegroundColor Cyan -NoNewline | |
Write-Host ' to ' -NoNewline | |
Write-Host $changeDetail.Name -ForegroundColor Cyan | |
$changeConfirmed = (Read-Host 'Proceed? [y/N]').Trim().ToUpper() -eq 'Y' | |
} | |
# Once the change is confirmed | |
If ($changeConfirmed) | |
{ | |
# Submit the change to the server | |
$changeResult = Set-JiraUser -User $changeUser.Name -Property $changeDetail -PassThru | |
# Report result | |
If ($changeResult -and ($changeResult.Name -eq $changeResult.EmailAddress)) { | |
If ($ConfirmChanges) { | |
Write-Host 'User update succeeded.' -ForegroundColor Green | |
} Else { | |
Write-Verbose 'User update succeeded.' | |
} | |
Write-Debug $changeResult | |
} Else { | |
Write-Host ('{0} - ' -f $changeUser.Name) -NoNewline | |
Write-Host 'User update FAILED.' -ForegroundColor Red | |
} | |
} | |
} | |
} | |
# Mark job completed | |
Write-Progress -Activity $jobActivity -Completed | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment