public/Invoke-VPASHealthCheck.ps1
|
<#
.Synopsis Run a system healthcheck CREATED BY: Vadim Melamed, EMAIL: vpasmodule@gmail.com .DESCRIPTION Use this function to run a health check that performs various checks (account compliance, component status, empty safes, inactive platforms, inactive users, etc.) .LINK https://vpasmodule.com/commands.html#Invoke-VPASHealthCheck .NOTES Category: PAM Tag: Metrics Since: v14.4.1 Version: 6 SelfHosted: TRUE PrivCloudStandard: TRUE SharedServices: TRUE SRS: TRUE .PARAMETER token HashTable of data containing various pieces of login information (PVWA, LoginToken, HeaderType, etc). If -token is not passed, function will use last known hashtable generated by New-VPASToken .PARAMETER ExportToCSV Output results to a CSV file found in AppData\Local\VPASModuleOutputs directory .PARAMETER CSVDirectory Output directory where the exported CSV file will be saved to Default value: C:\Users\{CurrentUser}\AppData\Local\VPASModuleOutputs\ExportedCSVs .PARAMETER InputParameters HashTable of values containing the parameters required to make the API call .EXAMPLE $HealthCheck = Invoke-VPASHealthCheck .EXAMPLE $InputParameters = @{ ExportToCSV = $true|$false CSVDirectory = "C:\Temp" } $HealthCheck = Invoke-VPASHealthCheck -InputParameters $InputParameters .OUTPUTS If successful: { "UnusedAssetsCheck": [ { "TargetName": "UnusedAppID", "Category": "ApplicationID", "Recommendation": "Recommendation: delete unused application IDs (UnusedAppID) to help reduce clutter", "Check": "UnusedAssetsCheck" }, { "TargetName": "UnusedSafe1", "Category": "Safe", "Recommendation": "Recommendation: delete unused Safes (UnusedSafe1) to help reduce clutter", "Check": "UnusedAssetsCheck" } ] } --- $false if failed #> function Invoke-VPASHealthCheck{ [OutputType('System.Object',[bool])] [CmdletBinding(DefaultParameterSetName='Set1')] Param( [Parameter(Mandatory=$false,ParameterSetName='Set1',ValueFromPipelineByPropertyName=$true)] [Switch]$ExportToCSV, [Parameter(Mandatory=$false,ParameterSetName='Set1',ValueFromPipelineByPropertyName=$true)] [String]$CSVDirectory, [Parameter(Mandatory=$true,ParameterSetName='InputParameters',ValueFromPipelineByPropertyName=$true,HelpMessage="Hashtable of parameters required to make API call, refer to get-help -examples for valid inputs")] [hashtable]$InputParameters, [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,Position=0)] [hashtable]$token ) Begin{ $tokenval,$sessionval,$PVWA,$Header,$ISPSS,$IdentityURL,$EnableTextRecorder,$AuditTimeStamp,$NoSSL,$VaultVersion,$HideWarnings,$AuthenticatedAs,$SubDomain,$EnableTroubleshooting,$APICounter,$Creds,$AuthType,$IDPLogin,$SRS = Get-VPASSession -token $token $CommandName = $MyInvocation.MyCommand.Name $log = Write-VPASTextRecorder -inputval $CommandName -token $token -LogType COMMAND } Process{ try{ if($PSCmdlet.ParameterSetName -eq "InputParameters"){ $KeyHash = @{ set1 = @{ AcceptableKeys = @("ExportToCSV","CSVDirectory") MandatoryKeys = @() } } $CheckSet = Test-VPASHashtableKeysHelper -InputHash $InputParameters -KeyHash $KeyHash if(!$CheckSet){ $log = Write-VPASTextRecorder -inputval "FAILED TO FIND TARGET PARAMETER SET" -token $token -LogType MISC Write-Verbose "FAILED TO FIND TARGET PARAMETER SET" Write-VPASOutput -str "FAILED TO FIND TARGET PARAMETER SET...VIEW EXAMPLES BELOW:" -type E $examples = Write-VPASExampleHelper -CommandName $CommandName return $false } else{ foreach($key in $InputParameters.Keys){ Set-Variable -Name $key -Value $InputParameters.$key } } } }catch{ $log = Write-VPASTextRecorder -inputval $_ -token $token -LogType ERROR $log = Write-VPASTextRecorder -inputval "REST API COMMAND RETURNED: FALSE" -token $token -LogType MISC Write-Verbose "FAILED TO GENERATE HEALTHCHECK REPORT" Write-VPASOutput -str $_ -type E return $false } try{ Write-VPASOutput -str "***INITIALIZING HEALTHCHECK VARIABLES***" -type G $outputmatrix = @{ VersionCheck = @() ComponentStatusCheck = @() EmptySafeCheck = @() ApplicationAuthMethodCheck = @() AccountComplianceCheck = @() InactivePlatformCheck = @() UnusedAssetsCheck = @() InactiveUserCheck = @() UnknownAssetCheck = @() } $onpremflag = $false if(!$ISPSS -and ($PVWA -notmatch ".privilegecloud.cyberark.")){ $onpremflag = $true } $SystemComponents = @{ CPM = @{ UniqueNames = @() } PVWA = @{ UniqueNames = @() } AIMPROV = @{ UniqueNames = @() } PSM = @{ UniqueNames = @() } VAULT = @{ Version = 0 } APPID = @{ Uniquenames = @() } SAFE = @{ Uniquenames = @() } PLATFORM = @{ Uniquenames = @() } PSMSERVERID = @{ Uniquenames = @() } CONNECTIONCOMPONENT = @{ Uniquenames = @() } ACCOUNT = @{ } } Write-VPASOutput -str "*Note, some of the checks below may take some time depending on the environment size" -type C #region VersionCheck Write-VPASOutput -str "***RUNNING COMPONENT VERSION + HEALTH CHECKS***" -type G $AllCPMs = Get-VPASSystemHealth -Component CPM -token $token $AllPSMs = Get-VPASSystemHealth -Component PSM -token $token $AllPVWAs = Get-VPASSystemHealth -Component PVWA -token $token $AllAIMs = Get-VPASSystemHealth -Component AIM -token $token $VaultVersion = (Get-VPASVaultVersion -token $token).ExternalVersion if(!$VaultVersion){ $SystemComponents.Vault = @{ Version = "UNCLEAR" } } else{ $tempversionarr = $VaultVersion -split "\." $VaultVersion = [Double]($tempversionarr[0] + "." + $tempversionarr[1]) $SystemComponents.Vault = @{ Version = $VaultVersion } } foreach($rec in $AllCPMs.ComponentsDetails){ $ComponentName = $rec.ComponentUserName $ComponentVersion = $rec.ComponentVersion $ComponentStatus = $rec.IsLoggedOn $ComponentIP = $rec.ComponentIP $tempversionarr = $ComponentVersion -split "\." $ComponentVersion = [Double]($tempversionarr[0] + "." + $tempversionarr[1]) $SystemComponents.CPM += @{ $ComponentName = @{ ComponentUsername = $ComponentName ComponentVersion = $ComponentVersion ComponentStatus = $ComponentStatus ComponentIP = $ComponentIP SafeAccess = $false } } $SystemComponents.CPM.UniqueNames += $ComponentName if($ComponentVersion -lt $VaultVersion){ $outputmatrix.VersionCheck += @{ Check = "VersionCheck" Category = "CPM" TargetName = $ComponentName Recommendation = "Recommendation: update CPM $ComponentName@$ComponentIP from $ComponentVersion to match vault version $VaultVersion" } } if(!$ComponentStatus){ $outputmatrix.ComponentStatusCheck += @{ Check = "ComponentStatusCheck" Category = "CPM" TargetName = $ComponentName Recommendation = "Recommendation: reconnect CPM $ComponentName@$ComponentIP to restore functionality" } } } foreach($rec in $AllPSMs.ComponentsDetails){ $ComponentName = $rec.ComponentUserName $ComponentVersion = $rec.ComponentVersion $ComponentStatus = $rec.IsLoggedOn $ComponentIP = $rec.ComponentIP $tempversionarr = $ComponentVersion -split "\." $ComponentVersion = [Double]($tempversionarr[0] + "." + $tempversionarr[1]) $SystemComponents.PSM += @{ $ComponentName = @{ ComponentUsername = $ComponentName ComponentVersion = $ComponentVersion ComponentStatus = $ComponentStatus ComponentIP = $ComponentIP } } $SystemComponents.PSM.UniqueNames += $ComponentName if($ComponentVersion -lt $VaultVersion){ $outputmatrix.VersionCheck += @{ Check = "VersionCheck" Category = "PSM" TargetName = $ComponentName Recommendation = "Recommendation: update PSM $ComponentName@$ComponentIP from $ComponentVersion to match vault version $VaultVersion" } } if(!$ComponentStatus){ $outputmatrix.ComponentStatusCheck += @{ Check = "ComponentStatusCheck" Category = "PSM" TargetName = $ComponentName Recommendation = "Recommendation: reconnect PSM $ComponentName@$ComponentIP to restore functionality" } } } if($onpremflag){ foreach($rec in $AllPVWAs.ComponentsDetails){ $ComponentName = $rec.ComponentUserName $ComponentVersion = $rec.ComponentVersion $ComponentStatus = $rec.IsLoggedOn $ComponentIP = $rec.ComponentIP $tempversionarr = $ComponentVersion -split "\." $ComponentVersion = [Double]($tempversionarr[0] + "." + $tempversionarr[1]) $SystemComponents.PVWA += @{ $ComponentName = @{ ComponentUsername = $ComponentName ComponentVersion = $ComponentVersion ComponentStatus = $ComponentStatus ComponentIP = $ComponentIP } } $SystemComponents.PVWA.UniqueNames += $ComponentName if($ComponentVersion -lt $VaultVersion){ $outputmatrix.VersionCheck += @{ Check = "VersionCheck" Category = "PVWA" TargetName = $ComponentName Recommendation = "Recommendation: update PVWA $ComponentName@$ComponentIP from $ComponentVersion to match vault version $VaultVersion" } } if(!$ComponentStatus){ $outputmatrix.ComponentStatusCheck += @{ Check = "ComponentStatusCheck" Category = "PVWA" TargetName = $ComponentName Recommendation = "Recommendation: reconnect PVWA $ComponentName@$ComponentIP to restore functionality" } } } } foreach($rec in $AllAIMs.ComponentsDetails){ $ComponentName = $rec.ComponentUserName $ComponentVersion = $rec.ComponentVersion $ComponentStatus = $rec.IsLoggedOn $ComponentIP = $rec.ComponentIP $tempversionarr = $ComponentVersion -split "\." $ComponentVersion = [Double]($tempversionarr[0] + "." + $tempversionarr[1]) $SystemComponents.AIMPROV += @{ $ComponentName = @{ ComponentUsername = $ComponentName ComponentVersion = $ComponentVersion ComponentStatus = $ComponentStatus ComponentIP = $ComponentIP SafeAccess = $false IsGroup = $false } } $SystemComponents.AIMPROV.UniqueNames += $ComponentName $epvgroups = (Get-VPASEPVUserDetails -EPVUsername $ComponentName -token $token).groupsMembership foreach($grouprec in $epvgroups){ $group = $grouprec.groupName if($SystemComponents.AIMPROV.$group){ $SystemComponents.AIMPROV.$group.Providers += $ComponentName } else{ $SystemComponents.AIMPROV += @{ $group = @{ IsGroup = $true Providers = @($ComponentName) SafeAccess = $false } } $SystemComponents.AIMPROV.Uniquenames += $group } } if($ComponentVersion -lt $VaultVersion){ $outputmatrix.VersionCheck += @{ Check = "VersionCheck" Category = "AIM" TargetName = $ComponentName Recommendation = "Recommendation: update AIM Provider $ComponentName@$ComponentIP from $ComponentVersion to match vault version $VaultVersion" } } if(!$ComponentStatus){ $outputmatrix.ComponentStatusCheck += @{ Check = "ComponentStatusCheck" Category = "AIM" TargetName = $ComponentName Recommendation = "Recommendation: reconnect AIM Provider $ComponentName@$ComponentIP to restore functionality" } } } #endregion VersionCheck #region ApplicationCheck Write-VPASOutput -str "***RUNNING APPLICATION HEALTH CHECKS***" -type G if($SystemComponents.AIMPROV.UniqueNames.Count -gt 0){ $AllApplications = Get-VPASAllApplications -token $token foreach($app in $AllApplications){ $appname = $app.AppID if($appname -eq "AIMWebService"){ #DO NOTHING } else{ $SystemComponents.APPID += @{ $appname = @{ AppID = $appname SafeAccess = $false IsGroup = $false } } $SystemComponents.APPID.Uniquenames += $appname $epvgroups = (Get-VPASEPVUserDetails -EPVUsername $appname -token $token).groupsMembership foreach($grouprec in $epvgroups){ $group = $grouprec.groupName if($SystemComponents.APPID.$group){ $SystemComponents.APPID.$group.AppIDs += $appname } else{ $SystemComponents.APPID += @{ $group = @{ IsGroup = $true AppIDs = @($appname) SafeAccess = $false } } $SystemComponents.APPID.Uniquenames += $group } } $ApplicationAuthmethods = Get-VPASApplicationAuthentications -AppID $appname -token $token if($ApplicationAuthmethods.authentication.Count -eq 0){ $outputmatrix.ApplicationAuthMethodCheck += @{ Check = "ApplicationAuthMethodCheck" Category = "Application" TargetName = $appname Recommendation = "Recommendation: Using an application with no authentication method configured is not recommended in any scenario. Add an authentication method to ApplicationID: $appname" } } } } } #endregion ApplicationCheck #region SafeCheck Write-VPASOutput -str "***RUNNING SAFE + SAFE MEMBER HEALTH CHECKS***" -type G $SkipSafes = @( "VaultInternal", "Notification Engine", "SharedAuth_Internal", "PVWAReports", "PVWATicketingSystem", "PVWAPublicData", "TelemetryConfig", "PasswordManager_Pending", "AccountsFeedADAccounts", "AccountsFeedDiscoveryLogs", "PSM", "PSMUniversalConnectors", "PSMRecordings", "PVWAConfig", "PVWAUserPrefs", "PVWAPrivateUserPrefs", "PVWATaskDefinitions", "PSMSessions", "PSMLiveSessions", "PSMUnmanagedSessionAccounts", "PSMNotifications", "PSMPConf", "PSMPLiveSessions", "PSMPADBUserProfile", "PSMPADBridgeCustom", "PSMPADBridgeConf", "AppProviderCacheSafe" ) foreach($val in $SystemComponents.CPM.UniqueNames){ $SkipSafes += $val $SkipSafes += $val + "_Accounts" } $AllSafes = Get-VPASAllSafes -IncludeAccounts -token $token foreach($safe in $AllSafes.value){ $safename = $safe.safeName if(!$SkipSafes.Contains($safename)){ $SystemComponents.SAFE.Uniquenames += $safename $SystemComponents.SAFE += @{ $safename = @{ Accounts = @{} } } #EMPTY SAFE CHECK if($safe.accounts.count -eq 0){ $outputmatrix.EmptySafeCheck += @{ Check = "EmptySafeCheck" Category = "Safe" TargetName = $safename Recommendation = "Recommendation: delete unused or empty safes ($safename) to help reduce clutter (assuming safe permissions allow viewing safe content)" } } else{ foreach($acct in $safe.accounts.id){ $SystemComponents.SAFE.$safename.Accounts += @{ $acct = @{ AcctID = $acct } } } } #GET MANAGED CPM $managedCPM = $safe.managingCPM if(![String]::IsNullOrEmpty($managedCPM)){ $SystemComponents.CPM.$managedCPM.SafeAccess = $true } #CHECK SAFE MEMBERS $AllSafeMembers = Get-VPASSafeMembers -safe $safename -token $token foreach($mem in $AllSafeMembers.value.membername){ if($SystemComponents.APPID.Uniquenames.Contains($mem)){ $SystemComponents.APPID.$mem.SafeAccess = $true } if($SystemComponents.AIMPROV.UniqueNames.Contains($mem)){ $SystemComponents.AIMPROV.$mem.SafeAccess = $true } } } } #endregion SafeCheck #region PSMCheck Write-VPASOutput -str "***RUNNING PSM + CONNECTOR HEALTH CHECKS***" -type G $AllPSMServerIDs = Get-VPASAllPSMServers -token $token foreach($PSMServerID in $AllPSMServerIDs.PSMServers.ID){ $SystemComponents.PSMSERVERID += @{ $PSMServerID = @{ PSMServerID = $PSMServerID InUse = $false } } $SystemComponents.PSMSERVERID.Uniquenames += $PSMServerID } $AllConnectors = Get-VPASAllConnectionComponents -token $token foreach($connector in $AllConnectors.PSMConnectors.ID){ if($connector -match "sample"){ $SystemComponents.CONNECTIONCOMPONENT += @{ $connector = @{ ConnectorID = $connector InUse = $true } } } else{ $SystemComponents.CONNECTIONCOMPONENT += @{ $connector = @{ ConnectorID = $connector InUse = $false } } } $SystemComponents.CONNECTIONCOMPONENT.Uniquenames += $connector } #endregion PSMCheck #region AccountCheck Write-VPASOutput -str "***RUNNING ACCOUNT HEALTH CHECKS***" -type G $ignoreplatforms = @("EPMLCDKey") $AllPlatforms = Get-VPASAllTargetPlatforms -token $token foreach($plat in $AllPlatforms.Platforms){ $platID = $plat.PlatformID $platStatus = $plat.Active $platPSM = $plat.PrivilegedSessionManagement.PSMServerId $SystemComponents.PLATFORM.Uniquenames += $platID $SystemComponents.PLATFORM += @{ $platID = @{ platformID = $platID platformStatus = $platStatus platformInUse = $false } } if(![String]::IsNullOrEmpty($platID)){ if(![String]::IsNullOrEmpty($platPSM)){ if($SystemComponents.PSMSERVERID.$platPSM){ $SystemComponents.PSMSERVERID.$platPSM.InUse = $true } else{ $outputmatrix.UnknownAssetCheck += @{ Check = "UnknownAssetCheck" Category = "PSM" TargetName = "$platPSM" Recommendation = "Recommendation: unknown PSMServerID assigned to platform $platID (PSMServerID: $platPSM)...assign an existing PSMServerID to restore functionality" } } } $platdetails = Get-VPASPSMSettingsByPlatformID -PlatformID $platID -token $token foreach($con in $platdetails.PSMConnectors.PSMConnectorID){ if($SystemComponents.CONNECTIONCOMPONENT.$con){ $SystemComponents.CONNECTIONCOMPONENT.$con.InUse = $true } else{ $outputmatrix.UnknownAssetCheck += @{ Check = "UnknownAssetCheck" Category = "PSMConnector" TargetName = "$con" Recommendation = "Recommendation: unknown PSMConnector assigned to platform $platID (PSMConnector: $con). Remove the connector from the platform to clear up clutter" } } } } } foreach($safe in $SystemComponents.SAFE.Keys){ #LOOP THROUGH EVERY SAFE if($safe -ne "Uniquenames"){ foreach($AcctID in $SystemComponents.SAFE.$safe.Accounts.Keys){ $AcctDetails = Get-VPASAccountDetailsExtended -AcctID $AcctID -token $token $IsCompliant = $AcctDetails.Compliance.IsCompliant $targetPlat = $AcctDetails.Platform.PlatformID $platstatus = $AcctDetails.Platform.IsActive $acctname = $AcctDetails.Details.Name if([String]::IsNullOrEmpty($targetPlat)){ $outputmatrix.InactivePlatformCheck += @{ Check = "InactivePlatformCheck" Category = "Account" TargetName = $acctname Recommendation = "Recommendation: accounts attached to an inactive or blank platform will remain non functional. Move $acctname from {BlankPlatform} to an active platfrom" } } elseif($ignoreplatforms.Contains($targetPlat)){ #DO NOTHING } else{ if($SystemComponents.PLATFORM.$targetPlat){ $SystemComponents.PLATFORM.$targetPlat.platformInUse = $true } else{ $SystemComponents.PLATFORM += @{ $targetPlat = @{ platformID = $targetPlat platformStatus = $platStatus platformInUse = $true } } } if(!$IsCompliant){ $outputmatrix.AccountComplianceCheck += @{ Check = "AccountComplianceCheck" Category = "Account" TargetName = $acctname Recommendation = "Recommendation: resolve any errors associated with the account ($acctname) to restore compliance and enable rotation where applicable" } } if(!$platStatus){ $outputmatrix.InactivePlatformCheck += @{ Check = "InactivePlatformCheck" Category = "Account" TargetName = $acctname Recommendation = "Recommendation: accounts attached to an inactive or blank platform will remain non functional. Move $acctname from platform $targetPlat to an active platfrom" } } } } } } #endregion AccountCheck #region UnusedAssetCheck Write-VPASOutput -str "***RUNNING UNUSED ASSETS CHECKS***" -type G #APPIDS - Step1 Groups foreach($targetval in $SystemComponents.APPID.Keys){ if($targetval -ne "Uniquenames"){ $inuse = $SystemComponents.APPID.$targetval.SafeAccess $isgroup = $SystemComponents.APPID.$targetval.IsGroup if($isgroup){ if($inuse){ foreach($appid in $SystemComponents.APPID.$targetval.AppIDs){ $SystemComponents.APPID.$appid.SafeAccess = $true } } } } } #APPIDS - Step2 AppIDs foreach($targetval in $SystemComponents.APPID.Keys){ if($targetval -ne "Uniquenames"){ $inuse = $SystemComponents.APPID.$targetval.SafeAccess $isgroup = $SystemComponents.APPID.$targetval.IsGroup if(!$isgroup){ if(!$inuse){ $outputmatrix.UnusedAssetsCheck += @{ Check = "UnusedAssetsCheck" Category = "ApplicationID" TargetName = $targetval Recommendation = "Recommendation: delete unused application IDs ($targetval) to help reduce clutter" } } } } } #PLATFORMS foreach($targetval in $SystemComponents.PLATFORM.Keys){ if($targetval -ne "Uniquenames"){ if($ignoreplatforms.Contains($targetval)){ #DO NOTHING } else{ $inuse = $SystemComponents.PLATFORM.$targetval.platformInUse $isactive = $SystemComponents.PLATFORM.$targetval.platformStatus if($isactive){ if(!$inuse){ $outputmatrix.UnusedAssetsCheck += @{ Check = "UnusedAssetsCheck" Category = "Platform" TargetName = $targetval Recommendation = "Recommendation: deactivate or delete unused platforms ($targetval) to help reduce clutter and CPM load" } } } } } } #AIMPROV - Step1 Groups foreach($targetval in $SystemComponents.AIMPROV.Keys){ if($targetval -ne "Uniquenames"){ $inuse = $SystemComponents.AIMPROV.$targetval.SafeAccess $isgroup = $SystemComponents.AIMPROV.$targetval.IsGroup if($isgroup){ if($inuse){ foreach($appid in $SystemComponents.AIMPROV.$targetval.Providers){ $SystemComponents.AIMPROV.$appid.SafeAccess = $true } } } } } #AIMPROV - Step2 Providers foreach($targetval in $SystemComponents.AIMPROV.Keys){ if($targetval -ne "Uniquenames"){ $inuse = $SystemComponents.AIMPROV.$targetval.SafeAccess $isgroup = $SystemComponents.AIMPROV.$targetval.IsGroup if(!$isgroup){ if(!$inuse){ $outputmatrix.UnusedAssetsCheck += @{ Check = "UnusedAssetsCheck" Category = "AIMProviders" TargetName = $targetval Recommendation = "Recommendation: delete/uninstall unused providers ($targetval) to help reduce clutter and to free up provider licenses" } } } } } #CPMs foreach($targetval in $SystemComponents.CPM.Keys){ if($targetval -ne "Uniquenames"){ $inuse = $SystemComponents.CPM.$targetval.SafeAccess if(!$inuse){ $outputmatrix.UnusedAssetsCheck += @{ Check = "UnusedAssetsCheck" Category = "CPM" TargetName = $targetval Recommendation = "Recommendation: delete/uninstall unused CPMs ($targetval) to help reduce clutter and to free up a CPM license" } } } } #PSMServerIDs foreach($targetval in $SystemComponents.PSMSERVERID.Keys){ if($targetval -ne "Uniquenames"){ $inuse = $SystemComponents.PSMSERVERID.$targetval.InUse if(!$inuse){ $outputmatrix.UnusedAssetsCheck += @{ Check = "UnusedAssetsCheck" Category = "PSMServer" TargetName = $targetval Recommendation = "Recommendation: delete unused PSM configuration ($targetval) to help reduce clutter" } } } } #ConnectionComponents foreach($targetval in $SystemComponents.CONNECTIONCOMPONENT.Keys){ if($targetval -ne "Uniquenames"){ $inuse = $SystemComponents.CONNECTIONCOMPONENT.$targetval.InUse if(!$inuse){ $outputmatrix.UnusedAssetsCheck += @{ Check = "UnusedAssetsCheck" Category = "ConnectionComponent" TargetName = $targetval Recommendation = "Recommendation: delete unused ConnectionComponent configurations ($targetval) to help reduce clutter" } } } } #endregion UnusedAssetCheck #region UserCheck Write-VPASOutput -str "***RUNNING USER HEALTH CHECKS***" -type G $curTime = ([int][double]::Parse((Get-Date (get-date (get-date).Date).ToLocalTime() -UFormat %s))) $cutTime = ([int][double]::Parse((Get-Date (get-date (get-date).Date.AddYears(-1)).ToLocalTime() -UFormat %s))) $ignoreusers = @() $AllUsers = Get-VPASAllEPVUsers -token $token foreach($user in $AllUsers.Users){ $userusername = $user.username $userid = $user.id $usertype = $user.userType if($usertype -eq "EPVUser"){ $userdetails = Get-VPASEPVUserDetails -EPVUserID $userid -token $token $lastlogin = $userdetails.lastSuccessfulLoginDate if($lastlogin -le $cutTime){ $outputmatrix.InactiveUserCheck += @{ Check = "InactiveUserCheck" Category = "User" TargetName = "$userusername" Recommendation = "Recommendation: $userusername has not logged into Idira (formerly CyberArk) in the last year. Consider removing the user to free up a user license" } } } } #endregion UserCheck if($ExportToCSV){ $runexport = Write-VPASExportCSV -Data $outputmatrix -CommandName $CommandName -CSVDirectory $CSVDirectory } $log = Write-VPASTextRecorder -inputval $outputmatrix -token $token -LogType RETURNARRAY Write-Verbose "PARSING DATA FROM IDIRA (formerly CyberArk)" Write-Verbose "RETURNING JSON OBJECT" return $outputmatrix }catch{ $log = Write-VPASTextRecorder -inputval $_ -token $token -LogType ERROR $log = Write-VPASTextRecorder -inputval "REST API COMMAND RETURNED: FALSE" -token $token -LogType MISC Write-Verbose "UNABLE TO GENERATE USER LICENSE REPORT" Write-VPASOutput -str $_ -type E return $false } } End{ $log = Write-VPASTextRecorder -inputval $CommandName -token $token -LogType DIVIDER $token = Update-VPASSession -AddCounter $APICounter -InputToken $token } } # SIG # Begin signature block # MIIsuQYJKoZIhvcNAQcCoIIsqjCCLKYCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU2N8aXU/Drh4169btSpCY7/cn # 51WggiXzMIIFbzCCBFegAwIBAgIQSPyTtGBVlI02p8mKidaUFjANBgkqhkiG9w0B # AQwFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVy # MRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEh # MB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTIxMDUyNTAwMDAw # MFoXDTI4MTIzMTIzNTk1OVowVjELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3Rp # Z28gTGltaXRlZDEtMCsGA1UEAxMkU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5n # IFJvb3QgUjQ2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjeeUEiIE # JHQu/xYjApKKtq42haxH1CORKz7cfeIxoFFvrISR41KKteKW3tCHYySJiv/vEpM7 # fbu2ir29BX8nm2tl06UMabG8STma8W1uquSggyfamg0rUOlLW7O4ZDakfko9qXGr # YbNzszwLDO/bM1flvjQ345cbXf0fEj2CA3bm+z9m0pQxafptszSswXp43JJQ8mTH # qi0Eq8Nq6uAvp6fcbtfo/9ohq0C/ue4NnsbZnpnvxt4fqQx2sycgoda6/YDnAdLv # 64IplXCN/7sVz/7RDzaiLk8ykHRGa0c1E3cFM09jLrgt4b9lpwRrGNhx+swI8m2J # mRCxrds+LOSqGLDGBwF1Z95t6WNjHjZ/aYm+qkU+blpfj6Fby50whjDoA7NAxg0P # OM1nqFOI+rgwZfpvx+cdsYN0aT6sxGg7seZnM5q2COCABUhA7vaCZEao9XOwBpXy # bGWfv1VbHJxXGsd4RnxwqpQbghesh+m2yQ6BHEDWFhcp/FycGCvqRfXvvdVnTyhe # Be6QTHrnxvTQ/PrNPjJGEyA2igTqt6oHRpwNkzoJZplYXCmjuQymMDg80EY2NXyc # uu7D1fkKdvp+BRtAypI16dV60bV/AK6pkKrFfwGcELEW/MxuGNxvYv6mUKe4e7id # FT/+IAx1yCJaE5UZkADpGtXChvHjjuxf9OUCAwEAAaOCARIwggEOMB8GA1UdIwQY # MBaAFKARCiM+lvEH7OKvKe+CpX/QMKS0MB0GA1UdDgQWBBQy65Ka/zWWSC8oQEJw # IDaRXBeF5jAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zATBgNVHSUE # DDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEMGA1Ud # HwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0FBQUNlcnRpZmlj # YXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBDAUAA4IBAQASv6Hvi3Sa # mES4aUa1qyQKDKSKZ7g6gb9Fin1SB6iNH04hhTmja14tIIa/ELiueTtTzbT72ES+ # BtlcY2fUQBaHRIZyKtYyFfUSg8L54V0RQGf2QidyxSPiAjgaTCDi2wH3zUZPJqJ8 # ZsBRNraJAlTH/Fj7bADu/pimLpWhDFMpH2/YGaZPnvesCepdgsaLr4CnvYFIUoQx # 2jLsFeSmTD1sOXPUC4U5IOCFGmjhp0g4qdE2JXfBjRkWxYhMZn0vY86Y6GnfrDyo # XZ3JHFuu2PMvdM+4fvbXg50RlmKarkUT2n/cR/vfw1Kf5gZV6Z2M8jpiUbzsJA8p # 1FiAhORFe1rYMIIGGjCCBAKgAwIBAgIQYh1tDFIBnjuQeRUgiSEcCjANBgkqhkiG # 9w0BAQwFADBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVk # MS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYw # HhcNMjEwMzIyMDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBUMQswCQYDVQQGEwJHQjEY # MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1Ymxp # YyBDb2RlIFNpZ25pbmcgQ0EgUjM2MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB # igKCAYEAmyudU/o1P45gBkNqwM/1f/bIU1MYyM7TbH78WAeVF3llMwsRHgBGRmxD # eEDIArCS2VCoVk4Y/8j6stIkmYV5Gej4NgNjVQ4BYoDjGMwdjioXan1hlaGFt4Wk # 9vT0k2oWJMJjL9G//N523hAm4jF4UjrW2pvv9+hdPX8tbbAfI3v0VdJiJPFy/7Xw # iunD7mBxNtecM6ytIdUlh08T2z7mJEXZD9OWcJkZk5wDuf2q52PN43jc4T9OkoXZ # 0arWZVeffvMr/iiIROSCzKoDmWABDRzV/UiQ5vqsaeFaqQdzFf4ed8peNWh1OaZX # nYvZQgWx/SXiJDRSAolRzZEZquE6cbcH747FHncs/Kzcn0Ccv2jrOW+LPmnOyB+t # AfiWu01TPhCr9VrkxsHC5qFNxaThTG5j4/Kc+ODD2dX/fmBECELcvzUHf9shoFvr # n35XGf2RPaNTO2uSZ6n9otv7jElspkfK9qEATHZcodp+R4q2OIypxR//YEb3fkDn # 3UayWW9bAgMBAAGjggFkMIIBYDAfBgNVHSMEGDAWgBQy65Ka/zWWSC8oQEJwIDaR # XBeF5jAdBgNVHQ4EFgQUDyrLIIcouOxvSK4rVKYpqhekzQwwDgYDVR0PAQH/BAQD # AgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwGwYD # VR0gBBQwEjAGBgRVHSAAMAgGBmeBDAEEATBLBgNVHR8ERDBCMECgPqA8hjpodHRw # Oi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RS # NDYuY3JsMHsGCCsGAQUFBwEBBG8wbTBGBggrBgEFBQcwAoY6aHR0cDovL2NydC5z # ZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290UjQ2LnA3YzAj # BggrBgEFBQcwAYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEM # BQADggIBAAb/guF3YzZue6EVIJsT/wT+mHVEYcNWlXHRkT+FoetAQLHI1uBy/YXK # ZDk8+Y1LoNqHrp22AKMGxQtgCivnDHFyAQ9GXTmlk7MjcgQbDCx6mn7yIawsppWk # vfPkKaAQsiqaT9DnMWBHVNIabGqgQSGTrQWo43MOfsPynhbz2Hyxf5XWKZpRvr3d # MapandPfYgoZ8iDL2OR3sYztgJrbG6VZ9DoTXFm1g0Rf97Aaen1l4c+w3DC+IkwF # kvjFV3jS49ZSc4lShKK6BrPTJYs4NG1DGzmpToTnwoqZ8fAmi2XlZnuchC4NPSZa # PATHvNIzt+z1PHo35D/f7j2pO1S8BCysQDHCbM5Mnomnq5aYcKCsdbh0czchOm8b # kinLrYrKpii+Tk7pwL7TjRKLXkomm5D1Umds++pip8wH2cQpf93at3VDcOK4N7Ew # oIJB0kak6pSzEu4I64U6gZs7tS/dGNSljf2OSSnRr7KWzq03zl8l75jy+hOds9TW # SenLbjBQUGR96cFr6lEUfAIEHVC1L68Y1GGxx4/eRI82ut83axHMViw1+sVpbPxg # 51Tbnio1lB93079WPFnYaOvfGAA0e0zcfF/M9gXr+korwQTh2Prqooq2bYNMvUoU # KD85gnJ+t0smrWrb8dee2CvYZXD5laGtaAxOfy/VKNmwuWuAh9kcMIIGRzCCBK+g # AwIBAgIQacs5SDkvNuif0aEmZmr03jANBgkqhkiG9w0BAQwFADBUMQswCQYDVQQG # EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdv # IFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2MB4XDTI1MDEyOTAwMDAwMFoXDTI4 # MDEyOTIzNTk1OVowXjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCk5ldyBKZXJzZXkx # HDAaBgNVBAoME0N5YmVyTWVsIENvbnN1bHRpbmcxHDAaBgNVBAMME0N5YmVyTWVs # IENvbnN1bHRpbmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDBQmSv # dfamF8o0CJr4vbHCcJ4rwx6T1HR3d32u4aIf9v9p/GV4nFdG4PP9SMjWw7Nx9CLF # qGPpkw7aDU2IxwpfPYExDzkCj2pgiyeVKlL0itTlPocb6i1cZLe/WHV7aUkGkVlf # vyYIqdJ9uw711dhNWmMhlqo+/qyp+gpKqaiFHm6mWNVg2KLTH5Pu38cBoGhS1tn7 # mlQbtALNjehkpFw2AAntEIBzM3ZEg9WBxQlgYY0yAPkydYbJfTEOEFJqHUPTSV46 # jx22Jb9dl0cEIPsGrCp+Jo5Ugusp9oZECZ8bGt7Vc9jYoIWGpqcRDq1JZFNCSVvN # E4N3ECGjq6W3kYW7ot0CP1DkpJ93a5wrksQ6bvYGUy3lghkMvzjkkq/NVUDEVcdN # R7PsUFf654vSw+iLINZ+9kYg+ZnplfndT/JSMJDAaWkM5oLu6+ao0774QWrsHOtt # z7M8EDU+3PntYHglwWoej6qXIFRurgXdwAXXyXYcSmkOTbPqrjSwsbs8CuSwGqeb # bRSDKfjRzDqQ9D1AZ/JHHaaUkBbAYBsVMrvypDSrP/1o37mt4Zky28BnEp5ztEGp # 0HJ44X4rFVWWz+BfeuZWcVUcGKW2YFHobNwGmJ/OanLvlnmtpZIRLF9ZkbzCHHom # i+RId4g3fc3FsGxKqEW9Vj8PCumwKc6LUwZU4wIDAQABo4IBiTCCAYUwHwYDVR0j # BBgwFoAUDyrLIIcouOxvSK4rVKYpqhekzQwwHQYDVR0OBBYEFCiCHmEfvPkU1uIc # 2sPugFDBq88SMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM # MAoGCCsGAQUFBwMDMEoGA1UdIARDMEEwNQYMKwYBBAGyMQECAQMCMCUwIwYIKwYB # BQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAgGBmeBDAEEATBJBgNVHR8E # QjBAMD6gPKA6hjhodHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWND # b2RlU2lnbmluZ0NBUjM2LmNybDB5BggrBgEFBQcBAQRtMGswRAYIKwYBBQUHMAKG # OGh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5n # Q0FSMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAN # BgkqhkiG9w0BAQwFAAOCAYEAmLUUP/C5nHN/qX27dIrfNezHdUul/uhOA5CwNkD7 # P4pvLJButR/S1OmvozuzJJTce6824IylnXkRwUFj04XLbodkBL7+YwQ5ml7CjdDS # Vo+sI/38jcEQ6FgosV/TTJSiFAgqMNwkx/kSzvQ1/Ufp5YVKggCXGJ4VitIzl5nM # bzzu35G/uy4vmCQfh0KPYUTJYiRsF6Z3XJiIVtYrEwN/ikif/WFGrzsFj1OOWHNn # 5qDOP80xExmRS09z/wdZE9RdjPv5fYLnKWy1+GQ/w1vzg/l2vUXIgBV0MxalUfTP # 4V9Spsodrb+noPXiCy5n+6hy9yCf3EQb3G1n8rT/a454fLSijMm6bhrgBRqhPUUt # n6ZIBdEJzJUI6ftuXrQnB/U7zf32xcTTAW7WPem7DFK/4JrSaxiXcSkxQ4kXJDVo # DPUJdpb0c5XdWVJO0DCkB35ONEIoqT6VjEIjLPSw9UXE420r1OIpV8FRJqrW4Fr5 # RUveEUlyF+FyygVOYZECNsjRMIIGgjCCBGqgAwIBAgIQNsKwvXwbOuejs902y8l1 # aDANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBK # ZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRS # VVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlv # biBBdXRob3JpdHkwHhcNMjEwMzIyMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjBXMQsw # CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS4wLAYDVQQDEyVT # ZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIFJvb3QgUjQ2MIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAiJ3YuUVnnR3d6LkmgZpUVMB8SQWbzFoVD9mU # EES0QUCBdxSZqdTkdizICFNeINCSJS+lV1ipnW5ihkQyC0cRLWXUJzodqpnMRs46 # npiJPHrfLBOifjfhpdXJ2aHHsPHggGsCi7uE0awqKggE/LkYw3sqaBia67h/3awo # qNvGqiFRJ+OTWYmUCO2GAXsePHi+/JUNAax3kpqstbl3vcTdOGhtKShvZIvjwulR # H87rbukNyHGWX5tNK/WABKf+Gnoi4cmisS7oSimgHUI0Wn/4elNd40BFdSZ1Ewpu # ddZ+Wr7+Dfo0lcHflm/FDDrOJ3rWqauUP8hsokDoI7D/yUVI9DAE/WK3Jl3C4LKw # Ipn1mNzMyptRwsXKrop06m7NUNHdlTDEMovXAIDGAvYynPt5lutv8lZeI5w3MOlC # ybAZDpK3Dy1MKo+6aEtE9vtiTMzz/o2dYfdP0KWZwZIXbYsTIlg1YIetCpi5s14q # iXOpRsKqFKqav9R1R5vj3NgevsAsvxsAnI8Oa5s2oy25qhsoBIGo/zi6GpxFj+mO # dh35Xn91y72J4RGOJEoqzEIbW3q0b2iPuWLA911cRxgY5SJYubvjay3nSMbBPPFs # yl6mY4/WYucmyS9lo3l7jk27MAe145GWxK4O3m3gEFEIkv7kRmefDR7Oe2T1HxAn # ICQvr9sCAwEAAaOCARYwggESMB8GA1UdIwQYMBaAFFN5v1qqK0rPVIDh2JvAnfKy # A2bLMB0GA1UdDgQWBBT2d2rdP/0BE/8WoWyCAi/QCj0UJTAOBgNVHQ8BAf8EBAMC # AYYwDwYDVR0TAQH/BAUwAwEB/zATBgNVHSUEDDAKBggrBgEFBQcDCDARBgNVHSAE # CjAIMAYGBFUdIAAwUAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC51c2VydHJ1 # c3QuY29tL1VTRVJUcnVzdFJTQUNlcnRpZmljYXRpb25BdXRob3JpdHkuY3JsMDUG # CCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0 # LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEADr5lQe1oRLjlocXUEYfktzsljOt+2sgX # ke3Y8UPEooU5y39rAARaAdAxUeiX1ktLJ3+lgxtoLQhn5cFb3GF2SSZRX8ptQ6Iv # uD3wz/LNHKpQ5nX8hjsDLRhsyeIiJsms9yAWnvdYOdEMq1W61KE9JlBkB20XBee6 # JaXx4UBErc+YuoSb1SxVf7nkNtUjPfcxuFtrQdRMRi/fInV/AobE8Gw/8yBMQKKa # Ht5eia8ybT8Y/Ffa6HAJyz9gvEOcF1VWXG8OMeM7Vy7Bs6mSIkYeYtddU1ux1dQL # bEGur18ut97wgGwDiGinCwKPyFO7ApcmVJOtlw9FVJxw/mL1TbyBns4zOgkaXFnn # fzg4qbSvnrwyj1NiurMp4pmAWjR+Pb/SIduPnmFzbSN/G8reZCL4fvGlvPFk4Uab # /JVCSmj59+/mB2Gn6G/UYOy8k60mKcmaAZsEVkhOFuoj4we8CYyaR9vd9PGZKSin # aZIkvVjbH/3nlLb0a7SBIkiRzfPfS9T+JesylbHa1LtRV9U/7m0q7Ma2CQ/t392i # oOssXW7oKLdOmMBl14suVFBmbzrt5V5cQPnwtd3UOTpS9oCG+ZZheiIvPgkDmA8F # zPsnfXW5qHELB43ET7HHFHeRPRYrMBKjkb8/IN7Po0d0hQoF4TeMM+zYAJzoKQnV # KOLg8pZVPT8wgganMIIEj6ADAgECAhEAkKwIciD9xafEa1zHDfc9BjANBgkqhkiG # 9w0BAQwFADBXMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVk # MS4wLAYDVQQDEyVTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIFJvb3QgUjQ2 # MB4XDTI2MDMyNTAwMDAwMFoXDTQxMDMyNDIzNTk1OVowVTELMAkGA1UEBhMCR0Ix # GDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEsMCoGA1UEAxMjU2VjdGlnbyBQdWJs # aWMgVGltZSBTdGFtcGluZyBDQSBSNDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw # ggIKAoICAQCu5EqiAa2CHGL5Zi1bmgPM8NUXwYZJ+BtQqHps43GLTC+sjVLypsBh # +8uv+TLkgtVGD//vSmA0qrzELf9YRCh2MTAA/aGaQZKGg0BRCmziR3pbCnvgWjtG # XBDUyn3j3K2lZAO8KxgFtlxwOYEAkL+CCqK4v9zzTl8ZwzDpPMiDIFa5THk8an1i # eF5I09cXNrPQw+1ER1liThaG0z6FrOpqwxZWmPRZQBw2E32878UB1bL0Zp91vuWZ # gsMpNNiPCoBj0/1F+LE8+NRokfqacFI0F2tftrRB2W7HQClLR9zjxFbWb5be2rce # IfNyHUUfKGIvMI2NzoxSlxXnFqUG887D8W1Cj8DFok688JKxWvHR/9aQykSbd+9V # utj36ij2sgq/125wTpUZ/AgC0ph50bRs7gFrUyaXE9wSsOqMvCCC+sEm7vd/BemS # G0TSHNXSmyCba+FCzekeWX03TRIcF3Laqd0Rw24OH7jpei4zaGhcI7nfdhBA4c8R # ScxNY6jeHLHHmSMMTk9Wqn7H4dLhUBP5YEwbgbN4uv1i9ltTnHli8t1xHV0StX9B # FgrnmunTX19kUXY1H5ORJbRZyZDdvm1oZyteDj0SnMozr+YSmdIleDUTXdfoY7b2 # taz8s2+QbOxLxcahEIYGWzqu6h955tKwcANHcZ4gTmAhT3btuOiQsQIDAQABo4IB # bjCCAWowHwYDVR0jBBgwFoAU9ndq3T/9ARP/FqFsggIv0Ao9FCUwHQYDVR0OBBYE # FDp0pQxnxkJQwv21/Me7KTSC9Hq5MA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8E # CDAGAQH/AgEAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMCMGA1UdIAQcMBowCAYGZ4EM # AQQCMA4GDCsGAQQBsjEBAgEDCDBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3Js # LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNUaW1lU3RhbXBpbmdSb290UjQ2LmNy # bDB8BggrBgEFBQcBAQRwMG4wRwYIKwYBBQUHMAKGO2h0dHA6Ly9jcnQuc2VjdGln # by5jb20vU2VjdGlnb1B1YmxpY1RpbWVTdGFtcGluZ1Jvb3RSNDYucDdjMCMGCCsG # AQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOC # AgEAMt5SR2bxngNm+N8oc6Gq76Gx1c235fkX7jw8Ho9MAkJGADerHE7dhsBXttqm # zgr/7ZZahZSykGRPhPY1crj028kB8KzO0dKC2qQBAwtfgqMLKkkX/6bYq2uT33eD # 6ByAp2/XKD0LcmZh0kKecvSBr6ln9ajX6u1dnx2fA7xEKy1M3qBhfQSUWLtjs2nF # t0ELVLptzTlX9ID0cL+iOPfdboZ3CelT+JXKVKR2Sge0d4YiFAtPZkfSo8z1Z1x7 # y/Z9mwMIlBAnyuWXs4YsNuxdrYIt/QxE31PDOJ9DesS4Bc7H9OTORlEV/AvfiF/V # epKZpira1MzLYuCw+uoLZn/pkpvd+CvNTS+mEHjBJNa6WK1j8qXFu+jIq+sG9QIL # HiyB6p/xpHrkJu8zkw393+VqF9eKlTY2VjRxdycZLrVemZ4Yp3wi33b+W58CllH3 # HqjmowlZ7SOrgmx8YwYOkgrHsXOQHyBp6O4FRb8In0+FzjT7ElGie9V7CfhL3IlV # FZ4zjuKsZtH1iU3fGu4z/JnOGT6sCb0BbTqe/uhvpFCQBdH5xPGIA/LrbQUXjU2t # WJgHhTIqnN/HvHyOHi5tM4zP3nhgh2rJ6Kqq2xsHBeNYs/R18xQ8DeIg+c90Eoae # h0YlN1KU8AyYol3K9M+qY5ez8syd/7ZlrRnoVewgH3P1pcswggbiMIIEyqADAgEC # AhEA507yVbBQT/rbpt/3/IujFTANBgkqhkiG9w0BAQwFADBVMQswCQYDVQQGEwJH # QjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSwwKgYDVQQDEyNTZWN0aWdvIFB1 # YmxpYyBUaW1lIFN0YW1waW5nIENBIFI0MTAeFw0yNjAzMjUwMDAwMDBaFw0zNzA2 # MjQyMzU5NTlaMHIxCzAJBgNVBAYTAkdCMRcwFQYDVQQIEw5HcmVhdGVyIExvbmRv # bjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTAwLgYDVQQDEydTZWN0aWdvIFB1 # YmxpYyBUaW1lIFN0YW1waW5nIFNpZ25lciBSMzcwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCy/8NtS9xQ2UUtBRF32bj7VK3n4m50Uqjk/zTciSziYV40 # H1LKah0/oEklYG42E4VCP3DvsBUB6DmpCkDZ0jCnZBPIEevaH15ZJOQwFWP2ZXr5 # YjlJpb68Nlbs+ElNvKx32/1YHde3qqUSLybjulxPLz6T85+HOIqK7M1Bep8Lspyh # EP/q6nw5kGxTSrGvufmeH+JF8CnVBcVMFA40FlIYh0cDJVFhhfTfdWgLy/vWuLMQ # oKkf3s/FvByf16r0rtbyHm/iemwxSioJL9zyZDDKUNAbHXl0dhXo2VxUV2NcPXWX # uoKsjL+6cfk6Vm2DHnxAlFdFsaBDIF1JOkSnC6PeLlBznZn2buF3vIIYJcq6N/ze # FRCk4/HXDz7zgRsRRMdUB+rhyk5FoZaBjw0nLq3GZ3fClLUx5es5pUAxzNODMBn7 # JkFYip2BAGBPER5eV0ROhk6tGTG+fUiMiV+vgjg1YnP5FvnYWyEtWeQD/B2hp3vz # 0RvtdkM0p3igyadzrfpOBq5ppVk/YsuhTQkP99ivneHAGfi5e7lmxJ+meoBPrRLu # zMmb81rzzbESjJHMsn5RVtc6Ucs7rcMqQC13PUIO7BbGBETV2ufCmV6lPTp3P7XJ # OvmnUCRTPbVvMTpxP/z+SOHg4/OCBhiqs4FA9+4oQvlkk9w32NGASli9GWrm5wID # AQABo4IBjjCCAYowHwYDVR0jBBgwFoAUOnSlDGfGQlDC/bX8x7spNIL0erkwHQYD # VR0OBBYEFGEQ6XoSr1HEhdTyz6R0D1DNIK/4MA4GA1UdDwEB/wQEAwIGwDAMBgNV # HRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMEoGA1UdIARDMEEwCAYG # Z4EMAQQCMDUGDCsGAQQBsjEBAgEDCDAlMCMGCCsGAQUFBwIBFhdodHRwczovL3Nl # Y3RpZ28uY29tL0NQUzBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vY3JsLnNlY3Rp # Z28uY29tL1NlY3RpZ29QdWJsaWNUaW1lU3RhbXBpbmdDQVI0MS5jcmwwegYIKwYB # BQUHAQEEbjBsMEUGCCsGAQUFBzAChjlodHRwOi8vY3J0LnNlY3RpZ28uY29tL1Nl # Y3RpZ29QdWJsaWNUaW1lU3RhbXBpbmdDQVI0MS5jcnQwIwYIKwYBBQUHMAGGF2h0 # dHA6Ly9vY3NwLnNlY3RpZ28uY29tMA0GCSqGSIb3DQEBDAUAA4ICAQAD6j2N0azN # +hl6k6bKB5/U6VuSOs93ZBb3Pczy9VtBIKu4947Z5GwL0aFngIxl+GSuLFrJgPru # BCRvKJEJsm7kv+LQ1COVCEG9tZ+IRtr4ocUoa53lgdFaENlS0N4wgkZkbQEPv+x+ # 1lSjYh+T4JeL9mUznT7Erc6Sp5dWLka5sMP/m3GZi6oJPdPcsCKWagH7m2H2xDGI # yHJC5PdH9phvi/KmhkktiSVTNNqVeV5bWdX2zhRE6UTfz0IcMoCL996lFIydXxOC # E4MNDHDM0as4lnTiT/KHMccO6l8c9TnUVgmpci9ar1IABZ2U1XUkYjGGSn9MC3EH # DP9V39VuBVvZ33/BEV/EWSRrf07T7jFplKX+gQr/UOqPGMlE7ZJ72UaUkNJy7bVl # 3bcLKzdpjIHzLkf/4MVa1V7w8wqCv5W4gOnRGTlud5UMARbRM8BPxR/CXYXoMmIO # D8pmTk2axgRL4LG8XtuchISdCHRmtacAmLGq5XSYSVTHTXADlO48iDKh3HM2r98L # SF6f0sG12d8V9Jn7C3wDUieOxuKj4MdWrW+hiJU2kF87v6eH00HgCFFc2V0+CvfO # CMn7juzS41jLaINcBlKWQ/fKb/uDLfWOW73z1I2lFY7Xj8tQ1XYtK5eREjWItM8j # pl1cbQOc88btR+0XS2TmboE/141+va2PWzGCBjAwggYsAgEBMGgwVDELMAkGA1UE # BhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UEAxMiU2VjdGln # byBQdWJsaWMgQ29kZSBTaWduaW5nIENBIFIzNgIQacs5SDkvNuif0aEmZmr03jAJ # BgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0B # CQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAj # BgkqhkiG9w0BCQQxFgQU+aVApNF+V+3Iv0KcjDGt3xJYAbowDQYJKoZIhvcNAQEB # BQAEggIAJgSeS0sPFDLOYbQ4QcAqjJYBPfFkj+cf0Gh1pE7db/SkT8iKeX9hRn+k # JI7gpo0dDefjHGuOGAK1P36sR3Wyb4L5FjWu0gPc1Y6ISl8C2e7Tlb9DPtnJdJGB # 64/Qg6aTVFJyQ9QNrJmLro6A22NI504WgqDRTgzlV5QjSf4PfY+VpS9gU5FhuMJ0 # HghIVPPVGfEXwOtQ8c3PJQ9I++RWm1Ww+CMfr9odj6Ic/eQJnUYTDGIGNF/JsDYE # VVaedFo0sGJbZBpq4UurVH/tTBpAJaLYHpQUNN3MbyVy7gkxdEcGyU0YS2eWBXTF # w0pv0JwyVealknLkJLQtBdCARSWI5+VyRLTPRkHitRbe2mhH+H7XHvFUx3OGC+eI # qSNg0B/clla+tX2vWkdzNz5hbEnF9b6AnndUfBJU9qjx62whGnpeDI8IpvNNXMbX # edn9pnxP492OMIaQ5Hb2hF/uCEugmh36biN4jcKDwYwjK0sXQwAGc/Vg46MfLaAi # kVMiRosrD6zjb2w8vtsTvZb7TdwJZG2otkcboFCEYf+5ZKqH5lpvoEO3fbhPY6GJ # nziGNN7biT525wAULbx6yNR6W6nUA1T6JeHyeh2qGrpeuESX6t+QUpW5c1GmuVQS # xGhh9fWglYEgxoeEKsukYOXmM/UOUWSKp3TnTawY5h9Bt5LLFkqhggMjMIIDHwYJ # KoZIhvcNAQkGMYIDEDCCAwwCAQEwajBVMQswCQYDVQQGEwJHQjEYMBYGA1UEChMP # U2VjdGlnbyBMaW1pdGVkMSwwKgYDVQQDEyNTZWN0aWdvIFB1YmxpYyBUaW1lIFN0 # YW1waW5nIENBIFI0MQIRAOdO8lWwUE/626bf9/yLoxUwDQYJYIZIAWUDBAICBQCg # eTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNjEw # MTcwMzA3MjJaMD8GCSqGSIb3DQEJBDEyBDAEKOAgr3+qNOOJlDHAiXxfYDvG0AT8 # Xui2KhFIiny6yPAIi6eEAwx8yY8NS/DYPDYwDQYJKoZIhvcNAQEBBQAEggIAKxw0 # F8ibY1T7g4BtY7HJJs+sr9ywM/ORNgtJIU7s+GXZI4JzZPT85Djpt2ZgBEKhzU8G # Ipa/jkMbmWqGWeqIfwpcbqww/kQDX9ElKAVN7tyR7wfc3E6nRSVyIohB2sxeJdT1 # 97inI8NcslFufKQiaVtZ+B3+WkvPdgkAqHoLaqD2rE0bvF3MG9a0j6Qk95Pf8sUO # r57GT1C2v+h496uyLiJtagyexC2UrvTURrm/bxdVVcqzU9N4NEVnLfYMwzL7e70v # F8KM5Dx98C43O6c4J2qZQ61P+cMaGLPe7DQ3CtT2PCkFsf/nC69lCa83KkP5gF5c # 4y2ro8DTTrVD2KHQfAm4lCTZ4UMCDEoRs7gfn8xzxdC+A2/knyFReGU3vfUOTO2l # y7tVgldsFkI7zAjwtBP5ZPb1Oqc8vWvq1EoJeDMiVJaRsxoHYfWuIdq2gx3gN+q8 # LjebcjF5cb3UWsPWwsu58R5gWgONvBIbkDxrthl/FUxHhEXzEohjc4xmyb0EDI/6 # xlhv5VqKoMJYgjsnAnA9N0iWYCWpFACLNyfjINjP2zHgJUCEz0dqkQaCwxK/c/T/ # chyv2C/CPw2BUt1H7DYS6BiTBNbyJ7f9xFczr7Cyk5bB5UzPik+ogkA+Z+q15yh6 # jM8Zfbx43nO8JsYSk58qbIqaqyuARwETbzeJytk= # SIG # End signature block |