What a great feeling when your blog is up and running! I think, I should post something here while it is still up :)

Today I want to post about new release of my PowerShell PKI module which is released today on CodePlex.

What’s new

1) Introduced module components

After a brief talk with a colleague I decided to split the module in two parts: client and server. Previously my module required RSAT installation in order to use it, while there were a lot of commands which do not require them and are not related to ADCS management. Therefore I divided module in two components: Client and Server. Client component contains commands which are related to local PKI management and do not require RSAT installation. Server component is intended for ADCS management and requires RSAT installation. Here is a module folder structure:

image

Depending on which component is installed (Server or Client) corresponding folder may not appear. Library folder contains primary interop assemblies and .NET style core DLL that implements module functionality by exposing framework classes. Types folder contains extended type system (ETS) definitions and formatting rules for output objects. Plain and simple. Unexpectedly Advanced Installer allowed to create component selection in about 3-4 clicks.

2) Certificate Enrollment Policy service (CEP) endpoint support

Certificate enrollment web services (CEP/CES) were implemented in Windows Server 2008 R2 and they dramatically enhance ADCS usage experience. Previously ADCS could be used only within domain environment without a possibility to place CA servers behind restricted firewall. Now you don’t need direct connection to CA server and expose server’s RPC port to clients. Since CEP/CES implements enrollment protocol in XML over HTTPS, it is possible to use domain CA servers for non-domain users and computers. You can read more here: Certificate Enrollment Web Services in Active Directory Certificate Services. Previously I supported CEP/CES service installation and now there is a support for CEP server endpoint. The appropriate class is located in PKI.Enrollment.Policy namespace. Here is a short example how you can use them. We will use PolicyServerClient class by using the only public constructor:

[↓] [vPodans] $policy = New-Object PKI.Enrollment.Policy.PolicyServerClient "https://CEP.domain.lv/ADPolicyProvider_
CEP_UsernamePassword/service.svc/CEP",$true,"UserNameAndPassword","username@domain.lv","P@ssw0rd"
[↓] [vPodans] $policy


Name           : Sysadmins LV External Enrollment Policy
PolicyId       : {F29AC102-CDCD-4AA8-B1F5-761051FB52C5}
URL            : https://CEP.domain.lv/ADPolicyProvider_CEP_UsernamePassword/service.svc/CEP
Authentication : UserNameAndPassword
Priority       : 2147483645
Flags          : None
FilePath       : C:\Users\vPodans\AppData\Local\Microsoft\Windows\X509Enrollment\2229e8d870ebe2a74d49c5c873f9646b49b373
                 bf
UserContext    : True
FromPolicy     : False
PolicyLoaded   : True
Templates      :



[↓] [vPodans] $policy.Register()
[↓] [vPodans] Get-EnrollmentPolicyServerClient -UserContext


Name           : Sysadmins LV External Enrollment Policy
PolicyId       : {F29AC102-CDCD-4AA8-B1F5-761051FB52C5}
URL            : https://CEP.domain.lv/ADPolicyProvider_CEP_UsernamePassword/service.svc/CEP
Authentication : UserNameAndPassword
Priority       : 2147483645
Flags          : None
FilePath       : C:\Users\vPodans\AppData\Local\Microsoft\Windows\X509Enrollment\2229e8d870ebe2a74d49c5c873f9646b49b373
                 bf
UserContext    : True
FromPolicy     : False
PolicyLoaded   : False
Templates      :



[↓] [vPodans]

In the first command we created enrollment policy endpoint object. During this call, constructor attempts to contact CEP server to retrieve additional policy server information (like policy friendly name and ID). Then we call Register() method with no parameters. Now, you can use Certificates MMC snap for certificate enrollment:

image

and use Get-EnrollmentPolicyServerClient command to retrieve registered policy endpoints. There is a method LoadPolicy method which loads policy and retrieves available certificate templates:

[↓] [vPodans] $policy.LoadPolicy("username@domain.lv","P@ssw0rd")
[↓] [vPodans] $policy


Name           : Sysadmins LV External Enrollment Policy
PolicyId       : {F29AC102-CDCD-4AA8-B1F5-761051FB52C5}
URL            : https://CEP.domain.lv/ADPolicyProvider_CEP_UsernamePassword/service.svc/CEP
Authentication : UserNameAndPassword
Priority       : 2147483645
Flags          : None
FilePath       : C:\Users\vPodans\AppData\Local\Microsoft\Windows\X509Enrollment\2229e8d870ebe2a74d49c5c873f9646b49b373
                 bf
UserContext    : True
FromPolicy     : False
PolicyLoaded   : True
Templates      : {CAExchange, Machine, EVWebServerV2, EVWebServerV3...}



[↓] [vPodans] $policy.Templates

