netnerds.net

18Jun/130

Update Your NetApp Virtual Storage Console SSL Certs with your own Windows Domain CA Certificates using PowerShell

Ahhh, it seems like replacing SSL certificates in vSphere is a never-ending process. My vSphere farm was not prompting me about untrusted SSL certs until I installed the NetApp Virtual Storage Console. Using the template from my previous posts, however, I was able to quickly update VSC's certs using a combination of the practical admin's post and NetApp's KB (login required).

The pratical admin post kept VSC's keystore password encrypted, but with vSphere keystore passwords being so easily available on the Internet and NetApp's KB suggesting to place the password on the filesystem in plain-text, I did it the easy way and kept the password (netapp) in clear text in the config file. I've tested this script on both VSC 4.1 and 4.2 and it worked quite well.

You can copy and paste the code below, or download the script directly here.

Note: this script uses the Windows CA default WebServer Certificate Template. It also makes backups of your original certificates.

#########################################################################################
#
#   NetApp Virtual Storage Console SSL Generation and Replacement script version 0.5
#   Tested on VSC 4.1 and 4.2
#   No guarantees, warranties, etc.
#   Blog post: http://goo.gl/Cdlhb
#
#########################################################################################

# Place the certs on a network location if your farm is larger than one server
$basedir = "\\fileserver\share\Certs"

# Enter your Windows Certificate Authority information
# below. Make sure it responds to certutil requests.
$rootCA = "dc.base.local"
$rootCAName = "BASE-DC-CA"
$email = "vmware@base.local"
$org = "NetNerds"
$city = "Kaplan"
$state = "LA"
$country = "US"

# Enter the path of your VSC Installation
$vscdir = "C:\Program Files\NetApp\Virtual Storage Console"

# Enter the path of your openssl.exe (0.x and 1.x are supported).
# If you don't have OpenSSL already, the script will download it for you.
$openssldir = "C:\OpenSSL-Win32"
$openssl = $openssldir+"\bin\openssl.exe"

##############################################################################################
#
#	You probably don't need to change anything below.
#
##############################################################################################

$thisfqdn = ("$env:computername.$env:userdnsdomain").ToLower()
$backuptime = (Get-Date -uformat "%m%d%Y%H%M%S")
$wc = New-Object System.Net.WebClient

if (!(Test-Path "$basedir")) { $null = New-Item -Type Directory "$basedir" }

Write-Host -Foreground "DarkBlue" -Background "White" "Downloading root CA Cert.."
$url = "http://$rootCA/certsrv/certnew.cer?ReqID=CACert&Renewal=0&Enc=b64"
$root64 = "$basedir\Root64.cer"
$wc.UseDefaultCredentials = $true; $wc.DownloadFile($url,$root64)

if (!(Test-Path($openssl))) {
	Write-Host -Foreground "DarkBlue" -Background "White" "Downloading OpenSSL.."
	$null = New-Item -Type Directory $openssldir
	$sslurl = "https://openssl-for-windows.googlecode.com/files/openssl-0.9.8k_WIN32.zip"
	$sslzip = "$env:temp\openssl.zip"
	$wc.DownloadFile($sslurl,$sslzip)
	$env:path = $env:path + ";$openssldir"

	Write-Host -Foreground "DarkBlue" -Background "White" "Extracting OpenSSL.."
	$shellApplication = new-object -com shell.application
	$zipPackage = $shellApplication.NameSpace($sslzip)
	$destinationFolder = $shellApplication.NameSpace($openssldir)
	$destinationFolder.CopyHere($zipPackage.Items())
	Remove-Item $sslzip
} 

######################################################################
#
#	Generate Certs
#
######################################################################

Write-Host -Foreground "DarkBlue" -Background "White" "Generating service certs.."
	$service = "$thisfqdn-netapp"
	$server = $thisfqdn.Substring(0,$thisfqdn.IndexOf("."))

	$servicedir = "$basedir\$service"
	$servicecfg = "$servicedir\$service.cfg"
	$tempkey = "$servicedir\temp.key"
	$netappkey = "$servicedir\netapp.key"
	$netappcsr = "$servicedir\netapp.csr"
	$netappcrt = "$servicedir\netapp.crt"
	$netapppfx = "$servicedir\netapp.pfx"
	$chainpem = "$servicedir\chain.pem"
	$backupdir = "$servicedir\backup-$backuptime"
	$keyalias = "netapp" 

	if (Test-Path($servicedir)) { $null = Remove-Item "$servicedir\*.*" } else {$null = mkdir $servicedir } 

	Set-Content $servicecfg "[ req ]"
	Add-Content $servicecfg " default_md = sha512"
	Add-Content $servicecfg " default_bits = 2048"
	Add-Content $servicecfg " default_keyfile = netapp.key"
	Add-Content $servicecfg " distinguished_name = req_distinguished_name"
	Add-Content $servicecfg " encrypt_key = no"
	Add-Content $servicecfg " prompt = no"
	Add-Content $servicecfg " string_mask = nombstr"
	Add-Content $servicecfg " req_extensions = v3_req"
	Add-Content $servicecfg "`n[ v3_req ]"
	Add-Content $servicecfg " basicConstraints = CA:FALSE"
	Add-Content $servicecfg " keyUsage = digitalSignature, keyEncipherment, dataEncipherment"
	Add-Content $servicecfg " extendedKeyUsage = serverAuth"
	Add-Content $servicecfg " subjectAltName = DNS:$server, DNS:$thisfqdn"
	Add-Content $servicecfg "`n[ req_distinguished_name ]"
	Add-Content $servicecfg " countryName = $country"
	Add-Content $servicecfg " stateOrProvinceName = $state"
	Add-Content $servicecfg " localityName = $city"
	Add-Content $servicecfg " 0.organizationName = $org"
	Add-Content $servicecfg " organizationalUnitName = $service"
	Add-Content $servicecfg " commonName = $thisfqdn"

	&$openssl req -new -nodes -out $netappcsr -keyout $tempkey -config $servicecfg
	&$openssl rsa -in $tempkey -out $netappkey
	Remove-Item $tempkey
	certreq -submit -config "$rootCA\$rootCAName" -attrib "CertificateTemplate:WebServer" $netappcsr $netappcrt
	&$openssl pkcs12 -export -in $netappcrt -inkey $netappkey -certfile $root64 -name $keyalias -passout pass:netapp -out $netapppfx
	Get-Content $netappcrt > $chainpem; Get-Content $root64 >> $chainpem

