<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>netnerds.net</title>
	
	<link>http://blog.netnerds.net</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Thu, 20 Jun 2013 11:27:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/netnerdsnet" /><feedburner:info uri="netnerdsnet" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Update NetApp Virtual Storage Console SSL Certs with your own Windows Domain CA Certificates using PowerShell</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/9arM29-3Myc/</link>
		<comments>http://blog.netnerds.net/2013/06/update-your-netapp-virtual-storage-console-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powercli/#comments</comments>
		<pubDate>Tue, 18 Jun 2013 12:10:04 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Virtualization]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2803</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>Ahhh, it seems like replacing SSL certificates in vSphere is a <a href="http://blog.netnerds.net/2013/06/update-your-vsphere-5-1u1-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/">never</a>-<a href="http://blog.netnerds.net/2013/06/update-your-esxs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powercli/">ending</a> <a href="http://blog.netnerds.net/2013/06/update-your-vsphere-5-0-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/">process</a>. 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 <a href="http://practical-admin.com/blog/?p=1217">practical admin's post</a> and <a href="https://kb.netapp.com/support/index?page=content&#038;id=1012835">NetApp's KB</a> (login required). </p>
<p>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.</p>
<p>You can copy and paste the code below, or download the script directly <a href=http://blog.netnerds.net/wp-content/uploads/2013/06/ReplaceSSL-netapp.ps1>here</a>.</p>
<p>Note: this script uses the Windows CA default WebServer Certificate Template. It also makes backups of your original certificates.</p>
<pre  class="brush:powershell">#########################################################################################
#
#   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&#038;Renewal=0&#038;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"

	&#038;$openssl req -new -nodes -out $netappcsr -keyout $tempkey -config $servicecfg
	&#038;$openssl rsa -in $tempkey -out $netappkey
	Remove-Item $tempkey
	certreq -submit -config "$rootCA\$rootCAName" -attrib "CertificateTemplate:WebServer" $netappcsr $netappcrt
	&#038;$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 = (&#038;"$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 = (&#038;"$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!"
</pre>
<p>Done!</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/9arM29-3Myc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/06/update-your-netapp-virtual-storage-console-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powercli/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/06/update-your-netapp-virtual-storage-console-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powercli/</feedburner:origLink></item>
		<item>
		<title>Update vSphere 4.1U3 and 5.0 SSL Certs with your own Windows Domain CA Certificates using PowerShell</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/gDKluei3sl0/</link>
		<comments>http://blog.netnerds.net/2013/06/update-your-vsphere-5-0-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/#comments</comments>
		<pubDate>Tue, 11 Jun 2013 18:22:36 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Virtualization]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2774</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>While it took quite awhile to figure out how to <a href=http://blog.netnerds.net/2013/06/update-your-vsphere-5-1u1-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/>replace vSphere 5.1 and 5.1U1's SSL certs</a>, 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 <a href="/aboutus/#lab">lab environment</a>.)</p>
<p>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.</p>
<p>So without further ado, you can download <b><a href='http://blog.netnerds.net/wp-content/uploads/2013/06/ReplaceSSL-vSphere41-50.ps1'>ReplaceSSL-vSphere41-50.ps1</b></a>, 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:</p>
<div class="dirtycodenoclick"><code># Place the certs on a network location if your farm is larger than one server<br />
$basedir = &quot;\\fileserver\share\Certs&quot;<br />
<br /># Enter your Windows Certificate Authority information below.<br />
# Make sure it responds to certutil and web requests.<br />
$rootCA = &quot;dc.base.local&quot;<br />
$rootCAName = &quot;BASE-DC-CA&quot;<br />
$email = &quot;vmware@base.local&quot;<br />
$org = &quot;NetNerds&quot;<br />
$city = &quot;Kaplan&quot;<br />
$state = &quot;LA&quot;<br />
$country = &quot;US&quot;<br />
<br /># Make sure you follow Derek Seaman&#039;s instructions<br />
# to create a new certificate template @ http://goo.gl/m98FE<br />
$certTemplate = &quot;CertificateTemplate:VMware-SSL&quot;<br />
<br /># Enter the path of your openssl.exe (0.x and 1.x are supported).<br />
# If you don&#039;t have OpenSSL already, the script will download it for you.<br />
$openssldir = &quot;C:\OpenSSL-Win32&quot;<br />
$openssl = $openssldir+&quot;\bin\openssl.exe&quot;</code></div>
<p><br/><br />
If you are interested in the approximate steps taken, you can browse <a href=http://blog.netnerds.net/2013/06/update-your-vsphere-5-1u1-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/>the vSphere 5.1 SSL replacement post</a>. Just be aware that the SSO section does not apply.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/gDKluei3sl0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/06/update-your-vsphere-5-0-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/06/update-your-vsphere-5-0-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/</feedburner:origLink></item>
		<item>
		<title>Update ESX SSL Certs with your own Windows Domain CA Certificates using PowerCLI</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/56iyCi6HPWQ/</link>
		<comments>http://blog.netnerds.net/2013/06/update-your-esxs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powercli/#comments</comments>
		<pubDate>Tue, 11 Jun 2013 09:14:34 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Virtualization]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2562</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>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. </p>
<p>Below is a script I use in conjunction with my <a href="http://blog.netnerds.net/2013/06/update-your-vsphere-5-1u1-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/">vSphere/PowerShell Replace SSL script</a>.</p>
<p>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 <img src='http://blog.netnerds.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><b>"What it does.."</b><br />
</p>
<ul>
<li>Creates the certificate directory if it does not exist
<li>Logs into specified vSphere Server
<li>Automatically downloads Root64.cer from the CA's web service
<li>Downloads and extracts OpenSSL if the files do not exist in the specified path
<li>Generates all SSL certificates for each of the services on the server.
</ul>
<p><u>If $upsateesx is set to true..</u>
<ul>
<li>Downloads Putty SCP
<li>Checks to see if SSH is running on the esx host. If not, it temporarily enables it
<li>Prompts for and validates credentials
<li>Backs up all SSL Certs on the server
<li>Uploads the new certs
<li>Returns SSH to previous state
</ul>
<p>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.</p>
<pre  class="brush:powershell">##############################################################################################
#
#   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&#038;Renewal=0&#038;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"

	&#038;$openssl req -new -nodes -out $ruicsr -keyout $tempkey -config $servicecfg
	&#038;$openssl rsa -in $tempkey -out $ruikey
	Remove-Item $tempkey
	certreq -submit -config "$rootCA\$rootCAName" -attrib $certTemplate $ruicsr $ruicrt
	&#038;$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" | &#038;($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" | &#038;($scp) -scp -batch -pw $esxpassword "$esxsslpath/rui.key" $backupdir
		echo "Y" | &#038;($scp) -scp -batch -pw $esxpassword "$esxsslpath/rui.crt" $backupdir

		Write-Host -Foreground "Black" -Background "White" "Uploading new certs.."
		echo "Y" | &#038;($scp) -scp -batch -pw $esxpassword "$ruikey" $esxsslpath
		echo "Y" | &#038;($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 }
