ITGlue to Hudu Migration Considerations

Migration Preparation

The ITGlue to Hudu migration script originally created by Luke Whitelocker has been rebuilt to make the script more interactive. The script has also been updated to include previously unsupported functions in the main script.

Updated instructions on running the script itself has been placed on the Github link, pointing to MSPGeek BookStack instance. A copy of the instructions have been placed here too.

Hudu Self-Hosted

Hudu on-premises has a API Rate Limit that can be configured with an Environment Variable. See the related article for details on configuring this.

If you have a WAF in front of Hudu, you should perfrom the migration from a computer that is bypassing the WAF, routing traffic directly to the Hudu server. The WAF can interfere with content in the API payloads such as scripts, or commands as it may deem some of the requests to be attacks.

ITGlue

The ITGlue API doesn't like the use of "commas (,)" when doing a search by name. To prevent issues, rename all organizations to remove any commas from the name.

ITGlue allows for more than one client to exist with the same Name. Hudu does not. This causes issues during migration as the first client will succeed and subsequent clients with the exact same name will fail with Name Already Taken error from Hudu's API. Make sure any client is at least named with a unique name so that the migration can complete successfully.

Blank passwords in ITGlue will cause issues on import and cause the entire password to fail. Make sure the API Key you're using has password access, and that all passwords have values if they're important.

See below for identifying items that didn't properly create in Hudu.

Running the Script

This version of the script brings an interactive migration process, settings will get saved by default to %APPDATA%\HuduMigration although they can be moved and then re-imported from a different path after creation.

Settings that will be saved include API Keys, URLs, Prefixes, and so on. You can modify the settings.json file directly as long as you use values that are expected.

Settings that are not saved include the migration preferences (such as what entites to migrate) 

TIP: Load the script through DOT SOURCING . .\migration\ITGlue-Hudu-Migration.ps1 so that the session saves the answers in context, and you can re-run as necessary.

Instructions

Some of the instructions from the original script are still valid. You will need BOTH an ITGlue API Key, and a full ITGlue Export extracted in order for this to work

 

  1. Download/Clone the repo into a folder on your jump computer. Make sure you get the entire repo.

  2. Unblock the ZIP file from the Properties page, and extract it into a folder (not the export folder ideally)
  3. Extract your ITGlue Export to a folder on the same computer, you'll need to provide the path for the extracted contents when prompted by the options.
  4. Use Dot Sourcing to run the main file "ITGlue-Hudu-Migration.ps1" from the path of where you extracted the ZIP file of the repo
  5. You'll be prompted for the initial setup and it will save the settings to a file.

    image.png

  6. You can also resume a session and import the saved settings if you need to.

    image.png

  7. As pictured, the import mode options are not saved into the settings file, as you have the opportunity to change what you import each time.

    It's highly recommended you perform the import in the order of the operations.

  8. Using Dot Sourcing to load the script will save your answers into variables and so interrupting and resuming the migration but keeping the PowerShell session active will allow you to quickly bypass most of the questions. With Dot Sourcing you'll also get access to the variables at the end of the script run to examine the data or modify the parameters of the run. For example change the "$resumeQuestion" from "yes" to "no" or vice versa to resume an import or start over from scratch.

Here's a summary of instructions from the original instructoins that have been adjusted

MSPP.IO Instructions

  1. Have a base Hudu install with no  integrations setup. Sync things like companies and contacts from your PSA and configurations from your RMM once the migration is completed. Don’t setup any Layouts and let the migration create the initial assets.
    • Perform a clean up of you IT Glue environment. Make sure you have cleaned up any duplicate records. Removed any old ones you don’t want to migrate.
    • Check your Flexible Layouts don’t have any fields named the same thing on the same layout. For example we had two fields called Pre-Shared Key on our Wireless asset. (One for primary one for guest). If this is the case rename one of them.
  1. In IT Glue perform a full export and wait for that to complete and download the zip file.
  2. Extract that ZIP to C:\ITGlue\ making sure that extracted files end up directly in a subfolder called "export".
  3. Obtain an API Key with password access from IT Glue
  4. Obtain an API Key with password access for Hudu.
  5. Download/Clone the repo into a folder on your jump computer - placing it into the "migration" folder within the C:\ITGlue directory
  6. Double check your backups of Hudu
  7. Run the script using Powershell 7 with dot sourcing, and answer questions as the script runs.

Script Completed

There are a few things to do once the script has finished. This will cover the following

  • Adding Attachments into Hudu
  • Creating the final Relationships

Unsupported Relationships

Please note the relationships are built at the time of the Assets being populated, if your script got interrupted and you resumed it in the middle, it's best to clear out the assets.json file and restart it from the point of populating the assets to accurate capture the relationships.

There will be a variable you can use called $RelationsToCreate, you can use the following code block for now to build these out. This will eventually be merged into the main script process.

These include relationships that are embedded to unsupported items (Articles, Companies, and so on)

$relations = ($relationsToCreate | % {Add-HuduRelation -relation $_})

Then you can check $relations.count and $relationstocreate.count to compare and see what's missing if any failed.

If the session was closed after the assets were finshed, but the assets did complete successfully, you can load the Relations JSON file into a variable and process it the same way. The JSON file will be in the same place as the logs path.

Activating Hudu Asset Layouts

While this has been added to the latest version of the script, it has not been tested yet. You can use this one-liner to get all Hudu Asset Layouts and mark them as active.