###############################################################################
#
# NetApp Virtual Storage Console
#
###############################################################################

	Write-Host -Foreground "DarkBlue" -Background "White" "Updating NetApp Virtual Storage Console.."

	Stop-Service NVPF

	Write-Host -Foreground "DarkBlue" -Background "White" "Backing up current keystore.."
	$null = (New-Item -Type Directory $backupdir)
	Move-Item "$vscdir\etc\keystore.properties" $backupdir
	Move-Item "$vscdir\etc\nvpf.keystore" $backupdir

	Set-Content "$vscdir\etc\keystore.properties" "http.ssl.keystore.file=etc/nvpf.keystore"
	Add-Content "$vscdir\etc\keystore.properties" "http.ssl.keystore.password=netapp"
	Add-Content "$vscdir\etc\keystore.properties" "http.ssl.key.password=netapp"

	Write-Host -Foreground "DarkBlue" -Background "White" "Creating new NetApp Virtual Storage Console keystore.."
	$null = (&"$vscdir\jre\bin\keytool.exe" -v -importkeystore -srckeystore "$servicedir\netapp.pfx" -srcstoretype pkcs12 -srcstorepass netapp -srcalias "netapp" -destkeystore "$vscdir\etc\nvpf.keystore" -deststoretype JKS -deststorepass netapp -destkeypass netapp -destalias "netapp")
	$null = (&"$vscdir\jre\bin\keytool.exe" -alias "netapp" -noprompt -v -importcert -keystore "$vscdir\etc\nvpf.keystore" -deststoretype JKS -storepass netapp -file $netappcrt)

	Start-Service NVPF

Write-Host -Foreground "DarkBlue" -Background "White" "Done!"

Done!

Posted by: Chrissy LeMaire   Filed under: PowerShell, Security, Virtualization No Comments
11Jun/130

Update vSphere 4.1U3 and 5.0 SSL Certs with your own Windows Domain CA Certificates using PowerShell

While it took quite awhile to figure out how to replace vSphere 5.1 and 5.1U1's SSL certs, converting that script to work with 4.1U3 and 5.0. It probably helps that SSO doesn't exist (or I couldn't find it -- I haven't used vCenter on a regular basis since about 2006, but I've learned quite a bit from these SSL replacement scripts in my lab environment.)

I was surprised to find that that vSphere 4.1 and 5.0 are far more architecturally similar than 5.0 and 5.1. The 5.0 script required just one extra line of code to adjust for a different registry entry, then it worked very well on 4.1U3.

So without further ado, you can download ReplaceSSL-vSphere41-50.ps1, modify the variables as necessary and run it on each of your farm servers. This script requires you to modify just 10 variables as seen in the snippet below:

# Place the certs on a network location if your farm is larger than one server
$basedir = "\\fileserver\share\Certs"

# Enter your Windows Certificate Authority information below.
# Make sure it responds to certutil and web requests.
$rootCA = "dc.base.local"
$rootCAName = "BASE-DC-CA"
$email = "vmware@base.local"
$org = "NetNerds"
$city = "Kaplan"
$state = "LA"
$country = "US"

# Make sure you follow Derek Seaman's instructions
# to create a new certificate template @ http://goo.gl/m98FE
$certTemplate = "CertificateTemplate:VMware-SSL"

# Enter the path of your openssl.exe (0.x and 1.x are supported).
# If you don't have OpenSSL already, the script will download it for you.
$openssldir = "C:\OpenSSL-Win32"
$openssl = $openssldir+"\bin\openssl.exe"



If you are interested in the approximate steps taken, you can browse the vSphere 5.1 SSL replacement post. Just be aware that the SSO section does not apply.

Posted by: Chrissy LeMaire   Filed under: PowerShell, Security, Virtualization No Comments
11Jun/130

Update Your ESX’s SSL Certs with your own Windows Domain CA Certificates using PowerCLI

Replacing ESX SSL is the easiest of all the vSphere components, in my opinion. Unlike vSphere 5.1, you can use Microsoft's Web Server SSL template, and there's no need to use the Java keytool or reregister the service with SSO.

Below is a script I use in conjunction with my vSphere/PowerShell Replace SSL script.

This is the first time I've actually used PowerCLI so I'm unsure if this script follows Best Practices, but hey, it worked for me in my lab environment ;)

"What it does.."

  • Creates the certificate directory if it does not exist
  • Logs into specified vSphere Server
  • Automatically downloads Root64.cer from the CA's web service
  • Downloads and extracts OpenSSL if the files do not exist in the specified path
  • Generates all SSL certificates for each of the services on the server.

If $upsateesx is set to true..

  • Downloads Putty SCP
  • Checks to see if SSH is running on the esx host. If not, it temporarily enables it
  • Prompts for and validates credentials
  • Backs up all SSL Certs on the server
  • Uploads the new certs
  • Returns SSH to previous state

Once the new certs have been uploaded, you will have to restart the ESX host, or set it into maintenance mode and restart the Management services.

##############################################################################################
#
#   ESX Certificate Generation and Upload version 0.5
#   Tested on:  ESX 5.1 / vCenter 5.1U1 / PowerCLI 5.1 Release 2
#               ESX 4.1 / vCenter 4.1U3
#   No guarantees, warranties, etc.
#   Blog post: http://goo.gl/OdIlF
#
##############################################################################################

# vCenter Server FQDN
$vcserver = "vcenter41.base.local"

# It is recommended that you place the certs on a network location
$basedir = "\\fileserver\share\Certs"

