Hi there! PowerShell Crypto Guy is again here!

Today I've finished SetupCA.ps1 script testing and I'm ready to share it with you. Of course this is not the first attempt to install CA role from cmdline, there is already SetupCA.vbs script written by Windows PKI team. To be honest, this is not the first PowerShell script for CA installation from cmdline. The first attempt was made by Hasain Alshakarti — http://secadmins.com/?dl_id=3. However this script just illustrates basic API functionality with ability to specify CA name, CA certificate validity and CA type. There is no error handling at all, even whether the CA can be installed on the computer.

My script is primarily intended for automated CA installation and as the only way to install CA service on Server Core installations, because there is no server manager UI. I will not post the script here, but attach as a file (there are 346 lines of PowerShell code).

Abstract

At first I want to compare my script — SetupCA.ps1 and Microsoft's SetupCA.vbs. The advantages of my script:

  • Much less code (but who cares?);
  • The code uses the most efficient APIs (unlike SetupCA.vbs that actively uses some hand-routines, instead of using available APIs);
  • Unlike original CASetup.vbs, PowerShell implementation can setup root CA with custom validity (by default 5 years);
  • User-friendly and unified syntax. Most parameters are self-explanatory;
  • The script has improved error handling with detailed (as possible) error messages;
  • It works really faster than VBS;

The disadvantages:

  • Requires PowerShell 2.0 (not installed by default on Windows Server 2008/2008 R2 Server Core installations);
  • Is published after SetupCA.vbs and has no chances to become so popular as existing VBS script.

But in any way, for PS guys this might be preferred, because PS really rocks!

Script parameters

The script shares 3 parametersets for CA installation:

  1. NewKeySet — to generate new public/private key pair. All parameters within this parameter set are optional;
  2. PFXKeySet — this parameterset is commonly used for CA failover cluster installations. During setup you specify only path to a PFX file and password.
  3. ExistingKeySet — is similar to previous. During installation you specify CA certificate thumbprint. CA certificate must be already installed in system certificate store.

Install CA with new keys

The following parameters can be used:

  • CAName (optional)

This parameter specifies custom CA certificate name/subject (what you see in the certificate display UI). If not passed, a '<ComputerName>-CA' form is used for workgroup CAs and '<DomainName>-<ComputerName-CA>' form is used for domain CAs. The parameter supports Unicode names.

  • CADNSuffix (optional)

This parameter specifies DN suffix to specify some additional information. For example, company name, country, city, etc. DN suffix is empty for workgroup CAs and includes current domain distinguished name (for example, DC=domain,DC=com). The parameter accepts suffixes in a X500 form, for example: OU=Information Systems, O=Sysadmins LV, C=LV.

  • CAType (optional)

Specifies CA type — Standalone Root, Standalone Subordinate, Enterprise Root, Enterprise Subordinate. If not passed, for non-domain environments or if you don't have Enterprise Admins rights, Standalone Root is used. If you have Enterprise Admins rights and your forest already has installed CAs, Enterprise Subordinate is used. If no Enterprise CAs installed in the forest, Enterprise Root is used.

  • ParentCA (optional)

This parameter allows you to specify parent CA location only if you install Enterprise Subordinate CA. For other CA types, the parameter is ignored. Parent CA information must be passed in the following form: CAComputerName\CASanitizedName. Sanitized name is a sanitized form of CA name (subject). Mostly sanitized name is the same as CA name (unless you use Unicode and/or special characters, that are disallowed in X500). If the parameter is not specified, a certificate request will be generated on the root of system drive. I've decided to not implement this parameter for Standalone Subordinate CAs, because mostly they are installed in a workgroup environments and direct request submission to other CAs is likely unavailable (due of computer authentication complexity in non-domain environments). However, if you need it — contact me.

  • CSP (optional)

Specifies custom cryptographic service provider. By default 'RSA#Microsoft Software Key Storage Provider' is used (in most cases you will use default CSP). You need to explicitly specify custom CSP only when you setup completely CNG authority (CSPs with ECDSA prefix) or you use HSM. Each HSM uses it's own custom CSP. You must install HSM middleware before CA installation.

The full list of supportable and available "by default" CSP for Windows Server 2008+ is:

Microsoft Base Cryptographic Provider v1.0
Microsoft Base DSS Cryptographic Provider
Microsoft Base Smart Card Crypto Provider
Microsoft Enhanced Cryptographic Provider v1.0
Microsoft Strong Cryptographic Provider
RSA#Microsoft Software Key Storage Provider
DSA#Microsoft Software Key Storage Provider
ECDSA_P256#Microsoft Software Key Storage Provider
ECDSA_P384#Microsoft Software Key Storage Provider
ECDSA_P521#Microsoft Software Key Storage Provider
RSA#Microsoft Smart Card Key Storage Provider
ECDSA_P256#Microsoft Smart Card Key Storage Provider
ECDSA_P384#Microsoft Smart Card Key Storage Provider
ECDSA_P521#Microsoft Smart Card Key Storage Provider
  • KeyLength (optional)

