In the previous post I have described the current SharePoint 2013 environment and the steps to be taken to implement SSL and get it all back working like charm. In this second part of the series I will described how to deploy and install your certificates with PowerShell. If you have just one or 2 servers I can image the doing it all manually can be quicker then creating an script first and then use it. However, if you have lots of servers (including test, acceptance, etc,,) PowerShell scripts you’ll need.
Configuration File
I wanted to use a generic PowerShell script. All the variables are stored in a configuration file. I came up with something like this:
<configuration> <certificates> <certificate filename="AddTrustExternalCARoot.crt" name="AddTrustExternalCARoot" store="Root" /> <certificate filename="TrustedSecureCertificateAuthority5.crt" name="TrustedSecureCertificateAuthority5" store="CA" /> <certificate filename="USERTrustRSAAddTrustCA.crt" name="USERTrustRSAAddTrustCA" store="CA" /> <certificate filename="wildcard_company_com.pfx" name="Wildcard Company" store="My" password="VerySecretOfCourse" /> <certificate filename="wildcard_spapps_company_com.pfx" name="Wildcard SPApps" store="My" password="VerySecretOfCourse" /> </certificates> <servers> <server name="NL1601" certificatelocation="d$\Install\Certificates" bindings="TRUE"> <certificate name="AddTrustExternalCARoot" /> <certificate name="TrustedSecureCertificateAuthority5" /> <certificate name="USERTrustRSAAddTrustCA" /> <certificate name="Wildcard Company" /> <certificate name="Wildcard SPApps" /> </server> <server name="NL1602" certificatelocation="d$\Install\Certificates" bindings="TRUE"> <certificate name="AddTrustExternalCARoot" /> <certificate name="TrustedSecureCertificateAuthority5" /> <certificate name="USERTrustRSAAddTrustCA" /> <certificate name="Wildcard Company" /> <certificate name="Wildcard SPApps" /> </server> </servers> </configuration>
The Certificate elements describe the physical files you want the install. Although I will use the latter two for my SharePoint sites and Add-ins, the certificate must be valid all the way up in the chain. Therefor I also deploy the root certificate authority.
The Server elements describe the servers where the certificates will be deployed to. The attribute certificateLocation describes the location where the files are copied to. For each server element I configure which certificates I want to deploy and install.
Deployment Script
I will provide the complete script, but for the sake of readability I will describe the nifty bits.
First I am copying the files to all servers:
[xml]$config = Get-Content Deploy-Certificates.config $config.Configuration.Servers.Server | % { $server = $_ $serverName = $_.name Write-Host Write-Host -f Cyan Server: $servername # Create destination folder if not exists $destination = "\\$($serverName)\" + $server.certificateLocation Write-Host Ensuring install folder $destination... -NoNewline if(-not(Test-Path -path $destination)) { $f = New-Item $destination -Type Directory -Force } Write-Host -f Green " [Done]" # Copy certificate files to destination folder Write-Host Copying certificate files... -NoNewline $server.Certificate | % { $certificateName = $_.Name $certificate = $config.Configuration.Certificates.Certificate | ? { $_.name -eq $certificateName } $certificateFile = $certificate.fileName $f = Copy-Item -Path "$currentScriptLocation\Certificates\$certificateFile" -Destination $destination } Write-Host -f Green " [Done]" }
Secondly I open a remote PowerShell session to that server. Within this session I will install the certificates into “local” certificate stores.
# Install each certificate $session = New-PsSession –ComputerName $serverName Write-Host -f White Installing certificates... $server.Certificate | % { $certificateName = $_.Name Write-Host `t$certificateName -NoNewline $certificate = $config.Configuration.Certificates.Certificate | ? { $_.name -eq $certificateName } $certificateFile = $certificate.fileName $certificatePassword = $certificate.password $certificateStore = "cert:\LocalMachine\" + $certificate.store $certificateLocation = $server.certificateLocation.Replace("$", ":") $localCertificateFile = $certificateLocation + "\" + $certificateFile if( $certificateFile.EndsWith(".crt")) { Invoke-Command -Session $session -ScriptBlock { param( $localCertificateFile, $certificateStore) $crt = Import-Certificate -FilePath $localCertificateFile -CertStoreLocation $certificateStore -Confirm:$false } -ArgumentList $localCertificateFile, $certificateStore } else { Invoke-Command -Session $session -ScriptBlock { param( $localCertificateFile, $certificateStore, $certificatePassword) $securePwd = ConvertTo-SecureString -String $certificatePassword -Force –AsPlainText $pfx = Import-PfxCertificate -FilePath $localCertificateFile -CertStoreLocation $certificateStore -Exportable:$true -Password $securePwd -Confirm:$false } -ArgumentList $localCertificateFile, $certificateStore, $certificatePassword } Write-Host -f Green " [Done]" }
In this script I use 2 interesting cmdlets, Import-Certificate and Import-PfxCertificate. Both are part of the module PKIClient, which is default available for Windows Server 2012 R2 systems.
With the Invoke-Command I use the session object to call the Import-Certificate cmdlets and the ArgumentList to pass any variables to the ScriptBlock.
How do you know what the PowerShell notation is for the correct Certificate Store? Well, I used the following cmdlets:
This gives you all certificate stores on the local machine.
Running the complete script
Create a folder to store your script and configuration file. Collect all your certificates and store them in the subfolder Certificates.
Start a PowerShell session, go to the folder where the script is and run it.
NOTE: You must be a local administrator on all the servers and Remote PowerShell must be enabled.
In next part I will describe how to change the SharePoint Web Applications to use SSL and HTTPS.
[Update: you can download the complete script here]
Originally posted at