# Enter your Windows Certificate Authority information
# below. Make sure your $rootCA responds to certutil and web requests.
$rootCA = "dc.base.local"
$rootCAName = "BASE-DC-CA"
$email = "vmware@base.local"
$org = "NetNerds"
$city = "Kaplan"
$state = "LA"
$country = "US"

# This can be WebServer or the VMware-SSL certificate
# template found here: http://goo.gl/m98FE
$certTemplate = "CertificateTemplate:WebServer"

# Enter the path of your openssl.exe (0.x and 1.x are supported).
# If you don't have OpenSSL already, the script will download it for you.
$openssldir = "C:\OpenSSL-Win32"
$openssl = $openssldir+"\bin\openssl.exe"

# Do you want the script to automatically backup the old ESX certs
# and upload the new certs to each esx host?
$updateesx = $true

##############################################################################################
#
#	You shouldn't need to change anything below.
#
##############################################################################################
if (!(Test-Path("$basedir"))) { $null = mkdir "$basedir" }

$backuptime = (get-date -uformat "%m%d%Y%H%M%S")
$esxhosts = @{}

Write-Host -Foreground "Black" -Background "White" "Logging into $vcserver."
if ($global:DefaultVIServers.Count -eq 0 -or ($global:DefaultVIServers).Name -ne $vcserver) {Connect-ViServer $vcserver}

Write-Host -Foreground "Black" -Background "White" "Getting list of esx servers."
$esxServers = (Get-VMHost).Name
foreach ($esxServer in $esxServers) {
	$esxdir = "$basedir\$esxServer-esx"
	$esxhosts.Add("$esxServer-esx", $esxServer)
}

Write-Host -Foreground "Black" -Background "White" "Downloading root CA Cert.."
$wc = New-Object System.Net.WebClient
$url = "http://$rootCA/certsrv/certnew.cer?ReqID=CACert&Renewal=0&Enc=b64"
$root64 = "$basedir\Root64.cer"
$wc.UseDefaultCredentials = $true
$wc.DownloadFile($url,$root64)

if (!(Test-Path($openssl))) {
	Write-Host -Foreground "Black" -Background "White" "Downloading OpenSSL.."
	$null = mkdir $openssldir
	$sslurl = "https://openssl-for-windows.googlecode.com/files/openssl-0.9.8k_WIN32.zip"
	$sslzip = "$env:temp\openssl.zip"
	$wc.DownloadFile($sslurl,$sslzip)
	$env:path = $env:path + ";$openssldir"

	Write-Host -Foreground "Black" -Background "White" "Extracting OpenSSL.."
	$shellApplication = new-object -com shell.application
	$zipPackage = $shellApplication.NameSpace($sslzip)
	$destinationFolder = $shellApplication.NameSpace($openssldir)
	$destinationFolder.CopyHere($zipPackage.Items())
	Remove-Item $sslzip
} 

$wc = New-Object System.Net.WebClient
if ($updateesx -eq $true) {
	Write-Host -Foreground "Black" -Background "White" "Downloading Putty SCP.."
	$scpurl = "http://tartarus.org/simon/20090227-kbdint-batch/x86/pscp.exe" # patched version for keyhost prompt issue
	$scp = "$env:temp\pscp.exe"
	$wc.DownloadFile($scpurl,$scp)
}

