In Windows Server 2012, if you implement Certificate Enrollment Web Services to target an Issuing certification authority (CA) that has spaces in the name, some additional configuration is required:
  1. You must modify the URI in the Application Settings for the Certificate Enrollment Web Services virtual application.
  2. You must modify the value set for the msPKI-Enrollment-Servers of the Issuing CA(s).

Warning: If you do not perform these additional steps, then your certificate clients will receive the following error message when they attempt to enroll for a certificate using Certificate Enrollment Web Services: The endpoint address URL is invalid


Modify Application Settings

To modify the URI in the Application Settings for Certificate Enrollment Web Services virtual application
1.    Ensure that you are connected to the computer running the Certificate Enrollment Web Service server role.
2.    From Server Manager, click Tools, and then click the Internet Information Services (IIS) Manager.
3.    In the Connections pane, expand the web site that you want to manage.
Note: If you see an Internet Information Services (IIS) Manager message that asks if you want to get started with Microsoft Web Platform, click Cancel.
4.    Expand Sites, and then expand the Default Web Site.
5.    Click the virtual application that corresponds to the Certificate Enrollment Web Service that you are running.
6.    In the center pane, double-click Application Settings.
7.    In Application Settings, double-click URI.
8.    In Edit Application Settings, under Value, enter %20 for every space in the uniform resource identifier value.
9.    Once you have a URI value that where all spaces have been replaced with %20, click OK.



Tip: You can accomplish the same thing using the command line with appcmd for IIS
  1. Open a Command Prompt or Windows PowerShell as an administrator on the computer that is running the Certificate Enrollment Web Services.
  2. Change to the %systemroot%\system32\inetsrv directory, so you can use the appcmd utility.
  3. Run the command appcmd list apps to see a list of applications running on the computer. Identify the Certificate Enrollment Web Services application that you want to modify. This application should have CES in the APP name and is typically running in the applicationPool:WSEnrollmentServer.
  4. Run the command appcmd list config "Default Web Site/<appname>" /section:appsettings. Replace the <appname> with the name of the Certificate Enrollment Web Services application that you identified in the previous step.
  5. Run the command appcmd config "Default Web Site/<appname>" /section:appsettings /"[key='URI'.value:"<newURI>". Replace <appname> with the application name you identified in step 3. Replace <newURI> with the same URI that you saw in Step 4, except for each space in the URI, replace it with %20. See the following figure for an example of these commands.
  6. Restart the IIS server (iisreset).




Modify Application Settings by using Windows PowerShell

The Windows PowerShell script in this section performs the following tasks:

  1. Connects IIS server and retrieves all Certificate Enrollment Web Services applications (regardless of in which web site they are installed);
  2. Retrieves original Certificate Enrollment Web Services URL and encodes it properly, as needed.
  3. Writes the properly encoded URL to the IIS virtual application.
  4. Saves the changes and then restarts IIS service to apply the changes.

Note: You may have to modify your Windows PowerShell executionpolicy implementation to run the script and you will have to be a local IIS Administrator. You can copy and paste the following script into a file PS1 file. Ensure that you run it from an elevated Windows PowerShell prompt.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
# import required assemblies and modules
Add-Type -AssemblyName System.Web
Import-Module WebAdministration
# retrieve Certificate Enrollment Service applications on the server
$Apps = Get-WebApplication | Where-Object {$_.physicalpath.StartsWith("$($env:windir)\SystemData\CES")}
if (!$Apps) {return}
# loop over each CES app
foreach ($app in $Apps) {
    # retrieve application settings
    $webConfigStore = [Web.Configuration.WebConfigurationManager]::OpenWebConfiguration($app.path)
    # retrieve CES URL
    $url = $webConfigStore.AppSettings.Settings["uri"].Value
    if (!$url) {return}
    # encode and write back new URL to application settings
    $webConfigStore.AppSettings.Settings["uri"].Value = [web.httputility]::UrlPathEncode($url)
    # save changes in IIS
    $webConfigStore.Save("Modified")
}
# restart IIS service
iisreset

Modify the msPKI-Enrollment-Servers value in Active Directory Domain Services