DisplayName                         SchemaVersion  SupportedCA                               AutoenrollmentAllowed
-----------                         -------------  -----------                               ---------------------
CA Exchange                               2        Windows Server 2003 Enterprise Edition                    False
Computer                                  1        Windows 2000 Server                                       False
EV WebServer V2                           2        Windows Server 2003 Enterprise Edition                    False
EV WebServer V3                           3        Windows Server 2008 Enterprise Edition                    False
Kerberos Authentication                   2        Windows Server 2003 Enterprise Edition                    False
OCSP Response Signing                     3        Windows Server 2008 Enterprise Edition                    False
Offline Code Signing                      2        Windows Server 2003 Enterprise Edition                    False
Offline OCSP Response Signing             3        Windows Server 2008 Enterprise Edition                    False
Offline RDP-TLS                           2        Windows Server 2003 Enterprise Edition                    False
RAS and IAS Server                        2        Windows Server 2003 Enterprise Edition                    False
RDP-TLS                                   2        Windows Server 2003 Enterprise Edition                    False
Smart Card V2                             2        Windows Server 2003 Enterprise Edition                    False


[↓] [vPodans]

I’m running these commands on my notebook which is member of workgroup (not domain member). When LoadPolicy method is called, a Templates property is populated with available for you (template list depends on your permissions) templates. I made a huge job on certificate template API extension to support template retrieval (via internal constructor) from CEP response. If you no longer need this policy server endpoint, just call Unregister method:

[↓] [vPodans] $cep = Get-EnrollmentPolicyServerClient -UserContext
[↓] [vPodans] $cep[0].Unregister()
[↓] [vPodans] Get-EnrollmentPolicyServerClient -UserContext
[↓] [vPodans]

3) Enrollment Policy service endpoint URL update in Active Directory

As a part of enhanced CEP support in the module I provided a CEP endpoint URL update in Active Directory. When you install Enrollment Web Service (CES), it generates a default URL that uses CES server’s name in the URL address. However, when you want to make this server available from outside of your network (from internet) to support external and non-domain clients, you most likely wouldn’t use internal server name in the URL. Instead, you will use some of external names which are resolvable from internet. In order to avoid manual Active Directory modification, you can edit URLs from PowerShell. First, retrieve existing URL by calling Get-CertificationAuthority command. CES URLs are stored in EnrollmentServiceURI, modify Uri property of the object and call UpdateEnrollmentServiceUri method on CertificateAuthority object:

PS C:\> # retrieve CA object
PS C:\> $ca = Get-CA "hq-s-i*"
PS C:\> # display existing CES URLs
PS C:\> $ca.EnrollmentServiceURI

Priority Authentication         RenewalOnly Uri
-------- --------------         ----------- ---
1        UserNameAndPassword    False       https://pkix.sysadmins.lv/Sysadmins LV Internal Class 1 SubCA-1_CES_User...
1        Kerberos               False       https://hq-s-pkix.sysadmins.lv/Sysadmins LV Internal Class 1 SubCA-1_CES...


PS C:\> # select a required URL index to print the full URL
PS C:\> $ca.EnrollmentServiceURI[0].Uri.AbsoluteUri
https://pkix.sysadmins.lv/Sysadmins%20LV%20Internal%20Class%201%20SubCA-1_CES_UsernamePassword/service.svc/CES
PS C:\> # modify URL in notepad or in external text editor and write new URL back
PS C:\> $ca.EnrollmentServiceURI[0].Uri = "https://****.sysadmins.lv/Sysadmins%20LV%20Internal%20Class%201%20SubCA-1_CES
_UsernamePassword/service.svc/CES"
PS C:\> # save changes in Active Directory
PS C:\> $ca.UpdateEnrollmentServiceUri()
PS C:\>

I believe it is very useful functionality.

4) Certificate template enhancement

I rewrote the code in certificate template classes to make it more consistent and convenient for future enhancements. First, I added more settings to display (almost all). As already showed, there is a way to create certificate template not only from Active Directory, but from CEP response too. The code is now ready (I believe) for future enhancements, like template modification from PowerShell and template duplication. Also, I have a concept for certificate template serialization for offline transfer between AD forests. Here is how certificate template settings looks:

[↓] [vPodans] $policy.Templates[0].Settings


ValidityPeriod        : 1 weeks
RenewalPeriod         : 1 days
SubjectType           : Computer
SubjectName           : EnrolleeSuppliesSubject
EnhancedKeyUsage      :
CertificatePolicies   :
Purpose               : Encryption
Cryptography          : [Cryptography Settings]
                          CSP list:
                             Microsoft Enhanced Cryptographic Provider v1.0
                             Microsoft Base Cryptographic Provider v1.0

                          Key Algorithm: RSA (1.2.840.113549.1.1.1)
                          Hash Algorithm: sha1 (1.3.14.3.2.26)
                          Key Length: 2048
                          Private key options: None
                          KeySpec: AT_KEYEXCHANGE
                          CNG key usage: None
Extensions            : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptograp
                        hy.Oid, System.Security.Cryptography.Oid}
SupersededTemplates   :
CAManagerApproval     : False
RegistrationAuthority : [Issuance Requirements]
                          Authorized signature count: 0
                          Reenrollment requires: same criteria as for enrollment.
CriticalExtensions    : {}
KeyArchivalSettings   : [Key Archival Settings]
                          Key archival required: False
EnrollmentOptions     : 1
GeneralFlags          : 200768



[↓] [vPodans]

It is all for the first part. In the next post I’ll continue to speak about new enhancements and features in the module.

As always, module page is:

>> PS PKI Module v2.6 <<


Share this article:

Comments:


Post your comment:

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