######################################################################
#
#	Generate Certs
#
######################################################################
Write-Host -Foreground "Black" -Background "White" "Generating service certs.."
foreach ($esxhost in $esxhosts.GetEnumerator()) {
	$service = $esxhost.Name
	$esxserverfqdn = $esxhost.Value
	$esxserver = $esxserverfqdn.Substring(0,$esxserverfqdn.IndexOf("."))

	$servicedir = "$basedir\$service"
	$servicecfg = "$servicedir\$service.cfg"
	$tempkey = "$servicedir\temp.key"
	$ruikey = "$servicedir\rui.key"
	$ruicsr = "$servicedir\rui.csr"
	$ruicrt = "$servicedir\rui.crt"
	$ruipfx = "$servicedir\rui.pfx"
	$chainpem = "$servicedir\chain.pem"
	$backupdir = "$servicedir\backup-$backuptime"
	$keyalias = "rui" 

	if (Test-Path($servicedir)) { $null = Remove-Item "$servicedir\*.*" } else {$null = mkdir $servicedir }

	Set-Content $servicecfg "[ req ]"
	Add-Content $servicecfg " default_md = sha512"
	Add-Content $servicecfg " default_bits = 2048"
	Add-Content $servicecfg " default_keyfile = rui.key"
	Add-Content $servicecfg " distinguished_name = req_distinguished_name"
	Add-Content $servicecfg " encrypt_key = no"
	Add-Content $servicecfg " prompt = no"
	Add-Content $servicecfg " string_mask = nombstr"
	Add-Content $servicecfg " req_extensions = v3_req"
	Add-Content $servicecfg "`n[ v3_req ]"
	Add-Content $servicecfg " basicConstraints = CA:FALSE"
	Add-Content $servicecfg " keyUsage = digitalSignature, keyEncipherment, dataEncipherment"
	Add-Content $servicecfg " extendedKeyUsage = serverAuth"
	Add-Content $servicecfg " subjectAltName = DNS:$esxserver, DNS:$esxserverfqdn"
	Add-Content $servicecfg "`n[ req_distinguished_name ]"
	Add-Content $servicecfg " countryName = $country"
	Add-Content $servicecfg " stateOrProvinceName = $state"
	Add-Content $servicecfg " localityName = $city"
	Add-Content $servicecfg " 0.organizationName = $org"
	Add-Content $servicecfg " organizationalUnitName = $service"
	Add-Content $servicecfg " commonName = $esxserverfqdn"

	&$openssl req -new -nodes -out $ruicsr -keyout $tempkey -config $servicecfg
	&$openssl rsa -in $tempkey -out $ruikey
	Remove-Item $tempkey
	certreq -submit -config "$rootCA\$rootCAName" -attrib $certTemplate $ruicsr $ruicrt
	&$openssl pkcs12 -export -in $ruicrt -inkey $ruikey -certfile $root64 -name $keyalias -passout pass:testpassword -out $ruipfx
	Get-Content $ruicrt > $chainpem; Get-Content $root64 >> $chainpem

	### Start ESX cert upload if updateesx is true and certificate generation is successful
	if ($updateesx -eq $true -and (Test-Path($ruikey)) -and (Test-Path($ruicrt))) {
		$disablessh = $null; $failedauth = 0
		$sshservice = (Get-VMHostService -VMHost $esxserverfqdn -Server $vcserver | Where { $_.Key -eq "TSM-SSH"})

		if ($sshservice.Running -eq $false) {
			Write-Host -Foreground "Black" -Background "White" "Temporarily enabling SSH on $esxserverfqdn" ; $disablessh = $true
			$null = Start-VMHostService -HostService $sshservice -Confirm:$false
		}

		Write-Host -Foreground "Black" -Background "White" "Validating authentication."
		Write-Host -Foreground "Black" -Background "White" "You can ignore any SSH keyhost prompts you may see.."
		do {
				$msg = "Enter the username and password for $esxserverfqdn";
				$creds = $Host.UI.PromptForCredential($caption,$msg,"root",$domain)
				$esxusername = $creds.username;	$esxpassword = $creds.GetNetworkCredential().password
				$esxsslpath = "$esxusername@$esxserverfqdn"+":/etc/vmware/ssl/"
				$authenticated = $null
				$checkauth = (Echo "Y" | &($scp) -scp -pw $esxpassword -ls $esxsslpath)

				if ($checkauth -eq $null) {
					$authenticated = $false
					$failedauth++
				}
			}	until ($authenticated -ne $false -or $failedauth -gt 4)	

		if ($failedauth -gt 4) { Write-Host -Foreground "Black" -Background "White" "Sorry, too many failed logins."; Break }
		Write-Host -Foreground "Black" -Background "White" "`rAuthentication accepted!"

		Write-Host -Foreground "Black" -Background "White" "Backing up current certs.."
		$null = (New-Item -Type Directory $backupdir)
		echo "Y" | &($scp) -scp -batch -pw $esxpassword "$esxsslpath/rui.key" $backupdir
		echo "Y" | &($scp) -scp -batch -pw $esxpassword "$esxsslpath/rui.crt" $backupdir

		Write-Host -Foreground "Black" -Background "White" "Uploading new certs.."
		echo "Y" | &($scp) -scp -batch -pw $esxpassword "$ruikey" $esxsslpath
		echo "Y" | &($scp) -scp -batch -pw $esxpassword "$ruicrt" $esxsslpath

		if ($disablessh) {
			Write-Host -Foreground "Black" -Background "White" "Returning SSH to disabled state on $esxserverfqdn"
			$null = Stop-VMHostService -HostService $sshservice -Confirm:$false
		}

		Write-Host -Foreground "Black" -Background "White" "Finished uploading files on $esxserverfqdn. Reboot the ESX host to activate new certificates."
	}

}

if ($updateesx -eq $true) { $null = Remove-Item $scp }

Alternatively, you can download the .ps1 file from here.

Note that you will have to re-add ESX to vCenter because the host's SSL thumbprint has changed. Regarding updating ESX's SSL, Derek Seaman suggests:

If your ESXi host is already managed by vCenter, the HA agent can get very confused by the new SSL certificate thumbprint. I would strongly suggest you first put your host in maintenance mode, remove it from the vCenter inventory, update the SSL certificate, reboot the ESXi host, then re-add it to the vCenter inventory.

Posted by: Chrissy LeMaire   Filed under: PowerShell, Security, Virtualization No Comments
11Jun/130

Update vSphere 5.1 SSL Certs with your own Windows Domain CA Certificates using PowerShell

One month ago when I finally got my vSphere lab set up, I had no idea that getting rid of those annoying untrusted SSL errors would be such a colossal undertaking. I have my own domain CA and thought it would be easy to automate the process of replacing the self-signed vSphere SSl certs with my own trusted certs.

At first, I attempted to use strictly Windows commands (certutil, certreq, etc) and PowerShell, but eventually gave in and incorporated OpenSSL into my script. Generating the certs were just the beginning, though.

Replacing the certificates in an automated fashion and getting each service to behave after the change was an extremely time-consuming task. VMware's documentation and KB articles leave a lot of room for improvement, but fortunately, David Seaman's blog was able to provide a lot of information that was either easy to miss, or missing entirely.

Numerous articles suggested using VMware's Certificate Automation Tool but the tool wasn't automated enough for my liking, even with supplemental scripts provided by other bloggers. I looked into guts of the Certificate Automation tool and, after a good bit of trial and error, replicated many of its techniques using PowerShell. Using these techniques, and following the suggestions found on forums and blogs, I was able to create a script that can replace the SSL certs of all of my vSphere lab servers in under 20 minutes, a majority of which is spent watching PowerShell stop and start services.

This script requires you to enter less than 15 variables as seen in the snippet below:

# SSO Server FQDN
$ssoserver = "vcenter.base.local"

# Place the certs on a network location if your farm is larger than one server
$basedir = "\\fileserver\share\Certs"

# Enter your SSO master password below. You will be prompted for your vCenter Server
# credentials at runtime.
$masteradmin = "admin@System-Domain"
$masterpass = "Fakepass.123"

# Enter your Windows Certificate Authority information below.
# Make sure it responds to certutil and web requests.
$rootCA = "dc.base.local"
$rootCAName = "BASE-DC-CA"
$email = "vmware@base.local"
$org = "NetNerds"
$city = "Kaplan"
$state = "LA"
$country = "US"

# Make sure you follow Derek Seaman's instructions
# to create a new certificate template @ http://goo.gl/m98FE
$certTemplate = "CertificateTemplate:VMware-SSL"

# Enter the path of your openssl.exe (0.x and 1.x are supported).
# If you don't have OpenSSL already, the script will download it for you.