To modify the msPKI-EnrollmentServices value in the Configuration container of Active Directory Domain Services (AD DS) you can use the Certutil command.
  1. Ensure that the account you are using has the ability to modify the ms-PKIEnrollmentServices value in the Configuration container of AD DS. A member of the Enterprise Admins group has this permission by default.
  2. Open a Windows PowerShell prompt or Command Prompt as administrator on the computer running Certificate Enrollment Web Services.
  3. Run a Certutil command with the following syntax: Certutil -config "<configurationofCA>" -enrollmentserverUrl "<URIname> delete. For example, if your Issuing CA configuration is "MT-CA1.margiestravel.com\MT Issuing CA" and the enrollment server URI that you are trying to replace is https://MT-CES.margies.travel.com/MT Issuing CA_CES_UsernamePassword/service.svc/CES, then you would run the following command: Certutil -config " MT-CA1.margiestravel.com\MT Issuing CA" -enrollmentserverUrl " https://MT-CES.margies.travel.com/MT Issuing CA_CES_UsernamePassword/service.svc/CES" delete
    • Note: You can determine the config of the CA by running the Certutil command without any parameters at the command prompt.
  4. Next, you must set the enrollment server URI that you want to use, along with the authentication type and priority. You can learn more about the actual command by running Certutil -enrollmentserverurl /?. For example, if you wanted to replace the previously removed URI with one that included the %20 for the spaces in the name and utilize Username authentication, the command you would run is: certutil -config "MT-CA1.margiestravel.com\MT Issuing CA" -enrollmentserverUrl https://MT-CES.margiestravel.com/MT%20Issuing%20CA_CES_UsernamePassword/service.svc/CES Username 1

Modify the msPKI-Enrollment-Servers value in by using Windows PowerShell

 The script in this section performs the following:

  1. Connects to the directory and retrieves Certificate Enrollment Web Service URLs
  2. Encodes each properly, as needed.
  3. Writes the encoded URLs back to the directory.

The advantages of this script (compare to the previous solution that uses certutil.exe tool) are:
a) Do not require manual CA name typing. The script automatically checks all CES URLs in Active Directory;
b) do not require manual character replacement. URLs are encoded automatically;
c) keeps URL parameters (priority, authentication, renewal settings) without a change. A caller is not required to update them manually;
d) handles all additional special characters (not only space character) that require additional encoding.

Note: You may have to modify your Windows PowerShell executionpolicy implementation to run the script and you will have to be running the script as a member of Enterprise Admins (or have the necessary permissions to write to the Active Directory Configuration container). You can copy and paste the following script into a file PS1 file. Ensure that you run it from an elevated Windows PowerShell prompt.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
Add-Type -AssemblyName System.Web
# Connect to Enrollment Services container in configuration naming context
$RootDSE = [ADSI]"LDAP://RootDSE"
$ConfigContext = "CN=Enrollment Services,CN=Public Key Services,CN=Services," + $RootDSE.configurationNamingContext
$adsi = [ADSI]"LDAP://$ConfigContext"
$adsi.psbase.Children | ForEach-Object {
    if (!$_) {return}
    # prepare an array for new (fixed) URLs
    $entries = @()
    # enumerate all CES URLs for the current CA server
    $_."msPKI-Enrollment-Servers" | ForEach-Object {
        if (!$_) {return}
        # retrieve priority, authentication and renewal settings. They are not changed.
        $priority = $_[0].ToString()
        $authentication = $_[2].ToString()
        $RenewalOnly = $_[4].ToString()
        # extract current URL. We use regexp to grab only required part
        if ($_ -match "https.+service\.svc/CES") {
            $url = $matches[0]
            # encode extracted URL if necessary. If no encoding is required, the URL is not changed
            $url = [web.httputility]::UrlPathEncode($url)
            # build final entry for current CES entry and add it to array
            $entries += $priority + "`n" + $authentication + "`n" + $RenewalOnly + "`n" + $url
        }
    }
    # write encoded URLs back to Active Directory
    $_."msPKI-Enrollment-Servers" = $entries
    $_.SetInfo()
}

Acknowledgement: Thanks to Vadims Podans for his contribution of the Windows PowerShell scripts