Public/Get-VdcAttribute.ps1
function Get-VdcAttribute { <# .SYNOPSIS Get object attributes as well as policy attributes .DESCRIPTION Retrieves object attributes as well as policy attributes. You can either retrieve all attributes or individual ones. Policy folders can have attributes as well as policies which apply to the resultant objects. For more info on policies and how they are different than attributes, see https://docs.venafi.com/Docs/current/TopNav/Content/Policies/c_policies_tpp.php. Attribute properties are directly added to the return object for ease of access. To retrieve attribute configuration, see the Attribute property of the return object which has properties Name, PolicyPath, Locked, Value, Overridden (when applicable), and CustomFieldGuid (when applicable). .PARAMETER Path Path to the object. If the root is excluded, \ved\policy will be prepended. .PARAMETER Attribute Only retrieve the value/values for this attribute. For custom fields, you can provide either the Guid or Label. .PARAMETER Class Get policy attributes instead of object attributes. Provide the class name to retrieve the value(s) for. If unsure of the class name, add the value through the TLSPDC UI and go to Support->Policy Attributes to find it. The Attribute property of the return object will contain the path where the policy was applied. .PARAMETER All Get all object attributes or policy attributes. This will perform 3 steps, get the object type, enumerate the attributes for the object type, and get all the values. Note, expect this to take longer than usual given the number of api calls. .PARAMETER NoLookup Default functionality is to perform lookup of attributes names to see if they are custom fields or not. If they are, pass along the guid instead of name required by the api for custom fields. To override this behavior and use the attribute name as is, add -NoLookup. Useful if, on the off chance, you have a custom field with the same name as a built-in attribute. Can also be used with -All and the output will contain guids instead of looked up names. .PARAMETER ThrottleLimit Limit the number of threads when running in parallel; the default is 100. Applicable to PS v7+ only. .PARAMETER VenafiSession Authentication for the function. The value defaults to the script session object $VenafiSession created by New-VenafiSession. A TLSPDC token can be provided directly. If providing a TLSPDC token, an environment variable named VDC_SERVER must also be set. .INPUTS Path .OUTPUTS PSCustomObject .EXAMPLE Get-VdcAttribute -Path '\VED\Policy\certificates\test.gdb.com' -Attribute 'State' Name : test.gdb.com Path : \VED\Policy\Certificates\test.gdb.com TypeName : X509 Server Certificate Guid : b7a7221b-e038-41d9-9d49-d7f45c1ca128 Attribute : {@{Name=State; PolicyPath=\VED\Policy\Certificates; Locked=False; Value=UT; Overridden=False}} State : UT Retrieve a single attribute .EXAMPLE Get-VdcAttribute -Path '\VED\Policy\certificates\test.gdb.com' -Attribute 'State', 'Driver Name' Name : test.gdb.com Path : \VED\Policy\Certificates\test.gdb.com TypeName : X509 Server Certificate Guid : b7a7221b-e038-41d9-9d49-d7f45c1ca128 Attribute : {@{Name=State; PolicyPath=\VED\Policy\Certificates; Locked=False; Value=UT; Overridden=False}, @{Name=Driver Name; PolicyPath=; Locked=False; Value=appx509certificate; Overridden=False}} State : UT Driver Name : appx509certificate Retrieve multiple attributes .EXAMPLE Get-VdcAttribute -Path '\VED\Policy\certificates\test.gdb.com' -Attribute 'ServiceNow Assignment Group' Name : test.gdb.com Path : \VED\Policy\Certificates\test.gdb.com TypeName : X509 Server Certificate Guid : b7a7221b-e038-41d9-9d49-d7f45c1ca128 Attribute : {@{CustomFieldGuid={7f214dec-9878-495f-a96c-57291f0d42da}; Name=ServiceNow Assignment Group; PolicyPath=; Locked=False; Value=Venafi Management; Overridden=False}} ServiceNow Assignment Group : Venafi Management Retrieve a custom field attribute. You can specify either the guid or custom field label name. .EXAMPLE Get-VdcAttribute -Path '\VED\Policy\mydevice\myapp' -Attribute 'Certificate' -NoLookup Name : myapp Path : \VED\Policy\mydevice\myapp TypeName : Adaptable App Guid : b7a7221b-e038-41d9-9d49-d7f45c1ca128 Attribute : {@{Name=Certificate; PolicyPath=; Value=\VED\Policy\mycert; Locked=False; Overridden=False}} Certificate : \VED\Policy\mycert Retrieve an attribute value without custom value lookup .EXAMPLE Get-VdcAttribute -Path '\VED\Policy\certificates\test.gdb.com' -All Name : test.gdb.com Path : \VED\Policy\Certificates\test.gdb.com TypeName : X509 Server Certificate Guid : b7a7221b-e038-41d9-9d49-d7f45c1ca128 Attribute : {@{CustomFieldGuid={7f214dec-9878-495f-a96c-57291f0d42da}; Name=ServiceNow Assignment Group; PolicyPath=; Locked=False; Value=Venafi Management; Overridden=False}…} ServiceNow Assignment Group : Venafi Management City : Salt Lake City Consumers : {\VED\Policy\Installations\Agentless\US Zone\mydevice\myapp} Contact : local:{b1c77034-c099-4a5c-9911-9e26007817da} Country : US Created By : WebAdmin Driver Name : appx509certificate ... Retrieve all attributes applicable to this object .EXAMPLE Get-VdcAttribute -Path 'Certificates' -Class 'X509 Certificate' -Attribute 'State' Name : Certificates Path : \VED\Policy\Certificates TypeName : Policy Guid : a91fc152-a9fb-4b49-a7ca-7014b14d73eb Attribute : {@{Name=State; PolicyPath=\VED\Policy\Certificates; Locked=False; Value=UT}} ClassName : X509 Certificate State : UT Retrieve a policy attribute value for the specified policy folder and class. \ved\policy will be prepended to the path. .EXAMPLE Get-VdcAttribute -Path '\VED\Policy\certificates' -Class 'X509 Certificate' -All Name : Certificates Path : \VED\Policy\Certificates TypeName : Policy Guid : a91fc152-a9fb-4b49-a7ca-7014b14d73eb Attribute : {@{CustomFieldGuid={7f214dec-9878-495f-a96c-57291f0d42da}; Name=ServiceNow Assignment Group; PolicyPath=; Locked=False; Value=}…} ClassName : X509 Certificate Approver : local:{b1c77034-c099-4a5c-9911-9e26007817da} Key Algorithm : RSA Key Bit Strength : 2048 Managed By : Aperture Management Type : Enrollment Network Validation Disabled : 1 Notification Disabled : 0 ... Retrieve all policy attributes for the specified policy folder and class .EXAMPLE Find-VdcCertificate | Get-VdcAttribute -Attribute Contact,'Managed By','Want Renewal' -ThrottleLimit 50 Name : mycert Path : \VED\Policy\mycert TypeName : X509 Server Certificate Guid : 1dc31664-a9f3-407c-8bf3-1e388e90a114 Attribute : {@{Name=Contact; PolicyPath=\VED\Policy; Value=local:{ab2a2e32-b412-4466-b5b5-484478a99bf4}; Locked=False; Overridden=False}, @{Name=Managed By; PolicyPath=\VED\Policy; Value=Aperture; Locked=True; Overridden=False}, @{Name=Want Renewal; PolicyPath=\VED\Policy; Value=0; Locked=True; Overridden=False}} Contact : local:{ab2a2e32-b412-4466-b5b5-484478a99bf4} Managed By : Aperture Want Renewal : 0 ... Retrieve specific attributes for all certificates. Throttle the number of threads to 50, the default is 100 .LINK https://docs.venafi.com/Docs/currentSDK/TopNav/Content/SDK/WebSDK/r-SDK-POST-Config-findpolicy.php .LINK https://docs.venafi.com/Docs/current/TopNav/Content/SDK/WebSDK/r-SDK-POST-Config-readeffectivepolicy.php #> [CmdletBinding(DefaultParameterSetName = 'Attribute')] [Alias('Get-TppAttribute')] param ( [Parameter(Mandatory, ParameterSetName = 'Attribute', ValueFromPipeline, ValueFromPipelineByPropertyName)] [Parameter(Mandatory, ParameterSetName = 'All', ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('DN')] [String] $Path, [Parameter(Mandatory, ParameterSetName = 'Attribute')] [ValidateNotNullOrEmpty()] [String[]] $Attribute, [ValidateNotNullOrEmpty()] [Alias('ClassName', 'PolicyClass')] [string] $Class, [Parameter(Mandatory, ParameterSetName = 'All')] [switch] $All, [Parameter()] [switch] $NoLookup, [Parameter()] [int32] $ThrottleLimit = 100, [Parameter()] [psobject] $VenafiSession ) begin { Write-Verbose $PSCmdlet.ParameterSetName Test-VenafiSession -VenafiSession $VenafiSession -Platform 'VDC' $newAttribute = $Attribute if ( $All -and $Class ) { Write-Verbose "Getting attributes for class $Class" $newAttribute = Get-VdcClassAttribute -ClassName $Class | Select-Object -ExpandProperty Name -Unique } $allItems = [System.Collections.Generic.List[hashtable]]::new() } process { if ( $PSCmdlet.ParameterSetName -eq 'Attribute') { # small number of attributes so focus parallelism on the objects # this is done in the end block $allItems.Add( @{ Path = $Path | ConvertTo-VdcFullPath Attribute = $newAttribute } ) return } # All parameter set below # with -All there is a large list of attributes so focus parallelism on them $newPath = $Path | ConvertTo-VdcFullPath $thisObject = Get-VdcObject -Path $newPath if ( $Class -and ($thisObject.TypeName -ne 'Policy') ) { Write-Error ('You are attempting to retrieve policy attributes, but {0} is not a policy path' -f $newPath) return } $return = [pscustomobject] @{ Name = $thisObject.Name Path = $newPath TypeName = $thisObject.TypeName Guid = $thisObject.Guid Attribute = [pscustomobject] @{} } if ( $Class ) { $return | Add-Member @{ 'ClassName' = $Class } } else { # get list of attributes for this specific class $newAttribute = Get-VdcClassAttribute -ClassName $thisObject.TypeName | Select-Object -ExpandProperty Name -Unique } $allAttributes = Invoke-VenafiParallel -InputObject $newAttribute -ScriptBlock { $thisAttribute = $PSItem if ( $using:Class ) { $params = @{ Method = 'Post' Body = @{ Class = $using:Class ObjectDN = $using:newPath AttributeName = $thisAttribute } UriLeaf = 'config/FindPolicy' } } else { $params = @{ Method = 'Post' Body = @{ ObjectDN = $using:newPath AttributeName = $thisAttribute } UriLeaf = 'config/ReadEffectivePolicy' } } Write-Verbose "Processing attribute $thisAttribute" $customField = $null if ( -not $using:NoLookup ) { # parallel lookup $customField = $VenafiSession.CustomField | Where-Object { $_.Label -eq $thisAttribute -or $_.Guid -eq $thisAttribute } if ( -not $customField ) { # sequential lookup $customField = $VenafiSessionNested.CustomField | Where-Object { $_.Label -eq $thisAttribute -or $_.Guid -eq $thisAttribute } } if ( $customField ) { $params.Body.AttributeName = $customField.Guid } } # disabled is a special kind of attribute which cannot be read with readeffectivepolicy if ( $params.Body.AttributeName -eq 'Disabled' ) { $oldUri = $params.UriLeaf $params.UriLeaf = 'Config/Read' $response = Invoke-VenafiRestMethod @params $params.UriLeaf = $oldUri } else { $response = Invoke-VenafiRestMethod @params } if ( $response.Error ) { if ( $response.Result -in 601, 112) { Write-Error "'$thisAttribute' is not a valid attribute for $newPath. Are you looking for a policy attribute? If so, add -Class." continue } elseif ( $response.Result -eq 102) { # attribute is valid, but value not set # we're ok with this one } else { Write-Error $response.Error continue } } $valueOut = $null if ( $response.Values ) { switch ($response.Values.GetType().Name) { 'Object[]' { switch ($response.Values.Count) { 1 { $valueOut = $response.Values[0] } Default { $valueOut = $response.Values } } } Default { $valueOut = $response.Values } } } $newProp = [pscustomobject] @{} # only add attributes to the root of the response object if they have a value # always add them to .Attribute ($newProp) if ( $CustomField ) { $newProp | Add-Member @{ Name = $customField.Label 'CustomFieldGuid' = $customField.Guid } if ( $valueOut ) { $using:return | Add-Member @{ $customField.Label = $valueOut } } } else { if ( $valueOut ) { $using:return | Add-Member @{ $thisAttribute = $valueOut } -ErrorAction SilentlyContinue } $newProp | Add-Member @{ Name = $thisAttribute } } $newProp | Add-Member @{ Value = $valueOut PolicyPath = $response.PolicyDN Locked = $response.Locked } # overridden not available at policy level if ( -not $PSBoundParameters.ContainsKey('Class') ) { $newProp | Add-Member @{ 'Overridden' = $response.Overridden } } $newProp } -ThrottleLimit $ThrottleLimit -ProgressTitle 'Getting attributes' $return.Attribute = @($allAttributes) $return } end { # parallelism is focused on the objects, not attributes # used when -Attribute is provided, not -All Invoke-VenafiParallel -InputObject $allItems -ScriptBlock { $newPath = $PSItem.Path $thisObject = Get-VdcObject -Path $newPath if ( $using:Class -and ($thisObject.TypeName -ne 'Policy') ) { Write-Error ('You are attempting to retrieve policy attributes, but {0} is not a policy path' -f $newPath) return } $newAttribute = $PSItem.Attribute $return = [pscustomobject] @{ Name = $thisObject.Name Path = $newPath TypeName = $thisObject.TypeName Guid = $thisObject.Guid Attribute = [pscustomobject] @{} } if ( $using:Class ) { $return | Add-Member @{ 'ClassName' = $using:Class } $params = @{ Method = 'Post' Body = @{ Class = $using:Class ObjectDN = $newPath } UriLeaf = 'config/FindPolicy' } } else { $params = @{ Method = 'Post' Body = @{ ObjectDN = $newPath } UriLeaf = 'config/ReadEffectivePolicy' } } $allAttributes = foreach ($thisAttribute in $newAttribute) { Write-Verbose "Processing attribute $thisAttribute" $params.Body.AttributeName = $thisAttribute $customField = $null if ( -not $using:NoLookup ) { # parallel lookup $customField = $VenafiSession.CustomField | Where-Object { $_.Label -eq $thisAttribute -or $_.Guid -eq $thisAttribute } if ( -not $customField ) { # sequential lookup $customField = $VenafiSessionNested.CustomField | Where-Object { $_.Label -eq $thisAttribute -or $_.Guid -eq $thisAttribute } } if ( $customField ) { $params.Body.AttributeName = $customField.Guid } } # disabled is a special kind of attribute which cannot be read with readeffectivepolicy if ( $params.Body.AttributeName -eq 'Disabled' ) { $oldUri = $params.UriLeaf $params.UriLeaf = 'Config/Read' $response = Invoke-VenafiRestMethod @params $params.UriLeaf = $oldUri } else { $response = Invoke-VenafiRestMethod @params } if ( $response.Error ) { if ( $response.Result -in 601, 112) { Write-Error "'$thisAttribute' is not a valid attribute for $newPath. Are you looking for a policy attribute? If so, add -Class." continue } elseif ( $response.Result -eq 102) { # attribute is valid, but value not set # we're ok with this one } else { Write-Error $response.Error continue } } $valueOut = $null if ( $response.Values ) { switch ($response.Values.GetType().Name) { 'Object[]' { switch ($response.Values.Count) { 1 { $valueOut = $response.Values[0] } Default { $valueOut = $response.Values } } } Default { $valueOut = $response.Values } } } $newProp = [pscustomobject] @{} # only add attributes to the root of the response object if they have a value # always add them to .Attribute ($newProp) if ( $CustomField ) { $newProp | Add-Member @{ Name = $customField.Label 'CustomFieldGuid' = $customField.Guid } if ( $valueOut ) { $return | Add-Member @{ $customField.Label = $valueOut } } } else { if ( $valueOut ) { $return | Add-Member @{ $thisAttribute = $valueOut } -ErrorAction SilentlyContinue } $newProp | Add-Member @{ Name = $thisAttribute } } $newProp | Add-Member @{ Value = $valueOut PolicyPath = $response.PolicyDN Locked = $response.Locked } # overridden not available at policy level if ( -not $using:Class ) { $newProp | Add-Member @{ 'Overridden' = $response.Overridden } } $newProp } $return.Attribute = @($allAttributes) $return } -ThrottleLimit $ThrottleLimit -ProgressTitle 'Getting attributes' } } # SIG # Begin signature block # MIIoFQYJKoZIhvcNAQcCoIIoBjCCKAICAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUybmMaWhDw/JQaYTaDXA4+v3Q # 9mqggiE9MIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIGrjCCBJag # AwIBAgIQBzY3tyRUfNhHrP0oZipeWzANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQG # EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl # cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjIw # MzIzMDAwMDAwWhcNMzcwMzIyMjM1OTU5WjBjMQswCQYDVQQGEwJVUzEXMBUGA1UE # ChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQg # UlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMIICIjANBgkqhkiG9w0BAQEF # AAOCAg8AMIICCgKCAgEAxoY1BkmzwT1ySVFVxyUDxPKRN6mXUaHW0oPRnkyibaCw # zIP5WvYRoUQVQl+kiPNo+n3znIkLf50fng8zH1ATCyZzlm34V6gCff1DtITaEfFz # sbPuK4CEiiIY3+vaPcQXf6sZKz5C3GeO6lE98NZW1OcoLevTsbV15x8GZY2UKdPZ # 7Gnf2ZCHRgB720RBidx8ald68Dd5n12sy+iEZLRS8nZH92GDGd1ftFQLIWhuNyG7 # QKxfst5Kfc71ORJn7w6lY2zkpsUdzTYNXNXmG6jBZHRAp8ByxbpOH7G1WE15/teP # c5OsLDnipUjW8LAxE6lXKZYnLvWHpo9OdhVVJnCYJn+gGkcgQ+NDY4B7dW4nJZCY # OjgRs/b2nuY7W+yB3iIU2YIqx5K/oN7jPqJz+ucfWmyU8lKVEStYdEAoq3NDzt9K # oRxrOMUp88qqlnNCaJ+2RrOdOqPVA+C/8KI8ykLcGEh/FDTP0kyr75s9/g64ZCr6 # dSgkQe1CvwWcZklSUPRR8zZJTYsg0ixXNXkrqPNFYLwjjVj33GHek/45wPmyMKVM # 1+mYSlg+0wOI/rOP015LdhJRk8mMDDtbiiKowSYI+RQQEgN9XyO7ZONj4KbhPvbC # dLI/Hgl27KtdRnXiYKNYCQEoAA6EVO7O6V3IXjASvUaetdN2udIOa5kM0jO0zbEC # AwEAAaOCAV0wggFZMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLoW2W1N # hS9zKXaaL3WMaiCPnshvMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9P # MA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB3BggrBgEFBQcB # AQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggr # BgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1 # c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0gBBkwFzAI # BgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQB9WY7Ak7Zv # mKlEIgF+ZtbYIULhsBguEE0TzzBTzr8Y+8dQXeJLKftwig2qKWn8acHPHQfpPmDI # 2AvlXFvXbYf6hCAlNDFnzbYSlm/EUExiHQwIgqgWvalWzxVzjQEiJc6VaT9Hd/ty # dBTX/6tPiix6q4XNQ1/tYLaqT5Fmniye4Iqs5f2MvGQmh2ySvZ180HAKfO+ovHVP # ulr3qRCyXen/KFSJ8NWKcXZl2szwcqMj+sAngkSumScbqyQeJsG33irr9p6xeZmB # o1aGqwpFyd/EjaDnmPv7pp1yr8THwcFqcdnGE4AJxLafzYeHJLtPo0m5d2aR8XKc # 6UsCUqc3fpNTrDsdCEkPlM05et3/JWOZJyw9P2un8WbDQc1PtkCbISFA0LcTJM3c # HXg65J6t5TRxktcma+Q4c6umAU+9Pzt4rUyt+8SVe+0KXzM5h0F4ejjpnOHdI/0d # KNPH+ejxmF/7K9h+8kaddSweJywm228Vex4Ziza4k9Tm8heZWcpw8De/mADfIBZP # J/tgZxahZrrdVcA6KYawmKAr7ZVBtzrVFZgxtGIJDwq9gdkT/r+k0fNX2bwE+oLe # Mt8EifAAzV3C+dAjfwAL5HYCJtnwZXZCpimHCUcr5n8apIUP/JiW9lVUKx+A+sDy # Divl1vupL0QVSucTDh3bNzgaoSv27dZ8/DCCBrAwggSYoAMCAQICEAitQLJg0pxM # n17Nqb2TrtkwDQYJKoZIhvcNAQEMBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoT # DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UE # AxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIxMDQyOTAwMDAwMFoXDTM2 # MDQyODIzNTk1OVowaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBS # U0E0MDk2IFNIQTM4NCAyMDIxIENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC # AgoCggIBANW0L0LQKK14t13VOVkbsYhC9TOM6z2Bl3DFu8SFJjCfpI5o2Fz16zQk # B+FLT9N4Q/QX1x7a+dLVZxpSTw6hV/yImcGRzIEDPk1wJGSzjeIIfTR9TIBXEmtD # mpnyxTsf8u/LR1oTpkyzASAl8xDTi7L7CPCK4J0JwGWn+piASTWHPVEZ6JAheEUu # oZ8s4RjCGszF7pNJcEIyj/vG6hzzZWiRok1MghFIUmjeEL0UV13oGBNlxX+yT4Us # SKRWhDXW+S6cqgAV0Tf+GgaUwnzI6hsy5srC9KejAw50pa85tqtgEuPo1rn3MeHc # reQYoNjBI0dHs6EPbqOrbZgGgxu3amct0r1EGpIQgY+wOwnXx5syWsL/amBUi0nB # k+3htFzgb+sm+YzVsvk4EObqzpH1vtP7b5NhNFy8k0UogzYqZihfsHPOiyYlBrKD # 1Fz2FRlM7WLgXjPy6OjsCqewAyuRsjZ5vvetCB51pmXMu+NIUPN3kRr+21CiRshh # WJj1fAIWPIMorTmG7NS3DVPQ+EfmdTCN7DCTdhSmW0tddGFNPxKRdt6/WMtyEClB # 8NXFbSZ2aBFBE1ia3CYrAfSJTVnbeM+BSj5AR1/JgVBzhRAjIVlgimRUwcwhGug4 # GXxmHM14OEUwmU//Y09Mu6oNCFNBfFg9R7P6tuyMMgkCzGw8DFYRAgMBAAGjggFZ # MIIBVTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRoN+Drtjv4XxGG+/5h # ewiIZfROQjAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8B # Af8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYIKwYBBQUHAQEEazBpMCQG # CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKG # NWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290 # RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMBwGA1UdIAQVMBMwBwYFZ4EMAQMw # CAYGZ4EMAQQBMA0GCSqGSIb3DQEBDAUAA4ICAQA6I0Q9jQh27o+8OpnTVuACGqX4 # SDTzLLbmdGb3lHKxAMqvbDAnExKekESfS/2eo3wm1Te8Ol1IbZXVP0n0J7sWgUVQ # /Zy9toXgdn43ccsi91qqkM/1k2rj6yDR1VB5iJqKisG2vaFIGH7c2IAaERkYzWGZ # gVb2yeN258TkG19D+D6U/3Y5PZ7Umc9K3SjrXyahlVhI1Rr+1yc//ZDRdobdHLBg # XPMNqO7giaG9OeE4Ttpuuzad++UhU1rDyulq8aI+20O4M8hPOBSSmfXdzlRt2V0C # FB9AM3wD4pWywiF1c1LLRtjENByipUuNzW92NyyFPxrOJukYvpAHsEN/lYgggnDw # zMrv/Sk1XB+JOFX3N4qLCaHLC+kxGv8uGVw5ceG+nKcKBtYmZ7eS5k5f3nqsSc8u # pHSSrds8pJyGH+PBVhsrI/+PteqIe3Br5qC6/To/RabE6BaRUotBwEiES5ZNq0RA # 443wFSjO7fEYVgcqLxDEDAhkPDOPriiMPMuPiAsNvzv0zh57ju+168u38HcT5uco # P6wSrqUvImxB+YJcFWbMbA7KxYbD9iYzDAdLoNMHAmpqQDBISzSoUSC7rRuFCOJZ # DW3KBVAr6kocnqX9oKcfBnTn8tZSkP2vhUgh+Vc7tJwD7YZF9LRhbr9o4iZghurI # r6n+lB3nYxs6hlZ4TjCCBsIwggSqoAMCAQICEAVEr/OUnQg5pr/bP1/lYRYwDQYJ # KoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2 # IFRpbWVTdGFtcGluZyBDQTAeFw0yMzA3MTQwMDAwMDBaFw0zNDEwMTMyMzU5NTla # MEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4GA1UE # AxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjMwggIiMA0GCSqGSIb3DQEBAQUAA4IC # DwAwggIKAoICAQCjU0WHHYOOW6w+VLMj4M+f1+XS512hDgncL0ijl3o7Kpxn3GIV # WMGpkxGnzaqyat0QKYoeYmNp01icNXG/OpfrlFCPHCDqx5o7L5Zm42nnaf5bw9Yr # IBzBl5S0pVCB8s/LB6YwaMqDQtr8fwkklKSCGtpqutg7yl3eGRiF+0XqDWFsnf5x # XsQGmjzwxS55DxtmUuPI1j5f2kPThPXQx/ZILV5FdZZ1/t0QoRuDwbjmUpW1R9d4 # KTlr4HhZl+NEK0rVlc7vCBfqgmRN/yPjyobutKQhZHDr1eWg2mOzLukF7qr2JPUd # vJscsrdf3/Dudn0xmWVHVZ1KJC+sK5e+n+T9e3M+Mu5SNPvUu+vUoCw0m+PebmQZ # BzcBkQ8ctVHNqkxmg4hoYru8QRt4GW3k2Q/gWEH72LEs4VGvtK0VBhTqYggT02ke # fGRNnQ/fztFejKqrUBXJs8q818Q7aESjpTtC/XN97t0K/3k0EH6mXApYTAA+hWl1 # x4Nk1nXNjxJ2VqUk+tfEayG66B80mC866msBsPf7Kobse1I4qZgJoXGybHGvPrhv # ltXhEBP+YUcKjP7wtsfVx95sJPC/QoLKoHE9nJKTBLRpcCcNT7e1NtHJXwikcKPs # CvERLmTgyyIryvEoEyFJUX4GZtM7vvrrkTjYUQfKlLfiUKHzOtOKg8tAewIDAQAB # o4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/ # BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcB # MB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQWBBSltu8T # 5+/N0GSh1VapZTGj3tXjSTBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsMy5k # aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0 # YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0 # cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGlt # ZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCBGtbeoKm1mBe8cI1P # ijxonNgl/8ss5M3qXSKS7IwiAqm4z4Co2efjxe0mgopxLxjdTrbebNfhYJwr7e09 # SI64a7p8Xb3CYTdoSXej65CqEtcnhfOOHpLawkA4n13IoC4leCWdKgV6hCmYtld5 # j9smViuw86e9NwzYmHZPVrlSwradOKmB521BXIxp0bkrxMZ7z5z6eOKTGnaiaXXT # UOREEr4gDZ6pRND45Ul3CFohxbTPmJUaVLq5vMFpGbrPFvKDNzRusEEm3d5al08z # jdSNd311RaGlWCZqA0Xe2VC1UIyvVr1MxeFGxSjTredDAHDezJieGYkD6tSRN+9N # UvPJYCHEVkft2hFLjDLDiOZY4rbbPvlfsELWj+MXkdGqwFXjhr+sJyxB0JozSqg2 # 1Llyln6XeThIX8rC3D0y33XWNmdaifj2p8flTzU8AL2+nCpseQHc2kTmOt44Owde # OVj0fHMxVaCAEcsUDH6uvP6k63llqmjWIso765qCNVcoFstp8jKastLYOrixRoZr # uhf9xHdsFWyuq69zOuhJRrfVf8y2OMDY7Bz1tqG4QyzfTkx9HmhwwHcK1ALgXGC7 # KP845VJa1qwXIiNO9OzTF/tQa/8Hdx9xl0RBybhG02wyfFgvZ0dl5Rtztpn5aywG # Ru9BHvDwX+Db2a2QgESvgBBBijCCB3wwggVkoAMCAQICEASyQEzq0fdqCZAgPWOK # ulswDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lD # ZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2ln # bmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMTAeFw0yMzA5MTMwMDAwMDBaFw0y # NDA5MTIyMzU5NTlaMIGDMQswCQYDVQQGEwJVUzENMAsGA1UECBMEVXRhaDEXMBUG # A1UEBxMOU2FsdCBMYWtlIENpdHkxFTATBgNVBAoTDFZlbmFmaSwgSW5jLjEeMBwG # A1UECxMVUHJvZmVzc2lvbmFsIFNlcnZpY2VzMRUwEwYDVQQDEwxWZW5hZmksIElu # Yy4wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDPaBrbDQ0fOiorU2nC # Zx7SrZVmSiwwhrgzDh4WENmJKVpZbBdtYoERBUQSd3+Y+WY4y/aPAEQ9oF1PNfhu # nkDiCvY3CnDYeOv2ex8G64w1WQIKKZd2OpsuGLJTShshiT7kQwfQufCfUC6lNuO2 # PreSqztkN8tFWrqNS0YlV18MoGsgCPKZ49eLnwbX33UnqLyiDe8qGE73uxZyIZct # uWKtQU0ylmkrfZSsevZCSUiqFKjW5y9NPvHwQVbk/ffPZ6eJAIO+ywRSxXu8N1zj # OWXaKj4HWPu9U6Jwsb4/wnGGPLXex4qyYBdLB8gPnW1Y7dXZJ8RkTbF+7FE31ss5 # 1fIH3zTyJ8gDLEubPfoqruRpf8tDp4Z5UPBue90BShRwIpgYrsU9hCEnRmfG1clE # p9BTistpki1W2cls99cYlfVpcljXR8plK+cR9hGtxvqkxUXELIAyhkRTddKD1tLS # hz1+D4VOOSdzPJcWMwP3s9lbwZwsBdZK6Ruy3LNIe+HQ2He3IbJc/LL7IbEyoDDp # 6WincVwbWyrpGL2BI0D6gLMPZV/Cgqk8meiYsMati4Jgz9TVYbaGL/OCeGf8u797 # wUpOQjxlGFUHVh+/hWCvEZLHRYEj7hYHoHCLouNWZK5qwlnQ6huXuKTn2eSx5hzz # zlTluOBZmtRteF/DfiVStWR8yQIDAQABo4ICAzCCAf8wHwYDVR0jBBgwFoAUaDfg # 67Y7+F8Rhvv+YXsIiGX0TkIwHQYDVR0OBBYEFKgZ4jlQ/frPU8WlXRbihgk1MZUo # MD4GA1UdIAQ3MDUwMwYGZ4EMAQQBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cu # ZGlnaWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYB # BQUHAwMwgbUGA1UdHwSBrTCBqjBToFGgT4ZNaHR0cDovL2NybDMuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAy # MUNBMS5jcmwwU6BRoE+GTWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy # dFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3JsMIGU # BggrBgEFBQcBAQSBhzCBhDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl # cnQuY29tMFwGCCsGAQUFBzAChlBodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v # RGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0Ex # LmNydDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQANZ3pxjdxS5dfEWE7g # 75U9E/E2K25iik7LeuC8uKjpidxh9tt9kpGYoFhvv0B7pz82zPords+WGz1S5ezp # RWVXBGEel/zDWSjUj2VkuNkzyBuC9d62HIgHdu8MOstfIRJRfiIAv9QM3K4OOxAE # 5N77ta/Jc+tmGqUkvSTA7qRowV9+b5X7NpMGtJrNyjsYuVdW2nr6NZgQdJ3PJp42 # Bjk3iPecqWx1WjguHKe7KoL1pPJZ/EL0o8qlE2r20bGRMfKN4IHrVj/IDoLrcakO # Z+hm0PTHjqfOvWvsAblz/9N36D2woDitpqLZHFyYtfCggQb/lb/rRwpMBTjgSdRb # h6n+uY8EEumKdjdyD6TZvlSMEhRth5tqdFUeJmaAK0spBgsd0fzK70tlz3ojp0aa # bTwLzOxk9PKJiD0lp0o+UB2QjewHV3zbrdR+xrrO8cS9IrdCe60vEd9053/tdHCp # JbH+heuTyOCC8CjcgAYRf9L5xEGMVi2Ypm6FlQ9BKHwtuJR+xEuwb92iagonDUlV # m5t4U5GAHLKxyogMAigCm2PJl6golqX4wXUOGQacF6FQ11l76riHjdyvnvcJmXhd # nBjnDfLd6RzgCGWz2QT9W8yqTEZ8ehOzCZpJUzcQm5nnUUKDTnjOiRoESDFnj/n2 # C+NQp9E25RgLwV8Pkt2PSgjbVDGCBkIwggY+AgEBMH0waTELMAkGA1UEBhMCVVMx # FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVz # dGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQBLJA # TOrR92oJkCA9Y4q6WzAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAA # oQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4w # DAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUlAASTGS+omurNiKWZxpsnPF8 # NkAwDQYJKoZIhvcNAQEBBQAEggIAngUdH45e8pyqTf7gzktVgUHVa0aRAxqbHnRF # TXnPMPrdvm7zlaThVzSsSNSN46KPFtbkf6XRUO7q80CskhelQeTbX+mHPjlBRvwE # Ku3x2CBeMhB3Lw/BU2nyc7hTElBida08E87tBOw2mKQY3SAYUFI8bxVXWH4hhtMw # zsggckoKAgjdozidgcSVw1to5soBUSEe32qk6H0rmYK/3fKJlMnuEOqhpziEMYyd # Q3usUl5auUVbC/mi+YMg8iOnp/D+lX/z20AmD1cxntAsj6F7LEo5+7mitMRaRUeN # Z3DBpe4L0CFu4ScJzf2IS90NKe+MCFNBmYe8sz8VEr9TPaYf6lPD+f+vTVqMFXeP # 7jvCqqQJSCHmiKBsVNGMuHvQGUBPBANnUC3e3D/kO+8Z2kC9lO0Ka6AellM1+Mws # m2JRiABlqAxPZ2mLftafJ0eAWj2j32YKlEd5hgDjPcL7V6cMsGuV4ChuLqJBEylo # xD+wxFyPOlO8/DrCRQrtnuQgMnoL8jSsoYN1nLHhBHpRRrz9LKfBPHZnmfnt/BSG # avi594jFW7McjnkEiHgn2YN5tqs+UZsgLOWYikuPbvBzkInAJ2Js7KXcj+885OEg # J889R54F0UQ95gQtYBTjydk5zwepbKhSk/EDuiPSOk6uZIC7hPkkSYmanadF3HdU # l5Uv5HyhggMgMIIDHAYJKoZIhvcNAQkGMYIDDTCCAwkCAQEwdzBjMQswCQYDVQQG # EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0 # IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBAhAFRK/z # lJ0IOaa/2z9f5WEWMA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqG # SIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjQwMzI3MDA1MjUwWjAvBgkqhkiG9w0B # CQQxIgQglHG7tauec/d3CsWheji/kbEvZAwT5idr7Iy1W1L1DeYwDQYJKoZIhvcN # AQEBBQAEggIAcIIWd3OL0xjjAVIN+VL1C2Jd1brFHYRoiKob/YfF1Z9wLwXu6Ja8 # aHhvlx1JMkmlUDM4CRqbZrJJ9fBIZ3H77EivVORxADbvRTtKydW14e1BpKshhIap # 1iD3aAfsjsKq/W0pewAztDIL9QYEDJad10ccP1JDfJkLwo2CQsLumHOsVlvS6KFC # xt4JGNN/H1IZjHdyaosGcRtIFXnaKFZ7+69zrMWTCw4baJrz7RD14Q4IQdl1keuK # i4SplOmYFL4ELNWzROlT5XlTmAlVvFMKiRa4UjTbRLhVfQDF2L/qZkXAcuTac1Ud # gik/L3dSH26CzJ1h/lCnp8ouifcsQ9mRzGYnDgde1qkEi/GVeRvttPLLxHv95vo4 # 8pse8o+D0lBP8T58DpoVGwRDWPvoIQPR2K4mtU6PVH2ks1rt+/KInkJ6cTHqgSGI # 50Z5ua1Et18ukgoWohKrlWDHMdT+uav922wynUZregfJZxb67iaNlj4cyXiCPg4M # TPmM3V5Lr3DJN8MMp1raOTTsHlnOP5SmZLM5HvLbJsh15y2iNmm6UhqzR74losvP # cTvQYyvh4+XJH2wXo51ULzWOETYFNd5VSK7CFXc0kJU3r5a+hDuaT+2zr8RUsgfK # Mu++bbm4CIE8IjMbgNetEPgq8ch5UXSjQay0Ajs+DAcuenvz0qNtYOQ= # SIG # End signature block |