$openssldir = "C:\OpenSSL-Win32"
$openssl = $openssldir+"\bin\openssl.exe"


You can see that the SSO admin username and password are in plain text. Unlike vCenter credentials, there was no easy way to validate the SSO username/password and the pros of placing the username and password there in plain text outweighed the cons. vCenter credentials were easier to validate and more of a priority for me to protect since they're usually Windows credentials.

Also, note that the default "Web Server" SSL certificate template is no longer adequate. Please visit Derek Seaman's blog for instructions on how to create a certificate template which will work for all of the vSphere services.

"What it does.."

Start up

  • If the server running the script is not the SSO server, it ensures the remote SSO Server's SSL certs have been updated first
  • Checks the registry to see which vSphere services exist on the server running the script and sets service variables
  • Creates the certificate directory if it does not exist
  • Backs up all SSL Certs on the server
  • Validates vCenter authentication if vCenter or VUM exist on the server
  • Automatically downloads Root64.cer from the CA's web service
  • Downloads and extracts OpenSSL if the files do not exist in the specified path
  • Generates all SSL certificates for each of the services on the server. Uses server name + service name as the OU so that each cert can be distinguished.

If SSO service exists

  • Stops SSO Service
  • Generates new SSO keystore using the newly created SSO SSL certificate
  • Copies Root64.cer to %programdata%\VMware\SSL\ca_certificates.cer
  • Creates new hash file in %programdata%\VMware\SSL
  • Updates SSO using rsautil.cmd
  • Starts SSO Service
  • Automatically builds service.properties and service_id files and stores them in %programdata%\VMware\ServiceIDs
  • Reregisters all services using new root certificate
  • Restarts SSO, and if they exist Log Browser, Web Client and Inventory services.

If Inventory service exists

  • Unregisters Inventory service with SSO
  • Stops Inventory service
  • Copies new certs to the Inventory service SSL directory
  • Starts Inventory Service
  • Registers Inventory service with SSO

If vCenter service exists

  • Copies new certs to the vCenter service SSL directory
  • Using credentials previously entered, logs into vCenter service's mob website to automatically invoke reloadSslCertificate
  • Restarts all vCenter related services
  • Reregisters vCenter with Inventory Service

If WebClient services exists

  • Stops WebClient and LogBrowser services
  • Removes all files from SerenityDB directory
  • Copies new certs to the Web Client and Log Browser service SSL directories
  • Stops vCenter and Inventory Services if they exist on the local server
  • Restarts SSO service on local or remote server
  • Starts vCenter and Inventory Services if they exist on the local server
  • Starts WebClient and LogBrowser services

If Update Manager exists

  • Stops Update Manager services
  • Copies new certs to the Update Manager service SSL directory
  • Generates new Update Manager keystore using the newly minted Update Manager Certificates
  • Updates registry entry with keystore password (testpassword)
  • Runs vciInstallUtils to update VUM using credentials previously entered
  • Starts Update Manager services

If Orchestrator exists

  • Copies new certs to the Orchestrator service SSL directory
  • Stops services if necessary
  • Generates new Orchestrator keystore using newly created Orchestrator certificates
  • Adds SSO Certificate to keystore
  • Restarts Orchestrator services then returns them to their previous state of Running or Stopped

If you have vCenter servers in linked mode and are running the Web Client, you may run into the error message "Cannot connect to Inventory Service on [server]" when logging into the Web Client. I have not found a predictable way to fix this. Usually, it can be solved by first restarting the server running Web Client, then restarting the vCenter/Inventory server.

This script also has other limitations, many of them similar to the Certificate Automation Tool.

Limitations

Limitations specific to this script

  • Only uses Windows Domain Certificate Authorities
  • Does not account for intermediary CAs
  • Has not been tested in large environments with HA and DRS
  • Has not been tested with environments running: VMware Site Recovery Manager, vSphere Data Recovery, vCloud Director, or third-party solutions
  • Does not have a rollback feature, yet. For rollback, I relied on Snapshots and database backups.
  • Does not have advanced logging
  • I don't recommend running this in a production environment until it's been vetted by far more people