</pre>
<p>Alternatively, you can download the .ps1 file from <a href=http://blog.netnerds.net/wp-content/uploads/2013/06/ReplaceSSL-ESX.ps1>here</a>.</p>
<p><small><b>Note that you will have to re-add ESX to vCenter because the host's SSL thumbprint has changed.</b></small> Regarding updating ESX's SSL, <a href="http://www.derekseaman.com/2013/02/vmware-vcenter-51-installation-part-15.html">Derek Seaman</a> suggests:<br />
<blockquote>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.</p></blockquote>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/56iyCi6HPWQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/06/update-your-esxs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powercli/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/06/update-your-esxs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powercli/</feedburner:origLink></item>
		<item>
		<title>Update vSphere 5.1 SSL Certs with your own Windows Domain CA Certificates using PowerShell</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/zyIQBAXYUAQ/</link>
		<comments>http://blog.netnerds.net/2013/06/update-your-vsphere-5-1u1-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/#comments</comments>
		<pubDate>Tue, 11 Jun 2013 08:56:38 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Virtualization]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2569</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>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. </p>
<p>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. </p>
<p>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.</p>
<p>Numerous articles suggested using <a href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&#038;cmd=displayKC&#038;externalId=2041600">VMware's Certificate Automation Tool</a> 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.</p>
<p>This script requires you to enter less than 15 variables as seen in the snippet below:</p>
<div class="dirtycodenoclick"><code># SSO Server FQDN<br />
$ssoserver = &quot;vcenter.base.local&quot;<br />
<br /># Place the certs on a network location if your farm is larger than one server<br />
$basedir = &quot;\\fileserver\share\Certs&quot;<br />
<br /># Enter your SSO master password below. You will be prompted for your vCenter Server<br />
# credentials at runtime.<br />
$masteradmin = &quot;admin@System-Domain&quot;<br />
$masterpass = &quot;Fakepass.123&quot;<br />
<br /># Enter your Windows Certificate Authority information below.<br />
# Make sure it responds to certutil and web requests.<br />
$rootCA = &quot;dc.base.local&quot;<br />
$rootCAName = &quot;BASE-DC-CA&quot;<br />
$email = &quot;vmware@base.local&quot;<br />
$org = &quot;NetNerds&quot;<br />
$city = &quot;Kaplan&quot;<br />
$state = &quot;LA&quot;<br />
$country = &quot;US&quot;<br />
<br /># Make sure you follow Derek Seaman&#039;s instructions<br />
# to create a new certificate template @ http://goo.gl/m98FE<br />
$certTemplate = &quot;CertificateTemplate:VMware-SSL&quot;<br />
<br /># Enter the path of your openssl.exe (0.x and 1.x are supported).<br />
# If you don&#039;t have OpenSSL already, the script will download it for you.<br />
<br />$openssldir = &quot;C:\OpenSSL-Win32&quot;<br />
$openssl = $openssldir+&quot;\bin\openssl.exe&quot;</code></div>
<p><br/></p>
<p>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.</p>
<p>Also, note that the default "Web Server" SSL certificate template is no longer adequate. Please visit <a href="http://goo.gl/m98FE">Derek Seaman's blog</a> for instructions on how to create a certificate template which will work for all of the vSphere services. </p>
<h2>"What it does.."</h2>
<p></p>
<p><u>Start up</u></p>
<ul>
<li>If the server running the script is not the SSO server, it ensures the remote SSO Server's SSL certs have been updated first
<li>Checks the registry to see which vSphere services exist on the server running the script and sets service variables
<li>Creates the certificate directory if it does not exist
<li>Backs up all SSL Certs on the server
<li>Validates vCenter authentication if vCenter or VUM exist on the server
<li>Automatically downloads Root64.cer from the CA's web service
<li>Downloads and extracts OpenSSL if the files do not exist in the specified path
<li>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.
</ul>
<p><u>If SSO service exists</u>
<ul>
<li>Stops SSO Service
<li>Generates new SSO keystore using the newly created SSO SSL certificate
<li>Copies Root64.cer to <small>%programdata%\VMware\SSL\ca_certificates.cer</small>
<li>Creates new hash file in <small>%programdata%\VMware\SSL</small>
<li>Updates SSO using rsautil.cmd
<li>Starts SSO Service
<li>Automatically builds service.properties and service_id files and stores them in <small>%programdata%\VMware\ServiceIDs</small>
<li>Reregisters all services using new root certificate
<li>Restarts SSO, and if they exist Log Browser, Web Client and Inventory services.
</ul>
<p><u>If Inventory service exists</u>
<ul>
<li>Unregisters Inventory service with SSO
<li>Stops Inventory service
<li>Copies new certs to the Inventory service SSL directory
<li>Starts Inventory Service
<li>Registers Inventory service with SSO
</ul>
<p><u>If vCenter service exists</u>
<ul>
<li>Copies new certs to the vCenter service SSL directory
<li>Using credentials previously entered, logs into vCenter service's mob website to automatically invoke reloadSslCertificate
<li>Restarts all vCenter related services
<li>Reregisters vCenter with Inventory Service
</ul>
<p><u>If WebClient services exists</u>
<ul>
<li>Stops WebClient and LogBrowser services
<li>Removes all files from <a href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&#038;cmd=displayKC&#038;externalId=2036505">SerenityDB</a> directory
<li>Copies new certs to the Web Client and Log Browser service SSL directories
<li>Stops vCenter and Inventory Services if they exist on the local server
<li>Restarts SSO service on local or remote server
<li>Starts vCenter and Inventory Services if they exist on the local server
<li>Starts WebClient and LogBrowser services
</ul>
<p><u>If Update Manager exists</u>
<ul>
<li>Stops Update Manager services
<li>Copies new certs to the Update Manager service SSL directory
<li>Generates new Update Manager keystore using the newly minted Update Manager Certificates
<li>Updates registry entry with keystore password (testpassword)
<li>Runs vciInstallUtils to update VUM using credentials previously entered
<li>Starts Update Manager services
</ul>
<p><u>If Orchestrator exists</u>
<ul>
<li>Copies new certs to the Orchestrator service SSL directory
<li>Stops services if necessary
<li>Generates new Orchestrator keystore using newly created Orchestrator certificates
<li>Adds SSO Certificate to keystore
<li>Restarts Orchestrator services then returns them to their previous state of Running or Stopped
</ul>
<p>If you have vCenter servers in linked mode and are running the Web Client, you may run into the error message <b><small>"Cannot connect to Inventory Service on [server]"</small></b> when logging into the Web Client. I have not found a predictable way to fix this. <b><small>Usually</small></b>, it can be solved by first restarting the server running Web Client, then restarting the vCenter/Inventory server.</p>
<p>This script also has other limitations, many of them similar to the Certificate Automation Tool.<br />
<br/></p>
<h2>Limitations</h2>
<p></p>
<p><u>Limitations specific to this script</u>
<ul>
<li>Only uses Windows Domain Certificate Authorities
<li>Does not account for intermediary CAs
<li>Has not been tested in large environments with HA and DRS
<li>Has not been tested with environments running: VMware Site Recovery Manager, vSphere Data Recovery, vCloud Director, or third-party solutions
<li>Does not have a rollback feature, yet. For rollback, I relied on Snapshots and database backups.
<li>Does not have advanced logging
<li>I don't recommend running this in a production environment until it's been vetted by far more people
</ul>
<p><u>Limitations that exist in VMware's tool that likely exist within this script</u>
<ul>
<li>vCenter Single Sign-On Password cannot contain spaces
<li>vCenter Orchestrator may fail to connect when using multiple vCenter Servers.
<ul>
<li>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.</li>
<li>Add all vCenter Certificates found in your Certs directory.</li>
<li>Note that if vCenter and VMO are running on the same server, the vCenter cert will be automatically added.</li>
</ul>
<li>Client Not authenticated error when connecting to VMware Inventory service in Linked Mode Configurations. Wait 10 minutes and this should resolve itself.</ul>
<h2>Why I prefer using this script over VMware's</h2>
<ul>
<li>Requires minimal information and interaction
<ul>
<li>Automatically downloads OpenSSL if neccessary</li>
<li>Automatically generates the certificates based off of a few variables</li>
<li>Automatically detects services and runs the SSL updates in the necessary order without user intervention</li>
<li>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:</ul>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/06/authenticate.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/06/authenticate.png" alt="" title="authenticate" width="505" height="370" class="aligncenter size-full wp-image-2661" /></a></p>
<li>Replaces all of the same certificates: SSO, Inventory Service, vCenter, Update Manager, Web Client/Log Browser, and Orchestrator
<li>Also, works on vSphere farms with multiple servers (you must update the SSO server first)
<li>It's all contained in just one (nearly 600 line) script
<li>Works on 5.1 and 5.1U1
</ul>
<p>In the end, your Cert collection will look something like this:</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/06/blog.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/06/blog.png" alt="" title="blog" width="504" height="391" class="aligncenter size-full wp-image-2629" /></a><br />
* Note that the esx certificate output was created using <a href="http://blog.netnerds.net/2013/06/update-your-esxs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powercli/">this script</a>.</p>
<p>And each of your services will be encrypted with trusted certificates:<center><br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/06/sso.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/06/sso-150x150.png" alt="" title="sso" width="150" height="150" /></a> &nbsp;&nbsp; <a href="http://blog.netnerds.net/wp-content/uploads/2013/06/inventoryservice.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/06/inventoryservice-150x150.png" alt="" title="inventoryservice" width="150" height="150" /></a> &nbsp;&nbsp; <a href="http://blog.netnerds.net/wp-content/uploads/2013/06/vcenter.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/06/vcenter-150x150.png" alt="" title="vcenter" width="150" height="150" /></a><br />
<br/><br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/06/vcenter2.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/06/vcenter2-150x150.png" alt="" title="vcenter2" width="150" height="150"/></a> &nbsp;&nbsp; <a href="http://blog.netnerds.net/wp-content/uploads/2013/06/vmo.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/06/vmo-150x150.png" alt="" title="vmo" width="150" height="150"/></a> &nbsp;&nbsp; <a href="http://blog.netnerds.net/wp-content/uploads/2013/06/vum.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/06/vum-150x150.png" alt="" title="vum" width="150" height="150"/></a></p>
<p>And, of course, Web Client, after a couple reboots.<br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/06/webclient.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/06/webclient-1024x708.png" alt="" title="webclient" width="512" height="354" /></a></center></p>
<h2>Getting started</h2>
<ol>
<li>Ensure your Windows Domain CA certificate is <a href="http://technet.microsoft.com/en-us/library/cc754841.aspx">trusted by members of your domain</a>
<li>Take a snapshot of each vSphere server on which you will run this script
<li>Backup each of your databases
<li>Find a secure location on the network to store your certs (ie. \\fileserver\share\Certs)
<li>Visit Derek Seaman's blog and <a href="http://goo.gl/m98FE">create a new certificate template</a>
<li>Shut down the following services if they exist: VMware Site Recovery Manager, vSphere Data Recovery, vCloud Director, third-party solutions that connect to vCenter.
<li>Download the <a href='http://blog.netnerds.net/wp-content/uploads/2013/06/ReplaceSSL-vSphere51.ps1'><b>ReplaceSSL-vSphere51.ps1</b></a> script
<li>Change the variables
<li>Run the script first on the server running the SSO
<li>Run the script on all other servers
<li>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.
<li>Consider running the complimentary ESX Script
</ol>
<p>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.</p>
<p>Finally, bask in the glory of your trusted SSL certificates:</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/06/verified.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/06/verified.png" alt="" title="verified" width="318" height="506" class="aligncenter size-full wp-image-2648" /></a></p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/zyIQBAXYUAQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/06/update-your-vsphere-5-1u1-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/06/update-your-vsphere-5-1u1-labs-ssl-certs-with-your-own-windows-domain-ca-certificates-using-powershell/</feedburner:origLink></item>
		<item>
		<title>PowerShell Get-WinEvent Bug Workaround on Windows 2008 R2 Server — Importing Windows Forwarded Events into SQL Server using PowerShell</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/9U02OZLeGIw/</link>
		<comments>http://blog.netnerds.net/2013/04/powershell-get-winevent-bug-workaround-on-windows-2008-r2-server-importing-windows-forwarded-events-into-sql-server-using-powershell/#comments</comments>
		<pubDate>Wed, 10 Apr 2013 13:52:49 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2448</guid>
		<description><![CDATA[This is sort of a continuation of my earlier post, Importing Windows Forwarded Events into SQL Server using PowerShell, where I mentioned that I was unable to get the script to work on Windows 2008 R2 due to a known bug in Get-WinEvents. I had to end up deploying my solution to a Windows 2008 [...]]]></description>
			<content:encoded><![CDATA[<p>This is sort of a continuation of my earlier post, <a href=http://blog.netnerds.net/2013/03/importing-windows-forwarded-events-into-sql-server-using-powershell/>Importing Windows Forwarded Events into SQL Server using PowerShell</a>, where I mentioned that I was unable to get the script to work on Windows 2008 R2 due to a <a href=http://connectppe.microsoft.com/PowerShell/feedback/details/716533/get-winevent-does-not-return-the-content-of-the-event-message-in-v3-ctp2>known bug</a> in Get-WinEvents. I had to end up deploying my solution to a Windows 2008 R2 Server and was required to write a workaround -- here it is. As always, I prefer using natively available commands, so I eschewed LogParser and used <b>wevtutil.exe</b> instead. </p>
<div class="dirtycodenoclick"><code># Grab events from the last 65 minutes<br />
[xml]$xml = (wevtutil&nbsp;&nbsp;/r:dc qe Application /e:Events)<br />
# build the sql data connection<br />
$connectionString = &quot;Data Source=SQLSERVER;Integrated Security=true;Initial Catalog=EventCollections;&quot;<br />
$bulkCopy = new-object (&quot;Data.SqlClient.SqlBulkCopy&quot;) $connectionString<br />
$bulkCopy.DestinationTableName = &quot;Events&quot;<br />
<br />#/q:&quot;*[System[TimeCreated[timediff(@SystemTime) &lt;= 3900000]]]&quot;<br />
# build the datatable<br />
$dt = New-Object &quot;System.Data.DataTable&quot;<br />
$null = $dt.Columns.Add(&quot;ID&quot;)<br />
$null = $dt.Columns.Add(&quot;LevelDisplayName&quot;)<br />
$null = $dt.Columns.Add(&quot;LogName&quot;)<br />
$null = $dt.Columns.Add(&quot;MachineName&quot;)<br />
$null = $dt.Columns.Add(&quot;Message&quot;)<br />
$null = $dt.Columns.Add(&quot;ProviderName&quot;)<br />
$null = $dt.Columns.Add(&quot;RecordID&quot;)<br />
$null = $dt.Columns.Add(&quot;TaskDisplayName&quot;)<br />
$null = $dt.Columns.Add(&quot;TimeCreated&quot;)<br />
<br /># populate data table<br />
$xml.Events.Event | ForEach-Object {<br />
&nbsp;&nbsp; $row = $dt.NewRow()&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$eventID = $_.System.EventID.&quot;#text&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!$eventID) { $eventID = $_.System.EventID }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;ID&quot;) = $eventID&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$eventlevel = $_.System.Level<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch ($eventlevel)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1 {$eventLevel = &quot;Critical&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2 {$eventLevel = &quot;Error&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3 {$eventLevel = &quot;Warning&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4 {$eventLevel = &quot;Information&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;LevelDisplayName&quot;) = $eventLevel<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;LogName&quot;) = $_.System.Channel<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;MachineName&quot;) = $_.System.Computer<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;Message&quot;) = $_.RenderingInfo.Message<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;ProviderName&quot;) = $_.System.Provider.Name<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;RecordID&quot;) = $_.System.EventRecordID<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;TaskDisplayName&quot;) = $_.RenderingInfo.Task<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row.Item(&quot;TimeCreated&quot;) =&nbsp;&nbsp;[datetime]$_.System.TimeCreated.SystemTime<br />
&nbsp;&nbsp; $dt.Rows.Add($row)<br />
}<br />
&nbsp;&nbsp;<br />
# Write to the database!<br />
$bulkCopy.WriteToServer($dt)</code></div>
<p><br/><br />
This code imports events from the last 65 minutes. For the initial import, set $xml to <b>wevtutil.exe qe ForwardedEvents /e:Events</b>. As an aside, I was surprised to see that wevtutil is FAR faster than PowerShell's Get-WinEvent, especially during the initial import of a large logs.</p>
<pre>PS C:\Scripts&gt; Measure-Command {c:\scripts\final-getwinevent.ps1}
Days&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0
Hours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0
Minutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 1
Seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 19
Milliseconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 293
Ticks&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 792930218
TotalDays&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0.00091774330787037
TotalHours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0.0220258393888889
TotalMinutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 1.32155036333333
TotalSeconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 79.2930218
TotalMilliseconds : 79293.0218

PS C:\Scripts&gt; Measure-Command {c:\scripts\final-wevtutil.ps1}
Days&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0
Hours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0
Minutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0
Seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 4
Milliseconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 957
Ticks&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 49571333
TotalDays&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 5.73742280092593E-05
TotalHours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0.00137698147222222
TotalMinutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0.0826188883333333
TotalSeconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 4.9571333
TotalMilliseconds : 4957.1333
</pre>
<p><br/><br />
From 79 seconds to 5 for 5500 records! Looks like having to rewrite this was a good thing, after all.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/9U02OZLeGIw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/04/powershell-get-winevent-bug-workaround-on-windows-2008-r2-server-importing-windows-forwarded-events-into-sql-server-using-powershell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/04/powershell-get-winevent-bug-workaround-on-windows-2008-r2-server-importing-windows-forwarded-events-into-sql-server-using-powershell/</feedburner:origLink></item>
		<item>
		<title>Quick and Dirty: Backup SQL Server Express Instances on Enterprise Networks</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/tzvfoopMEvs/</link>
		<comments>http://blog.netnerds.net/2013/04/quick-and-dirty-backup-sql-server-express-instances-on-enterprise-networks/#comments</comments>
		<pubDate>Fri, 05 Apr 2013 15:09:00 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2415</guid>
		<description><![CDATA[I know the ideal Enterprise network won't have any SQL Server Express instances, but every large network that I've ever worked on has at least a few. Many times, it's powering apps like SolarWinds or BackupExec. Since SQL Express doesn't run SQL Agent, it can be a pain to backup and maintain the systems. There [...]]]></description>
			<content:encoded><![CDATA[<p>I know the ideal Enterprise network won't have any SQL Server Express instances, but every large network that I've ever worked on has at least a few. Many times, it's powering apps like SolarWinds or BackupExec. Since SQL Express doesn't run SQL Agent, it can be a pain to backup and maintain the systems. </p>
<p>There are a lot of blog posts out there that use PowerShell or some other scheduled script to perform the backups, but it occurred to me the other day that I can totally run all of my backup and maintenance scripts from <b>another SQL Server's SQL Agent</b>. Duh! The key is to use the Connections tab to connect to other SQL instances.</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/04/sqlexpress1.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/04/sqlexpress1.png" alt="" title="sqlexpress1" width="471" height="254" class="aligncenter size-full wp-image-2423" /></a></p>
<p>I'll be honest, because these servers may come and go and their databases are unpredictable, I don't want to install anything local like <a href=http://ola.hallengren.com/>Ola Hallengren's Backup and Maintenance Scripts</a>, so I setup simple Maintenance Plans with the following parameters:</p>
<ul>
<li>I made one plan with multiple subplans.</li>
<li>Weekly: Full backup, integrity checks, index rebuild, Maintenance cleanup task (4 weeks), History cleanup task (4 weeks)</li>
<li>Daily: Differential, Maintenance cleanup task (4 weeks)</li>
<li>Staggered schedules between server backups -- I don't expect SQL Express databases to take any longer than 30 minutes, so every instance backup is scheduled 30 minutes apart.</li>
<li>The backups go to the same network share as the rest of the SQL instances which kinda look like this: \\sqlbackupserver\backups\HOSTNAME\full, \\sqlbackupserver\backups\HOSTNAME\diff.
<li>No transaction log backups are scheduled -- so far, I haven't found a SQL Express instance with databases that are set to anything but the SIMPLE recovery model.</li>
</ul>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/04/sqlexpress.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/04/sqlexpress.png" alt="" title="sqlexpress" width="497" height="383" class="aligncenter size-full wp-image-2416" /></a></p>
<p>Make sure the SQL Server Agent account has adequate access to the SQL Server Express, and that you don't check "Compress backups." Otherwise, your backups will fail with a <small><b>Backup Error: 3041, Severity: 16, State: 1</b></small> error code as SQL Express doesn't support compressed backups.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/tzvfoopMEvs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/04/quick-and-dirty-backup-sql-server-express-instances-on-enterprise-networks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/04/quick-and-dirty-backup-sql-server-express-instances-on-enterprise-networks/</feedburner:origLink></item>
		<item>
		<title>Safely Enable SQL Server Agent MultiServer Administration using PowerShell</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/9mm-m2p65dg/</link>
		<comments>http://blog.netnerds.net/2013/04/safely-enable-sql-server-agent-multiserver-administration-using-powershell/#comments</comments>
		<pubDate>Fri, 05 Apr 2013 10:40:18 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2363</guid>
		<description><![CDATA[Update: You can't even independently schedule slave jobs. Count my organization as yet another that won't be implementing MultiServer Administration. Grrr. I always forget about Multiserver Administration. I've actually never worked in an environment that uses it, even though it seems to have a lot of potential. I think one of the biggest reasons is [...]]]></description>
			<content:encoded><![CDATA[<p><b>Update: You can't even independently schedule slave jobs.</b> Count my organization as yet another that won't be implementing MultiServer Administration. Grrr.</p>
<p>I always forget about <a href=http://www.mssqltips.com/sqlservertip/2445/sql-server-multi-server-administration/>Multiserver Administration</a>. I've actually never worked in an environment that uses it, even though it seems to have a lot of potential. I think one of the biggest reasons is that most organizations do not use SSL encryption between SQL Servers, yet out of the box, Multiserver Administration requires SSL encryption for communication between the master and the targets. </p>
<p>Want to change this option? <b>You'll have to modify the registry</b>. Come on, Microsoft: nobody wants to touch a production SQL Server's registry and I think this is the biggest roadblock to mass adoption of Multiserver Administration.</p>
<p>The registry subkey that needs to be changed is <a href=http://msdn.microsoft.com/en-us/library/ms365379.aspx>MsxEncryptChannelOptions</a>. There isn't a whole lot of information about this subkey (such as what other services it impacts) but I'm hoping that since its prefixed with "Msx" that and sits in the SQLAgent key, the change will be isolated to Multiserver Administration. So here are the 3 options:</p>
<table style="border: 1px solid black;" cellpadding=1 cellspacing=1>
<tr>
<td style="border: 1px solid black;">0</td>
<td style="border: 1px solid black;" valign=top>Disables encryption between this target server and the master server. Choose this option only when the channel between the target server and master server is secured by another means.</td>
</tr>
<tr>
<td style="border: 1px solid black;">1</td>
<td valign=top style="border: 1px solid black;">Enables encryption only between this target server and the master server, but no certificate validation is required.</td>
</tr>
<tr>
<td style="border: 1px solid black;">2</td>
<td style="border: 1px solid black;" valign=top>Enables full SSL encryption and certificate validation between this target server and the master server. This setting is the default.</td>
</tr>
</table>
<p><br/></p>
<p>Like the table says, 2 (Encryption+SSL required) is the default. Most blogs I've seen change their option to 0 (No encryption), but I tested it with 1 (Encryption enabled+ SSL not required) and default out of the box SQL encryption settings and it worked. Microsoft says this about the default encryption:</p>
<blockquote><p>Credentials (in the login packet) that are transmitted when a client application connects to SQL Server are always encrypted. SQL Server will use a certificate from a trusted certification authority if available. If a trusted certificate is not installed, SQL Server will generate a self-signed certificate when the instance is started, and use the self-signed certificate to encrypt the credentials.</p></blockquote>
<p>I always prefer encryption if it's not disruptive, so this is the setting I will recommend, and the setting that is default in the script below. This script asks for the SQL Server version (SQL2k5 is not supported because I no longer use it and instance paths are more challenging.) </p>
<div class="dirtycodenoclick"><code>Write-Host &quot;***** Set SQL Agent Encryption Options on Target Servers *****`n &quot;<br />
<br /># Menu for SQL Server Version. SQL Server 2005 could work in theory, but<br />
# it&#039;s registry values are unpredictable and I didn&#039;t want to mess.<br />
<br />[int]$menuChoice = 0<br />
&nbsp;&nbsp;&nbsp;&nbsp; while ( $menuChoice -lt 1 -or $menuChoice -gt 3 ){<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;1. SQL Server 2008&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;2. SQL Server 2008 R2&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;3. SQL Server 2012&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; [Int]$menuChoice = read-host &quot;Select your SQL Server version&quot; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
Switch( $menuChoice ){<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1{$SQLVersion = &quot;10&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp; 2{$SQLVersion = &quot;10_50&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp; 3{$SQLVersion = &quot;11&quot;}<br />
default{$SQLVersion = &quot;10_50&quot;}<br />
}<br />
<br /># Enter the name of your SQL Server<br />
Write-Host &quot;Enter the hostname of SQL Server (do not include instance name)&quot;<br />
$ServerName = Read-Host &quot;If you are using a cluster, enter the individual node name&quot;<br />
$ServerName = $ServerName.ToUpper()<br />
<br /># And the instance<br />
$Instance = Read-Host &quot;Enter Instance Name (leave blank for default)&quot;<br />
if (!$Instance) {$Instance = &quot;MSSQLSERVER&quot; }<br />
$Instance = $Instance.ToUpper()<br />
<br />Write-Host &quot;`nOptions for Encryption`n&quot;<br />
[int]$menuChoice = -1<br />
&nbsp;&nbsp;&nbsp;&nbsp; while ( $menuChoice -lt 0 -or $menuChoice -gt 2 ){<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;0. Disables encryption between this target server and the master server.&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;1. Enables encryption only between this target server and the master server, but no certificate validation is required.&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-host &quot;2. Enables full SSL encryption and certificate validation between this target server and the master server. &quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; [Int]$menuChoice = read-host &quot;Select Encryption Option for SQL Agent Master/Target Communication&quot; }<br />
Switch( $menuChoice ){<br />
&nbsp;&nbsp;&nbsp;&nbsp; 0{$EncryptionOption = &quot;0&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1{$EncryptionOption = &quot;1&quot;}<br />
&nbsp;&nbsp;&nbsp;&nbsp; 2{$EncryptionOption = &quot;2&quot;}<br />
default{$EncryptionOption = &quot;1&quot;}<br />
}<br />
<br />$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(&quot;LocalMachine&quot;, $ServerName)<br />
$regKey= $reg.OpenSubKey(&quot;SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL$SQLVersion.$Instance\SQLServerAgent&quot;,$true)<br />
<br />if ($regkey -ne $null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; $oldValue = $regKey.GetValue(&quot;MsxEncryptChannelOptions&quot;)<br />
&nbsp;&nbsp;&nbsp;&nbsp; $regKey.SetValue(&quot;MsxEncryptChannelOptions&quot;,&quot;0000000$EncryptionOption&quot;,[Microsoft.Win32.RegistryValueKind]::DWORD)<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-Host &quot;Done&quot;<br />
&nbsp;&nbsp;&nbsp;&nbsp; $newValue = $regKey.GetValue(&quot;MsxEncryptChannelOptions&quot;)<br />
&nbsp;&nbsp;&nbsp;&nbsp; Write-Host &quot;Server: $Servername`nOld value: $oldValue`nNew value: $newValue&quot;<br />
} else<br />
{ &quot;No match. Make sure you typed in the proper hostname and instance name.&quot; }</code></div>
<p><br/><br />
(Thanks to <a href=http://quickclix.wordpress.com/2012/08/14/making-powershell-menus/>quickclix</a> for the easy PowerShell menu code.)</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/04/powershell.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/04/powershell.png" alt="" title="powershell" width="509" height="167" class="aligncenter size-full wp-image-2397" /></a></p>
<p>Once you've run this script and modified the settings on your Target servers, you can easily setup <a href=http://www.mssqltips.com/sqlservertip/2445/sql-server-multi-server-administration/>Multiserver Administration</a>. Note that the default setting may create a SQL Server login for the target server automatically. I uncheck that option because I'm trying to get away from local SQL Server logins and all of my SQL Agents run under the same domain account anyway.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/9mm-m2p65dg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/04/safely-enable-sql-server-agent-multiserver-administration-using-powershell/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/04/safely-enable-sql-server-agent-multiserver-administration-using-powershell/</feedburner:origLink></item>
		<item>
		<title>Importing Windows Forwarded Events into SQL Server using PowerShell</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/7E_u6Skb7T4/</link>
		<comments>http://blog.netnerds.net/2013/03/importing-windows-forwarded-events-into-sql-server-using-powershell/#comments</comments>
		<pubDate>Wed, 20 Mar 2013 16:38:46 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2306</guid>
		<description><![CDATA[Over the past couple weeks, I've looked into a number of ways of parsing and importing Windows Forwarded Events into SQL Server: from using SSIS to LogParser to PowerShell to setting up a linked server to the "Forwarding Events.evtx" file. Ultimately, the only thing that worked was PowerShell's Get-WinEvent cmdlet. And then, it only worked [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past couple weeks, I've looked into a number of ways of parsing and importing <a href=http://blog.netnerds.net/2013/03/centralizing-windows-events-using-a-collector-initiated-subscription/>Windows Forwarded Events</a> into SQL Server: from using SSIS to LogParser to PowerShell to setting up a linked server to the "Forwarding Events.evtx" file. </p>
<p>Ultimately, the only thing that worked was PowerShell's Get-WinEvent cmdlet. And then, it only worked in one specific case for me -- if the events are collected and parsed on a Windows 2012 server. As of today, there's an <a href=http://connectppe.microsoft.com/PowerShell/feedback/details/716533/get-winevent-does-not-return-the-content-of-the-event-message-in-v3-ctp2>unresolved bug</a> in Get-WinEvent that often results in NULL LevelDisplayName, Message, and TaskDisplayName columns. I copied the exact code below on a Win2k8 R2 server and a Win 8 workstation and ran into the NULLs issue repeatedly. Your results may vary, however, as some users have reported success by tweaking a few things in Win2k8 R2 Server.</p>
<p>So, fire up a Windows 2012 box, setup your SQL Server and let's get started:</p>
<h2>The SQL Part</h2>
<p>After looking at the data returned by Get-WinEvent, I found the following columns to be the most useful: ID, LevelDisplayName, LogName, MachineName, Message, ProviderName, RecordID, TaskDisplayName, TimeCreated. Then I created a table using those columns: </p>
<div class="dirtycodenoclick"><code>CREATE DATABASE EventCollections<br />
GO<br />
USE EventCollections<br />
GO<br />
&#45;- the table name loosely relates to the name of my Win Event Subscription name<br />
CREATE TABLE [dbo].[GeneralEvents](<br />
&nbsp;&nbsp;&nbsp;&nbsp; [Id] [int] NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [LevelDisplayName] [varchar](50) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [LogName] [varchar](50) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [MachineName] [varchar](255) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [Message] [varchar](max) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [ProviderName] [varchar](255) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [RecordID] [bigint] NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [TaskDisplayName] [varchar](50) NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [TimeCreated] [smalldatetime] NULL<br />
)<br />
&#45;- Create Unique Clustered Index with IGNORE_DUPE_KEY=ON to avoid duplicates in sqlbulk imports<br />
CREATE UNIQUE CLUSTERED INDEX [ClusteredIndex-EventCombo] ON [dbo].[GeneralEvents]<br />
(<br />
&nbsp;&nbsp;&nbsp;&nbsp; [RecordID] ASC,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [MachineName] ASC,<br />
&nbsp;&nbsp;&nbsp;&nbsp; [LogName] ASC<br />
) WITH (IGNORE_DUP_KEY = ON)<br />
GO<br />
</code></div>
<p><br/><br />
In order to avoid duplicates during the hourly imports, I created the table using a unique index with IGNORE_DUP_KEY = ON on 3 columns: RecordID, MachineName and LogName. </p>
<p>Next I had to decide how I'd get the data from PowerShell into SQL Server. After reading up on <a href=http://www.sqlservercentral.com/articles/powershell/65196/>sqlservercentral.com</a> and <a href="http://blogs.technet.com/b/heyscriptingguy/archive/2011/11/28/four-easy-ways-to-import-csv-files-to-sql-server-with-powershell.aspx">technet</a>, I decided on hourly imports using <b>sqlbulkcopy</b>. </p>
<h2>The PowerShell Part</h2>
<p>Forwarded Events are a tricky thing. For some reason, the way that one would usually filter Get-WinEvent results using <a href=http://theboywonder.co.uk/2012/03/15/speeding-up-get-winevent-in-powershell-by-using-filterhashtable/>FilterHasTable</a> kept returning the result <i>Get-WinEvent : No events were found that match the specified selection criteria.</i> I found a number of <a href=http://www.experts-exchange.com/Programming/Languages/Scripting/Powershell/Q_27580312.html>others</a> who ran into this issue, too and similar errors occurred when people attempted to use LogParser. After all that, I didn't have much hope in FilterXML working, but it actually did! So we're going to use that after we perform our initial import.</p>
<p>Here's the code for the <b>initial import</b> which gathers ALL events in Forwarded Events.</p>
<div class="dirtycodenoclick"><code>$events = Get-WinEvent ForwardedEvents |&nbsp;&nbsp;Select-Object ID, LevelDisplayName, LogName, MachineName, Message, ProviderName, RecordID, TaskDisplayName, TimeCreated&nbsp;&nbsp;<br />
<br />$connectionString = &quot;Data Source=sqlserver;Integrated Security=true;Initial Catalog=EventCollections;&quot;<br />
$bulkCopy = new-object (&quot;Data.SqlClient.SqlBulkCopy&quot;) $connectionString<br />
$bulkCopy.DestinationTableName = &quot;GeneralEvents&quot;<br />
$dt = New-Object &quot;System.Data.DataTable&quot;<br />
<br /># build the datatable<br />
$cols = $events | select -first 1 | get-member -MemberType NoteProperty | select -Expand Name<br />
foreach ($col in $cols)&nbsp;&nbsp;{$null = $dt.Columns.Add($col)}<br />
&nbsp;&nbsp;<br />
foreach ($event in $events)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp; $row = $dt.NewRow()<br />
&nbsp;&nbsp;&nbsp;&nbsp; foreach ($col in $cols) { $row.Item($col) = $event.$col }<br />
&nbsp;&nbsp;&nbsp;&nbsp; $dt.Rows.Add($row)<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
 # Write to the database!<br />
 $bulkCopy.WriteToServer($dt)</code></div>
<p><br/><br />
You may noticed that I manually built a datatable instead of using <a href="http://gallery.technet.microsoft.com/scriptcenter/4208a159-a52e-4b99-83d4-8048468d29dd">Out-DataTable.ps1</a>, which appears to be a fan favorite. I felt the code above kept things a little more tidy and the performance is still quite good.</p>
<p>Since Event Collection is an on-going thing, you'll likely want to import them on a regular basis. I built the necessary XML query by right clicking on Forwarded Events in Event Viewer -> Filter Current Log... -> Logged: (Change to one hour) -> Click XML tab at top -> Copy/Paste -> Voila.</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/savexml.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/savexml-300x114.png" alt="" title="savexml" width="300" height="114" class="aligncenter size-medium wp-image-2292" /></a></p>
<p>Actually, using the syntax of this query, I figured out the syntax for FilterHashTable but having the GUI build my query makes it easy, so I stuck with that. Here is the code for the <b>hourly import</b> that you can setup in Task Scheduler.</p>
<div class="dirtycodenoclick"><code># While this script is intended to run on an hourly basis, the filter is set for going back 65 minutes.<br />
# This allows the script to run for 5 minutes without any missing any events. Because we setup the<br />
# table using the IGNORE_DUPE_KEY = ON, duplicate entries are ignored in the database.<br />
<br />$xml = @&#039;<br />
&lt;QueryList&gt;<br />
&nbsp;&nbsp;&lt;Query Id=&quot;0&quot; Path=&quot;ForwardedEvents&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;Select Path=&quot;ForwardedEvents&quot;&gt;*[System[TimeCreated[timediff(@SystemTime) &amp;lt;= 3900000]]]&lt;/Select&gt;<br />
&nbsp;&nbsp;&lt;/Query&gt;<br />
&lt;/QueryList&gt;<br />
&#039;@<br />
<br />$events = Get-WinEvent -FilterXml $xml |&nbsp;&nbsp;Select-Object ID, LevelDisplayName, LogName, MachineName, Message, ProviderName, RecordID, TaskDisplayName, TimeCreated&nbsp;&nbsp;<br />
<br />$connectionString = &quot;Data Source=sqlserver;Integrated Security=true;Initial Catalog=EventCollections;&quot;<br />
$bulkCopy = new-object (&quot;Data.SqlClient.SqlBulkCopy&quot;) $connectionString<br />
$bulkCopy.DestinationTableName = &quot;GeneralEvents&quot;<br />
$dt = New-Object &quot;System.Data.DataTable&quot;<br />
<br /># build the datatable<br />
$cols = $events | select -first 1 | get-member -MemberType NoteProperty | select -Expand Name<br />
foreach ($col in $cols)&nbsp;&nbsp;{$null = $dt.Columns.Add($col)}<br />
&nbsp;&nbsp;<br />
foreach ($event in $events)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp; $row = $dt.NewRow()<br />
&nbsp;&nbsp;&nbsp;&nbsp; foreach ($col in $cols) { $row.Item($col) = $event.$col }<br />
&nbsp;&nbsp;&nbsp;&nbsp; $dt.Rows.Add($row)<br />
&nbsp;&nbsp;}</p>
<p># Write to the database!<br />
$bulkCopy.WriteToServer($dt) </code></div>
<p><br/></p>
<p>With any luck, your SQL output should look something like this:</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/sqloutput.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/sqloutput.png" alt="" title="sqloutput" width="422" height="146" class="aligncenter size-full wp-image-2354" /></a></p>
<p>Woo.</p>
<p>EDIT: If you care about speed, check out <a href=http://blog.netnerds.net/2013/04/powershell-get-winevent-bug-workaround-on-windows-2008-r2-server-importing-windows-forwarded-events-into-sql-server-using-powershell/>this post</a> where I write about using wevtutil instead of Get-WinEvent.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/7E_u6Skb7T4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/03/importing-windows-forwarded-events-into-sql-server-using-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/03/importing-windows-forwarded-events-into-sql-server-using-powershell/</feedburner:origLink></item>
		<item>
		<title>Centralizing Windows Events using a Collector Initiated Subscription</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/KCU0wCRv6sU/</link>
		<comments>http://blog.netnerds.net/2013/03/centralizing-windows-events-using-a-collector-initiated-subscription/#comments</comments>
		<pubDate>Wed, 20 Mar 2013 14:35:38 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2307</guid>
		<description><![CDATA[So it seems like the best way to go about centralizing Windows Events in an Enterprise is to use GPO, but if you can't or don't want to involve Active Directory GPOs, here's a guide on using one server to go out and collect Windows Events from other servers on your domain. Things you'll need: [...]]]></description>
			<content:encoded><![CDATA[<p>So it seems like the best way to go about centralizing Windows Events in an Enterprise is <a href=http://www.avecto.com/documents/solution-guides/EventCentralization.pdf>to use GPO</a>, but if you can't or don't want to involve Active Directory GPOs, here's a guide on using one server to go out and collect Windows Events from other servers on your domain.</p>
<p>Things you'll need: Windows Server 2012 or 2008 R2, <a href="http://www.windowsecurity.com/articles-tutorials/authentication_and_encryption/Centralized-Auditing-here-FREE.html">the appropriate ports open on your firewall if you're running one</a>, access to a Domain Admin service account or the ability to add a Machine account to a local group on each of the servers you're collecting from.</a></p>
<p>So here's how to setup a Windows 2012 or 2008 R2 Server as the Event Collection Server: first, open up Event Viewer, right click on <b>Forwarded Events</b> and click <b>Properties</b>.</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/event1.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/event1.png" alt="" title="event1" width="357" height="413" class="aligncenter size-full wp-image-2256" /></a></p>
<p>Note that Application, Security and System look a bit different than the others. I believe that's because they are considered Classic Windows Events. Classic Windows Events can be easily parsed in PowerShell using Get-EventLog and WMI's Win32_NTEventLogFile but the newer Event Types are a bit trickier. </p>
<p>The first thing you see in the Forwarded Events property tab is this:</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/logprops.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/logprops-300x267.png" alt="" title="logprops" width="300" height="267" class="aligncenter size-medium wp-image-2257" /></a></p>
<p>Note the location of the ForwardedEvents.evtx file as it may come in handy for future troubleshooting or archiving. Next, click on the "Subscriptions" tab, then <b>Create</b>. </p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/subproperties.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/subproperties-300x251.png" alt="" title="subproperties" width="300" height="251" class="aligncenter size-medium wp-image-2254" /></a></p>
<p>Now here, I will create just one generic Subscription to capture all Critical and error events. You can create multiple subscriptions for differing criteria and just send all of them to the Forwarded Events log. So select "<b>Collector Initiated</b>" and "<b>Select Computers</b>." Unfortunately, you have to add each server one by one when using the GUI. If you want to add in bulk, you'll likely have to do it using Group Policy and Source Initiation. I haven't found a way to do it in PowerShell yet.</p>
<p>Click <b>Select Events</b> and select what you'd like. My servers are super verbose, and I really only care about Criticals and Errors so I select those two Event Levels, and then By log: Application and System.</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/selectevents.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/selectevents-300x300.png" alt="" title="selectevents" width="300" height="300" class="aligncenter size-medium wp-image-2280" /></a></p>
<p>Once you're done with your Event selections, click on <b>Advanced</b> to modify the account you'd like to use as the collector (in my lab, I used a Domain Admin account). </p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/advancedsubs.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/advancedsubs-300x223.png" alt="" title="advancedsubs" width="300" height="223" class="aligncenter size-medium wp-image-2255" /></a></p>
<p>If you use a Machine account or a non-admin, you'll have to go to each of the forwarding servers and add the Computer or User AD account to <b><a href="http://allcomputers.us/windows_7/forwarding-events-(part-2)---how-to-troubleshoot-event-forwarding---how-to-configure-event-forwarding-in-workgroup-environments.aspx">Event Log Readers</a></b>. </p>
<p>Here, you can also configure the Event Delivery Optimization. I left it default for now, though later I do plan to explore delivering Events over HTTPS. Click OK until you're back at Event Viewer. Wait a few minutes and the Events should start coming in. In my experience, for each new computer I setup, I'll get one Information event from the Microsoft-Windows-EventForwarder provider. The event itself is kind of useless, saying "the description for Event 111 cannot be found." but I've learned to accept it's the Event Forwarding confirming there's a new computer in the subscription.</p>
<p>When things get going, your Windows Forwarding collection should look something like this:<br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/03/finalevent.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/finalevent-300x99.png" alt="" title="finalevent" width="300" height="99" class="aligncenter size-medium wp-image-2279" /></a></p>
<p>In this screenshot, I've highlighted Attach Task to Event which allows you to run a program or send an email when the event occurs. Pretty cool.</p>
<p>If you need additional help, Microsoft has a <a href=http://blogs.technet.com/b/wincat/archive/2008/08/11/quick-and-dirty-large-scale-eventing-for-windows.aspx>Quick and Dirty Large Scale Eventing for Windows</a> guide that is good for troubleshooting.</p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/KCU0wCRv6sU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/03/centralizing-windows-events-using-a-collector-initiated-subscription/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/03/centralizing-windows-events-using-a-collector-initiated-subscription/</feedburner:origLink></item>
		<item>
		<title>HOW-TO Setup Windows 2012 Server Core Remote Desktop Services to Securely Administer Windows over RDP and SSL</title>
		<link>http://feedproxy.google.com/~r/netnerdsnet/~3/qucZwusFg1E/</link>
		<comments>http://blog.netnerds.net/2013/03/how-to-setup-windows-2012-server-core-remote-desktop-services-to-securely-administer-windows-over-rdp-and-ssl/#comments</comments>
		<pubDate>Mon, 04 Mar 2013 20:30:06 +0000</pubDate>
		<dc:creator>Chrissy LeMaire</dc:creator>
				<category><![CDATA[IIS]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.netnerds.net/?p=2165</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>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.</p>
<p>Initially, I set up my RD Gateway using too many Remote Desktop Services: Remote Desktop Connection Broker, Remote Desktop Gateway &#038; Remote Desktop Web Access, but that was because was lead astray by Windows 2012's new GUI. Now, I've narrowed it down <i>only</i> to RD Gateway and I'm even fond of Metro (:O) </p>
<p>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.</p>
<p>During the Role installation do: Role-based or feature-based installation -> Remote Desktop Services -> Remote Desktop Gateway<br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/03/rdgateway.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/rdgateway-300x208.png" alt="" title="rdgateway" width="300" height="208" class="aligncenter size-medium wp-image-2167" /></a></p>
<p>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 <small><b>D:\sources\sxs</b></small> (assuming your ISO is attached to <b><small>D:</small></b>)</p>
<p>Click Install and wait for the installation to complete. Now it's time to configure RD Gateway. </p>
<p>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 <b><small>external FQDN</small></b>. 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.</p>
<p>Now, you'll need to configure RD Gateway. Go to Server Manager -> Tasks -> RD Gateway Manager.<br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/03/certarea.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/certarea.png" alt="" title="certarea" width="539" height="161" class="aligncenter size-full wp-image-2174" /></a></p>
<p>Click <i><small>View or modify certificate properties</small></i>. If you don't have a Domain Certificate, just click <i><small>Create and import certificate</small></i> and ensure you use your external FQDN for the certificate name. Otherwise, choose <i><small>Select an existing certificate...</small></i>. Choose your certificate</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/certselect.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/certselect.png" alt="" title="certselect" width="539" height="128" class="aligncenter size-full wp-image-2183" /></a></p>
<p>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)</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/thing.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/thing.png" alt="" title="thing" width="375" height="391" class="aligncenter size-full wp-image-2190" /></a></p>
<p>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</p>
<p>Finally, open up Services and Start Remote Desktop Gateway</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/services.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/services.png" alt="" title="services" width="509" height="103" class="aligncenter size-full wp-image-2193" /></a></p>
<p>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.</p>
<p><u>A few important things to note</u><br />
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.</p>
<p>Configuring the Remote Desktop Client is easy. Open up your Remote Desktop Client -> Advanced -> (Connect from Anywhere) Settings.<br />
<a href="http://blog.netnerds.net/wp-content/uploads/2013/03/rdp.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/rdp-287x300.png" alt="" title="rdp" width="287" height="300" class="aligncenter size-medium wp-image-2138" /></a></p>
<p>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.</p>
<p>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." </p>
<p>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)</p>
<p><a href="http://blog.netnerds.net/wp-content/uploads/2013/03/ssl.png"><img src="http://blog.netnerds.net/wp-content/uploads/2013/03/ssl.png" alt="" title="ssl" width="334" height="261" class="aligncenter size-full wp-image-2145" /></a></p>
<p>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.</p>
<p>You should now be able to connect and securely manage your network, all over SSL <img src='http://blog.netnerds.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/netnerdsnet/~4/qucZwusFg1E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.netnerds.net/2013/03/how-to-setup-windows-2012-server-core-remote-desktop-services-to-securely-administer-windows-over-rdp-and-ssl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.netnerds.net/2013/03/how-to-setup-windows-2012-server-core-remote-desktop-services-to-securely-administer-windows-over-rdp-and-ssl/</feedburner:origLink></item>
	</channel>
</rss>
