globalscape/powershell/ProvisionAdminSite.ps1

523 lines
24 KiB
PowerShell
Raw Normal View History

2022-04-27 14:05:07 -05:00
<#
.SYNOPSIS
Create the management site for access to certs, logs, NSG whitelists/blacklists/etc.
.DESCRIPTION
Create the management site for access to certs, logs, NSG whitelists/blacklists/etc.
Environment variables ARCUS_STATICFOLDERPATH, ARCUS_CUSTUNIQUE, ARCUS_SHAREDFOLDERPATH, ARCUS_LOGFOLDERPATH
TODO: set insecure protocols to listen to localhost only
TODO: remediate customers who got the AdminSite the week of 190701 - disable the folder scans, flatten dir structure - gghsca, vitamin shop, almost
#>
param(
[Parameter(Mandatory=$False)][string]$serverName = "localhost",
[Parameter(Mandatory=$False)][int]$eftAdminPort = 1100,
[Parameter(Mandatory=$False)][string]$eftAdminName = "",
[Parameter(Mandatory=$False)][int]$authMethod = 1,
[Parameter(Mandatory=$False)][string]$eftAdminPassword = "",
[Parameter(Mandatory=$True)][string]$customerSiteName = "", # name of the site where mgmt users will live -- we'll create the user template and group there
[Parameter(Mandatory=$False)][int]$httpPort = 6996, # Requirement 373920: place admin health check on obscure port on management site
[switch]$deleteFolderMonitors
)
#-----------------------------------------------------------------
# LogWrite function
#-----------------------------------------------------------------
Function LogWrite ($logstring, $logtype = 'INFORMATION') {
Write-Output $logstring
$env:ARCUS_DEPLOYMENTLOG = "C:\eft-pkgs\DeployatronLogMgmtSite.log"
$timestamp = Get-Date -Format g
Add-content $env:ARCUS_DEPLOYMENTLOG -value "$timestamp-Phase2-$logtype-$logstring"
if ($logtype -eq "ERROR") { $EventId = 50001 }else { $EventId = 50000 }
Write-EventLog -LogName Application -EventId 50000 -Source Deployatron -EntryType $logtype -Message $logstring
}
Function FindSite([string]$mySiteName) {
$oSites = $oServer.Sites();
$mySite = $null
for ( $i = 0; $i -lt $oSites.Count(); $i++ ) {
$mySite = $oSites.Item($i);
if ($mySite.Name -eq $mySiteName ) {
#Write-Host "site name is " $oSite.Name
break;
}
else {
$mySite = $null
}
}
return $mySite
}
$bAutoStart = $True # don't start the site by default if we're dealing with HTTP and it hasn't been limited to localhost
$bCreateCerts = $False # vanilla user doesn't have access to configure share to house certs
$bBasicMgmtOnly = $True # basic is certs and logs ; others include setting up for NSGs, etc.?
$adminSitePort = 6995
$bHttpsAccess = $False
$bConnected = $False
$oServer = new-object -comobject 'SFTPCOMInterface.CIServer'
$nConnectTrials = 0 # TODO: DWM: handle inability to log into due to other node having the admin lock - impose max retries?
while ( ! $bConnected ) {
try {
$oServer.ConnectEx("localhost", 1100, 1, $env:ARCUS_EFTADMINNAME, $env:ARCUS_EFTADMINPASS)
$bConnected = $True
LogWrite "Logged into EFT Server to build mgmt site"
break;
}
catch {
LogWrite "Caught an exception staring site:" "ERROR"
LogWrite "Exception Type: $($_.Exception.message)" "ERROR"
LogWrite "Exception Message: $($_.Exception.Message)" "ERROR"
Start-Sleep -s 2
$nConnectTrials++
if ($nConnectTrials -gt 5) {
LogWrite "failed: ConnectEx - service up? Admin Lock? .... exiting" "ERROR"
Return # exit the script block, but not the entire script
}
}
}
$adminsitename = "ArcusManagement"
$oSite = FindSite $adminsitename
#
# create the Arcus Admin site if it doesn't already exist ... this is where event rules will reside
#
if ( $null -eq $oSite) {
# notify
LogWrite "failed to find site $adminsitename ... creating";
$message = @{"Phase" = "2";
"starttime" = $(Get-Date -Format g);
"hostname" = $(hostname);
"resourcegroup" = $env:ARCUS_RESOURCEGROUP;
"subscriptionid" = $env:ARCUS_SUBSCRIPTIONID;
"arcusenv" = $env:ARCUS_ENVIRONMENT;
"status" = "failed to find site $adminsitename ... creating"
"custunique" = $env:ARCUS_CUSTUNIQUE
}
Send-DeploymentQueueMessage $message
LogWrite "Wrote message to queue $($message | Out-String)"
$adminsiteroot = "$env:ARCUS_SHAREDFOLDERPATH\InetPub\EFTRoot\ManagementSite"
$adminauddata = "$ConfigFolderPath\ManagementSite.aud"
$oSites = $oServer.Sites()
$oSites.AddLocalSite($adminsitename, $adminsiteroot, $adminauddata, 0, $adminSitePort, $True, $True, $bAutoStart, $True)
$oServer.ApplyChanges()
#
# find the just-created admin site
#
$oSite = FindSite $adminsitename
if (-not $oSite) {
LogWrite "failed to find created site $adminsitename" "ERROR"
Exit
}
else {
LogWrite "found (newly created) site $adminsitename" "INFO"
}
}
#
# get the customer site
#
$customerSite = FindSite $customerSiteName #$env:ARCUS_CUSTUNIQUE
if (-not $customerSite) {
LogWrite ("failed to find customer site {0}" -f $customerSiteName) "ERROR"
}
else {
LogWrite "found customer site" "INFO"
}
#
# more site configuration
#
$oSite.SetFTPAccess($False)
$oSite.SetHTTPSAccess($False)
$oSite.SetHTTPSPort($adminSitePort)
$oSite.BanIPForInvalidLoginAttempts = $True
$oSite.BanIPForInvalidLoginAttemptsWithExistingUsername = $True
$oSite.AllowChangePassword = $True
$oSite.InvalidLoginAttemptsCountToBanIP = 10
$oSite.ForcePasswordResetOnInitialLogin = $False
$oSite.RequireStrongPasswords = $True
$bRestart = $oSite.SetHttpPort($httpPort) # 373920: place admin health check on obscure port on management site
$oSite.SetHTTPAccess($True) | Out-Null
LogWrite "set mgmt site protocol ports and parameters"
try { $oSite.Stop() } catch { LogWrite "exception stopping site"; }
if ($bAutoStart) {
$oSite.Start()
}
#
# create the management user template in the original site if it doesn't already exit
#
$adminSTName = "ArcusMgmt_UserTemplate"
$clientSettings = $customerSite.GetSettingsLevelSettings($adminSTName)
if (-not $clientSettings) {
$adminST = $customerSite.CreateSettingsLevel($adminSTName, "Arcus Management Settings Template", 0)
$clientSettings = $customerSite.GetSettingsLevelSettings($adminSTName)
if ($clientSettings) {
if ($bSimpleHomeFolder) {
$clientSettings.SetHomeDirString("ArcusManagementVFS")
}
else {
$clientSettings.SetHomeDirString("ArcusManagementVFS") # TODO
}
$ClientSettings.SetHomeDir(1)
$ClientSettings.SetRequireStrongPasswords(1)
$oServer.ApplyChanges()
LogWrite "created SettingsLevel $adminSTName on customer site"
}
else {
LogWrite "GetSettingsLevelSettings $adminSTName failed" "ERROR"
}
}
else {
LogWrite "SettingsLevel $adminSTName already exists"
}
#
# create a permissions group
#
try {
$permGroups = $customerSite.GetPermissionGroups();
$permGroupExists = $False;
for ($i = 0; $i -lt $permGroups.Count; $i++) {
if ($permGroups[$i] -eq "ArcusManagementGroup") {
$permGroupExists = $True
break;
}
}
if (-not $permGroupExists) {
$customerSite.CreatePermissionGroup("ArcusManagementGroup");
LogWrite "CreatePermissionGroup ArcusManagementGroup on customer site"
}
else {
LogWrite "permissions group ArcusManagementGroup already exists on customer site"
}
}
catch {
LogWrite "failed: CreatePermissionGroup ArcusManagementGroup on customer site" "ERROR"
}
#
# create a VFS link from the customer site to the arcus admin site
# Requirement 367654: Create folder for self service files
# TODO: permissions
#
try {
$customerSite.CreatePhysicalFolder("ArcusManagementVFS")
}
catch {
# will throw an MX exception if the folder already exists
}
$staticConfigFolder = $env:ARCUS_STATICFOLDERPATH
$logFolder = $env:ARCUS_LOGFOLDERPATH
$siteRootFolder = ("\\{0}.file{1}gsbdata\InetPub\EFTRoot" -f $env:ARCUS_USERDATASTORAGEACCOUNT, $env:ARCUS_AZUREENDPOINT) -replace '/', '\' # link to first site, what about others
$managementSiteFolder = "{0}/AdminSite" -f $env:ARCUS_CONFIGFOLDERPATH #$AzureShare
$userDataFolder = "{0}/" -f $env:ARCUS_SHAREDFOLDERPATH
$adminFolders = @{
"ARMDB-Dumps" = @{ "Target" = "$managementSiteFolder/ARMDB-Dumps" ; "Writeable" = $True ; "Deleteable" = $True } ;
"Certs" = @{ "Target" = "$staticConfigFolder" ; "Writeable" = $True ; "Deleteable" = $False } ;
"Logs" = @{ "Target" = "$logFolder" ; "Writeable" = $False ; "Deleteable" = $False } ;
"Admin" = @{ "Target" = "$env:ARCUS_ADMINFOLDERPATH" ; "Writeable" = $True ; "Deleteable" = $True } ;
"Site-Root" = @{ "Target" = "$siteRootFolder" ; "Writeable" = $True ; "Deleteable" = $True } ;
"Backups" = @{ "Target" = "$managementSiteFolder/Backups" ; "Writeable" = $True ; "Deleteable" = $True } ;
"Restore" = @{ "Target" = "$managementSiteFolder/Backups/Restore" ; "Child" = $True } ;
"AdminUsers" = @{ "Target" = "$managementSiteFolder/AdminUsers" ; "Writeable" = $True ; "Deleteable" = $True } ;
"Settings" = @{ "Target" = "$managementSiteFolder/Settings" ; "Writeable" = $True ; "Deleteable" = $True } ;
"Custom" = @{ "Target" = "$managementSiteFolder/Custom" ; "Writeable" = $True ; "Deleteable" = $True } ;
"Custom/Email" = @{ "Target" = "$managementSiteFolder/Custom/Email" ; "Child" = $True } ;
"Custom/Logo" = @{ "Target" = "$managementSiteFolder/Custom/OAI" ; "Child" = $True } ;
"Custom/WTCMessage" = @{ "Target" = "$managementSiteFolder/Custom/WTCMessage" ; "Child" = $True } ;
"Downloads" = @{ "Target" = "$managementSiteFolder/Downloads" ; "Writeable" = $False ; "Deleteable" = $True } ; # not in list, but already implemented
"RestoredFiles" = @{ "Target" = "$siteRootFolder/RestoredFiles" ; "Writeable" = $True ; "Deleteable" = $True } ;
"BulkUserExport" = @{ "Target" = "$managementSiteFolder/BulkUserExport" ; "Writeable" = $True ; "Deleteable" = $True } ;
"BulkUserImport" = @{ "Target" = "$managementSiteFolder/BulkUserImport" ; "Writeable" = $True ; "Deleteable" = $True } ;
"EventRules" = @{ "Target" = "$managementSiteFolder/EventRules" ; "Writeable" = $True ; "Deleteable" = $True } ;
"EventRules/AWE" = @{ "Target" = "$managementSiteFolder/EventRules/AWE" ; "Child" = $True } ;
"BastionSettings" = @{ "Target" = "$managementSiteFolder/BastionSettings" ; "Writeable" = $True ; "Deleteable" = $True } ;
}
try {
mkdir $managementSiteFolder
LogWrite "mkdir $managementSiteFolder"
}
catch {
LogWrite "failed: mkdir $managementSiteFolder" "ERROR"
}
# TODO: remove Backups/Restore from the user data share if it exists. The old folder existing is just an inconvenience if the restores
# are going to the user data share to avoid volume shadow copies. (Actually, Product doesn't think any production environments got deployed
# this way, so this is less of a priority ... and if we do that, we'd also have to adjust the folder monitor, too)
foreach ($folderAlias in $adminFolders.Keys) {
$f = $adminFolders[$folderAlias]
# create the target folder - certs and logs target already created (though maybe logs haven't been for older deployments)
if ($f -ne "Certs" -or $f -ne "Logs") {
#$oSite.CreatePhysicalFolder($f.Target) # this complains that -- Could not obtain the specified folder from the VFS tree.
LogWrite ("creating target folder {0}" -f $f.Target)
try {
if (-not (Test-Path $f.Target)) {
mkdir $f.Target | Out-Null # this requires the (config, logs?) shares to be mounted with appropriate permissions ; if already exits, no harm
LogWrite ("mkdir {0}" -f $f.Target)
}
else {
LogWrite ("target folder {0} already exists" -f $f.Target)
}
}
catch {
LogWrite ("error performing mkdir {0}" -f $f.Target) "ERROR"
}
}
if ($f.Child) {
# target VFS link is to a parent folder
continue;
}
# TODO: maybe better to delete to ensure we have the desired permissions and configuration?
#vfList = $oSite.GetVirtualFolderList("")
#Write-Output $vfList
# TODO: need to detect if folder already exists -- recreating it disturbs permissions
$bVirtualFolderExists = $null
$virtualFolder = "/ArcusManagementVFS/{0}" -f $folderAlias
try {
$bVirtualFolderExists = $customerSite.IsFolderVirtual($virtualFolder)
LogWrite ("$virtualFolder IsFolderVirtual: $bVirtualFolderExists")
}
catch {
}
if ($bVirtualFolderExists) {
LogWrite "$folderAlias already exists as a virtual folder ... skipping"
continue
}
LogWrite ("creating management site virtual folder {0} with target {1}" -f $folderAlias, $f.Target)
$customerSite.CreateVirtualFolder($virtualFolder, $f.Target)
# file permissions ; TODO: delete
$oPermission = $customerSite.GetBlankPermission("/ArcusManagementVFS/{0}" -f $folderAlias, "ArcusManagementGroup") #"ArcusManagement_UserTemplate") #"All Users")
$oPermission.FileDownload = $True
$oPermission.DirShowInList = $True
$oPermission.DirList = $True
if ($f.Writeable) {
$oPermission.FileUpload = $True
}
if ($f.Deleteable) {
$oPermission.FileDelete = $True
}
$customerSite.SetPermission($oPermission, $True)
}
$oServer.ApplyChanges()
LogWrite "done configuring management site" # TODO: DWM: write status to deployment queue for success visibility
#
# create event rules (TODO: DWM -- should we consider .psm1 modules for better testing, standalone invocation?)
# TODO: make error checking synchronous ... what is the COM equivalent of checking the "If Error Stop Processing?"
#
Function CreateMgmtSiteAction($osite, [string]$name, [int32]$processTimeout, [string]$adminSitePathToMonitor, [string]$parentPath,
[string]$inputParamName = "-jsonFile", [string]$conditionSuffix = "json") {
$scriptsDir = "{0}\Scripts64e3e669f861" -f $env:ARCUS_CONFIGFOLDERPATH
#
# create custom command to process NSG rules
#
LogWrite "creating $name CustomCommand"
try { $oCommandSettings = $oSite.GetCommandSettings($name) } catch { }
if ($oCommandSettings) {
$ccParams = $oCommandSettings.Parameters;
if($ccParams -match '\\gsbshared\\Scripts\\') {
$ccParams = $ccParams -replace '\\gsbshared\\Scripts\\', '\gsbshared\Scripts64e3e669f861\'
$oCommandSettings.Parameters = $ccParams;
$oServer.ApplyChanges();
LogWrite "Command $name already exists ... correcting Scripts path"
}
else {
LogWrite "Command $name already exists ... skipping"
}
}
else {
$oCommandSettings = $oSite.CreateCommand($name)
$oCommandSettings.Name = $name
$oCommandSettings.Executable = "C:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe"
$oCommandSettings.Parameters = "-ExecutionPolicy Bypass -File $scriptsDir\$name.ps1 $inputParamName %1%" # script signing an issue? prevents script from living on config share
$oCommandSettings.IsEnabled = $True
$oCommandSettings.RedirectOutputToLog = $False
if ($processTimeout -gt 0) {
$oCommandSettings.EnableProcessTimeOut = $True
$oCommandSettings.ProcessTimeOut = $processTimeout
}
else {
$oCommandSettings.EnableProcessTimeOut = $False
}
$oServer.ApplyChanges()
LogWrite "DONE: creating $name CustomCommand"
}
#
# create the FolderMonitor rule with a Virtual Path condition of *\ARMDB-Dumps\*.json ... invoke the FailedLoginReports command above
#
$cFolderMonitor = 0x1005;
$eventRules = $oSite.EventRules($cFolderMonitor);
$folderMonitorName = "{0}FolderMonitor" -f $name
$existingFM = $eventRules.Find($folderMonitorName)
if ($existingFM) {
if($deleteFolderMonitors) {
for($i = 0; $i -lt $eventRules.Count(); $i++) {
$erParams = $eventRules.Item($i).GetParams()
LogWrite "looking to delete folder monitor: $folderMonitorName ; comparing with $($erParams.Name)"
if($erParams.Name -eq $folderMonitorName) {
$eventRules.Delete($i)
LogWrite "deleting folder monitor $folderMonitorName"
break
}
}
}
else {
LogWrite "folder monitor $folderMonitorName already exists ... returning"
return
}
}
$folderToMonitor = ("{0}\{1}" -f $parentPath, $adminSitePathToMonitor)
mkdir $folderToMonitor -ErrorAction Ignore # this may fail if vanilla user doesn't have access to share
$eventRuleParams = New-Object -ComObject 'SFTPComInterface.CIFolderMonitorEventRuleParams';
$eventRuleParams.Name = $folderMonitorName;
$eventRuleParams.Enabled = $true;
$eventRuleParams.Description = "{0}FolderMonitor" -f $name;
$eventRuleParams.Path = $folderToMonitor
# enable this in the bootstrap script which will have access (running as the service account), but disable when running
# as a vanilla user because they will not have access
#if(-not (Test-Path $eventRuleParams.Path)) {
# LogWrite ("Folder Monitor target folder {0} does not exist ... skipping" -f $eventRuleParams.Path)
# return
#}
# disabling scans for now. Peraton seemed to require them, but scan can re-process files unless Archiving is in play, and archiving
# complicates the handoff with the powershell script (file is archived before the script processes it?)
$eventRuleParams.UsePeriodicDirectoryPoll = $False #$True
# $eventRuleParams.PollIntervalSeconds = 60
# $eventRuleParams.PollInterval = 60
# $eventRuleParams.PollIntervalType = 0 # seconds
LogWrite ("creating {0}FolderMonitor FolderMonitor event with path of {1}" -f $name, $eventRuleParams.Path)
$eventRule = $eventRules.Add($eventRules.Count(), $eventRuleParams);
LogWrite ("DONE: creating {0}FolderMonitor FolderMonitor event" -f $name)
LogWrite "creating the if file added condition"
$folderOperationProperty = 5008 # Folder operation
$conditionEqual = 0x01; # equal to
$varConditionValue = "added"
$bNot = $True
$ifFileAdded = $eventRule.AddIfStatement(0, $folderOperationProperty, $conditionEqual, $varConditionValue, $bNot);
$ifFileAddedStatements = $ifFileAdded.IfSection;
$stopAction = New-Object -ComObject 'SFTPComInterface.CIStopActionParams';
$ifFileAddedStatements.Add(0, $stopAction) | Out-Null
LogWrite "DONE: creating the if file added condition"
LogWrite "creating the if file path condition"
# having problems creating single match to handle multiple suffixes (array of matches doesn't work?), so create separate IF for each suffix
foreach($suffix in ($conditionSuffix -split ",")) {
$fileNameEventProperty = 5001 # 5001 is physical path, 5005 is file name;
$conditionMatch = 0x10;
$varConditionValue = "*\{0}\*.{1}" -f $adminSitePathToMonitor, $suffix
$bNot = $False
$ifMatch = $eventRule.AddIfStatement(1, $fileNameEventProperty, $conditionMatch, $varConditionValue, $bNot);
$ifMatchStatements = $ifMatch.IfSection;
LogWrite "DONE: creating the if file path condition"
LogWrite "creating the command action to invoke the powershell script"
$customCommandActionParams = New-Object -ComObject 'SFTPComInterface.CICommandActionParams'
$customCommandActionParams.Command = $name
$customCommandActionParams.Parameters = "%FS.PATH%"
$customCommandActionParams.WorkingFolder = "C:\"
$customCommandAction = $ifMatchStatements.Add(0, $customCommandActionParams);
}
LogWrite "DONE: creating the command action to invoke the powershell script"
LogWrite "applying changes"
$oServer.ApplyChanges()
LogWrite "DONE: applying changes"
}
CreateMgmtSiteAction -osite $oSite -name "ArmReports" -processTimeout 1200 -adminSitePathToMonitor "ARMDB-Dumps" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\AdminSite"
CreateMgmtSiteAction -osite $oSite -name "UpdateBackupPolicy" -processTimeout 60 -adminSitePathToMonitor "Backups" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\AdminSite"
CreateMgmtSiteAction -osite $oSite -name "ScanRestorePoints" -processTimeout 60 -adminSitePathToMonitor "Restore" -parentPath $env:ARCUS_SHAREDFOLDERPATH # user data share to avoid volume shadow copies
CreateMgmtSiteAction -osite $oSite -name "DisableAdmin" -processTimeout 60 -adminSitePathToMonitor "AdminUsers" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\AdminSite" # TODO: limit folder monitor to disable-admin.json, archive
$currentVersion = $env:ARCUS_CURRENTEFTVERSION
$suffices = @{}
if($currentVersion.StartsWith("7")) {
$suffices['PGP'] = 'asc'
$suffices['SSH'] = 'pub'
} else {
$suffices['PGP'] = 'json' # used to acccept asc directly, but now need json to specify site
$suffices['SSH'] = 'json'
}
CreateMgmtSiteAction -osite $oSite -name "ImportPgpKey" -processTimeout 60 -adminSitePathToMonitor "PgpKeyImports" `
-inputParamName "-keyFile" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\Config_Static" -conditionSuffix $suffices['PGP']
CreateMgmtSiteAction -osite $oSite -name "ImportSshPubKey" -processTimeout 60 -adminSitePathToMonitor "SshKeyImports" `
-inputParamName "-keyFile" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\Config_Static" -conditionSuffix $suffices['SSH']
CreateMgmtSiteAction -osite $oSite -name "ImportSslCert" -processTimeout 60 -adminSitePathToMonitor "SslCertImports" `
-inputParamName "-jsonFile" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\Config_Static" -conditionSuffix "json"
CreateMgmtSiteAction -osite $oSite -name "ExportPgpKey" -processTimeout 60 -adminSitePathToMonitor "PgpKeyExports" `
-inputParamName "-jsonFile" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\Config_Static" -conditionSuffix "json"
CreateMgmtSiteAction -osite $oSite -name "ExportSshPubKey" -processTimeout 60 -adminSitePathToMonitor "SshKeyExports" `
-inputParamName "-jsonFile" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\Config_Static" -conditionSuffix "json"
CreateMgmtSiteAction -osite $oSite -name "ExportSslCert" -processTimeout 60 -adminSitePathToMonitor "SslCertExports" `
-inputParamName "-jsonFile" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\Config_Static" -conditionSuffix "json"
CreateMgmtSiteAction -osite $oSite -name "EFT.UserBulk.Import" -processTimeout 1800 -adminSitePathToMonitor "BulkUserImport" `
-inputParamName "-UserCsvlist" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\AdminSite" -conditionSuffix "csv"
CreateMgmtSiteAction -osite $oSite -name "EFT.UserBulk.Export" -processTimeout 1800 -adminSitePathToMonitor "BulkUserExport" `
-inputParamName "-jsonFile" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\AdminSite" -conditionSuffix "json"
CreateMgmtSiteAction -osite $oSite -name "BastionWhitelistIPs" -processTimeout 1800 -adminSitePathToMonitor "BastionSettings" `
-inputParamName "-jsonFile" -parentPath "$($env:ARCUS_CONFIGFOLDERPATH)\AdminSite" -conditionSuffix "json"