From 23ad3e0f6409fb50ef3126346c4615924ef6122a Mon Sep 17 00:00:00 2001 From: Baoyin Qiao Date: Thu, 2 Apr 2020 18:57:41 +0800 Subject: [PATCH 1/3] Create Readme file --- .../VMware.TrustedInfrastructure.Helper/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Modules/VMware.TrustedInfrastructure.Helper/README.md diff --git a/Modules/VMware.TrustedInfrastructure.Helper/README.md b/Modules/VMware.TrustedInfrastructure.Helper/README.md new file mode 100644 index 0000000..8e5f2de --- /dev/null +++ b/Modules/VMware.TrustedInfrastructure.Helper/README.md @@ -0,0 +1,15 @@ +Prerequisites/Steps to use this module: + 1. You must be a Trust Authority Administrator, a part of the TrustedAdmins group and also have the "Host.Inventory.Add Host To Cluster" privilege on vCenter system. + 2. The ESXi host must be wiped from existing Trusted Infrastructure configuration. If the ESXi host has been previously configured as part of vSphere Trust Authority (part of a vCenter configured for vSphere Trust Authority, a Trust Authority Cluster or Trusted Cluster), you must use the decommission script first. + 3. Clusters should be in a healthy state (check all vSphere Trust Authority APIs which return Health field). + 4. The ESXi host must be removed from vCenter. +- 5. You must know the ESXi host root credentials (username and password). +- 5. You must have purchased sufficient license for vSphere Trust Authority. +- 7. You must have PowerCLI 12.0.0 and above. +- 8. Following PowerCLI module is required to be imported: VMware.VimAutomation.Security. +- 9. Run the command Get-Command -Module VMware.TrustedInfrastructure.Helper. This should inform the following functions are available: + - Add-TrustAuthorityVMHost + - Add-TrustedVMHost + If you do not see these functions listed, the PowerCLI module is not loaded correctly. + 10. Run Get-Help Add-TrustAuthorityVMHost -full and Get-Help Add-TrustedVMHost -full to see how to use these two functions. + 11. Others, please refer vSphere documentation. From 3d74470c70c9141e25d2d1600794f3049c100f95 Mon Sep 17 00:00:00 2001 From: Baoyin Qiao Date: Thu, 2 Apr 2020 18:58:49 +0800 Subject: [PATCH 2/3] Update README.md --- .../VMware.TrustedInfrastructure.Helper/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/VMware.TrustedInfrastructure.Helper/README.md b/Modules/VMware.TrustedInfrastructure.Helper/README.md index 8e5f2de..059f61b 100644 --- a/Modules/VMware.TrustedInfrastructure.Helper/README.md +++ b/Modules/VMware.TrustedInfrastructure.Helper/README.md @@ -1,15 +1,15 @@ Prerequisites/Steps to use this module: 1. You must be a Trust Authority Administrator, a part of the TrustedAdmins group and also have the "Host.Inventory.Add Host To Cluster" privilege on vCenter system. - 2. The ESXi host must be wiped from existing Trusted Infrastructure configuration. If the ESXi host has been previously configured as part of vSphere Trust Authority (part of a vCenter configured for vSphere Trust Authority, a Trust Authority Cluster or Trusted Cluster), you must use the decommission script first. + 2. The ESXi host must be wiped from existing Trusted Infrastructure configuration. If the ESXi host has been previously configured as part of vSphere Trust Authority (part of a vCenter configured for vSphere Trust Authority, a Trust Authority Cluster or Trusted Cluster), you must use the decommission script first. 3. Clusters should be in a healthy state (check all vSphere Trust Authority APIs which return Health field). 4. The ESXi host must be removed from vCenter. -- 5. You must know the ESXi host root credentials (username and password). -- 5. You must have purchased sufficient license for vSphere Trust Authority. -- 7. You must have PowerCLI 12.0.0 and above. -- 8. Following PowerCLI module is required to be imported: VMware.VimAutomation.Security. -- 9. Run the command Get-Command -Module VMware.TrustedInfrastructure.Helper. This should inform the following functions are available: + 5. You must know the ESXi host root credentials (username and password). + 6. You must have purchased sufficient license for vSphere Trust Authority. + 7. You must have PowerCLI 12.0.0 and above. + 8. Following PowerCLI module is required to be imported: VMware.VimAutomation.Security. + 9. Run the command Get-Command -Module VMware.TrustedInfrastructure.Helper. This should inform the following functions are available: - Add-TrustAuthorityVMHost - Add-TrustedVMHost - If you do not see these functions listed, the PowerCLI module is not loaded correctly. + If you do not see these functions listed, the PowerCLI module is not loaded correctly. 10. Run Get-Help Add-TrustAuthorityVMHost -full and Get-Help Add-TrustedVMHost -full to see how to use these two functions. 11. Others, please refer vSphere documentation. From adba00b7e822af02d7bec55002b450bc5f0d7758 Mon Sep 17 00:00:00 2001 From: Baoyin Qiao Date: Thu, 2 Apr 2020 19:00:30 +0800 Subject: [PATCH 3/3] Adding the module script and manifest of it --- .../VMware.TrustedInfrastructure.Helper.psd1 | 316 +++++ .../VMware.TrustedInfrastructure.Helper.psm1 | 1176 +++++++++++++++++ 2 files changed, 1492 insertions(+) create mode 100644 Modules/VMware.TrustedInfrastructure.Helper/VMware.TrustedInfrastructure.Helper.psd1 create mode 100644 Modules/VMware.TrustedInfrastructure.Helper/VMware.TrustedInfrastructure.Helper.psm1 diff --git a/Modules/VMware.TrustedInfrastructure.Helper/VMware.TrustedInfrastructure.Helper.psd1 b/Modules/VMware.TrustedInfrastructure.Helper/VMware.TrustedInfrastructure.Helper.psd1 new file mode 100644 index 0000000..274d301 --- /dev/null +++ b/Modules/VMware.TrustedInfrastructure.Helper/VMware.TrustedInfrastructure.Helper.psd1 @@ -0,0 +1,316 @@ +# +# Module manifest for module 'VMware.TrustedInfrastructure.Helper' +# +# Generated by: VMware +# +# Generated on: 2020/04/02 +# + +@{ + +# Script module or binary module file associated with this manifest. +# RootModule = '' + +# Version number of this module. +ModuleVersion = '1.0' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = 'dbf002d4-1f6a-43d7-994f-3275275e08f9' + +# Author of this module +Author = 'VMware' + +# Company or vendor of this module +CompanyName = 'VMware, Inc.' + +# Copyright statement for this module +Copyright = 'Copyright (c) 2020 VMware, Inc. All rights reserved.' + +# Description of the functionality provided by this module +# Description = '' + +# Minimum version of the Windows PowerShell engine required by this module +# PowerShellVersion = '' + +# Name of the Windows PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the Windows PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# CLRVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +RequiredModules = @( + +@{"ModuleName"="VMware.VimAutomation.Security";"ModuleVersion"="12.0.0.15939672"} + +) + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +NestedModules = @('VMware.TrustedInfrastructure.Helper.psm1') + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +# FunctionsToExport = @() + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +CmdletsToExport = @('Add-TrustedVMHost', 'Add-TrustAuthorityVMHost') + +# Variables to export from this module +# VariablesToExport = '*' + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +# AliasesToExport = @() + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + } # End of PSData hashtable + +} # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + +# SIG # Begin signature block +# MIIi9AYJKoZIhvcNAQcCoIIi5TCCIuECAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBpNQqsdVk1BjVn +# MMKwrDCn/ghozrgmuT8MkgPS925Zl6CCD8swggTMMIIDtKADAgECAhBdqtQcwalQ +# C13tonk09GI7MA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNVBAYTAlVTMR0wGwYDVQQK +# ExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3Qg +# TmV0d29yazEwMC4GA1UEAxMnU3ltYW50ZWMgQ2xhc3MgMyBTSEEyNTYgQ29kZSBT +# aWduaW5nIENBMB4XDTE4MDgxMzAwMDAwMFoXDTIxMDkxMTIzNTk1OVowZDELMAkG +# A1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0 +# bzEVMBMGA1UECgwMVk13YXJlLCBJbmMuMRUwEwYDVQQDDAxWTXdhcmUsIEluYy4w +# ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCuswYfqnKot0mNu9VhCCCR +# vVcCrxoSdB6G30MlukAVxgQ8qTyJwr7IVBJXEKJYpzv63/iDYiNAY3MOW+Pb4qGI +# bNpafqxc2WLW17vtQO3QZwscIVRapLV1xFpwuxJ4LYdsxHPZaGq9rOPBOKqTP7Jy +# KQxE/1ysjzacA4NXHORf2iars70VpZRksBzkniDmurvwCkjtof+5krxXd9XSDEFZ +# 9oxeUGUOBCvSLwOOuBkWPlvCnzEqMUeSoXJavl1QSJvUOOQeoKUHRycc54S6Lern +# 2ddmdUDPwjD2cQ3PL8cgVqTsjRGDrCgOT7GwShW3EsRsOwc7o5nsiqg/x7ZmFpSJ +# AgMBAAGjggFdMIIBWTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDArBgNVHR8E +# JDAiMCCgHqAchhpodHRwOi8vc3Yuc3ltY2IuY29tL3N2LmNybDBhBgNVHSAEWjBY +# MFYGBmeBDAEEATBMMCMGCCsGAQUFBwIBFhdodHRwczovL2Quc3ltY2IuY29tL2Nw +# czAlBggrBgEFBQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTATBgNVHSUE +# DDAKBggrBgEFBQcDAzBXBggrBgEFBQcBAQRLMEkwHwYIKwYBBQUHMAGGE2h0dHA6 +# Ly9zdi5zeW1jZC5jb20wJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdi5zeW1jYi5jb20v +# c3YuY3J0MB8GA1UdIwQYMBaAFJY7U/B5M5evfYPvLivMyreGHnJmMB0GA1UdDgQW +# BBTVp9RQKpAUKYYLZ70Ta983qBUJ1TANBgkqhkiG9w0BAQsFAAOCAQEAlnsx3io+ +# W/9i0QtDDhosvG+zTubTNCPtyYpv59Nhi81M0GbGOPNO3kVavCpBA11Enf0CZuEq +# f/ctbzYlMRONwQtGZ0GexfD/RhaORSKib/ACt70siKYBHyTL1jmHfIfi2yajKkMx +# UrPM9nHjKeagXTCGthD/kYW6o7YKKcD7kQUyBhofimeSgumQlm12KSmkW0cHwSSX +# TUNWtshVz+74EcnZtGFI6bwYmhvnTp05hWJ8EU2Y1LdBwgTaRTxlSDP9JK+e63vm +# SXElMqnn1DDXABT5RW8lNt6g9P09a2J8p63JGgwMBhmnatw7yrMm5EAo+K6gVliJ +# LUMlTW3O09MbDTCCBVkwggRBoAMCAQICED141/l2SWCyYX308B7KhiowDQYJKoZI +# hvcNAQELBQAwgcoxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5j +# LjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMp +# IDIwMDYgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFF +# MEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZp +# Y2F0aW9uIEF1dGhvcml0eSAtIEc1MB4XDTEzMTIxMDAwMDAwMFoXDTIzMTIwOTIz +# NTk1OVowfzELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0 +# aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTAwLgYDVQQDEydT +# eW1hbnRlYyBDbGFzcyAzIFNIQTI1NiBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqG +# SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCXgx4AFq8ssdIIxNdok1FgHnH24ke021hN +# I2JqtL9aG1H3ow0Yd2i72DarLyFQ2p7z518nTgvCl8gJcJOp2lwNTqQNkaC07BTO +# kXJULs6j20TpUhs/QTzKSuSqwOg5q1PMIdDMz3+b5sLMWGqCFe49Ns8cxZcHJI7x +# e74xLT1u3LWZQp9LYZVfHHDuF33bi+VhiXjHaBuvEXgamK7EVUdT2bMy1qEORkDF +# l5KK0VOnmVuFNVfT6pNiYSAKxzB3JBFNYoO2untogjHuZcrf+dWNsjXcjCtvanJc +# YISc8gyUXsBWUgBIzNP4pX3eL9cT5DiohNVGuBOGwhud6lo43ZvbAgMBAAGjggGD +# MIIBfzAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9zMi5zeW1j +# Yi5jb20wEgYDVR0TAQH/BAgwBgEB/wIBADBsBgNVHSAEZTBjMGEGC2CGSAGG+EUB +# BxcDMFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vY3BzMCgG +# CCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vcnBhMDAGA1UdHwQp +# MCcwJaAjoCGGH2h0dHA6Ly9zMS5zeW1jYi5jb20vcGNhMy1nNS5jcmwwHQYDVR0l +# BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMDMA4GA1UdDwEB/wQEAwIBBjApBgNVHREE +# IjAgpB4wHDEaMBgGA1UEAxMRU3ltYW50ZWNQS0ktMS01NjcwHQYDVR0OBBYEFJY7 +# U/B5M5evfYPvLivMyreGHnJmMB8GA1UdIwQYMBaAFH/TZafC3ey78DAJ80M5+gKv +# MzEzMA0GCSqGSIb3DQEBCwUAA4IBAQAThRoeaak396C9pK9+HWFT/p2MXgymdR54 +# FyPd/ewaA1U5+3GVx2Vap44w0kRaYdtwb9ohBcIuc7pJ8dGT/l3JzV4D4ImeP3Qe +# 1/c4i6nWz7s1LzNYqJJW0chNO4LmeYQW/CiwsUfzHaI+7ofZpn+kVqU/rYQuKd58 +# vKiqoz0EAeq6k6IOUCIpF0yH5DoRX9akJYmbBWsvtMkBTCd7C6wZBSKgYBU/2sn7 +# TUyP+3Jnd/0nlMe6NQ6ISf6N/SivShK9DbOXBd5EDBX6NisD3MFQAfGhEV0U5eK9 +# J0tUviuEXg+mw3QFCu+Xw4kisR93873NQ9TxTKk/tYuEr2Ty0BQhMIIFmjCCA4Kg +# AwIBAgIKYRmT5AAAAAAAHDANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJVUzET +# MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV +# TWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3NvZnQgQ29kZSBW +# ZXJpZmljYXRpb24gUm9vdDAeFw0xMTAyMjIxOTI1MTdaFw0yMTAyMjIxOTM1MTda +# MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV +# BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZl +# cmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMT +# PFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBB +# dXRob3JpdHkgLSBHNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK8k +# CAgpejWeYAyq50s7Ttx8vDxFHLsr4P4pAvlXCKNkhRUn9fGtyDGJXSLoKqqmQrOP +# +LlVt7G3S7P+j34HV+zvQ9tmYhVhz2ANpNje+ODDYgg9VBPrScpZVIUm5SuPG5/r +# 9aGRwjNJ2ENjalJL0o/ocFFN0Ylpe8dw9rPcEnTbe11LVtOWvxV3obD0oiXyrxyS +# Zxjl9AYE75C55ADk3Tq1Gf8CuvQ87uCL6zeL7PTXrPL28D2v3XWRMxkdHEDLdCQZ +# IZPZFP6sKlLHj9UESeSNY0eIPGmDy/5HvSt+T8WVrg6d1NFDwGdz4xQIfuU/n3O4 +# MwrPXT80h5aK7lPoJRUCAwEAAaOByzCByDARBgNVHSAECjAIMAYGBFUdIAAwDwYD +# VR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAYYwHQYDVR0OBBYEFH/TZafC3ey78DAJ +# 80M5+gKvMzEzMB8GA1UdIwQYMBaAFGL7CiFbf0NuEdoJVFBr9dKWcfGeMFUGA1Ud +# HwROMEwwSqBIoEaGRGh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3By +# b2R1Y3RzL01pY3Jvc29mdENvZGVWZXJpZlJvb3QuY3JsMA0GCSqGSIb3DQEBBQUA +# A4ICAQCBKoIWjDRnK+UD6zR7jKKjUIr0VYbxHoyOrn3uAxnOcpUYSK1iEf0g/T9H +# BgFa4uBvjBUsTjxqUGwLNqPPeg2cQrxc+BnVYONp5uIjQWeMaIN2K4+Toyq1f75Z +# +6nJsiaPyqLzghuYPpGVJ5eGYe5bXQdrzYao4mWAqOIV4rK+IwVqugzzR5NNrKSM +# B3k5wGESOgUNiaPsn1eJhPvsynxHZhSR2LYPGV3muEqsvEfIcUOW5jIgpdx3hv08 +# 44tx23ubA/y3HTJk6xZSoEOj+i6tWZJOfMfyM0JIOFE6fDjHGyQiKEAeGkYfF9sY +# 9/AnNWy4Y9nNuWRdK6Ve78YptPLH+CHMBLpX/QG2q8Zn+efTmX/09SL6cvX9/zoc +# Qjqh+YAYpe6NHNRmnkUB/qru//sXjzD38c0pxZ3stdVJAD2FuMu7kzonaknAMK5m +# yfcjKDJ2+aSDVshIzlqWqqDMDMR/tI6Xr23jVCfDn4bA1uRzCJcF29BUYl4DSMLV +# n3+nZozQnbBP1NOYX0t6yX+yKVLQEoDHD1S2HmfNxqBsEQOE00h15yr+sDtuCjqm +# a3aZBaPxd2hhMxRHBvxTf1K9khRcSiRqZ4yvjZCq0PZ5IRuTJnzDzh69iDiSrkXG +# GWpJULMF+K5ZN4pqJQOUsVmBUOi6g4C3IzX0drlnHVkYrSCNlDGCEn8wghJ7AgEB +# MIGTMH8xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlv +# bjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEwMC4GA1UEAxMnU3lt +# YW50ZWMgQ2xhc3MgMyBTSEEyNTYgQ29kZSBTaWduaW5nIENBAhBdqtQcwalQC13t +# onk09GI7MA0GCWCGSAFlAwQCAQUAoIGWMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3 +# AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCoGCisGAQQBgjcCAQwx +# HDAaoRiAFmh0dHA6Ly93d3cudm13YXJlLmNvbS8wLwYJKoZIhvcNAQkEMSIEIM0S +# yl+DLO5/G6CpV6dDnBERqJttAW4XXH7Aky0XuDpFMA0GCSqGSIb3DQEBAQUABIIB +# AFFIiFbh7hbtFYhpRzq2TM3DZ2R+LpRz2DdVTOR8iLirTkwcZvCMbsx4wZbcoDpQ +# uldpdbJS1CuXAX+TW48NtE/ph0wA+c2D5CgAvyamV9Zz/Jog9W8bYrytl3A1JNCk +# cT6xdg8L+E6OAx1L4ls8giqJXOoJSpFX4fD8Wzdd2cA4GgfPSZ3V+KahgxnOmglp +# rVcsFfdMywtGyfVyYU5ZP/a2Wo9uGioZVYaRuW6gUc8aziUWpeeUCPDeOMTpRCVE +# Hu4YO7usse7/W2c4sQGe273k/AYyyVf1pLQrmoW5Q453KcpiZa3FJAPBoyamCO2i +# 0b1IdrfRwgriLapWu2Qv4SyhghAjMIIQHwYKKwYBBAGCNwMDATGCEA8wghALBgkq +# hkiG9w0BBwKggg/8MIIP+AIBAzEPMA0GCWCGSAFlAwQCAQUAMIHmBgsqhkiG9w0B +# CRABBKCB1gSB0zCB0AIBAQYJKwYBBAGgMgIDMDEwDQYJYIZIAWUDBAIBBQAEIPY5 +# SN6u90hWWtb8WksRwND3bUpYHl/udJrlk3gg43Q7Ag4BbKiJKXgAAAAAAKUUyRgT +# MjAyMDA0MDIxMDI5MTcuMjUzWjADAgEBoGOkYTBfMQswCQYDVQQGEwJKUDEcMBoG +# A1UEChMTR01PIEdsb2JhbFNpZ24gSy5LLjEyMDAGA1UEAxMpR2xvYmFsU2lnbiBU +# U0EgZm9yIEFkdmFuY2VkIC0gRzMgLSAwMDMtMDGgggxqMIIE6jCCA9KgAwIBAgIM +# M5Agd2HEJt2UUAMNMA0GCSqGSIb3DQEBCwUAMFsxCzAJBgNVBAYTAkJFMRkwFwYD +# VQQKExBHbG9iYWxTaWduIG52LXNhMTEwLwYDVQQDEyhHbG9iYWxTaWduIFRpbWVz +# dGFtcGluZyBDQSAtIFNIQTI1NiAtIEcyMB4XDTE4MDYxNDEwMDAwMFoXDTI5MDMx +# ODEwMDAwMFowXzELMAkGA1UEBhMCSlAxHDAaBgNVBAoTE0dNTyBHbG9iYWxTaWdu +# IEsuSy4xMjAwBgNVBAMTKUdsb2JhbFNpZ24gVFNBIGZvciBBZHZhbmNlZCAtIEcz +# IC0gMDAzLTAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv3Gj+IDO +# E5Be8KfdP9KY8kE6Sdp/WC+ePDoBE8ptNJlbDCccROdW4wkv9W+rTr4nYmbGuLKH +# x2W+xsBeqT6u+yR0iyv4aARkhqo64qohj/rxnbkYMF6afAf1O3Uu2gklGav+c+lx +# neyq9j4ShYEUJPjmPpnfrvO5i9UmywSommFW7yhwqEtqKyVq5aA2ny25mofcdA4f +# QqBBOpYHDst7MtUBC1ORfVY0T7S8sHRHnKp6bF/kjlGfk5BhAz6PX0FBUHg5LRIS +# 3OvqADCyP+FtE7d1SBVrTg7Rl+NO25bZ0WKvCEHPIg/o3c7Y6pNWbtM6j2dKaki6 +# /GHlbFmzEi0CgQIDAQABo4IBqDCCAaQwDgYDVR0PAQH/BAQDAgeAMEwGA1UdIARF +# MEMwQQYJKwYBBAGgMgEeMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2Jh +# bHNpZ24uY29tL3JlcG9zaXRvcnkvMAkGA1UdEwQCMAAwFgYDVR0lAQH/BAwwCgYI +# KwYBBQUHAwgwRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL2NybC5nbG9iYWxzaWdu +# LmNvbS9ncy9nc3RpbWVzdGFtcGluZ3NoYTJnMi5jcmwwgZgGCCsGAQUFBwEBBIGL +# MIGIMEgGCCsGAQUFBzAChjxodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2Nh +# Y2VydC9nc3RpbWVzdGFtcGluZ3NoYTJnMi5jcnQwPAYIKwYBBQUHMAGGMGh0dHA6 +# Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9nc3RpbWVzdGFtcGluZ3NoYTJnMjAdBgNV +# HQ4EFgQUeaezg3HWs0B2IOZ0Crf39+bd3XQwHwYDVR0jBBgwFoAUkiGnSpVdZLCb +# tB7mADdH5p1BK0wwDQYJKoZIhvcNAQELBQADggEBAIc0fm43ZxsIEQJttimYchTL +# SH7IyY8viQ2vD/IsIZBuO7ccAaqBaMQQI0v4CeOrX+pFps4O/qSA6WtqDAD5yoYQ +# DD7/HxrpHOUil2TZrOnj6NpTYGMLt45P3NUh9J3eE2o4NeVs4yZM29Z0Z0W5TwTE +# WAgam2ZFPSQaGpJXyV8oR3hn21zKrQvotw/RthYyNCIENnJM73umvLauBMDZeKCI +# yIZrGNqWjStuIlzLf70XvZ63toZNgxBNsDKy4BOgy2DihHUU6SG9EKKktgjPOw0p +# WVmp08NMDX9CzIgUtELlugTVmEqkjQc9SR94bWVtYL38zlnrLOnFqtqt7taTrBUw +# ggQVMIIC/aADAgECAgsEAAAAAAExicZQBDANBgkqhkiG9w0BAQsFADBMMSAwHgYD +# VQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2ln +# bjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0xMTA4MDIxMDAwMDBaFw0yOTAzMjkx +# MDAwMDBaMFsxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNh +# MTEwLwYDVQQDEyhHbG9iYWxTaWduIFRpbWVzdGFtcGluZyBDQSAtIFNIQTI1NiAt +# IEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqpuOw6sRUSUBtpaU +# 4k/YwQj2RiPZRcWVl1urGr/SbFfJMwYfoA/GPH5TSHq/nYeer+7DjEfhQuzj46FK +# bAwXxKbBuc1b8R5EiY7+C94hWBPuTcjFZwscsrPxNHaRossHbTfFoEcmAhWkkJGp +# eZ7X61edK3wi2BTX8QceeCI2a3d5r6/5f45O4bUIMf3q7UtxYowj8QM5j0R5tnYD +# V56tLwhG3NKMvPSOdM7IaGlRdhGLD10kWxlUPSbMQI2CJxtZIH1Z9pOAjvgqOP1r +# oEBlH1d2zFuOBE8sqNuEUBNPxtyLufjdaUyI65x7MCb8eli7WbwUcpKBV7d2ydiA +# CoBuCQIDAQABo4HoMIHlMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/ +# AgEAMB0GA1UdDgQWBBSSIadKlV1ksJu0HuYAN0fmnUErTDBHBgNVHSAEQDA+MDwG +# BFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5jb20v +# cmVwb3NpdG9yeS8wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9iYWxz +# aWduLm5ldC9yb290LXIzLmNybDAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpjmove +# 4t0bvDANBgkqhkiG9w0BAQsFAAOCAQEABFaCSnzQzsm/NmbRvjWek2yX6AbOMRhZ +# +WxBX4AuwEIluBjH/NSxN8RooM8oagN0S2OXhXdhO9cv4/W9M6KSfREfnops7yyw +# 9GKNNnPRFjbxvF7stICYePzSdnno4SGU4B/EouGqZ9uznHPlQCLPOc7b5neVp7uy +# y/YZhp2fyNSYBbJxb051rvE9ZGo7Xk5GpipdCJLxo/MddL9iDSOMXCo4ldLA1c3P +# iNofKLW6gWlkKrWmotVzr9xG2wSukdduxZi61EfEVnSAR3hYjL7vK/3sbL/RlPe/ +# UOB74JD9IBh4GCJdCC6MHKCX8x2ZfaOdkdMGRE4EbnocIOM28LZQuTCCA18wggJH +# oAMCAQICCwQAAAAAASFYUwiiMA0GCSqGSIb3DQEBCwUAMEwxIDAeBgNVBAsTF0ds +# b2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYD +# VQQDEwpHbG9iYWxTaWduMB4XDTA5MDMxODEwMDAwMFoXDTI5MDMxODEwMDAwMFow +# TDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkds +# b2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wggEiMA0GCSqGSIb3DQEBAQUA +# A4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2hMoonv0FdhHFrYhy/EYCQ8eyip0E +# XyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9DCuul9e2FIYQebs7E4B3jAjhSdJq +# Yi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkmDoMVxu9bi9IEYMpJpij2aTv2y8go +# keWdimFXN6x0FNx04Druci8unPvQu7/1PQDhBjPogiuuU6Y6FnOM3UEOIDrAtKeh +# 6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTvriBJ/K1AFUjRAjFhGV64l++td7dk +# mnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZphYIXAgMBAAGjQjBAMA4GA1UdDwEB +# /wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSP8Et/qC5FJK5NUPpj +# move4t0bvDANBgkqhkiG9w0BAQsFAAOCAQEAS0DbwFCq/sgM7/eWVEVJu5YACUGs +# sxOGhigHM8pr5nS5ugAtrqQK0/Xx8Q+Kv3NnSoPHRHt44K9ubG8DKY4zOUXDjuS5 +# V2yq/BKW7FPGLeQkbLmUY/vcU2hnVj6DuM81IcPJaP7O2sJTqsyQiunwXUaMld16 +# WCgaLx3ezQA3QY/tRG3XUyiXfvNnBB4V14qWtNPeTCekTBtzc3b0F5nCH3oO4y0I +# rQocLP88q1UOD5F+NuvDV0m+4S4tfGCLw0FREyOdzvcya5QBqJnnLDMfOjsl0oZA +# zjsshnjJYS8Uuu7bVW/fhO4FCU29KNhyztNiUGUe65KXgzHZs7XKR1g/XzGCAokw +# ggKFAgEBMGswWzELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt +# c2ExMTAvBgNVBAMTKEdsb2JhbFNpZ24gVGltZXN0YW1waW5nIENBIC0gU0hBMjU2 +# IC0gRzICDDOQIHdhxCbdlFADDTANBglghkgBZQMEAgEFAKCB8DAaBgkqhkiG9w0B +# CQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIAZrKdIvpe4etJdIpute +# bD7Bkgo2OLI6O5CjboEGMuXnMIGgBgsqhkiG9w0BCRACDDGBkDCBjTCBijCBhwQU +# rmsC2QsljAmRsRYSid62aVY5HW8wbzBfpF0wWzELMAkGA1UEBhMCQkUxGTAXBgNV +# BAoTEEdsb2JhbFNpZ24gbnYtc2ExMTAvBgNVBAMTKEdsb2JhbFNpZ24gVGltZXN0 +# YW1waW5nIENBIC0gU0hBMjU2IC0gRzICDDOQIHdhxCbdlFADDTANBgkqhkiG9w0B +# AQEFAASCAQCtspr11iTT8uoLlJY6Gmk9/dEzqYSh+ib0ml+qk5WNO2g0ggA42yp9 +# lnUfnLFUdqTCTm1kP5QHYISnBRVq88TDVqPOlxMUr/pxaWGi95NgkMbYS0A9bEf1 +# 0B1BjUsVHdEcRmW3RYU6bgmcoMKCNNvt2U0+r/e85MW358FMr5+Qwje5xKFhFKQi +# wZkY34+ycnFsyMBwDCYeMxIWEAJdFdp+BQ1NI4hE1+whqEoXxBFbHABzoK7CQfZt +# x38BWzvhRjGc4DFiTH25oqKHmzvvBrtIBhR1KGP0UxgJtLIkBu1lqqVCpD2DuOpu +# 6Q/wMh8Z+1DanPs+68ioAyOE0N4MaVz+ +# SIG # End signature block diff --git a/Modules/VMware.TrustedInfrastructure.Helper/VMware.TrustedInfrastructure.Helper.psm1 b/Modules/VMware.TrustedInfrastructure.Helper/VMware.TrustedInfrastructure.Helper.psm1 new file mode 100644 index 0000000..b2cfe08 --- /dev/null +++ b/Modules/VMware.TrustedInfrastructure.Helper/VMware.TrustedInfrastructure.Helper.psm1 @@ -0,0 +1,1176 @@ +# Script Module : VMware.TrustedInfrastructure.Helper +# Version : 1.0 + +# Copyright © 2020 VMware, Inc. All Rights Reserved. + +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +$TrustedClusterSettingsFile = +-join((48..57 + 65..90 + 97..122) | get-random -count 6 | %{[char]$_})+".json" + +$TrustAuthorityClusterSettingsFile = +-join((48..57 + 65..90 + 97..122) | get-random -count 6 | %{[char]$_})+".json" + +Function Add-TrustAuthorityVMHost { + <# + .SYNOPSIS + + This cmdlet adds a new host into the specific Trust Authority cluster. + There are some preconditions need to be met: + 1. The newly added host is cleared of any previous Trust Authority configurations + 2. The Trust Authority Cluster settings are all healthy + 3. The connection user has the needed privileges. Please, check vSphere documentation. + 4. The trust between Key Servers and TrustAuthorityKeyProvider uses the signed client certificate, user should provide its privateKey part + + .DESCRIPTION + This cmdlet adds a new host into the specific Trust Authority cluster. + + .PARAMETER TrustAuthorityCluster + Specifies the Trust Authority cluster you want to add the new host. + + .PARAMETER VMHostAddress + Specifies the ip address of the new host you want to add to the specific Trust Authority cluster. + + .PARAMETER Credential + Specifies the credential of the new host. + + .PARAMETER DestDir + Specifies the location where you want to save the settings + + .PARAMETER PrivateKey + Specifies the private key part of the ClientCertificate of the TrustAuthorityKeyProvider. It's a hashtable type with: the keyprovider.Name as the Key, and the File having the PrivateKey string for the ClientCertificate of the keyprovider as its Value. + + .PARAMETER BaseImageFolder + Specifies the folder having all the baseImage files to re-create the TrustAuthorityVMHostBaseImage. + + .EXAMPLE + PS C:\> $ts = Get-TrustAuthorityCluster "mycluster" + PS C:\> $pass = Read-Host "Please enter the host's password" -AsSecureString + PS C:\> $credential = New-Object System.Management.Automation.PSCredential -ArgumentList root,$pass + PS C:\> $privateKeyHash = @{"provider1"="c:\myprivatekey.txt";} + PS C:\> Add-TrustAuthorityVMHost -TrustAuthorityCluster $ts -VMHostAddress 1.1.1.1 -Credential $credential -DestDir c:\destDir\ -PrivateKey $privateKeyHash -BaseImageFolder "c:\baseImages\" + + Add the host 1.1.1.1 with the $credential to Trust Authority cluster "mycluster", also saves the setting file of the trustedcluster "mycluster" to folder c:\destDir\. + + .EXAMPLE + PS C:\> $ts = Get-TrustAuthorityCluster "mycluster" + PS C:\> Add-TrustAuthorityVMHost -TrustAuthorityCluster $ts -VMHostAddress 1.1.1.1 -Credential root -DestDir c:\destDir\ -BaseImageFolder "c:\baseImages\" + + Add the host 1.1.1.1 with the credential root (a window wizard will be prompted to let you input the password for the user root) to Trust Authority cluster "mycluster", also saves the setting file of the trustedcluster "mycluster" to folder c:\destDir\. + + .NOTES + Author : Carrie Yang + Author email : yangm@vmware.com + #> + + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [VMware.VimAutomation.Security.Types.V1.TrustedInfrastructure.TrustAuthorityCluster] $TrustAuthorityCluster, + + [Parameter(Mandatory=$True)] + [String] $VMHostAddress, + + [Parameter(Mandatory=$True)] + [System.Management.Automation.Credential()] + $Credential, + + [Parameter(Mandatory=$True)] + [String] $DestDir, + + [hashtable] $PrivateKey, + + [Parameter(Mandatory=$True)] + [String] $BaseImageFolder + ) + + Begin { + Write-Warning "Please confirm the new host to add is cleared from any previous Trust Authority Configurations." -WarningAction Inquire + + Write-Warning "Please confirm the connection user has the privilege to add the new host to the cluster $($TrustAuthorityCluster.Name)." -WarningAction Inquire + + Write-Warning "Please confirm the connection user has been added to 'TrustedAdmins' group." -WarningAction Inquire + + $server = GetViServer -clusterUid $TrustAuthorityCluster.Uid + + ConfirmIsVCenter $server + + Check-VMHostVersionAndLicense -VMHostName $VMHostAddress -Credential $Credential -CheckLicense:$false -ErrorAction Stop + $DestinationFile = Join-Path $destDir $TrustAuthorityClusterSettingsFile + Write-Verbose "The file to save settings is $DestinationFile" + + Check-TrustAuthorityClusterHealth -TrustAuthorityCluster $TrustAuthorityCluster + IsSelfSignedClientCertificate -TrustAuthorityCluster $TrustAuthorityCluster -privateKey $privateKey + } + + Process { + Save-TrustAuthorityClusterSettings -TrustAuthorityCluster $TrustAuthorityCluster -DestinationFile $DestinationFile -ErrorAction Stop + + Join-VMHost -ClusterName $TrustAuthorityCluster.Name -VMHostAddress $VMHostAddress -Credential $Credential -ErrorAction Stop + Apply-TrustAuthorityClusterSettings -TrustAuthorityCluster $TrustAuthorityCluster -SettingsFile $DestinationFile -BaseImageFolder $baseImageFolder -PrivateKey $privateKey -ErrorAction Stop + } +} + +Function Add-TrustedVMHost { + <# + .SYNOPSIS + + This cmdlet adds a new host into the specific Trusted cluster. + There are some preconditions need to be met: + 1. No active workloads in the workload host as the cmdlet will interrup the workloads + 2. The newly added host is cleared of any previous Trust Authority Configurations + 3. Sufficient license + + .DESCRIPTION + This cmdlet adds a new host into the specific Trusted cluster. + + .PARAMETER TrustedCluster + Specifies the Trusted cluster you want to add the new host. + + .PARAMETER VMHostAddress + Specifies the ip address of the new host you want to add to the specific Trusted cluster. + + .PARAMETER Credential + Specifies the credential of the new host. + + .PARAMETER DestDir + Specifies the location where you want to save the settings + + .EXAMPLE + PS C:\> $ts = Get-TrustedCluster "mycluster" + PS C:\> $pass = Read-Host "Please enter the host's password" -AsSecureString + PS C:\> $credential = New-Object System.Management.Automation.PSCredential -ArgumentList root,$pass + PS C:\> Add-TrustedVMHost -TrustedCluster $ts -VMHostAddress 1.1.1.1 -Credential $credential -DestDir c:\destDir\ + + Add the host 1.1.1.1 with the $credential to Trusted Cluster "mycluster", also saves the setting file of the trustedcluster "mycluster" to folder c:\destDir\. + + .EXAMPLE + PS C:\> $ts = Get-TrustedCluster "mycluster" + PS C:\> Add-TrustedVMHost -TrustedCluster $ts -VMHostAddress 1.1.1.1 -Credential root -DestDir c:\destDir\ + + Add the host 1.1.1.1 with the credential root (a window wizard will be prompted to let you input the password for the user root) to Trusted Cluster "mycluster", also saves the setting file of the trustedcluster "mycluster" to folder c:\destDir\. + + .NOTES + Author : Carrie Yang + Author email : yangm@vmware.com + #> + + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [VMware.VimAutomation.Security.Types.V1.TrustedInfrastructure.TrustedCluster] $TrustedCluster, + + [Parameter(Mandatory=$True)] + [String] $VMHostAddress, + + [Parameter(Mandatory=$True)] + [System.Management.Automation.Credential()] + $Credential, + + [Parameter(Mandatory=$True)] + [String] $DestDir + ) + + Begin { + Write-Warning "Please confirm workload cluster has no currently active workloads! This operation will interrupt the active crypto operations." -WarningAction Inquire + + Write-Warning "Please confirm the new host to add is cleared from any previous Trust Authority Configurations." -WarningAction Inquire + + Write-Warning "Please confirm the connection user has the privilege to add the new host to the cluster $($TrustedCluster.Name)." -WarningAction Inquire + + Write-Warning "Please confirm the connection user has been added to 'TrustedAdmins' group." -WarningAction Inquire + + $server = GetViServer -clusterUid $TrustedCluster.Uid + Write-Verbose "The server got is: $server" + ConfirmIsVCenter $server + + Check-VMHostVersionAndLicense -VMHostName $VMHostAddress -Credential $Credential -CheckLicense:$true + $DestinationFile = Join-Path $DestDir $TrustedClusterSettingsFile + Write-Verbose "The file to save settings is $DestinationFile" + } + + Process { + Check-TrustedClusterSettings -TrustedCluster $TrustedCluster -ErrorAction Stop + Save-TrustedClusterSettings -TrustedCluster $TrustedCluster -DestinationFile $DestinationFile -ErrorAction Stop + Remove-TrustedClusterSettings -TrustedCluster $TrustedCluster -ErrorAction Stop + Join-VMHost -ClusterName $TrustedCluster.Name -VMHostAddress $VMHostAddress -Credential $Credential -ErrorAction Stop + Apply-TrustedClusterSettings -TrustedCluster $TrustedCluster -SettingsFile $DestinationFile -ErrorAction Stop + } +} + +Function Save-TrustedClusterSettings { + <# + .SYNOPSIS + This cmdlet saves the settings of the specific Trusted Cluster to the file $DestinationFile. + + .DESCRIPTION + This cmdlet saves the settings of the specific Trusted Cluster to the file $DestinationFile. + + .PARAMETER TrustedCluster + Specifies the Trusted Cluster you want to save the settings. + + .PARAMETER DestinationFile + Specifies the file you want to save the settings to. + + .EXAMPLE + PS C:\> $ts = Get-TrustedCluster "mycluster" + PS C:\> Save-TrustedClusterSettings -TrustedCluster $ts -DestinationFile "c:\myfile.json" + Saves the settings of Trusted Cluster "mycluster" to file c:\myfile.json. + + .NOTES + Author : Carrie Yang + Author email : yangm@vmware.com + #> + + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [VMware.VimAutomation.Security.Types.V1.TrustedInfrastructure.TrustedCluster] $TrustedCluster, + + [Parameter(Mandatory=$True)] + [String] $DestinationFile + ) + + Begin { + $greenvc = GetViServer -clusterUid $TrustedCluster.Uid + Write-Host "Saving the settings of TrustedCluster $($TrustedCluster.Name)..." + } + + Process { + $TrustedCluster = Get-TrustedCluster $TrustedCluster.Name -Server $greenvc + + $TrustedClusterjson = @" + { + "VC": "", + "TrustedCluster": + { + "Name": "$($TrustedCluster.Name)", + "AttestationServiceInfo": [], + "KeyProviderServiceInfo": [] + } + } +"@ + $attestInfo = $TrustedCluster.AttestationServiceInfo + $keyproviderInfo = $TrustedCluster.KeyProviderServiceInfo + $jsonObj = ConvertFrom-Json -InputObject $TrustedClusterjson + $jsonObj.VC = $greenvc + $jsonObj.TrustedCluster.AttestationServiceInfo = $attestInfo + $jsonObj.TrustedCluster.KeyProviderServiceInfo = $keyproviderInfo + + $jsonObj | ConvertTo-Json | Out-File $DestinationFile -Force + } +} + +Function Save-TrustAuthorityClusterSettings { + <# + .SYNOPSIS + This cmdlet saves the settings of the specific Trust Authority Cluster to the file $DestinationFile. + + .DESCRIPTION + This cmdlet saves the settings of the specific Trust Authority Cluster to the file $DestinationFile. + + .PARAMETER TrustedCluster + Specifies the Trust Authority Cluster you want to save the settings. + + .PARAMETER DestinationFile + Specifies the file you want to save the settings to. + + .EXAMPLE + + PS C:\> $ts = Get-TrustAuthorityCluster "mycluster" + PS C:\> Save-TrustAuthorityClusterSettings -TrustAuthorityCluster $ts -DestinationFile "c:\myfile.json" + Saves the settings of Trust Authority Cluster "mycluster" to file c:\myfile.json. + + .NOTES + Author : Carrie Yang + Author email : yangm@vmware.com + #> + + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [VMware.VimAutomation.Security.Types.V1.TrustedInfrastructure.TrustAuthorityCluster] $TrustAuthorityCluster, + + [Parameter(Mandatory=$True)] + [String] $DestinationFile + ) + + Begin { + $bluevc = GetViServer -clusterUid $TrustAuthorityCluster.Uid + Write-Host "Saving the settings of TrustAuthorityCluster $($TrustAuthorityCluster.Name)..." + } + + Process { + $json = @" + { + "VC": "", + "TrustAuthorityCluster": { + "Name": "", + "TrustAuthorityPrincipal": [], + "TrustAuthorityKeyProvider": [], + "TrustAuthorityVMHostBaseImage": [], + "TrustAuthorityTpm2AttestationSettings": {}, + "TrustAuthorityTpm2CACertificate": [], + "TrustAuthorityTpm2EndorsementKey": [] + } + } +"@ + $jsonObj = ConvertFrom-Json -InputObject $json + $jsonObj.VC = $bluevc + $jsonObj.TrustAuthorityCluster.Name = $TrustAuthorityCluster.Name + $kp = Get-TrustAuthorityKeyProvider -Cluster $TrustAuthorityCluster -Server $bluevc + + $i = 0 + + if ($kp -ne $null) { + $jsonObj.TrustAuthorityCluster.TrustAuthorityKeyProvider = $kp | Select-Object -Property Name, MasterKeyId, Description, ProxyAddress, ProxyPort, ConnectionTimeoutSeconds, KmipServerUsername + $clientCert = @{} + $serverCert = @{} + $clientCSR = @{} + } + + foreach ($_ in $kp) { + $kps = Get-TrustAuthorityKeyProviderServer -KeyProvider $_ -Server $bluevc| Select-Object -Property Address, Port, Name + $clientCertTemp = Get-TrustAuthorityKeyProviderClientCertificate -KeyProvider $_ -Server $bluevc + $clientCertStr = [System.Convert]::ToBase64String($($clientCertTemp.GetRawCertData())) + $serverCertTemp = Get-TrustAuthorityKeyProviderServerCertificate -KeyProvider $_ -Server $bluevc | Select-Object -Property CertificateRawData, Trusted + $clientCSRTemp = Get-TrustAuthorityKeyProviderClientCertificateCSR -KeyProvider $_ -Server $bluevc + + $jsonObj.TrustAuthorityCluster.TrustAuthorityKeyProvider[$i] | Add-Member -Name "KmipServers" -value $kps -MemberType NoteProperty + $jsonObj.TrustAuthorityCluster.TrustAuthorityKeyProvider[$i] | Add-Member -Name "ClientCertificate" -value $clientCertStr -MemberType NoteProperty + $jsonObj.TrustAuthorityCluster.TrustAuthorityKeyProvider[$i] | Add-Member -Name "ClientCertificateCSR" -value $clientCSRTemp -MemberType NoteProperty + $jsonObj.TrustAuthorityCluster.TrustAuthorityKeyProvider[$i] | Add-Member -Name "ServerCertificate" -value $serverCertTemp -MemberType NoteProperty + $i++ + + if ($clientCertTemp -ne $null) { + $clientCert.Add($_.Name, $clientCertTemp) + } + + if ($serverCertTemp -ne $null) { + $serverCert.Add($_.Name, $serverCertTemp) + } + + if (![string]::IsNullOrWhiteSpace($clientCSRTemp)) { + $clientCSR.Add($_.Name, $clientCSRTemp) + } + } + + $principals = Get-TrustAuthorityPrincipal -Cluster $TrustAuthorityCluster -Server $bluevc| Select-Object -Property Name, Issuer, Domain, Type, IssuerAlias, certRawData + + $tpm2Settings = Get-TrustAuthorityTpm2AttestationSettings -Cluster $TrustAuthorityCluster -Server $bluevc | Select-Object -Property RequireEndorsementKey, RequireCertificateValidation + $tpm2CA = Get-TrustAuthorityTpm2CACertificate -Cluster $TrustAuthorityCluster -Server $bluevc + $tpm2Ek = Get-TrustAuthorityTpm2EndorsementKey -Cluster $TrustAuthorityCluster -Server $bluevc + $baseImages = Get-TrustAuthorityVMHostBaseImage -Cluster $TrustAuthorityCluster -Server $bluevc + + $jsonObj.VC = GetViServer -clusterUid $TrustAuthorityCluster.Uid + $jsonObj.TrustAuthorityCluster.TrustAuthorityPrincipal = $principals + + $jsonObj.TrustAuthorityCluster.TrustAuthorityTpm2AttestationSettings = $tpm2Settings + + $jsonObj.TrustAuthorityCluster.TrustAuthorityTpm2CACertificate = $tpm2CA | Select-Object -Property Name + + $i = 0 + foreach ($_ in $tpm2CA) { + $certStr = ConvertFrom-X509Chain -CertChain $_.CertificateChain + $jsonObj.TrustAuthorityCluster.TrustAuthorityTpm2CACertificate[$i] | Add-Member -Name "certRawData" -value $certStr -MemberType NoteProperty + + $i++ + } + + $jsonObj.TrustAuthorityCluster.TrustAuthorityTpm2EndorsementKey = $tpm2Ek + $jsonObj.TrustAuthorityCluster.TrustAuthorityVMHostBaseImage = $baseImages + + $jsonObj | ConvertTo-Json -Depth 6 | Out-File $DestinationFile -Force + } +} + +Function Apply-TrustAuthorityClusterSettings { + <# + .SYNOPSIS + This cmdlet applies the settings in the specific $SettingsFile to a Trust Authority Cluster. + Here are some limitations when applying the TrustAuthorityKeyProvider Settings: + - The CSR configuration will not be preserved, user needs to reset the CSR and get it signed by the Key Server, then retrieve the signed client certificate to set it back to TrustAuthorityKeyProvider + - If self signed certificates are used for trust setup, they need to be redone on new host. + + .DESCRIPTION + This cmdlet applies the settings in the specific $SettingsFile to a Trust Authority Cluster + + .PARAMETER TrustAuthorityCluster + Specifies the Trust Authority Cluster you want to apply the settings + + .PARAMETER SettingsFile + Specifies the file having the settings you want to apply + + .PARAMETER PrivateKey + Specifies the private key part of the ClientCertificate of the TrustAuthorityKeyProvider. It is a hashtable type with: the Key is the TrustAuthorityKeyProvider.Name, and the Value is the filePath for the TrustAuthorityKeyProvider's ClientCertificate PrivateKey part. + + .PARAMETER BaseImageFolder + Specifies the folder having all the baseImage files to re-create the TrustAuthorityVMHostBaseImage. All the .tgz files under this folder and its sub-folders will be used to re-create TrustAuthorityVMHostBaseImage objects. + + .EXAMPLE + PS C:\> $privateKeyHash = @{"provider1"="c:\myprivatekey.txt";} + PS C:\> $ts = Get-TrustAuthorityCluster "mycluster" + PS C:\> Apply-TrustAuthorityClusterSettings -TrustAuthorityCluster $ts -SettingsFile "c:\myfile.json" -PrivateKey $privateKeyHash -BaseImageFolder "c:\myimages\" + Applies the settings in file c:\myfile.json to Trust Authority Cluster "mycluster" with all the baseimage files under c:\myimages\ recursively, and cmdlet will prompt for inputting the password for each TrustAuthorityKeyProvider, also the PrivateKey info saved in c:\myprivatekey.txt will be used for the TrustAuthorityKeyProvider provider1. + + .NOTES + Author : Carrie Yang + Author email : yangm@vmware.com + #> + + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [VMware.VimAutomation.Security.Types.V1.TrustedInfrastructure.TrustAuthorityCluster] $TrustAuthorityCluster, + + [Parameter(Mandatory=$True)] + [String] $SettingsFile, + + [hashtable] $PrivateKey, + + [String] $BaseImageFolder + ) + + Begin { + Write-Host "Applying the saved settings to TrustAuthorityCluster $($TrustAuthorityCluster.Name)..." + } + + Process { + Set-TrustAuthorityCluster -TrustAuthorityCluster $TrustAuthorityCluster -State Enabled -Confirm:$false + $blueserver = GetViServer -clusterUid $TrustAuthorityCluster.Uid + + $jsonObj = Get-Content $SettingsFile | Out-String |ConvertFrom-Json + if ($($jsonObj.TrustAuthorityCluster.Name) -ne $($TrustAuthorityCluster.Name)) { + Write-Warning "Wrong TrustAuthorityCluster or wrong json file provided, the json file is not for the TrustAuthorityCluster: $($TrustAuthorityCluster.Name)" + } + + $kp = $jsonObj."TrustAuthorityCluster".TrustAuthorityKeyProvider + $principals = $jsonObj."TrustAuthorityCluster".TrustAuthorityPrincipal + $tpm2Setting = $jsonObj."TrustAuthorityCluster".TrustAuthorityTpm2AttestationSettings + $tpm2CA = $jsonObj."TrustAuthorityCluster".TrustAuthorityTpm2CACertificate + $tpm2Ek = $jsonObj."TrustAuthorityCluster".TrustAuthorityTpm2EndorsementKey + $baseImages = $jsonObj."TrustAuthorityCluster".TrustAuthorityVMHostBaseImage + + if ($kp -ne $null) { + foreach ($_ in $kp) { + $kps = $_.KmipServers + $cmd = "New-TrustAuthorityKeyProvider" + $allArgs = @{ + 'TrustAuthorityCluster' = $TrustAuthorityCluster; + 'Name' = $($_.Name); + 'MasterKeyId' = $_.MasterKeyId; + 'KmipServerName' = $kps[0].Name; + 'KmipServerAddress' = $kps[0].Address; + 'KmipServerPort' = $kps[0].Port; + 'Server' = $blueserver; + } + + if (![String]::IsNullOrWhiteSpace($_.Description)) { + $allArgs += @{'Description' = $_.Description;} + } + + if (![String]::IsNullOrWhiteSpace($_.ProxyAddress)) { + $allArgs += @{'ProxyAddress' = $_.ProxyAddress;} + } + + if (![String]::IsNullOrWhiteSpace($_.ProxyPort)) { + $allArgs += @{'ProxyPort' = $_.ProxyPort;} + } + + if (![String]::IsNullOrWhiteSpace($_.ConnectionTimeOutSeconds)) { + $allArgs += @{'ConnectionTimeOutSeconds' = $_.ConnectionTimeOutSeconds;} + } + + if (![String]::IsNullOrWhiteSpace($_.KmipServerUsername)) { + $allArgs += @{'KmipServerUsername' = $_.KmipServerUsername;} + } + + $silent = & $cmd @allArgs + + if (($kps | Measure-Object).Count -gt 1) { + for ($i = 1; $i -gt ($kps | Measure-Object).Count; $i++) { + Add-TrustAuthorityKeyProviderServer -KeyProvider $_.Name -TrustAuthorityCluster $TrustAuthorityCluster -Address $kps[$i].Address -Name $kps[$i].Name -Port $kps[$i].Port -Server $blueserver + } + } + + if (![String]::IsNullOrWhiteSpace($($_.ClientCertificateCSR))) { + Write-Warning "CSR configuration won't be preserved, please manually establish the trust between kmip servers and trust authority keyprovider: $($_.Name)" + } + + if ($_.ClientCertificate -ne $null) { + if ($privateKey -ne $null -and $privateKey.ContainsKey($($_.Name))) { + $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 + $cert.Import([System.Text.Encoding]::Default.GetBytes($_.ClientCertificate)) + try { + $pkStr = [System.IO.File]::ReadAllText($privateKey.$($_.Name)) + } catch { + Throw "Failed to read privateKey file: $($privateKey.$($_.Name))" + } + Set-TrustAuthorityKeyProviderClientCertificate -KeyProvider $_.Name -TrustAuthorityCluster $TrustAuthorityCluster -Certificate $cert -PrivateKey $pkStr -Server $blueserver + } else { + New-TrustAuthorityKeyProviderClientCertificate -KeyProvider $_.Name -TrustAuthorityCluster $TrustAuthorityCluster -Server $blueserver + } + } + + if ($_.ServerCertificate -ne $null) { + $trustedcerts = [System.Collections.ArrayList]@() + foreach ($certStr in $_.ServerCertificate) { + $tempStr = $certStr.CertificateRawData + if ($certStr.Trusted) { + $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 + $cert.Import([System.Text.Encoding]::Default.GetBytes($tempStr)) + $silent = $trustedcerts.Add($cert) + } + } + Set-TrustAuthorityKeyProviderServerCertificate -KeyProvider $_.Name -TrustAuthorityCluster $TrustAuthorityCluster -Certificate $trustedcerts -Server $blueserver + } + + $kmipPwd = Read-Host "Enter the password of Trust Authority Key Provider $($_.Name) (Return if none)" -AsSecureString + + if ($kmipPwd.Length -gt 0) { + Set-TrustAuthorityKeyProvider -KeyProvider $_.Name -TrustAuthorityCluster $TrustAuthorityCluster -KmipServerPassword $kmipPwd -Server $blueserver + } + } + } + + if ($principals -ne $null) { + foreach ($_ in $principals) { + $chainList = [System.Collections.ArrayList]@() + foreach ($str in $_.certRawData) { + $chain = ConvertTo-X509Chain -certString $str + $silent = $chainList.Add($chain) + } + + New-TrustAuthorityPrincipal -TrustAuthorityCluster $TrustAuthorityCluster -Name $_.Name -Domain $_.Domain -Issuer $_.Issuer -CertificateChain $chainList -Type $_.Type -Server $blueserver -Confirm:$false + } + } + + if ($tpm2Setting -ne $null) { + Set-TrustAuthorityTpm2AttestationSettings -RequireCertificateValidation:$tpm2Setting.RequireCertificateValidation -RequireEndorsementKey:$tpm2Setting.RequireEndorsementKey -TrustAuthorityCluster $TrustAuthorityCluster -Confirm:$false + } + + if ($tpm2CA -ne $null) { + foreach ($_ in $tpm2CA) { + $chain = ConvertTo-X509Chain $_.certRawData + New-TrustAuthorityTpm2CACertificate -TrustAuthorityCluster $TrustAuthorityCluster -CertificateChain $chain -Name $_.Name -Server $blueserver -Confirm:$false + } + } + + if ($tpm2Ek -ne $null) { + foreach ($_ in $tpm2Ek) { + New-TrustAuthorityTpm2EndorsementKey -TrustAuthorityCluster $TrustAuthorityCluster -Name $_.Name -PublicKey $_.PublicKey -Server $blueserver -Confirm:$false + } + } + + if ($baseImages -ne $null) { + New-TrustAuthorityVMHostBaseImage -TrustAuthorityCluster $TrustAuthorityCluster -FilePath $baseImageFolder -Server $blueserver -Confirm:$false + } + } +} + + +Function Apply-TrustedClusterSettings { + <# + .SYNOPSIS + This cmdlet applies the settings in the specific $SettingsFile to a Trusted Cluster. + + .DESCRIPTION + This cmdlet applies the settings in the specific $SettingsFile to a Trusted Cluster + + .PARAMETER TrustedCluster + Specifies the Trusted Cluster you want to apply the settings. + + .PARAMETER SettingsFile + Specifies the file having the settings you want to apply. + + .EXAMPLE + PS C:\> $ts = Get-TrustedCluster "mycluster" + PS C:\> Apply-TrustedClusterSettings -TrustedCluster $ts -SettingsFile "c:\myfile.json" + Applies the settings in file c:\myfile.json to Trusted Cluster "mycluster". + + .NOTES + Author : Carrie Yang + Author email : yangm@vmware.com + #> + + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [VMware.VimAutomation.Security.Types.V1.TrustedInfrastructure.TrustedCluster] $TrustedCluster, + + [Parameter(Mandatory=$True)] + [String] $SettingsFile + ) + + Begin { + $greenvc = GetViServer -clusterUid $TrustedCluster.Uid + Write-Host "Applying the saved settings to TrustedCluster $($TrustedCluster.Name)..." + } + + Process { + $jsonObj = Get-Content $SettingsFile | ConvertFrom-Json + + if ($($jsonObj.TrustedCluster.Name) -ne $($TrustedCluster.Name)) { + Write-Warning "Wrong trustedcluster or wrong json file provided, the json file is not for the trustedcluster: $($TrustedCluster.Name)" + } + + if ($jsonObj.TrustedCluster.AttestationServiceInfo -ne $null) { + $attests = Get-AttestationServiceInfo | where {$($_.Name) -in $($jsonObj.TrustedCluster.AttestationServiceInfo)} + Add-TrustedClusterAttestationServiceInfo -TrustedCluster $TrustedCluster -AttestationServiceInfo $attests -Confirm:$false -Server $greenvc + } + + if ($jsonObj.TrustedCluster.KeyProviderServiceInfo -ne $null) { + $kms = Get-KeyProviderServiceInfo | where {$($_.Name) -in $($jsonObj.TrustedCluster.KeyProviderServiceInfo)} + Add-TrustedClusterKeyProviderServiceInfo -TrustedCluster $TrustedCluster -KeyProviderServiceInfo $kms -Confirm:$false -Server $greenvc + } + } +} + + + +Function Join-VMHost { + Param ( + [Parameter(Mandatory=$True)] + [String] $ClusterName, + + [Parameter(Mandatory=$True)] + [String] $VMHostAddress, + + [Parameter(Mandatory=$True)] + [System.Management.Automation.Credential()] + $Credential + ) + + Process { + Write-Host "Adding new host $VMHostAddress to cluster $ClusterName..." + Add-VMHost -Name $VMHostAddress -Credential $Credential -Location $ClusterName -Force + } +} + +Function Remove-TrustedClusterSettings { + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [VMware.VimAutomation.Security.Types.V1.TrustedInfrastructure.TrustedCluster] $TrustedCluster + ) + + Begin { + $greenvc = GetViServer -clusterUid $TrustedCluster.Uid + Write-Host "Removing the settings of TrustedCluster $($TrustedCluster.Name)..." + } + + Process { + if ($TrustedCluster.State -eq 'Enabled') { + Set-TrustedCluster -TrustedCluster $TrustedCluster -State Disabled -Server $greenvc -Confirm:$false + } else { + if ($TrustedCluster.KeyProviderServiceInfo -ne $null) { + Remove-TrustedClusterKeyProviderServiceInfo -TrustedCluster $TrustedCluster -KeyProviderServiceInfo $TrustedCluster.KeyProviderServiceInfo -Server $greenvc + } + } + } +} + + +Function IsSelfSignedClientCertificate { + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [VMware.VimAutomation.Security.Types.V1.TrustedInfrastructure.TrustAuthorityCluster] $TrustAuthorityCluster, + + [hashtable] $privateKey + ) + + Begin { + $bluevc = GetViServer -clusterUid $TrustAuthorityCluster.Uid + } + + Process { + $kp = Get-TrustAuthorityKeyProvider -TrustAuthorityCluster $TrustAuthorityCluster -Server $bluevc + + $privateKeyNotSet = $False + $kpNames = [System.Collections.ArrayList]@() + if ($kp -ne $null) { + foreach ($k in $kp) { + $clientCert = Get-TrustAuthorityKeyProviderClientCertificate -KeyProvider $k -TrustAuthorityCluster $TrustAuthorityCluster -Server $bluevc + if ($clientCert -ne $null -and !($privateKey -ne $null -and $privateKey.ContainsKey($($k.Name)))) { + $privateKeyNotSet = $True + $silent = $kpNames.Add($k.Name) + } + } + } + + if ($privateKeyNotSet) { + $kpnameStr = [System.String]::join(",", $($kpNames)) + Write-Warning "For self-signed client certificate, the cmdlet could not be able to establish the trust between the kmip servers and the keyprovider: ($kpnameStr). + Please manually use these followed cmdlets to establish the trust: New-TrustAuthorityKeyProviderClientCertificate, and Get-TrustAuthorityKeyProviderClientCertificate, then make the certificate be signed in kmip servers." -WarningAction Inquire + } + } +} + +Function Check-VMHostVersionAndLicense { + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True)] + [String] $VMHostName, + + [Parameter(Mandatory=$True)] + [System.Management.Automation.Credential()] + $Credential, + + [Parameter(Mandatory=$True)] + [bool]$CheckLicense + ) + + Begin { + Write-Host "Checking the version of the vmhost $VMHostName..." + } + + Process { + $server = Connect-VIServer -Server $VMHostName -Credential $Credential -ErrorAction:Stop + + $vmhost = Get-VMHost -server $server + + $apiVersion = [System.Version]$($vmhost.ApiVersion) + $MajorVersion = $apiVersion.Major + $MinorVersion = $apiVersion.Minor + $buildNum = $apiVersion.Build + if ($MajorVersion -lt 7 -And $MinorVersion -ne 0 -And $buildNum -ne 0) { + Disconnect-VIServer -Server $server -confirm:$false + Throw "VMHost of $apiVersion is not supported, only 7.0.0 is supported...`n" + } + + # Check license + if ($CheckLicense) { + Write-Host "Checking the license of the vmhost $VMHostName..." + $si = Get-View serviceinstance -Server $server + $lm = Get-View $si.Content.LicenseManager + $a = $lm.Licenses.Properties.Value | Where-Object {"trustedplatform" -in $_.Key} + if ($a -eq $null) { + Disconnect-VIServer -Server $server -confirm:$false + Throw "VMHost $VMHostName has no sufficient license to be configured as trusted infrastructure host...`n" + } + } + + Disconnect-VIServer -Server $server -confirm:$false + } +} + +Function Check-TrustAuthorityClusterHealth { + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [VMware.VimAutomation.Security.Types.V1.TrustedInfrastructure.TrustAuthorityCluster] $TrustAuthorityCluster + ) + + Begin { + $bluevc = GetViServer -clusterUid $TrustAuthorityCluster.Uid + } + + Process { + Write-Host "Checking the healthy status of TrustAuthorityCluster $($TrustAuthorityCluster.Name)..." + $TrustAuthorityCluster = Get-TrustAuthorityCluster -Name $TrustAuthorityCluster.Name -Server $bluevc + # Check the cluster is enabled + if ($TrustAuthorityCluster.State -ne 'Enabled') { + Throw "The given TrustAuthorityCluster $($TrustAuthorityCluster.Name) hasn't been configured yet!" + } + + # Check services healthy + $status = Get-TrustAuthorityServicesStatus -TrustAuthorityCluster $TrustAuthorityCluster -Server $bluevc + + if ($status.AttestationServiceStatus.Health -ne 'Ok') { + Throw "The AttestationServiceStatus is not healthy, please fix it first!" + } + + if ($status.KeyProviderServiceStatus.Health -ne 'Ok') { + Throw "The KeyProviderServiceStatus is not healthy, please fix it first!" + } + + # Check TrustAuthorityPrincipal's healthy + $principals = Get-TrustAuthorityPrincipal -TrustAuthorityCluster $TrustAuthorityCluster -Server $bluevc + + foreach ($p in $principals) { + if ($p.Health -ne 'Ok') { + Throw "The TrustAuthorityPrincipal $($p.Name) is not healthy, please fix it first!" + } + } + + # Check TrustAuthorityKeyProvider's healthy + $kp = Get-TrustAuthorityKeyProvider -TrustAuthorityCluster $TrustAuthorityCluster -Server $bluevc + foreach ($k in $kp) { + if ($k.Status.Health -ne 'Ok') { + Throw "TrustAuthorityKeyProvider $($k.Name) is not healthy, please fix it first!" + } + + foreach ($status in $k.Status.ServerStatus) { + if ($status.Health -ne 'Ok') { + Throw "The ServerStatus $($status.Name) in TrustAuthorityKeyProvider $($k.Name) is not healthy, please fix it first!" + } + } + } + + # Check tpm2 settings + $tpm2Setting = Get-TrustAuthorityTpm2AttestationSettings -TrustAuthorityCluster $TrustAuthorityCluster -Server $bluevc + if ($tpm2Setting.Health -ne 'Ok') { + Throw "TrustAuthorityTpm2AttestationSettings is not healthy, please fix it first!" + } + + # Check tpm2Ek healthy + $tpm2Eks = Get-TrustAuthorityTpm2EndorsementKey -TrustAuthorityCluster $TrustAuthorityCluster -Server $bluevc + if ($tpm2Eks -ne $null) { + foreach ($ek in $tpm2Eks) { + if ($ek.Health -ne 'Ok') { + Throw "TrustAuthorityTpm2EndorsementKey $($ek.Name) is not healthy, please fix it first!" + } + } + } + + # Check tpm2CA healthy + $tpm2cas = Get-TrustAuthorityTpm2CACertificate -TrustAuthorityCluster $TrustAuthorityCluster -Server $bluevc + if ($tpm2cas -ne $null) { + foreach ($ca in $tpm2cas) { + if ($ca.Health -ne 'Ok') { + Throw "TrustAuthorityTpm2CACertificate $($ca.Name) is not healthy, please fix it first!" + } + } + } + + # Check BaseImage healthy + $baseImages = Get-TrustAuthorityVMHostBaseImage -TrustAuthorityCluster $TrustAuthorityCluster -Server $bluevc + if ($baseImages -ne $null) { + foreach ($img in $baseImages) { + if ($img.Health -ne 'Ok') { + Throw "TrustAuthorityVMHostBaseImage $($img.Name) is not healthy, please fix it first!" + } + } + } + } +} + +Function Check-TrustedClusterSettings { + [CmdLetBinding()] + + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [VMware.VimAutomation.Security.Types.V1.TrustedInfrastructure.TrustedCluster] $TrustedCluster + ) + + Begin { + $greenvc = GetViServer -clusterUid $TrustedCluster.Uid + Write-Host "Checking the settings of TrustedCluster $($TrustedCluster.Name)..." + } + + Process { + $TrustedCluster = Get-TrustedCluster $TrustedCluster.Name -Server $greenvc + + if (!$TrustedCluster.AttestationServiceInfo -and !$TrustedCluster.KeyProviderServiceInfo) { + Throw "The cluster $($TrustedCluster.Name) hasn't been configured yet, you can add the host directly." + } + } +} + +Function GetViServer { + Param ( + [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] + [string] $clusterUid + ) + + Process { + $server = $global:DefaultVIServers | Where-Object { [VMware.VimAutomation.Sdk.Types.V1.DistinguishedName]::GetConnectionDn($clusterUid) -eq $_.Id} + + return $server + } +} + +Function ConfirmIsVCenter{ + <# + .SYNOPSIS + This function confirms the connected VI server is vCenter Server. + .DESCRIPTION + This function confirms the connected VI server is vCenter Server. + .EXAMPLE + C:\PS>ConfirmIsVCenter + Throws exception if the connected VIServer is not vCenter Server. + #> + + Param ( + [Parameter(Mandatory=$True)] + [ValidateNotNullOrEmpty()] + [String] $VIServer + ) + + Process { + if ([String]::IsNullOrWhiteSpace($VIServer)) { + Throw "Please provide a valid vCenter Server!" + } + + $SI = Get-View Serviceinstance -Server $VIServer + $VIType = $SI.Content.About.ApiType + + if ($VIType -ne "VirtualCenter") { + Throw "Operation requires vCenter Server!" + } + } +} + +Function ConvertFrom-X509Chain { + Param ( + [Parameter(Mandatory=$True)] + [System.Security.Cryptography.X509Certificates.X509Chain] $CertChain + ) + + Process { + $certStr = $null + foreach ($c in $($CertChain.ChainElements)) { + if ($certStr -eq $null) { + $certStr = [System.Convert]::ToBase64String($($c.Certificate.GetRawCertData())) + } else { + $certStr = $certStr, [System.Convert]::ToBase64String($($c.Certificate.GetRawCertData())) + } + } + + return $certStr + } +} + +Function ConvertTo-X509Chain { + Param ( + [Parameter(Mandatory=$True)] + [System.Array] $certString + ) + + Process { + $chain = new-object System.Security.Cryptography.X509Certificates.X509Chain + if ($certString.Length -gt 0) { + for ($i = 0; $i -lt $certString.Length - 1; $i++ ) { + $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 + $cert.Import([System.Text.Encoding]::Default.GetBytes($certString[$i].replace("\n", [Environment]::NewLine))) + $silent = $chain.ChainPolicy.ExtraStore.Add($cert) + } + } + + $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 + $cert.Import([System.Text.Encoding]::Default.GetBytes($certString[-1].replace("\n", [Environment]::NewLine))) + $silent = $chain.Build($cert) + + return $chain + } +} + + +Export-ModuleMember Add-TrustAuthorityVMHost, Add-TrustedVMHost + +# SIG # Begin signature block +# MIIi9AYJKoZIhvcNAQcCoIIi5TCCIuECAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCwMEx3Ndpn/K5N +# T9PigHlgbfEAXX20xwVouOnKKMD48KCCD8swggTMMIIDtKADAgECAhBdqtQcwalQ +# C13tonk09GI7MA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNVBAYTAlVTMR0wGwYDVQQK +# ExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3Qg +# TmV0d29yazEwMC4GA1UEAxMnU3ltYW50ZWMgQ2xhc3MgMyBTSEEyNTYgQ29kZSBT +# aWduaW5nIENBMB4XDTE4MDgxMzAwMDAwMFoXDTIxMDkxMTIzNTk1OVowZDELMAkG +# A1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0 +# bzEVMBMGA1UECgwMVk13YXJlLCBJbmMuMRUwEwYDVQQDDAxWTXdhcmUsIEluYy4w +# ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCuswYfqnKot0mNu9VhCCCR +# vVcCrxoSdB6G30MlukAVxgQ8qTyJwr7IVBJXEKJYpzv63/iDYiNAY3MOW+Pb4qGI +# bNpafqxc2WLW17vtQO3QZwscIVRapLV1xFpwuxJ4LYdsxHPZaGq9rOPBOKqTP7Jy +# KQxE/1ysjzacA4NXHORf2iars70VpZRksBzkniDmurvwCkjtof+5krxXd9XSDEFZ +# 9oxeUGUOBCvSLwOOuBkWPlvCnzEqMUeSoXJavl1QSJvUOOQeoKUHRycc54S6Lern +# 2ddmdUDPwjD2cQ3PL8cgVqTsjRGDrCgOT7GwShW3EsRsOwc7o5nsiqg/x7ZmFpSJ +# AgMBAAGjggFdMIIBWTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDArBgNVHR8E +# JDAiMCCgHqAchhpodHRwOi8vc3Yuc3ltY2IuY29tL3N2LmNybDBhBgNVHSAEWjBY +# MFYGBmeBDAEEATBMMCMGCCsGAQUFBwIBFhdodHRwczovL2Quc3ltY2IuY29tL2Nw +# czAlBggrBgEFBQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTATBgNVHSUE +# DDAKBggrBgEFBQcDAzBXBggrBgEFBQcBAQRLMEkwHwYIKwYBBQUHMAGGE2h0dHA6 +# Ly9zdi5zeW1jZC5jb20wJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdi5zeW1jYi5jb20v +# c3YuY3J0MB8GA1UdIwQYMBaAFJY7U/B5M5evfYPvLivMyreGHnJmMB0GA1UdDgQW +# BBTVp9RQKpAUKYYLZ70Ta983qBUJ1TANBgkqhkiG9w0BAQsFAAOCAQEAlnsx3io+ +# W/9i0QtDDhosvG+zTubTNCPtyYpv59Nhi81M0GbGOPNO3kVavCpBA11Enf0CZuEq +# f/ctbzYlMRONwQtGZ0GexfD/RhaORSKib/ACt70siKYBHyTL1jmHfIfi2yajKkMx +# UrPM9nHjKeagXTCGthD/kYW6o7YKKcD7kQUyBhofimeSgumQlm12KSmkW0cHwSSX +# TUNWtshVz+74EcnZtGFI6bwYmhvnTp05hWJ8EU2Y1LdBwgTaRTxlSDP9JK+e63vm +# SXElMqnn1DDXABT5RW8lNt6g9P09a2J8p63JGgwMBhmnatw7yrMm5EAo+K6gVliJ +# LUMlTW3O09MbDTCCBVkwggRBoAMCAQICED141/l2SWCyYX308B7KhiowDQYJKoZI +# hvcNAQELBQAwgcoxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5j +# LjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMp +# IDIwMDYgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFF +# MEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZp +# Y2F0aW9uIEF1dGhvcml0eSAtIEc1MB4XDTEzMTIxMDAwMDAwMFoXDTIzMTIwOTIz +# NTk1OVowfzELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0 +# aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTAwLgYDVQQDEydT +# eW1hbnRlYyBDbGFzcyAzIFNIQTI1NiBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqG +# SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCXgx4AFq8ssdIIxNdok1FgHnH24ke021hN +# I2JqtL9aG1H3ow0Yd2i72DarLyFQ2p7z518nTgvCl8gJcJOp2lwNTqQNkaC07BTO +# kXJULs6j20TpUhs/QTzKSuSqwOg5q1PMIdDMz3+b5sLMWGqCFe49Ns8cxZcHJI7x +# e74xLT1u3LWZQp9LYZVfHHDuF33bi+VhiXjHaBuvEXgamK7EVUdT2bMy1qEORkDF +# l5KK0VOnmVuFNVfT6pNiYSAKxzB3JBFNYoO2untogjHuZcrf+dWNsjXcjCtvanJc +# YISc8gyUXsBWUgBIzNP4pX3eL9cT5DiohNVGuBOGwhud6lo43ZvbAgMBAAGjggGD +# MIIBfzAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9zMi5zeW1j +# Yi5jb20wEgYDVR0TAQH/BAgwBgEB/wIBADBsBgNVHSAEZTBjMGEGC2CGSAGG+EUB +# BxcDMFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vY3BzMCgG +# CCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vcnBhMDAGA1UdHwQp +# MCcwJaAjoCGGH2h0dHA6Ly9zMS5zeW1jYi5jb20vcGNhMy1nNS5jcmwwHQYDVR0l +# BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMDMA4GA1UdDwEB/wQEAwIBBjApBgNVHREE +# IjAgpB4wHDEaMBgGA1UEAxMRU3ltYW50ZWNQS0ktMS01NjcwHQYDVR0OBBYEFJY7 +# U/B5M5evfYPvLivMyreGHnJmMB8GA1UdIwQYMBaAFH/TZafC3ey78DAJ80M5+gKv +# MzEzMA0GCSqGSIb3DQEBCwUAA4IBAQAThRoeaak396C9pK9+HWFT/p2MXgymdR54 +# FyPd/ewaA1U5+3GVx2Vap44w0kRaYdtwb9ohBcIuc7pJ8dGT/l3JzV4D4ImeP3Qe +# 1/c4i6nWz7s1LzNYqJJW0chNO4LmeYQW/CiwsUfzHaI+7ofZpn+kVqU/rYQuKd58 +# vKiqoz0EAeq6k6IOUCIpF0yH5DoRX9akJYmbBWsvtMkBTCd7C6wZBSKgYBU/2sn7 +# TUyP+3Jnd/0nlMe6NQ6ISf6N/SivShK9DbOXBd5EDBX6NisD3MFQAfGhEV0U5eK9 +# J0tUviuEXg+mw3QFCu+Xw4kisR93873NQ9TxTKk/tYuEr2Ty0BQhMIIFmjCCA4Kg +# AwIBAgIKYRmT5AAAAAAAHDANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJVUzET +# MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV +# TWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3NvZnQgQ29kZSBW +# ZXJpZmljYXRpb24gUm9vdDAeFw0xMTAyMjIxOTI1MTdaFw0yMTAyMjIxOTM1MTda +# MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV +# BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZl +# cmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMT +# PFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBB +# dXRob3JpdHkgLSBHNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK8k +# CAgpejWeYAyq50s7Ttx8vDxFHLsr4P4pAvlXCKNkhRUn9fGtyDGJXSLoKqqmQrOP +# +LlVt7G3S7P+j34HV+zvQ9tmYhVhz2ANpNje+ODDYgg9VBPrScpZVIUm5SuPG5/r +# 9aGRwjNJ2ENjalJL0o/ocFFN0Ylpe8dw9rPcEnTbe11LVtOWvxV3obD0oiXyrxyS +# Zxjl9AYE75C55ADk3Tq1Gf8CuvQ87uCL6zeL7PTXrPL28D2v3XWRMxkdHEDLdCQZ +# IZPZFP6sKlLHj9UESeSNY0eIPGmDy/5HvSt+T8WVrg6d1NFDwGdz4xQIfuU/n3O4 +# MwrPXT80h5aK7lPoJRUCAwEAAaOByzCByDARBgNVHSAECjAIMAYGBFUdIAAwDwYD +# VR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAYYwHQYDVR0OBBYEFH/TZafC3ey78DAJ +# 80M5+gKvMzEzMB8GA1UdIwQYMBaAFGL7CiFbf0NuEdoJVFBr9dKWcfGeMFUGA1Ud +# HwROMEwwSqBIoEaGRGh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3By +# b2R1Y3RzL01pY3Jvc29mdENvZGVWZXJpZlJvb3QuY3JsMA0GCSqGSIb3DQEBBQUA +# A4ICAQCBKoIWjDRnK+UD6zR7jKKjUIr0VYbxHoyOrn3uAxnOcpUYSK1iEf0g/T9H +# BgFa4uBvjBUsTjxqUGwLNqPPeg2cQrxc+BnVYONp5uIjQWeMaIN2K4+Toyq1f75Z +# +6nJsiaPyqLzghuYPpGVJ5eGYe5bXQdrzYao4mWAqOIV4rK+IwVqugzzR5NNrKSM +# B3k5wGESOgUNiaPsn1eJhPvsynxHZhSR2LYPGV3muEqsvEfIcUOW5jIgpdx3hv08 +# 44tx23ubA/y3HTJk6xZSoEOj+i6tWZJOfMfyM0JIOFE6fDjHGyQiKEAeGkYfF9sY +# 9/AnNWy4Y9nNuWRdK6Ve78YptPLH+CHMBLpX/QG2q8Zn+efTmX/09SL6cvX9/zoc +# Qjqh+YAYpe6NHNRmnkUB/qru//sXjzD38c0pxZ3stdVJAD2FuMu7kzonaknAMK5m +# yfcjKDJ2+aSDVshIzlqWqqDMDMR/tI6Xr23jVCfDn4bA1uRzCJcF29BUYl4DSMLV +# n3+nZozQnbBP1NOYX0t6yX+yKVLQEoDHD1S2HmfNxqBsEQOE00h15yr+sDtuCjqm +# a3aZBaPxd2hhMxRHBvxTf1K9khRcSiRqZ4yvjZCq0PZ5IRuTJnzDzh69iDiSrkXG +# GWpJULMF+K5ZN4pqJQOUsVmBUOi6g4C3IzX0drlnHVkYrSCNlDGCEn8wghJ7AgEB +# MIGTMH8xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlv +# bjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEwMC4GA1UEAxMnU3lt +# YW50ZWMgQ2xhc3MgMyBTSEEyNTYgQ29kZSBTaWduaW5nIENBAhBdqtQcwalQC13t +# onk09GI7MA0GCWCGSAFlAwQCAQUAoIGWMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3 +# AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCoGCisGAQQBgjcCAQwx +# HDAaoRiAFmh0dHA6Ly93d3cudm13YXJlLmNvbS8wLwYJKoZIhvcNAQkEMSIEIL6r +# SvvCSJpAoQz4YvtfQH11/WevM1ULBbGfNUE3j37RMA0GCSqGSIb3DQEBAQUABIIB +# AKUHXKwZcvP2g8/l7dqWyaG7h4q/yJDxaWpk9r1mnUSw1MBR+0AOCm1mquTlpFVH +# ZD1KMQWtu1rJDz5A7XAm8/n6LpyqCCHcgMm+hiEjA8r02oTA8vMFch3OR6Z1/aad +# tOBkeln18M9kVkQ//uociG89A2LkfE35UKAhnDVcOBNlU0g43n9vSgakNdOOc0ZI +# VC2FD/tn9QPJXtcZ0LAFrCPuiIya+gvQ1aQCALUYi+aLuARNN01KBMRFG9za/JwX +# L6rwInitQt/BRNDINiuuTI96xBEMq3JjzW9AE8jF1rVqr1ISBgf8ZZUHdnNHiE91 +# HxLh4zvDq7SEh2ne6UhOJg6hghAjMIIQHwYKKwYBBAGCNwMDATGCEA8wghALBgkq +# hkiG9w0BBwKggg/8MIIP+AIBAzEPMA0GCWCGSAFlAwQCAQUAMIHmBgsqhkiG9w0B +# CRABBKCB1gSB0zCB0AIBAQYJKwYBBAGgMgIDMDEwDQYJYIZIAWUDBAIBBQAEIII1 +# T46qC5Scv1JNpvu1aNNVzRq4lB1M9EZlbgeSsNYJAg4BbKiJKXgAAAAAAKUUzBgT +# MjAyMDA0MDIxMDI5MTguNjc5WjADAgEBoGOkYTBfMQswCQYDVQQGEwJKUDEcMBoG +# A1UEChMTR01PIEdsb2JhbFNpZ24gSy5LLjEyMDAGA1UEAxMpR2xvYmFsU2lnbiBU +# U0EgZm9yIEFkdmFuY2VkIC0gRzMgLSAwMDMtMDGgggxqMIIE6jCCA9KgAwIBAgIM +# M5Agd2HEJt2UUAMNMA0GCSqGSIb3DQEBCwUAMFsxCzAJBgNVBAYTAkJFMRkwFwYD +# VQQKExBHbG9iYWxTaWduIG52LXNhMTEwLwYDVQQDEyhHbG9iYWxTaWduIFRpbWVz +# dGFtcGluZyBDQSAtIFNIQTI1NiAtIEcyMB4XDTE4MDYxNDEwMDAwMFoXDTI5MDMx +# ODEwMDAwMFowXzELMAkGA1UEBhMCSlAxHDAaBgNVBAoTE0dNTyBHbG9iYWxTaWdu +# IEsuSy4xMjAwBgNVBAMTKUdsb2JhbFNpZ24gVFNBIGZvciBBZHZhbmNlZCAtIEcz +# IC0gMDAzLTAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv3Gj+IDO +# E5Be8KfdP9KY8kE6Sdp/WC+ePDoBE8ptNJlbDCccROdW4wkv9W+rTr4nYmbGuLKH +# x2W+xsBeqT6u+yR0iyv4aARkhqo64qohj/rxnbkYMF6afAf1O3Uu2gklGav+c+lx +# neyq9j4ShYEUJPjmPpnfrvO5i9UmywSommFW7yhwqEtqKyVq5aA2ny25mofcdA4f +# QqBBOpYHDst7MtUBC1ORfVY0T7S8sHRHnKp6bF/kjlGfk5BhAz6PX0FBUHg5LRIS +# 3OvqADCyP+FtE7d1SBVrTg7Rl+NO25bZ0WKvCEHPIg/o3c7Y6pNWbtM6j2dKaki6 +# /GHlbFmzEi0CgQIDAQABo4IBqDCCAaQwDgYDVR0PAQH/BAQDAgeAMEwGA1UdIARF +# MEMwQQYJKwYBBAGgMgEeMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2Jh +# bHNpZ24uY29tL3JlcG9zaXRvcnkvMAkGA1UdEwQCMAAwFgYDVR0lAQH/BAwwCgYI +# KwYBBQUHAwgwRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL2NybC5nbG9iYWxzaWdu +# LmNvbS9ncy9nc3RpbWVzdGFtcGluZ3NoYTJnMi5jcmwwgZgGCCsGAQUFBwEBBIGL +# MIGIMEgGCCsGAQUFBzAChjxodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2Nh +# Y2VydC9nc3RpbWVzdGFtcGluZ3NoYTJnMi5jcnQwPAYIKwYBBQUHMAGGMGh0dHA6 +# Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9nc3RpbWVzdGFtcGluZ3NoYTJnMjAdBgNV +# HQ4EFgQUeaezg3HWs0B2IOZ0Crf39+bd3XQwHwYDVR0jBBgwFoAUkiGnSpVdZLCb +# tB7mADdH5p1BK0wwDQYJKoZIhvcNAQELBQADggEBAIc0fm43ZxsIEQJttimYchTL +# SH7IyY8viQ2vD/IsIZBuO7ccAaqBaMQQI0v4CeOrX+pFps4O/qSA6WtqDAD5yoYQ +# DD7/HxrpHOUil2TZrOnj6NpTYGMLt45P3NUh9J3eE2o4NeVs4yZM29Z0Z0W5TwTE +# WAgam2ZFPSQaGpJXyV8oR3hn21zKrQvotw/RthYyNCIENnJM73umvLauBMDZeKCI +# yIZrGNqWjStuIlzLf70XvZ63toZNgxBNsDKy4BOgy2DihHUU6SG9EKKktgjPOw0p +# WVmp08NMDX9CzIgUtELlugTVmEqkjQc9SR94bWVtYL38zlnrLOnFqtqt7taTrBUw +# ggQVMIIC/aADAgECAgsEAAAAAAExicZQBDANBgkqhkiG9w0BAQsFADBMMSAwHgYD +# VQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2ln +# bjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0xMTA4MDIxMDAwMDBaFw0yOTAzMjkx +# MDAwMDBaMFsxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNh +# MTEwLwYDVQQDEyhHbG9iYWxTaWduIFRpbWVzdGFtcGluZyBDQSAtIFNIQTI1NiAt +# IEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqpuOw6sRUSUBtpaU +# 4k/YwQj2RiPZRcWVl1urGr/SbFfJMwYfoA/GPH5TSHq/nYeer+7DjEfhQuzj46FK +# bAwXxKbBuc1b8R5EiY7+C94hWBPuTcjFZwscsrPxNHaRossHbTfFoEcmAhWkkJGp +# eZ7X61edK3wi2BTX8QceeCI2a3d5r6/5f45O4bUIMf3q7UtxYowj8QM5j0R5tnYD +# V56tLwhG3NKMvPSOdM7IaGlRdhGLD10kWxlUPSbMQI2CJxtZIH1Z9pOAjvgqOP1r +# oEBlH1d2zFuOBE8sqNuEUBNPxtyLufjdaUyI65x7MCb8eli7WbwUcpKBV7d2ydiA +# CoBuCQIDAQABo4HoMIHlMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/ +# AgEAMB0GA1UdDgQWBBSSIadKlV1ksJu0HuYAN0fmnUErTDBHBgNVHSAEQDA+MDwG +# BFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5jb20v +# cmVwb3NpdG9yeS8wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9iYWxz +# aWduLm5ldC9yb290LXIzLmNybDAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpjmove +# 4t0bvDANBgkqhkiG9w0BAQsFAAOCAQEABFaCSnzQzsm/NmbRvjWek2yX6AbOMRhZ +# +WxBX4AuwEIluBjH/NSxN8RooM8oagN0S2OXhXdhO9cv4/W9M6KSfREfnops7yyw +# 9GKNNnPRFjbxvF7stICYePzSdnno4SGU4B/EouGqZ9uznHPlQCLPOc7b5neVp7uy +# y/YZhp2fyNSYBbJxb051rvE9ZGo7Xk5GpipdCJLxo/MddL9iDSOMXCo4ldLA1c3P +# iNofKLW6gWlkKrWmotVzr9xG2wSukdduxZi61EfEVnSAR3hYjL7vK/3sbL/RlPe/ +# UOB74JD9IBh4GCJdCC6MHKCX8x2ZfaOdkdMGRE4EbnocIOM28LZQuTCCA18wggJH +# oAMCAQICCwQAAAAAASFYUwiiMA0GCSqGSIb3DQEBCwUAMEwxIDAeBgNVBAsTF0ds +# b2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYD +# VQQDEwpHbG9iYWxTaWduMB4XDTA5MDMxODEwMDAwMFoXDTI5MDMxODEwMDAwMFow +# TDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkds +# b2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wggEiMA0GCSqGSIb3DQEBAQUA +# A4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2hMoonv0FdhHFrYhy/EYCQ8eyip0E +# XyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9DCuul9e2FIYQebs7E4B3jAjhSdJq +# Yi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkmDoMVxu9bi9IEYMpJpij2aTv2y8go +# keWdimFXN6x0FNx04Druci8unPvQu7/1PQDhBjPogiuuU6Y6FnOM3UEOIDrAtKeh +# 6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTvriBJ/K1AFUjRAjFhGV64l++td7dk +# mnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZphYIXAgMBAAGjQjBAMA4GA1UdDwEB +# /wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSP8Et/qC5FJK5NUPpj +# move4t0bvDANBgkqhkiG9w0BAQsFAAOCAQEAS0DbwFCq/sgM7/eWVEVJu5YACUGs +# sxOGhigHM8pr5nS5ugAtrqQK0/Xx8Q+Kv3NnSoPHRHt44K9ubG8DKY4zOUXDjuS5 +# V2yq/BKW7FPGLeQkbLmUY/vcU2hnVj6DuM81IcPJaP7O2sJTqsyQiunwXUaMld16 +# WCgaLx3ezQA3QY/tRG3XUyiXfvNnBB4V14qWtNPeTCekTBtzc3b0F5nCH3oO4y0I +# rQocLP88q1UOD5F+NuvDV0m+4S4tfGCLw0FREyOdzvcya5QBqJnnLDMfOjsl0oZA +# zjsshnjJYS8Uuu7bVW/fhO4FCU29KNhyztNiUGUe65KXgzHZs7XKR1g/XzGCAokw +# ggKFAgEBMGswWzELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt +# c2ExMTAvBgNVBAMTKEdsb2JhbFNpZ24gVGltZXN0YW1waW5nIENBIC0gU0hBMjU2 +# IC0gRzICDDOQIHdhxCbdlFADDTANBglghkgBZQMEAgEFAKCB8DAaBgkqhkiG9w0B +# CQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIA4jXM836yg3wGdHIpch +# UiliyMiFAI2ifPJZqDcXgJ1ZMIGgBgsqhkiG9w0BCRACDDGBkDCBjTCBijCBhwQU +# rmsC2QsljAmRsRYSid62aVY5HW8wbzBfpF0wWzELMAkGA1UEBhMCQkUxGTAXBgNV +# BAoTEEdsb2JhbFNpZ24gbnYtc2ExMTAvBgNVBAMTKEdsb2JhbFNpZ24gVGltZXN0 +# YW1waW5nIENBIC0gU0hBMjU2IC0gRzICDDOQIHdhxCbdlFADDTANBgkqhkiG9w0B +# AQEFAASCAQB89B/P9T38HdPsMvwHePaxCuxvcVOb0tWYORy4h/6961Hr8+uJi3g8 +# oPQl5tMvsUObcO+hMG8YyXfRpQRr5YrHeWpUGdQzMMHb+gC540P+r3jm6iWoKtpR +# 1WGSnQQUqKaB7a4wZtQoizzSm9a7hB4JEcDtb2Qh2jmSr4yhMx7XmFMLo7NVlEnW +# lS6kTYR9kE4qTagRIOZW5iIUjcAaVn/uhNAOZUjatErU8c/a8vJ7TxtPj4YSaK0J +# IeC+HeUYNRrjwtSgmnU+j/xg1Jo9zUoCGJHBIEJ9iwzgCeRLJuqHKUZiAGBZm09F +# EzycbyZmxfS5ui4MX5wSMdO1ETnvkbRc +# SIG # End signature block