Thursday, June 23, 2011

Programmatically Install X509 Certificates And Set Permissions

Using X509 certificates to secure WCF services doesn't take long to setup in a Windows 2008 R2 environment, but is rather user intensive and provides numerous opportunities for error. Below is a script that installs a certificate to the Personal store of the local computer and grants full access to the specified users. This saves time deploying across multiple environments and streamlines the setup for users who don't have experience with certificates.
param
(
	[switch] $Verbose
)

if ($Verbose)
{
    $VerbosePreference = 'Continue'
}

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Security")
$StoreScope = "LocalMachine";
$StoreName = "My";
if (Test-Path "cert:\$StoreScope\$StoreName")
{
	$certfile = Get-Item ".\ServiceX509.pfx";
	$certfile.FullName;

	$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $certfile.FullName,$null;

	try
	{
		$store = New-Object System.Security.Cryptography.X509Certificates.X509Store $StoreName, $StoreScope;
		$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
		$store.Add($cert)
		$store.Close()
		Write-Verbose "Successfully added '$certfile' to 'cert:\$StoreScope\$StoreName'."
		$keyPath = $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
		$folderlocation = gc env:ALLUSERSPROFILE 
		$folderlocation = $folderlocation + "\Microsoft\Crypto\RSA\MachineKeys\"  
		$filelocation = $folderlocation + $keyPath 
		("NETWORK SERVICE", "domain\AppPoolSvc") | % { 
			icacls $filelocation /grant "$($_):(F)";
			Write-Verbose "Successfully granted '$_' to '$($cert.FriendlyName)'.";
		}
	}
	catch
	{
		Write-Error ("Error adding '$certfile' to 'cert:\$StoreScope\$StoreName': $_ .") -ErrorAction:Continue
	}
}