Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
79bb3c6
todos for new description object
jworkmanjc Jan 6, 2026
78920e0
init script
jworkmanjc Jan 6, 2026
61d943b
skip user support
jworkmanjc Jan 6, 2026
c82c0a3
explicitly cast as a list
jworkmanjc Jan 6, 2026
f2393a7
add uid to deviceQuery
jworkmanjc Jan 6, 2026
b6c271e
invoke testing
jworkmanjc Jan 6, 2026
b8ce776
WriteToProgress SystemContext Updates
kmaranionjc Jan 6, 2026
a49569d
set system in start-migration
jworkmanjc Jan 6, 2026
72c9d93
Merge branch 'CUT-4862_statusReportingV2' of ssh://github.com/TheJump…
jworkmanjc Jan 6, 2026
d4c3fd1
write-toProgress new status object
jworkmanjc Jan 9, 2026
edfd3d0
merge auth method for writing description
jworkmanjc Jan 9, 2026
771b444
Invoke-SystemPut -> Invoke-SystemAPI
jworkmanjc Jan 9, 2026
0c62816
2.12
jworkmanjc Jan 9, 2026
9a87ce6
rename start-reversion tests file
jworkmanjc Jan 9, 2026
25d6462
Build-MigrationDescription Tests
jworkmanjc Jan 9, 2026
8d48a84
remove test data
jworkmanjc Jan 9, 2026
51b3341
API Context
jworkmanjc Jan 9, 2026
a572e68
retain CSV functionality
jworkmanjc Jan 9, 2026
177510e
test char count + compact invoke script + remove get-system
jworkmanjc Jan 9, 2026
9e9f5cc
build migration description tests
jworkmanjc Jan 9, 2026
dcd45ab
update tests to match minimized invoke function
jworkmanjc Jan 9, 2026
e153a9e
minimize device init
jworkmanjc Jan 12, 2026
f06448c
update invoke + tests
jworkmanjc Jan 12, 2026
4af0caf
migration tests
jworkmanjc Jan 12, 2026
fde027a
csvName param tests
jworkmanjc Jan 12, 2026
aa12292
migration description results + check if type is loaded
jworkmanjc Jan 12, 2026
287664b
toUpper in invoke-systemContextAPI
jworkmanjc Jan 12, 2026
c06da67
invoke migration tests
jworkmanjc Jan 12, 2026
196bf66
move systemContext required tests
jworkmanjc Jan 12, 2026
050e157
changes for Get-LatestADMUGUIExe
jworkmanjc Jan 12, 2026
4f12f26
build docs from windows
jworkmanjc Jan 12, 2026
2002c7c
date
jworkmanjc Jan 12, 2026
a8ffe74
localPath in Start-Reversion
jworkmanjc Jan 12, 2026
26b6af8
remove $localPath + test changes
kmaranionjc Jan 13, 2026
ec892d1
invoke CRLF character count
jworkmanjc Jan 13, 2026
6cf176b
print char count invoke migration tests [skip ci]
jworkmanjc Jan 13, 2026
4658acf
Merge branch 'CUT-4862_statusReportingV2' of ssh://github.com/TheJump…
jworkmanjc Jan 13, 2026
2d0df2d
reversion
kmaranionjc Jan 13, 2026
e857253
function names in Invoke
jworkmanjc Jan 13, 2026
527634d
date
jworkmanjc Jan 14, 2026
ed7149d
Merge branch 'CUT-4862_statusReportingV2' of ssh://github.com/TheJump…
jworkmanjc Jan 14, 2026
55c94b3
docs generated
jworkmanjc Jan 14, 2026
dcd531b
Get-MgUserFromCSV-csvName
jworkmanjc Jan 14, 2026
53eaa99
fix reversion test
kmaranionjc Jan 14, 2026
fd2c030
test
kmaranionjc Jan 14, 2026
72bb317
deviceQuery Tests
jworkmanjc Jan 14, 2026
d8dc145
retry on failure
jworkmanjc Jan 14, 2026
311600e
deviceQueryTests
jworkmanjc Jan 14, 2026
b87d6e2
Merge branch 'CUT-4862_statusReportingV2' of ssh://github.com/TheJump…
jworkmanjc Jan 14, 2026
c948af6
last login
jworkmanjc Jan 14, 2026
5fd03bf
fix for deviceQuery test
jworkmanjc Jan 15, 2026
38e797d
attribute support
jworkmanjc Jan 15, 2026
0554a9b
reportStatus tests
jworkmanjc Jan 15, 2026
fb3a635
date
jworkmanjc Jan 15, 2026
943a273
device query tests + date
jworkmanjc Jan 15, 2026
622c474
revert localUsers change
jworkmanjc Jan 15, 2026
3b64513
wrong sid in start-migration test
jworkmanjc Jan 15, 2026
3fd6f4c
remove description for now
jworkmanjc Jan 15, 2026
ed3f610
debug deviceQuery
jworkmanjc Jan 15, 2026
1c90e08
spacing pwsh syntax
jworkmanjc Jan 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion ModuleChangelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
## 2.12.0