$AllLayouts = Get-HuduAssetLayouts
$AllLayouts | % {Set-HuduAssetLayout -id $_.id -Active $true}

Archived Items

While the main script has been updated to automatically archive items as it imports them, it hasn't been fully tested yet. Use the following lines of code to archive anything that was previously archived in ITGlue. Errors are expected if the item is already archived.

# Pull a list of archived items
$ArchivedPasswords = $MatchedPasswords |? {$_.itgobject.attributes.archived -eq $true}
$ArchivedConfigurations = $MatchedConfigurations |? {$_.ITGObject.attributes.archived -eq $true}    
$ArchivedAssets = $MatchedAssets |? {$_.ITGObject.attributes.archived -eq $true}

# Documents isn't in the API we have to check the CSV for this
$DocsCsv = import-csv "$ITGLueExportPath\documents.csv"
$ArchivedDocs = $DocsCsv |? {$_.archived -eq 'yes'}

# Loop over everything and store results for later checking/handling.
$ptaresults = $ArchivedPasswords | % {Set-HuduPasswordArchive -id $_.huduid -Archive $true}
$ctaresults = $ArchivedConfigurations |% {Set-HuduAssetArchive -Id $_.huduid -CompanyId $_.huduobject.company_id -Archive $true}
$ataresults = $ArchivedAssets |% {Set-HuduAssetArchive -Id $_.huduid -CompanyId $_.huduobject.company_id -Archive $true}
$dtaresults = $ArchivedDocs |% {$i = $_; $A2D = $MatchedArticles |? {$_.itgid -eq $i.id}; Set-HuduArticleArchive -Id $A2D.HuduId -Archive $true } 

Missing items in Hudu

The ManualLog and Matched* variables can be used when troubleshooting, especially if you followed directions and dot sourced the powershell script instead of running it directly. Look for all items in the relevant variable where the HuduID is null or blank or where the HuduObject isn't populated. The ITGlue object and ID are stored alongside it in the same object so you can reference and retry the same entity for import.

Additionally if you're looping over or addressing a specific index you can update the HuduID and HuduObject with the updated/correct values so that you can re-export the entire Matched variable back out to the JSON log to retain a full complete valid log file for replay if necessary. Example script here

# Find passwords that didn't make it to Hudu
$MissingWifiPasswords = $MatchedPasswords |? {$_.huduid -eq ''}

# Loop over the missing wifi passwords and populate them, updating the original object back.
foreach ($mp in $MissingWifiPasswords) {
       	$fa = $MatchedAssets |? {($_.HuduObject.fields | ? {$_.label -eq 'ITGlue URL'}).value -eq $mp.ITGObject.attributes.'parent-url'}
       	# Below line disabled since the script now populates embedded fields, uncomment if embedded field is missing password
	# $HuduField = ($AllFields |? {$_.fieldtype -eq 'Password' -and $_.HuduLayoutID -eq $fa.HuduObject.asset_layout_id})
	$np = (New-HuduPassword -name "$($fa.name) $($mp.name)" -PasswordableType Asset -PasswordableId $fa.HuduObject.id -CompanyId $fa.HuduObject.company_id -Password $mp.ITGObject.attributes.password).asset_password
	$mp.huduobject = $np
	$mp.huduid = $np.id
	$mp.Imported = 'Created Manually'
	$mp.Matched = $true
       	# Below lines are disabled since the script now populates embedded fields, uncomment if embedded field is missing password
	#($fa.HuduObject.fields|? {$_.label -eq $HuduField.FieldName}).value = $np.password
	#$blah = Set-HuduAsset -Id $fa.HuduObject.id -Fields @{$HuduField.HuduParsedName = $np.password}
}

# Update the migration log files, (move/rename the existing ones first)
        $MatchedAssets | ConvertTo-Json -depth 100 | Out-File "$MigrationLogs\Assets.json"
        $MatchedAssetPasswords | ConvertTo-Json -depth 100 | Out-File "$MigrationLogs\AssetPasswords.json"
        $MatchedPasswords | ConvertTo-Json -depth 100 | Out-File "$MigrationLogs\Passwords.json"

In the above script, it handles a tricky scenario where the passwords are a flexible asset field on the Flexible Asset directly instead of it being a general or embedded password. In this case the original version of the script was missing those passwords as ITGlue buries the link between the two and it takes a few recursive lookups to get to the password. The latest version of the script should not have this issue but the method for fixing it demonstrates how you can do this in general for items that fail to make it to Hudu for a variety of reasons (API limits and so on).

File Attachments

When you're finished with the main script, and relationships created you can run the "Add-HuduAttachmentsViaAPI.ps1" script.

The script will start looking for all the obvious attachments, and then start looking for the non-obvious attachments (these are attachments that were included inside of an embedded upload field or pictures, on a Flexible Asset).

For the non-obvious attachments, the script will prompt for each folder of attachments, and ask you to provide the CSV name for that folder, as well as the header name for the field that contains the name of the file. The non-obvious attachments - such as files embedded on a Flexible Asset will be kept in folders where the name of the folder is concatenated with the flexible asset name, and the field of the flexible asset

Here are two screenshots showing that below.

image.png

image.png

After you select enter the CSV name, you have to open the CSV find the header and copy it exactly into the field as prompted.

image.png

The script will upload all attachments via the API so it can take some time.