This parameter specifies key length. If not specified, a 2048-bit key will be generated. There is a little trick: if you look to a CSP list (above), you will see that key length is specified for each ECDSA* provider. I've developed a script logic in that way, so the script ignores this parameter if one of ECDSA* CSP is explicitly chosen and uses key length that is supported by the CSP. Therefore you will not receive an error if you select 'ECDSA_P256#Microsoft Smart Card Key Storage Provider' CSP with 2048 key length. 256-bit key will be selected automatically.

  • HashAlgorithm (optional)

This parameter specifies hash algorithm that will be used for CA certificate/request hashing. Note that this is important for root CA installations. Subordinate CA certificates are hashed and signed by the parent CA with it's own settings. By default 'SHA1' is used (though this parameter is applicable for all CA installation types).

  • ValidForYears (optional)

Specifies the validity for root CA installations. By default root CA certificates are valid for 5 years. You can increase this value to 10, 20, 50, whatever you need. For any subordinate CA types this parameter is silently ignored. This is because subordinate CA validity is determined by the parent CA. This parameter accepts integer values, assuming that the value is specified in years.

  • RequestFileName (optional)

If you setup any sort of subordinate (not root) CAs you can specify custom path to a request file. By default request file is generated on the root of system drive.

Install CA and specify PFX for input information

As said, this setup type commonly is used when you setup additional failover cluster nodes or you restore CA from backup. If you specify PFX file, it is used as input information to properly setup Certification Authority. Therefore there are only 2 mandatory parameters:

  • CACertFile (mandatory)

Specifies the path to a PFX file with CA certificate. Relative paths are allowed. Setup API performs additional checks for the certificate. Therefore you must ensure if: this is CA certificate (but not EFS encryption ;)), CA certificate is trusted (for non-root certificates) and chains to trusted CA and CA certificate revocation checking can be performed. Otherwise you will unable to setup CA with that CA certificate.

  • Password (mandatory)

Specifies the password to open PFX file. The parameter supports only securestrings! You can't type a password as a simple text. This is made for security reasons. There are few ways to pass a password in a securestring form:

$Password = Read-Host –a

or

ConvertTo-SecureString <plaintext> –a –f

You can enclose last command in parentheses and pass directly as a parameter value.

Install CA and specify already installed certificate

This method differs with previous only by the place where the CA certificate is stored — in an external PFX file or already installed to the system store. Since it is already installed, the only parameter you need to specify is:

  • Thumbprint (mandatory)

this parameter specifies a thumbprint of the certificate to use. The certificate must be installed in Local Machine\Personal store and must be trusted (for non-root certificates) and must not be revoked (the issuer revocation information must be available).

Common parameters

The script uses some additional parameters that can be specified for any CA installation scenario:

  • DBDirectory (optional)

Specifies the path to a folder to store CA database. If not specified, the default path: %windir%\System32\CertLog folder is used. If you need to specify custom path (for example, shared storage for CA clusters), you need to specify the next parameter too. The path must be valid.

  • LogDirectory (optional)

Specifies the path to a folderto store CA database log files. By default %windir%\System32\CertLog folder is used. If you use custom path for either database or log folders, you must explicitly specify both paths. Probably I'll change this behavior in next versions.

  • OverwriteExisting (optional)

Specifies, whether to overwrite any existing database files in the specified directories.

  • AllowCSPInteraction (optional)

Specifies, whether the cryptographic service provider (CSP) is allowed to interact with the desktop. This parameter should be used only if you use custom hardware-based CSP (HSM or smart card CSP). In other cases you don't need to allow CSP interactions.

  • Force (optional)

By default, the script explicitly prompts you whether you want to install Certification Authority with selected values. If you want to implement silent (quiet) installations — specify this parameter to suppress any prompts during role installation.

Script installation

To install the script (expose included commands) you do either:

  • copy file contents to a console. Not very good choice :)
  • dot-source the script.

To dot-source the script you must type dot, space and path to a script file:

. c:\temp\setupca.ps1

and all commands from the file will be exposed to the PowerShell session and can be used like other native commands.

Examples

To simplify script usage, I'll provide some common examples.

To install offline Root CA you can do something like this:

  • Example 1