Limitations that exist in VMware's tool that likely exist within this script

  • vCenter Single Sign-On Password cannot contain spaces
  • vCenter Orchestrator may fail to connect when using multiple vCenter Servers.
    • You can update add additional vCenter Server SSL certificates using the VMO Configuration Webpage (https://vmoserver:8283/ default login: vmware/vmware -> vCenter Server -> SSL Certificates.
    • Add all vCenter Certificates found in your Certs directory.
    • Note that if vCenter and VMO are running on the same server, the vCenter cert will be automatically added.
  • Client Not authenticated error when connecting to VMware Inventory service in Linked Mode Configurations. Wait 10 minutes and this should resolve itself.

Why I prefer using this script over VMware's

  • Requires minimal information and interaction
    • Automatically downloads OpenSSL if neccessary
    • Automatically generates the certificates based off of a few variables
    • Automatically detects services and runs the SSL updates in the necessary order without user intervention
    • If vCenter or VUM exists on the server, you wil be prompted for your vCenter credentials. This is the extent of interaction that the script will require:

  • Replaces all of the same certificates: SSO, Inventory Service, vCenter, Update Manager, Web Client/Log Browser, and Orchestrator
  • Also, works on vSphere farms with multiple servers (you must update the SSO server first)
  • It's all contained in just one (nearly 600 line) script
  • Works on 5.1 and 5.1U1

In the end, your Cert collection will look something like this:


* Note that the esx certificate output was created using this script.

And each of your services will be encrypted with trusted certificates:


     


     

And, of course, Web Client, after a couple reboots.

Getting started

  1. Ensure your Windows Domain CA certificate is trusted by members of your domain
  2. Take a snapshot of each vSphere server on which you will run this script
  3. Backup each of your databases
  4. Find a secure location on the network to store your certs (ie. \\fileserver\share\Certs)
  5. Visit Derek Seaman's blog and create a new certificate template
  6. Shut down the following services if they exist: VMware Site Recovery Manager, vSphere Data Recovery, vCloud Director, third-party solutions that connect to vCenter.
  7. Download the ReplaceSSL-vSphere51.ps1 script
  8. Change the variables
  9. Run the script first on the server running the SSO
  10. Run the script on all other servers
  11. If the Web Client connects to multiple vCenter servers, reboot the server running Web Client, as well as the server(s) running Inventory Service and vCenter.
  12. Consider running the complimentary ESX Script

Once the scripts are complete, you can visit each of your sites to confirm the SSL Certificates have been replaced. Please note that Log Browser and the Web Client take up to 5 minutes to fully restart.

Finally, bask in the glory of your trusted SSL certificates:

Posted by: Chrissy LeMaire   Filed under: PowerShell, Security, Virtualization No Comments
4Mar/130

HOW-TO Setup Windows 2012 Server Core Remote Desktop Services to Securely Administer Windows over RDP and SSL

Alright, so I've wanted to setup a Remote Desktop Gateway for years, but the configuration seemed so.. time-intensive. Then I moved to Belgium, my living situation changed and I didn't want to setup a whole new VPN server to access my virtual lab.

Initially, I set up my RD Gateway using too many Remote Desktop Services: Remote Desktop Connection Broker, Remote Desktop Gateway & Remote Desktop Web Access, but that was because was lead astray by Windows 2012's new GUI. Now, I've narrowed it down only to RD Gateway and I'm even fond of Metro (:O)

So to get this going, all you have to do is install and configure the Remote Desktop Gateway Services (RD Gateway) Role. That seems obvious, but Server Manager's interface which prominently displays an unconfigured "Remote Desktop Services" tab made me think I was missing something.

During the Role installation do: Role-based or feature-based installation -> Remote Desktop Services -> Remote Desktop Gateway

Then click Next a bunch of times. Something odd, when it asks you "Do you need an alternate source path?", even if you have the Windows Server 2012 ISO attached, you'll still need to click "Specify an alternate source path" and enter D:\sources\sxs (assuming your ISO is attached to D:)

Click Install and wait for the installation to complete. Now it's time to configure RD Gateway.

OPTIONAL: If you're on a domain with a Certificate Authority, you'll want to configure IIS to use a Domain Certificate. Open IIS Manager -> Select your server -> Server Certificates -> Create Domain Certificate. For "Common Name" make sure you enter your external FQDN. Note: I chose to go with dyndns.org since I have a dynamic IP. It's required that you use an externally resolvable hostname, otherwise Remote Desktop will fail if you try to use an IP or mismatched hosts.

Now, you'll need to configure RD Gateway. Go to Server Manager -> Tasks -> RD Gateway Manager.

Click View or modify certificate properties. If you don't have a Domain Certificate, just click Create and import certificate and ensure you use your external FQDN for the certificate name. Otherwise, choose Select an existing certificate.... Choose your certificate

Click Import -> Apply. Now that you're back at the RD Gateway Manager, expand the tree under your server name. Click Policies then on the right, click Create Authorization Polices for RD Gateway. Create an RD CAP and RD RAP (Recommended). In the name field, you can enter whatever you'd like. I chose "Default" -> Next -> Add Group -> Domain Admins -> (leave Client Computer blank)

Next, you'll be given the option to Enable or Disable Device Redirection. I just choose the default (all clients) and click Next -> Next -> Next - Default -> Next -> Allow users to connect to any network resource -> Next -> Allow Connections only to port 3389 -> Next -> Finish

Finally, open up Services and Start Remote Desktop Gateway

Voila! Now you can go modify your router rules to connect port 443 to your RD Gateway Server and/or read the important notes below.

A few important things to note
As an added security pre-caution, I went into IIS and disabled Anonymous access to my root IIS folder and ensured Windows Authentication was still enabled for the RPC folders.

Configuring the Remote Desktop Client is easy. Open up your Remote Desktop Client -> Advanced -> (Connect from Anywhere) Settings.

Enter the external hostname that you entered earlier during the configuration of RD Gateway. Go back to the general tab, and enter the FQDN of the domain server you wish to connect to. Don't worry about resolving the hostname if you're using an external DNS server -- DNS is resolved at the RD Gateway so if the RD Gateway can resolve the hostname, you're set.

If you choose to use a self-signed cert or you are attempting to connect from a computer that's not on the domain, you'll have to import the SSL cert to your Trusted Root Certification Authority. Otherwise, you'll receive the error "This computer can't verify the identity of the RD Gateway 'sample.server.com'. It's not safe to connect to servers that are not identified. Contact your network administrator for assistance."

There are a few ways to do this, but here's how I do it. I use Chrome to hit my server (ex. https://myserver.dyndns.org)

Click Certificate Information -> Details -> Copy to File. Save the cert, then find it using Windows Explorer. Right-click on the cert -> Install Certificate -> Place all Certificate in the Following Store -> Trusted Root Certification Authority -> Next -> Finish -> Yes.

You should now be able to connect and securely manage your network, all over SSL :)

Posted by: Chrissy LeMaire   Filed under: IIS, Security, Windows No Comments
1Mar/130

NoMachine NX for OS X Successfully Authenticates But Won’t Load Sessions

I recently discovered NoMachine's NX while looking for an easy way to encrypt VNC. NX, if you aren't familiar with it, is generally a PITA to setup, but well worth the pain (on Linux anyway). All traffic goes over SSH and while the performance isn't as great as Windows' RDP, it's faster and more secure than VNC. NoMachine's NX client works on Windows, OS X and Linux and even works well on roaming profiles.

Installing NX Server on OS X is challenging. Well, installing it is easy, getting it to work is another story.

First, starting with Mountain Lion, Apple no longer ships OS X with X11 already installed so XQuartz must be downloaded and installed manually. Initially, I installed XQuartz X11 2.7.4 and NX for OSX 4.0.181-7.

After adding the nx user to my allowed list of SSH logins, connecting was easy using the account I use to login to my MacBook Pro everyday. When prompted for Desktop type, I selected Shadow.



