6

In my environment we host a whole lot of websites and WCF webservices in IIS (on Windows 2008 R2 and Windows 2012).

We are in the process of enabling HTTPS on these sites. This goes as follows:

  • Create a domain signed *.environment.domain certificate in IIS, using the Active Directory Certificate Authority that is available in our network.
  • Enable HTTPS on the sites, by changing the site bindings and applying the generated certificate.

Given the number of machines and sites, we would like to automate the required actions. I can apply the correct site bindings to the sites during deployment, but I have not found a solution for creating and installing a domain signed certificate in IIS yet.

I have already found out how to do this manually, using the 'Server Certificates' icon in IIS, and invoking the 'Create Domain Certificate' action there. I can supply the correct credentials, and when I specify the Certificate Authority I can create the desired certificates.

I also found that you can view wich certificates are installed in the machine using the cert:\ PowerShell drive:

cert:\LocalMachine\My> Get-ChildItem

And I have found that on Windows Server 2012 there is a New-SelfSignedCertificate PowerShell CmdLet available.

However, I cannot seem to find the required PowerShell commandos to combine all these actions on Windwos Server 2008 R2.

How do I create and install a domain signed SSL certificate in IIS, using PowerShell?

kasperd
  • 31,086
oɔɯǝɹ
  • 461

1 Answers1

6

Try the following:

function New-DomainSignedCertificate {
    [CmdletBinding()]
    param(
        [parameter(Mandatory=$true)]
        [string]
        $Hostname,

        [parameter(Mandatory=$true)]
        [string]
        $Organization,

        [parameter(Mandatory=$true)]
        [string]
        $OrganizationalUnit,

        [parameter(Mandatory=$true)]
        [string]
        $Locality,

        [parameter(Mandatory=$true)]
        [string]
        $State,

        [parameter(Mandatory=$true)]
        [string]
        $Country,

        [parameter(Mandatory=$true)]
        [string]
        $CertificateAuthority,

        [parameter(Mandatory=$false)]
        [string]
        $Keylength = "2048",

        [string]
        $workdir = $env:Temp
    )

    $fileBaseName = $Hostname -replace "\.", "_" 
    $fileBaseName = $fileBaseName -replace "\*", ""

    $infFile = $workdir + "\" + $fileBaseName + ".inf"
    $requestFile = $workdir + "\" + $fileBaseName + ".req"
    $CertFileOut = $workdir + "\" + $fileBaseName + ".cer"

    Try {
        Write-Verbose "Creating the certificate request information file ..."
        $inf = @"
[Version] 
Signature="`$Windows NT`$"

[NewRequest]
Subject = "CN=$Hostname, OU=$OrganizationalUnit, O=$Organization, L=$Locality, S=$State, C=$Country"
KeySpec = 1
KeyLength = $Keylength
Exportable = TRUE
FriendlyName = "$Hostname"
MachineKeySet = TRUE
SMIME = False
PrivateKeyArchive = FALSE
UserProtected = FALSE
UseExistingKeySet = FALSE
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
KeyUsage = 0xa0

[Extensions]
2.5.29.17 = "{text}"
_continue_ = "dns=$Hostname&"
"@

        $inf | Set-Content -Path $infFile

        Write-Verbose "Creating the certificate request ..."
        & certreq.exe -new "$infFile" "$requestFile"

        Write-Verbose "Submitting the certificate request to the certificate authority ..."
        & certreq.exe -submit -config "$CertificateAuthority" -attrib "CertificateTemplate:WebServer" "$requestFile" "$CertFileOut"

        if (Test-Path "$CertFileOut") {
            Write-Verbose "Installing the generated certificate ..."
            & certreq.exe -accept "$CertFileOut"
        }

    }
    Finally {
        Get-ChildItem "$workdir\$fileBaseName.*" | remove-item
    }
}

It basically just uses certreg.exe rather than native PowerShell cmdlets, (I'm not sure they exists, and if they do, there are usually not on older OSes).

The request details are in the here string, fix the subject and other settings if you need to. You may want to move more values up into the parameters section.

I create an inf file for the new request and convert it into a request file.

Then I submit the request to the CA specified in $CAName, if the executing user is a domain admin, the request is issued right away.

Finally I complete the request with -accept and do some cleanup.

I usually also export the new certificate into a PFX file.

for the IIS binding and certificate assignment you can use something like this:

 New-WebBinding -Name www.test.local   -Port 443 -Protocol https
 $thumb = (Get-ChildItem cert:\LocalMachine\MY | where-object { $_.FriendlyName -like "www.test.local" } | Select-Object -First 1).Thumbprint
 $guid = [guid]::NewGuid()
 & netsh http add sslcert hostnameport=www.test.local:443 certhash=$thumb appid=`{$guid`} certstorename=MY
Mike
  • 1,303