Install-CertificationAuthority -CAName "My Root CA" -CADNSuffix "OU=Information Systems, O=Sysadmins LV, C=LV" `
-CAType "Standalone Root" -ValidForYears 10

In this scenario you setup new Standalone Root CA with "CN=My Root CA, OU=Information Systems, O=Sysadmins LV, C=LV" subject, that will be valid for 10 years. The CA will use default paths to CA database and log files and certificate will use 'RSA#Microsoft Software Key Storage Provider' CSP with 2048-bit key and SHA1 hashing algorithm.

  • Example 2
Install-CertificationAuthority -CAName "My Root CA" -CADNSuffix "OU=Information Systems, O=Sysadmins LV, C=LV" `
-CAType "Standalone Root" -ValidForYears 20 -CSP "ECDSA_P256#Microsoft Smart Card Key Storage Provider" `
-HashAlgorithm SHA512

This example is similar to previous, with the exception that this CA will be completely CNG/SHA2 root. CA certificate will use CNG (not RSA) keys and hashing algorithm will be SHA512.

  • Example 3
Install-CertificationAuthority -CAName "Clustered CA" -CADNSuffix "OU=Information Systems, O=Sysadmins LV, C=LV" `
-CAType "Enterprise Subordinate" -KeyLength 4096 -DBDirectory "S:\CertDB" -LogDirectory "S:\CertLog" `
-RequestFileName "S:\Clustered CA.req"

This example assumes that you setup CA cluster first node (but not necessary). CA database will be stored on a shared storage (attached with S: drive letter). CA certificate will use default 'RSA#Microsoft Software Key Storage Provider' with 4096-bit key and default SHA1 hashing algorithm. CA certificate validity will be determined by the parent CA. In addition, CA certificate request will be stored on the shared storage.

  • Example 4
$Password = Read-Host -AsSecureString
Install-CertificationAuthority -CACertFile .\ClusteredCA.pfx -Password $Password `
-DBDirectory "S:\CertDB" -LogDirectory "S:\CertLog" -OverwriteExisting

This is two-line example. Say, you have successfully installed CA cluster first node and have exported CA certificate to a PFX, and moved it to the second node (to the current directory). At first you will be prompted for a password. Since you type password to a securestring prompt, no characters will be displayed. After that you will specify relative path to a PFX file and specify shared storage to store CA database and log files. You overwrite database files that was created during first node installation. Actually this command installs CA cluster second node.

  • Example 5