Once I connected, my session would appear for a split second then disappear. If you're quick, sometimes you can catch the session before it disappears then click Attach.


Oops! Missed it :(




Got it!

Now, initially when I'd attach, it would hang at "Requesting users authorization" but no window would pop up to request the authorization. I checked to ensure that PhysicalDesktopAuthorization 0 was set in server.cfg and sure enough it was. I thought, then, that maybe there was an issue with xauth. I spent about a day troubleshooting that, and eventually tried a different version of XQuartz. I uninstalled everything across the board. Then reinstalled everything across the board and still no dice. Messing with shadowing in the configs proved fruitless and decided to pour over NX's documentation one last time. This time, I saw that it should have installed the nxnode --mirror service, but no such service was running.

I created /Library/LaunchDaemons/com.nomachine.node.plist and pasted the following into it, ensuring that Username was set to my regular user account (otherwise, my session never showed)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>com.nomachine.node</string>
        <key>KeepAlive</key>
        <false/>
        <key>ProgramArguments</key>
        <array>
                <string>/Applications/NoMachine Service.app/Contents/Frameworks/bin/nxnode</string>
                <string>--mirror</string>
        </array>
        <key>UserName</key>
        <string>chrissylemaire</string>
        <key>RunAtLoad</key>
        <true/>
        <key>StandardErrorPath</key>
        <string>/Applications/NoMachine Service.app/Contents/Frameworks/var/log/nxnode_stderr.log</string>
        <key>StandardOutPath</key>
        <string>/Applications/NoMachine Service.app/Contents/Frameworks/var/log/nxnode_stdout.log</string>
        <key>WorkingDirectory</key>
        <string>/Applications/NoMachine Service.app/Contents/Frameworks/bin/</string>
        <key>Debug</key>
        <true/>
</dict>
</plist>



I ran launchctl load -w /Library/LaunchDaemons/com.nomachine.node.plist and voila! My screen appeared. It was ugly and smudgy, though, no matter how well I optimized my client settings. Look:

Also, it often freezes about 10 seconds after. Seeing that the screen quality wasn't worth it anyway, I decided to go with VNC over SSL until NoMachine NX is out of beta for OS X. Ultimately, I really wanted remote access to manage my virtual Windows farm, so I finally got around to installing and configuring Remote Desktop Gateway. If you're a Windows admin who wants secure Remote Desktop access, you should try Remote Desktop Gateway which does RDP over SSL RPC. It was easy-ish to setup and the quality is just as you'd expect from RDP. Slick!

Posted by: Chrissy LeMaire   Filed under: OS X & iDevices, Security No Comments
24Feb/121

Patterns and Practices: A Guide to Claims-Based Identity and Access Control – Free ebook.

While I usually like conversation-style technical books (think: Manning's In Action series and many Wrox books), Microsoft's Patterns and Practices series is one of my favorite even though they feel so formal. Recently, my buddy Buck Woody posted a link to the freely available Patterns and Practices book for A Guide to Claims-Based Identity and Access Control, Second Edition.

Book Map

Courtesy of Avkash Chauhan's Blog

It's the same book that can be purchased at Amazon.com for 23 dollars (make you holler.)

Posted by: Chrissy LeMaire   Filed under: Active Directory, Networking, Security 1 Comment
6Feb/122

Map a Secure SharePoint 2010/IIS Network Drive over SSL and WebDAV in Windows 7

Once, after viewing a SharePoint 2010 document library in Windows Explorer, I ran a net use and saw that Windows 7 had stored the credentials of my SSL-secured SharePoint intranet server. It took a bit of fiddling, but I eventually found you can, in fact, map a secure network drive using the command line:

net use W: \\sharepoint.local@SSL\DavWWWRoot\SiteCollectionName\SiteName /user:domain\username *

If your Site Collection is at the root of the server, you can just use \\sharepoint.local@SSL\DavWWWRoot. If you're not a fan of the command line, using the Windows GUI is also an option, as demonstrated here. Each of these methods requires a trusted certificate. I'm betting you can use self-signed cert if you just trust yourself as a root.

Posted by: Chrissy LeMaire   Filed under: IIS, Security, SharePoint 2 Comments
30Jan/123

SharePoint 2010: Stop Mixed Content Prompts on RSS Feeds Viewed on SSL-enabled Sites

I started on a new client site last week and my first task was immediately clear: I had to remove the Mixed Content Security prompt on the encrypted SharePoint intranet's front page. Firebug showed that my browser was making calls to feeds.feedburner.com even though the RSS feed was an entirely different address at cio.com.

My first instinct was to try to see if I could find the feed on HTTPS but https://feeds.cio.com did not respond to my request. Then I thought -- the only reason my browser would be making calls to feedburner would be for tracking. Although it's not a critical security threat or waste of bandwidth (the images were 1x1 gifs), I really didn't want feedburner to collect information about our intranet so I decided it was probably best to just remove all embedded HTML code in the description. After some research, it looked like XSL was likely the best way to do this.

I'm not an XSL pro, but I can get around. My initial search for sample code led me to a promising XSL function (which I can't find again to link :( ), but functions are only supported in XML namespace 2.0 and SharePoint uses 1.0 in the RSS Web Part. After reviewing the XSL provided in the SharePoint RSS Web Part, I decided to embed the strip-tags template within the GetSafeHTML template that is called for all the different types of feeds.

The following code removes all content within HTML tags (img, a, b, etc) so you're left with plain-text for the description. Clicking the title of the article to read more, still works, of course. To use this in your own RSS feed, edit the RSS Web Part, click on XSL Editor ... at the bottom of the web part panel, and replace the GetSafeHtml template with the following code:

        <xsl:template name="GetSafeHtml">
            <xsl:param name="Html"/>
            <xsl:choose>
                <xsl:when test="$rss_IsDesignMode = 'True'">
                    <xsl:call-template name="strip-tags">
                        <xsl:with-param name="text" select="$Html"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:call-template name="strip-tags">
                        <xsl:with-param name="text" select="rssaggwrt:MakeSafe($Html)"/>
                    </xsl:call-template>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>

        <xsl:template name="strip-tags">
            <xsl:param name="text"/>
            <xsl:choose>
                <xsl:when test="contains($text, '&lt;')">
                    <xsl:value-of select="substring-before($text, '&lt;')"/>
                    <xsl:call-template name="strip-tags">
                        <xsl:with-param name="text" select="substring-after($text, '&gt;')"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$text"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>

This code basically runs strip-tags on the final output of the description node, and aside from the strip-tags code itself, only adds 4 extra lines to your original XSL :)

Posted by: Chrissy LeMaire   Filed under: Security, SharePoint 3 Comments
20Feb/118

OpenWRT & PPTPD: A Love Story

Firesheep got me thinkin' that I should probably do a little more to beef up the security of my Internet connection on public networks. PPTP has always been a favorite of mine, because it hides traffic well enough to deter most people and it's easy to setup on both Linux and Windows. I ran a Windows PPTP server for years, but recently decided to just host the service my WRT54GS v3 router running OpenWRT. Three hours later, I've got it running smoothly. Here's how I did it:

First, I installed and setup OpenWrt Backfire 10.03 and set my internal IP pool to be on the 172.16.x net, with the gateway (OpenWRT router being 172.16.1.1). Then, I headed over to OpenWRT's PPTPD HOW-TO.

opkg update
opkg install pptpd
opkg install kmod-crypto
opkg install kmod-mppe
/etc/init.d/pptpd enable
/etc/init.d/pptpd start


I believe my /etc/ppp/options file doesn't have any modifications, but just in case, this is what it looks like:

#debug
logfile /dev/null
noaccomp
nopcomp
nocrtscts
lock
maxfail 0
lcp-echo-failure 5
lcp-echo-interval 1


Now that I think about it, very few modifications were ultimately made to /etc/ppp/options.pptpd

auth
name "pptp-server"
lcp-echo-failure 3
lcp-echo-interval 60
default-asyncmap
mtu 1482
mru 1482
nobsdcomp
nodeflate
#noproxyarp
#nomppc
chapms-strip-domain
# Otherwise, your chap-secret file will have to include "DOMAIN\\user" instead of user.
mppe required,no40,no56,stateless
require-mschap-v2
refuse-chap
refuse-mschap
refuse-eap
refuse-pap
ms-dns 172.16.1.1
#plugin radius.so
#radius-config-file /etc/radius.conf


If you compare this to the original file, you'll notice I deleted the entry "172.16.1.1:" at the top of the file, and added the entry: ms-dns 172.16.1.1. I don't know why, but DNS didn't work well when the the client's defaults were used so I forced them to use the router's LAN DNS server.

Then I added some users to the /etc/ppp/chap-secrets file. I'll paste the contents, then go over the details. Oh, and don't forget to chmod 600 /etc/chap-secrets because the file's perms are insecure by default:

#USERNAME  PROVIDER  PASSWORD  IPADDRESS
iphone  pptp-server     suprAdv4ncedPwd!       192.168.80.1
ipad    pptp-server     rlyAdv4ncedPwd!       192.168.80.11
hackbook        pptp-server     megaAdv4ncedPwd!       191.68.80.3
windows pptp-server     ttllyAdv4ncedPwd!       192.168.80.2
extra           pptp-server     megaAdv4ncedPwd! 192.68.80.4


The chap-secrets file alone suggests that OpenWRT/PPTP is not an enterprise solution. I wouldn't propose it for any company with a decent budget, but times are tough and ghetto is looking better than ever to many companies.

I would actually have fewer entries in this file if the IPADDRESS field was not such a big issue. Unfortunately, it seems that the DHCP pool has been compiled into the service. It sets up the router's pppN to be 192.168.0.x and assigns the clients a 192.168.1.x address by default. Which is unfortunate, because SO DOES EVER OTHER RESIDENTIAL ROUTER, EVER. So routing issues keep pop up. Because of that, I force PPTPD to assign each user a specific IP, in the 192.168.80.x range because I've never seen any router use that subnet.

The usernames are whatever you'd like them to be (I made them the name of my devices) but if you are dialing-in from a Windows machine, you will have to preface the username with the Windows domain name or the name of your workstation if you are not on a domain UPDATE: adding chapms-strip-domain to options.pptpd fixes this. The "pptp-server" is what the service was named in options.pptd, the password is just that, and the IPADDRESS is the IP that the given client will be assigned.

Initially, my /etc/firewall.user didn't have all the proper entries, so my client was able to authenticate and all that, but no traffic was being routed to the 172.16.x subnet, nor was it being routed to the Internet. Here's what worked:

# This file is interpreted as shell script.
# Put your custom iptables rules here, they will
# be executed with each firewall (re-)start.
iptables    -A input_wan -p tcp --dport 1723 -j ACCEPT
iptables    -A input_wan -p gre -j ACCEPT

iptables -A input_rule -i ppp+ -j ACCEPT
iptables -A forwarding_rule -i ppp+ -j ACCEPT
iptables -A forwarding_rule -o ppp+ -j ACCEPT
iptables -A output_rule -o ppp+ -j ACCEPT


The first block allows clients to connect to the PPTP service and the second one allows it to communicate with both the Internet and the local network. And voila, you are done. I know it seems straightforward and doesn't deviate much for the default install, but it took over three hours of trial and error to get here. I've logged in successfully with an iPhone (over 3G, EDGE and wifi), an iPad, a Windows 7 machine and Mac OS X. The iPhone is of special importance to me -- after connecting to a local coffee shop's unsecured network on my laptop and my iPhone, I successfully hijacked my iPhone's Facebook app session using FireSheep. So, now I'll be encapsulating all of my traffic by sending it over to the fiber connection at my office, what what.

Next up, I'll probably start playing around with the RADIUS plugin. Stay tuned.

Posted by: Chrissy LeMaire   Filed under: Linux, Networking, Security 8 Comments