Release Date: January 15, 2026

#### RELEASE NOTES

```
This release includes the option to update ADMU status on the JumpCloud system description field when migrating remotely. This allows administrators to track migration progress remotely.
```

#### FEATURES:

Additional method for remotely migrating system by reading the device description field.

#### IMPROVEMENTS:

Several new tests added to validate new features and existing functionality.

## 2.11.0

Release Date: January 2, 2026
Expand Down Expand Up @@ -56,7 +74,6 @@ Patch release to address several issues.
- This release introduces the ability to set a device's primary user using the PrimaryUser parameter. This can only be done when using the AutoBindJCUser feature as well as using SystemContext.
- Profile image permission backup functionality added


## 2.9.4

Release Date: November 06, 2025
Expand Down
1,309 changes: 586 additions & 723 deletions jumpcloud-ADMU-Advanced-Deployment/InvokeFromJCAgent/3_ADMU_Invoke.ps1

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion jumpcloud-ADMU/Docs/Start-Migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,4 +403,4 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable

## RELATED LINKS

[https://github.com/TheJumpCloud/jumpcloud-ADMU/wiki/Start-Migration](https://github.com/TheJumpCloud/jumpcloud-ADMU/wiki/Start-Migration)
[https://github.com/TheJumpCloud/jumpcloud-ADMU/wiki/Start-Migration](https://github.com/TheJumpCloud/jumpcloud-ADMU/wiki/Start-Migration)
201 changes: 201 additions & 0 deletions jumpcloud-ADMU/Docs/Start-Reversion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
---
external help file: JumpCloud.ADMU-help.xml
Module Name: JumpCloud.ADMU
online version: https://github.com/TheJumpCloud/jumpcloud-ADMU/wiki/Start-Reversion
schema: 2.0.0
---

# Start-Reversion

## SYNOPSIS
Reverts a user migration by restoring original registry files for a specified Windows SID.

## SYNTAX

```
Start-Reversion [-UserSID] <String> [[-TargetProfileImagePath] <String>] [-form <Boolean>] [-UserName <String>]
[-ProfileSize <String>] [-DryRun] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>]
```

## DESCRIPTION
This function reverts a user migration by:
1.
Looking up the account SID in the Windows registry ProfileList
2.
Identifying the .ADMU profile path
3.
Restoring original NTUSER.DAT and UsrClass.dat files from backups
4.
Preserving migrated files with _migrated suffix for rollback purposes

## EXAMPLES

### EXAMPLE 1
```
Start-Reversion -UserSID "S-1-5-21-123456789-1234567890-123456789-1001"
Reverts the migration for the specified user SID using the registry profile path.
```

### EXAMPLE 2
```
Start-Reversion -UserSID "S-1-5-21-123456789-1234567890-123456789-1001" -TargetProfileImagePath "C:\Users\john.doe"
Reverts the migration using a specific target profile path instead of the registry value.
```

### EXAMPLE 3
```
Start-Reversion -UserSID "S-1-5-21-123456789-1234567890-123456789-1001" -DryRun
Shows what would be reverted without making actual changes.
```

## PARAMETERS

### -UserSID
The Windows Security Identifier (SID) of the user account to revert.

```yaml
Type: System.String
Parameter Sets: (All)
Aliases:

Required: True
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -TargetProfileImagePath
The actual profile path to revert.
If not specified, will use the path from the registry.
This path will be validated to ensure it exists and is associated with the UserSID.

```yaml
Type: System.String
Parameter Sets: (All)
Aliases:

Required: False
Position: 2
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -form
{{ Fill form Description }}
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameter descriptions contain placeholder text '{{ Fill ... Description }}' that should be replaced with actual documentation for the 'form', 'UserName', and 'ProfileSize' parameters.

Suggested change
{{ Fill form Description }}
Indicates that the cmdlet is being invoked from a form or UI context and suppresses additional interactive prompts.

Copilot uses AI. Check for mistakes.

```yaml
Type: System.Boolean
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```

### -UserName
{{ Fill UserName Description }}
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameter descriptions contain placeholder text '{{ Fill ... Description }}' that should be replaced with actual documentation for the 'form', 'UserName', and 'ProfileSize' parameters.

Copilot uses AI. Check for mistakes.

```yaml
Type: System.String
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -ProfileSize
{{ Fill ProfileSize Description }}
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameter descriptions contain placeholder text '{{ Fill ... Description }}' that should be replaced with actual documentation for the 'form', 'UserName', and 'ProfileSize' parameters.

Copilot uses AI. Check for mistakes.

```yaml
Type: System.String
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -DryRun
Shows what actions would be performed without actually executing them.

```yaml
Type: System.Management.Automation.SwitchParameter
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```

### -Force
Bypasses confirmation prompts and forces the revert operation.

```yaml
Type: System.Management.Automation.SwitchParameter
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```

### -WhatIf
Shows what would happen if the cmdlet runs.
The cmdlet is not run.

```yaml
Type: System.Management.Automation.SwitchParameter
Parameter Sets: (All)
Aliases: wi

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -Confirm
Prompts you for confirmation before running the cmdlet.

```yaml
Type: System.Management.Automation.SwitchParameter
Parameter Sets: (All)
Aliases: cf

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).

## INPUTS

## OUTPUTS

### [PSCustomObject] Returns revert operation results with success status and details.
## NOTES

## RELATED LINKS
6 changes: 3 additions & 3 deletions jumpcloud-ADMU/JumpCloud.ADMU.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# Generated by: JumpCloud Customer Tools Team
#
# Generated on: 12/15/2025
# Generated on: 1/15/2026
#

@{
Expand All @@ -12,7 +12,7 @@
RootModule = 'JumpCloud.ADMU.psm1'

# Version number of this module.
ModuleVersion = '2.11.0'
ModuleVersion = '2.12.0'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down Expand Up @@ -69,7 +69,7 @@ Description = 'Powershell Module to run JumpCloud Active Directory Migration Uti
# NestedModules = @()

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @('Start-Migration' , 'Start-Reversion')
FunctionsToExport = 'Start-Migration', 'Start-Reversion'

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = '*'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
function Build-MigrationDescription {
<#
.SYNOPSIS
Builds or updates a migration description object for the device.

.DESCRIPTION
Creates a standardized description array with user migration status.
Handles both creating new descriptions and updating existing ones.

.PARAMETER UserSID
The SID of the user being migrated.

.PARAMETER MigrationUsername
The username of the user being migrated.

.PARAMETER StatusMessage
The status message to record.

.PARAMETER Percent
The progress percentage (or "ERROR" for failures).

.PARAMETER LocalPath
The local user profile path.

.PARAMETER authMethod
The authentication method used for reporting.
#>
param(

[Parameter(Mandatory = $true)]
[string]$UserSID,

[Parameter(Mandatory = $true)]
[string]$MigrationUsername,

[Parameter(Mandatory = $true)]
[string]$StatusMessage,

[Parameter(Mandatory = $true)]
[string]$Percent,

[Parameter(Mandatory = $false)]
[string]$LocalPath,

[Parameter(Mandatory = $false)]
[string]$authMethod
)

# Determine the status value based on percent
$statusValue = if ($Percent -eq "ERROR") {
"Failed"
} elseif ($Percent -eq "100%") {
"Completed"
} else {
"InProgress"
}

# determine the auth method
switch ($authMethod) {
"systemcontextapi" {
# get the systemDescription with system context api
$sysContextResult = Invoke-SystemContextAPI -Method GET -Endpoint 'Systems'
$ExistingDescription = $sysContextResult.description
}
"apikey" {
# get the systemDescription with api key
$apiKeyResult = Invoke-SystemAPI -JcApiKey $script:JumpCloudAPIKey -jcOrgID $script:JumpCloudOrgID -systemId $script:validatedSystemID -method "GET"
$ExistingDescription = $apiKeyResult.description
}
"none" {
# if no auth method, exit function return null
Write-ToLog -Message "Error fetching existing description: $_" -Level Warning
return $null
}
}
# Initialize or update description array
if (-not [string]::IsNullOrEmpty($ExistingDescription)) {
try {
$description = $ExistingDescription | ConvertFrom-Json
# Ensure it's always an array
if ($description -isnot [array]) { $description = @($description) }
# find the userSID in the existing description
$foundUser = $description | Where-Object { $_.sid -eq $UserSID }
if ($foundUser) {
# only update the message and status
$foundUser.msg = $StatusMessage
$foundUser.st = $statusValue
} else {
# User not found in existing description, add new entry
$description += [PSCustomObject]@{
sid = $UserSID
un = $MigrationUsername
localPath = if ($LocalPath) { $LocalPath.Replace('\', '/') } else { $null }
msg = $StatusMessage
st = $statusValue
uid = $null
lastLogin = $null
}
}
} catch {
Write-ToLog -Message "Error parsing existing system description JSON: $_" -Level Warning
# Fall through to create new description
$description = $null
}
}
# Create new description if not already initialized - always as array
if (-not $description) {
$description = @([PSCustomObject]@{
sid = $UserSID
un = $MigrationUsername
localPath = if ($LocalPath) { $LocalPath.Replace('\', '/') } else { $null }
msg = $StatusMessage
st = $statusValue
uid = $null
lastLogin = $null
})
}
# Ensure return is always an array (use unary comma for PowerShell 5.1 compatibility)
return @(, $description)
}
Loading