Install-CertificationAuthority -CAName "Company Enterprise CA-2" -CADNSuffix "O=Company, E=companypky@company.com" `
-CAType "Enterprise Subordinate" -ParentCA "ca01.company.com\Company Enterprise CA-1"

From best-practices perspective this is not a very good example, because it assumes at least 2 tiers of Enterprise CAs. However, it is still common. In a given example, Enterprise Subordinate CA will be installed and certificate request will be sent directly to existing Enterprise CA — 'Company Enterprise CA-1' that is hosted on 'ca01.company.com'. Note that existing CA must be online and must issue 'Subordinate Certification Authority' template.

Uninstall Certification Authority

The script provides an ability to uninstall CA role from the server. CA removal command consist of two optional parameters (switches):

  • AutoRestart (optional)

Automatically restarts computer to complete CA role removal. Otherwise you will have to restart the server manually.

  • Force (optional)

By default, the commands prompts you whether you want to remove CA role. Use –Force switch to suppress all prompts.

The syntax is very simple:

Uninstall-CertificationAuthority -AutoRestart -Force

The command will uninstall CA role, suppresses all prompts and automatically restarts the server upon completion.

And the last use this button to download the script:


Share this article:

Comments:

Felix Leven

Hi, I used yout script to deploy some offline/online CA's and it worked very well THX. I also want to share my experience with the users on expert exchange, but I need to ask about two errors I experienced first. 1. I used the script for an offline CA VM (no NIC) and was not able to run it. No Problems after adding a virtual NIC to the VM (not connected), but still confusing. 2. I deploy HashAlgorithm SH2 512 + default crypto provider by default and always get an error/warning (the error is connected to the GetHashAlgorithmList, not finding provider/Hast match). CA was up and running in the end, but still confusing. I hope you can clear things up and I can write some lines about your nice work.

Vadims Podans

1) I don't know what to tell you. Is there any error or any output? Never expereinced this issue. 2) If you specify custom key length or hash algorithm, you need to explicitly specify CSP. This is a bug.

Felix Leven

Yes, the script end's after installing servermanager, telling you that there is no networkconnection it can check. Id a NIC is installed, even in "not connected" state it works.

Pete Smith

Thank you for at great script. These days I'm trying to use this for installing multiple enterprise subordinate servers - using PS-Session / WinRM / Powershell remoting or whatever you wanna call it :) The script works fine when sitting at the console and running the script, but when I do this using Invoke-Command, I receive an error: Selected CA type: 'Enterprise subordinate' is not supported by current Windows Server installation. The following CA types are supported by this installation: Standalone Root, Standalone Subordinate... I'm using WS 2008 R2 SP1 Enterprise only in this environment. Do you know why the behaviour changes in a remote session? This is what I do: $blk_remote = { param($CAName,$CADNSuffix,$RenewalValidityPeriodUnits,$HashAlgorithm,$RenewalKeyLength,$DBDirectory,$LogDirectory,$CSP,$RequestFileName) function Install-CertificationAuthority { } Install-CertificationAuthority -CAName "$CAName" -CADNSuffix "$CADNSuffix" -CAType 'Enterprise Subordinate' -ValidForYears $RenewalValidityPeriodUnits -HashAlgorithm $HashAlgorithm -KeyLength $RenewalKeyLength -DBDirectory "$DBDirectory" -LogDirectory "$LogDirectory" -CSP "$CSP" -RequestFileName "$RequestFileName" -Force } $CAName = "My Remote SubCA 1" $CADNSuffix = "OU=JXYZ,O=Wizard,C=My Company" $RenewalValidityPeriodUnits = 5 $HashAlgorithm = "SHA1" $RenewalKeyLength = 2048 $DBDirectory = "c:\CA_DB" $LogDirectory = "c:\CA_Logs" $CSP = "RSA#Microsoft Software Key Storage Provider" $str_RequestFileName = "c:\SubCA-request.req" $session = New-PSSession -computername "2k8r2-ca1" invoke-command -session $session -scriptblock $blk_remote -argumentlist $CAName,$CADNSuffix,$RenewalValidityPeriodUnits,$HashAlgorithm,$RenewalKeyLength,$DBDirectory,$LogDirectory,$CSP,$str_RequestFileName Remove-PSSession -session $session Any help would be much appreciated, thanx!

Jakob Heidelberg

Thank you for pointing us in the right direction (by email). If anybody else should run into the same issue, the solution is to configure and use CredSSP! Example: $Cred = Get-Credential $Session = New-PSSession -computername "srv1" -authentication CredSSP -credential $Cred Or just: $Cred = Get-Credential Invoke-Command -computername "srv1" -authentication CredSSP -credential $Cred -scriptblock {"helo"} More info on CredSSP configuration here: http://msdn.microsoft.com/en-us/library/ee309365(v=vs.85).aspx http://blogs.msdn.com/b/powershell/archive/2008/06/05/credssp-for-second-hop-remoting-part-i-domain-account.aspx Thank you again!

Mathieu

Hello! We are using this script to implement CA certificats in our organisation. Everything is working just fine exept, we can not navigate to the CertSrv web page in IIS if we install throw the script. This is functionnal if we install the certificat manualy. We get a HTTP 500 internal server error. Has anyone else seen this problem? we are using the following command : Install-CertificationAuthority -CAName "CA-TECHNO" -CADNSuffix "DC=TECHNO,DC=gov" -CAType "Enterprise Root" -KeyLength 2048 -ValidForYears 10 -CSP "RSA#Microsoft Software Key Storage Provider" ` -HashAlgorithm SHA1 -LogDirectory "D:\Donne\CertLog" -DBDirectory "D:\Donne\CertLog" -force can anyone help us?

Vadims Podans

This version do not support web enrollment pages installation.

SecInfo

Does the script work on W2012R2?

Vadims Podans

Yes, it does support. However, starting with Windows Server 2012 you may consider to use built-in Install-AdcsCertificateAuthority cmdlet.

Daniel Mikes

Does line 60 deliberately have an empty catch?

Daniel Mikes

Is it possible to configure AIA en CDP with this script or to add this functionality?

Or must one use certutil to do that?

Daniel Mikes

Would you also recommend using the built-in Install-AdcsCertificateAuthority cmdlet when creating RootCA with existing KeySet from Utimaco HSM?

Daniel Mikes

Can one use this script to reinstall a RootCA from backup?

Vadims Podāns

I would recommend to use built-in Install-AdcsCertificateAuthority cmdlet. This script was developed when Microsoft did not have its own implementation. Now, this script provides no advantage over Microsoft's implementation. In fact, they are equal. If you are on Windows Server 2016+, you should use Microsoft built-in cmdlet.

Vadims Podāns

The line #60 deliberately has empty catch clause.


Post your comment:

Please, solve this little equation and enter result below. Captcha