Monthly Archives: August 2014

Sharepoint 2013 and Dynamics CRM 2013: Unable to open Sharepoint in IFRAME

With SharePoint 2013 there is new security pattern who is explained here

So for open the SharePoint page in an IFrame (like Dynamics CRM do) you need to add to the page this dedicated control:
<WebPartPages:AllowFraming runat=”server” />

I have added this control in the Master page and all go done

 

Configure ADFS 3.0 with Sharepoint 2013 for Claim authentication

Update Sptember, 23 2014

1. Install AD FS server
2. Install and configure SharePoint 2013 server
3. Configure ADFS
3.1 Create the claim rule
3.2 Export the Token-Signing certificate
4 Configure SharePoint 2013
4.1 Configure web application
4.2 Modify the SharePoint web application web.config
4.3 Remove authentication type request
9. Usefull link
The used lab environment are:
DC01 – Domain Controller and Federation Server
SQL01 – SQL Server 2012 Standard with Reporting Services
SHP01 – SharePoint 2013 SP 1 Enterprise
On all server is installed Windows Server 2012 R2 Standard.
Install Federation Server on the Domain Controller is not a good think!

1. Install and configure an AD FS server
Install the ADFS Service on Windows 2012 R2 (see link at point 9). In our case the fully qualify domain name of the machine is DC01.intra.zzlab.com and we use the external name sts.zzlab.com. So we need to add all the two name to the registry key as reported in this Microsoft KB article

2. Install and configure the SharePoint 2013 server
You need to use SharePoint 2013 with SP1 for installing on Windows Server 2012 R2. The setup of SharePoint is standard setup. SharePoint need to be SSL enabled. Add in the Intranet zone of internet explorer in the SharePoint server the address of the ADFS Server and the SharePoint web application.

3. Configure relay party on ADFS
On the ADFS Server open the AD FS Management tools and under the Trust Relationships folder on the left pane right click on Relying Party Trusts and select Add Relying Party Trust…
A. Welcome page
B. Select Data Source
Select the option “Enter data about the relying party manually”
C. Specify Display Name
Insert the Display name. I have used the FQDN of the SharePoint Server (shp01.intra.zzlab.com)
D. Choose profile
Use AD FS Profile
E. Configure certificate
This certificate are used for token encryption and need to be stored on the “Computer account” certificate store. I have used the SSL certificate of the SharePoint Server (shp01.intra.zzlab.com).
F. Configure URL
Select the option “Enable support for WS-Federation Passive Protocol” and insert the URL of the SharePoint Trust Service (https://<sharepoint server FQDN>/_trust/)
G. Configure identifiers
Add the uniform resource name (URN) (is the historical name for a uniform resource identifier (URI)) of your SharePoint in the standard form urn:sharepoint:<Any string>.
In my case I have used urn:sharepoint:zzlab
F. Configure Multi-Factor Authentication Now?
I have selected “I do not want to configure …”
G. Choose Issuance Authorization Rule
This is the standard authentication rule. I have select “Permit all users to access this relying party”
H. Ready to add trust
Is the review of the configuration
I. Finish

3.1 Create the claim rule
After the configuration wizard the system automatically open the rule control windows and we need add some rule (Issuance Transform Rules) to complete the Claims token. SharePoint use EmailAddress for authentication so we add a rule to send User Principal Name as Email Address
I have created this rules:

R1 Rule template: Pass Through or Filter an Incoming Claim
Claim rule name: Pass Through UPN (or something descriptive)
Incoming claim type: UPN
Pass through all claim values
R2 Rule template: Pass Through or Filter an Incoming Claim
Calim rule name: Pass Through Primary SID (or something descriptive)
Incoming claim type: Primary SID
Pass through all claim values
R3 Rule template: Transform an incoming Claim
Claim rule name: Transform Windows Account Name to Name (or something descriptive)
Incoming claim type: Windows account name
Outgoing claim type: Name (or *Name)
Pass through all claim values
R4 Rule template: Send LDAP Attributes as Claims
Calim rule name: Send UPN as Email Address (or something descriptive)
Attribute store: Select “Active Directory”
“Mapping of LDAP attributes to outgoing claim types” select: LDAP Attribute: User-Principal-Name
Under Outgoing Claim Type: E-Mail Address

3.2 Distribute the certificate
Export the certificate used by AD FS for token sign and save it on the SharePoint server (we don’t need the certificate private key)  inside the Computer certificate store.
SharePoint also need access to the private key of the certificate used for token encryption selected in the relay party configuration (3. Configure relay party on ADFS,  point E). So if you have used a different certificate need to export with private key and import inside SharePoint server (SHP01) computer certificate store.

4 Configure SharePoint 2013
First step is import the token-signing certificate on the SharePoint server. For do this we need to use the “SharePoint management shell”. First copy the exported certificate on the SharePoint server. In my case I have saved the certificate in C:\Temp so my <PathToTokenSignCert> is C:\Temp\TokenSignCert.cer.
After that use the command:
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("<FullPathOfTheTokenSignCertFile>")
New-SPTrustedRootAuthority -Name "Token Signing Cert" -Certificate $cert

Is important to import all the certificate chain with the same command
After that register the claim provider in SharePoint:

$emailClaimMap = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" -IncomingClaimTypeDisplayName "EmailAddress" -SameAsIncoming
$upnClaimMap = New-SPClaimTypeMapping -IncomingClaimType “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" -IncomingClaimTypeDisplayName “UPN” -SameAsIncoming
$roleClaimMap = New-SPClaimTypeMapping -IncomingClaimType “http://schemas.microsoft.com/ws/2008/06/identity/claims/role" -IncomingClaimTypeDisplayName “Role” -SameAsIncoming
$sidClaimMap = New-SPClaimTypeMapping -IncomingClaimType “http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid" -IncomingClaimTypeDisplayName “SID” -SameAsIncoming
$realm = “urn:sharepoint:zzlab”
$signInURL = “https://sts.zzlab.com/adfs/ls"
$ap = New-SPTrustedIdentityTokenIssuer -Name "ZZLAB AD Federation" -Description “ZZLAB AD Federation Server” -realm $realm -ImportTrustCertificate $cert -ClaimsMappings $emailClaimMap,$upnClaimMap,$roleClaimMap,$sidClaimMap -SignInUrl $signInURL -IdentifierClaim $emailClaimmap.InputClaimType

4.1 Configure web application to use ADFS
Using the SharePoint Central Administration web site enable the use of the newly created SPTrustedIdentityTokenIssuer. Go to Manage web applications and select the desired web application from the list. Select the Authentication Providers button and the desired SharePoint zone. Select the Trusted Identity Provider and the newly registered.

4.2 Modify the SharePoint web application web.config
We have used an encrypted token in ADFS and we have used an encryption certificate so we need to explain how decrypt the token. For decrypt the token we need access to the private key of the encryption certificate. SharePoint web application access the key using the same user of the Application Pool for the IIS web site. Using the Certificates snap-in look for the Computer account and find the certificate. Right click on it and using the All tasks > Manage private key … add the application pool user and give it the Read permission. For this reason we need to modify the web.config of the web application. Open the web.config with notepad and find the <microsoft.identityModel> section (in my case is the last section of the file who end just before the </configuration> tag. Inside the <securityTokenHandlers> add the path name for manage encrypted token <add type=”Microsoft.IdentityModel.Tokens.EncryptedSecurityTokenHandler, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ /> After that we need to explain at SharePoint what is the certificate used for encrypt the token, to do this we need add just before the tag </service>:

<serviceCertificate>
<certificateReference x509FindType="FindByThumbprint" findValue="<ThumbprintOfTheCertificate>" storeLocation="LocalMachine" storeName="My"/>
</serviceCertificate>

4.3 Remove authentication type request
At this point SharePoint ask with kind of authentication use: Federation Server or Windows You will likely want to remove this step and have all login efforts go directly to ADFS instead. Change the web application login page. Select “Custom Sign In Page” and use the url /_trust/default.aspx Save and wait.

9. Usefull link
AD FS Deployment documentation
Deploying ADFS 3.0 for SharePoint 2013 in a perimeter network

Install Dynamics CRM 2013 on premise

The lab environment:

DC01 – Windows 2012 R2 Core Edition as Domain Controller
SQL01 – Windows 2012 R2 Standard with SQL 2012 Server Enterprise with all features
CRM01 – Windows 2012 R2 Standard (where we install the Microsoft Dynamics CRM 2013)

Prepare the environment
Create in Active Directory a specific Organizational Unit used by the system for permission management
Set the SQL Server Agent Service who start in Automatic mode and start it
Create service user and add specific user permission
Install the Dynamics CRM Server Email Router service (We don’t need this service so I don’t have installed)
Install the Dynamics CRM Server
Install the Dynamics CRM Reporting Extensions on Microsoft Reporting Server Service
Update to service pack 1 the Dynamics CRM Server and Dynamics CRM Reporting Extensions

Create service user
You need 6 service user who are just members of Domain Users:

  • Application service (crmapp.service)
  • Deployment web service (crmdepweb.service)
  • Sandbox processing service (crmsandbox.service)
  • VSS Writer Service (crmvsswriter.service)
  • Asynchronous Processing Service (crmasync.service)
  • Monitoring Service (crmmonitor.service)

Add the Application service (crmapp.service) user and Asynchronous Processing Service (crmasync.service) user to the Performance Log User local group of the Dynamics CRM Server

I have used this PowerShell command:

Import-Module ActiveDirectory
$ADPathContainer = "OU=ServiceUser,OU=ZZLAB,DC=intra,DC=zzlab,DC=com"
New-ADUser -SamAccountName "crmapp.service" -UserPrincipalName "crmapp.service@intra.zzlab.com" -Name "CRM Application Service User" -DisplayName "CRM Application Service User" -GivenName "CRM Application" -SurName "Service User" -Path $ADPathContainer -AccountPassword (ConvertTo-SecureString 'Pa$$w0rd' -AsPlainText -Force) -Enabled $True -PasswordNeverExpires $True -ChangePasswordAtLogon $False
New-ADUser -SamAccountName "crmdepweb.service" -UserPrincipalName "crmdepweb.service@intra.zzlab.com" -Name "CRM Deployment Web Service User" -DisplayName "CRM Deployment Web Service User" -GivenName "CRM Deployment Web" -SurName "Service User" -Path $ADPathContainer -AccountPassword (ConvertTo-SecureString 'Pa$$w0rd' -AsPlainText -Force) -Enabled $True -PasswordNeverExpires $True -ChangePasswordAtLogon $False
New-ADUser -SamAccountName "crmsandbox.service" -UserPrincipalName "crmsandbox.service@intra.zzlab.com" -Name "CRM Sandbox Processing Service User" -DisplayName "CRM Sandbox Processing Service User" -GivenName "CRM Sandbox Processing" -SurName "Service User" -Path $ADPathContainer -AccountPassword (ConvertTo-SecureString 'Pa$$w0rd' -AsPlainText -Force) -Enabled $True -PasswordNeverExpires $True -ChangePasswordAtLogon $False
New-ADUser -SamAccountName "crmvsswriter.service" -UserPrincipalName "crmvsswriter.service@intra.zzlab.com" -Name "CRM VSS Writer Service User" -DisplayName "CRM VSS Writer Service User" -GivenName "CRM VSS Writer" -SurName "Service User" -Path $ADPathContainer -AccountPassword (ConvertTo-SecureString 'Pa$$w0rd' -AsPlainText -Force) -Enabled $True -PasswordNeverExpires $True -ChangePasswordAtLogon $False
New-ADUser -SamAccountName "crmasync.service" -UserPrincipalName "crmasynchronous.service@intra.zzlab.com" -Name "CRM Asynchronous Service User" -DisplayName "CRM Asynchronous Service User" -GivenName "CRM Asynchronous" -SurName "Service User" -Path $ADPathContainer -AccountPassword (ConvertTo-SecureString 'Pa$$w0rd' -AsPlainText -Force) -Enabled $True -PasswordNeverExpires $True -ChangePasswordAtLogon $False
New-ADUser -SamAccountName "crmmonitor.service" -UserPrincipalName "crmmonitor.service@intra.zzlab.com" -Name "CRM Monitoring Service User" -DisplayName "CRM Monitoring Service User" -GivenName "CRM Monitoring" -SurName "Service User" -Path $ADPathContainer -AccountPassword (ConvertTo-SecureString 'Pa$$w0rd' -AsPlainText -Force) -Enabled $True -PasswordNeverExpires $True -ChangePasswordAtLogon $False

Dynamics CRM Server Setup
Install the Dynamics CRM 2013 from the “autoplay menu” the application crash on my Windows 2012 R2 server. So I run the SetupServer.exe from the folder \Server\amd64.
The procedure ask me the following information:
1. Internet connection to check the upgrade
2. Insert the CRM 2013 product key
3. Accept the license agreement
4. Install required components
5. Select the installation location (I have accepted the default folder path)
6. Specify server role (I have installed every thinks on one server)
7. Specify deployment option (I have accepted the default “Create a new deployment” and I have specified the SQL01.intra.zzlab.com as SQL server)
8. Select the Organizational Unit (select the Organizational Unit created in the preparation environment section)
9. Specify the service user (Created in the preparation environment section)
10. Select the web site (I have choose for the default web site on my server)
11. Email Router Name (I have left blank because I don’t install the email router now)
12. Specify Organization Settings
13. Specify the report server url
14. Help us to improve customer experience
15. Select Microsoft Update preferences
16. System checks
17. Service disruption warnings
18. Ready to install

Install Dynamics CRM Reporting Extensions on Microsoft Reporting Service server
Also in this case the auto run setup lunch crash immediately on Windows 2012 R2 Server.
I run the SetupSrsDataConnector.exe from <DVD drive letter>:\Server\amd64\SrsDataConnector.
The setup wizard ask only for the Reporting Server name and automatically do everything.

Install the Service Pack 1 for Dynamics CRM Server and Dynamics CRM Reporting Extensions
The setup of service pack run automatically without any question

Create a self signed certificate with alternatives names

For many courses or test lab environment we need a certificate (SSL,…) so after some experience with OpenSSL I have found in internet and “rearrange” a work of other people for create a PowerShell Script for self signed certificate creation with Subject Alternatives Names.
The script need to be executed with administrative permission (start PowerShell as administrator) and store the new certificate in the Computer store machine. You can export the certificate and the private key using the MMC Certificates snap-in on windows installation with GUI. If you are using a Core windows installation you need the CERTUTIL command.

#####################################################################
#
# Creates self-signed signing certificate and install it to certificate store
# with alternative names
#
# Note: Requires at least Windows Vista. Windows XP/Windows Server 2003
# are not supported.
#
# LSO (Lorenzo Soncini) - August 12, 2014
#
# Update with information found
# http://forums.iis.net/t/1180823.aspx
#
# Pavel Khodak, 2012
# http://blogs.msdn.com/b/pavelkhodak/
#
# Based on the work of
# Vadims Podans - http://www.sysadmins.lv/
# Adam Conkle - http://social.technet.microsoft.com/wiki/contents/articles/4714.how-to-generate-a-self-signed-certificate-using-powershell-en-us.aspx
#####################################################################

# INPUT PARAMETER
# Change here the value to the Certificates Parameter
# Certificate subject in X500 format…
[string] $Subject = ‘CN = CRM01’
# CertificateFriendlyName…
[string] $FriendlyName = “CRM01 ZZLab Certificate”
# Subject Alternatives Names…
[string[]] $AltDnsNames = @(“crm.zzlab.com”, “crm.intra.zzlab.com”, “crm01.intra.zzlab.com”)
[Net.IPAddress[]] $IPAltNames
# Key length, use 2048 or more…
[int] $KeyLength = 2048
# Valid period …
[datetime] $NotBefore = [DateTime]::Now
[datetime] $NotAfter = $NotBefore.AddYears(5)
# END INPUT PARAMETER
#
try {
$OS = @(Get-WmiObject -Class Win32_OperatingSystem)
if ($OS[0].Version -lt 6) {
Write-Error “This version of Windows is not supported. Windows Server 2008 or Windows Vista or later is required.”
return
}
Write-Host “`n WARNING: This script sample is provided AS-IS with no warranties and confers no rights.” -ForegroundColor Yellow
Write-Host “`n This script sample will generate self-signed certificates with private key”
Write-Host ” in the Local Computer Personal certificate store.”
#region Enums
# http://msdn.microsoft.com/en-us/library/aa379394%28VS.85%29.aspx
$X500NameFlags = @{
STR_NONE = 0 # Display characteristics are not identified.
OID_NAME = 2 # OIDs are separated from their associated attribute value by using an equal sign (=).
X500_NAME = 3 # OIDs are converted to their X.500 key names.
}

# http://msdn.microsoft.com/en-us/library/aa379409%28VS.85%29.aspx
$X509KeySpec = @{
NONE = 0 # The intended use is not identified.
KEYEXCHANGE = 1 # The key can be used to encrypt (including key exchange) or sign depending on the algorithm.
SIGNATURE = 2 # The key can be used for signing.
}

# http://msdn.microsoft.com/en-us/library/aa379024.aspx
$MachineContext = @{
User = 0x0;
Computer = 0x1
}

# http://msdn.microsoft.com/en-us/library/aa374830.aspx
$AltNameType = @{
DNS_NAME = 3 # A Domain Name System (DNS) name such as MyDomain.Microsoft.com.
IP_ADDRESS = 8 # An Internet Protocol (IP) address in dotted decimal format 123.456.789.123.
}

# http://msdn.microsoft.com/en-us/library/aa374936%28v=VS.85%29.aspx
$EncodingType = @{
BASE64 = 0x1 # The string is base64 encoded without beginning and ending certificate headers.
}

# http://msdn.microsoft.com/en-us/library/aa376782%28VS.85%29.aspx
$InstallResponseRestrictionFlags = @{
AllowUntrustedCertificate = 0x2 # Installs untrusted end entity and certification authority certificates.
AllowUntrustedRoot = 0x4 # Same as AllowUntrustedCertificate but also installs the certificate even if the certificate chain cannot be built because the root is not trusted.
}

# http://msdn.microsoft.com/en-us/library/aa379399%28v=VS.85%29.aspx
$X509CertificateEnrollmentContext = @{
User = 0x1 # The certificate is intended for an end user.
Computer = 0x2 # The certificate is intended for a computer.
AdminForceMachine = 0x3 # The certificate is being requested by an administrator acting on the behalf of a computer.
}

# http://msdn.microsoft.com/en-us/library/aa379412.aspx
$X509PrivateKeyExportFlags = @{
ALLOW_EXPORT_NONE = 0x0 # Export is not allowed. This is the default value.
ALLOW_EXPORT = 0x1 # The private key can be exported.
PLAINTEXT_EXPORT_FLAG = 0x2 # The private key can be exported in plaintext form
ALLOW_ARCHIVING_FLAG = 0x4 # The private key can be exported once for archiving.
ALLOW_PLAINTEXT_ARCHIVING_FLAG = 0x8 # The private key can be exported once in plaintext form for archiving.
}

# http://msdn.microsoft.com/en-us/library/aa379417%28v=VS.85%29.aspx
$X509PrivateKeyUsageFlags = @{
NONE = 0 # The permitted uses are not defined.
DECRYPT = 0x1 # The key can be used to decrypt content.
SIGNING = 0x2 # The key can be used for signing.
ALL_USAGES = 0xffffff # All of the uses defined for this enumeration are permitted.
}

# http://msdn.microsoft.com/en-us/library/aa379410(v=VS.85).aspx
$X509KeyUsageFlags = @{
DIGITAL_SIGNATURE = 0x80 # Used with a Digital Signature Algorithm (DSA) to support services other than nonrepudiation, certificate signing, or revocation list signing.
KEY_ENCIPHERMENT = 0x20 # Used for key transport.
DATA_ENCIPHERMENT = 0x10 # Used to encrypt user data other than cryptographic keys.
}
#endregion

#region Create private key. http://msdn.microsoft.com/en-us/library/aa378921(VS.85).aspx

$PrivateKey = New-Object -ComObject X509Enrollment.CX509PrivateKey
$PrivateKey.ProviderName = “Microsoft RSA SChannel Cryptographic Provider”
$PrivateKey.KeySpec = $X509KeySpec.KEYEXCHANGE
$PrivateKey.KeyUsage = $X509PrivateKeyUsageFlags.ALL_USAGES
$PrivateKey.Length = $KeyLength
$PrivateKey.MachineContext = $MachineContext.Computer
# Set security descriptor. http://msdn.microsoft.com/en-us/library/windows/desktop/aa379034(v=vs.85).aspx
$PrivateKey.SecurityDescriptor = “D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)”
$PrivateKey.ExportPolicy = $X509PrivateKeyExportFlags.ALLOW_EXPORT
$PrivateKey.Create()
#endregion

#region Create certificate request template. http://msdn.microsoft.com/en-us/library/aa377124(VS.85).aspx

$Cert = New-Object -ComObject X509Enrollment.CX509CertificateRequestCertificate
$Cert.InitializeFromPrivateKey($X509CertificateEnrollmentContext.Computer, $PrivateKey, “”)
#region Add alternative names. http://msdn.microsoft.com/en-us/library/aa378081(v=VS.85).aspx
$altNamesCollection = New-Object -ComObject X509Enrollment.CAlternativeNames
$extNames = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames
foreach ($dnsName in $AltDnsNames) {
$altDnsName = New-Object -ComObject X509Enrollment.CAlternativeName
$altDnsName.InitializeFromString($AltNameType.DNS_NAME, $dnsName)
$altNamesCollection.Add($altDnsName)
}

foreach ($ip in $IPAltNames) {
$base64EncodedIp = [Convert]::ToBase64String($ip.GetAddressBytes())
$altNameIp = New-Object -ComObject X509Enrollment.CAlternativeName
$altNameIp.InitializeFromRawData($AltNameType.IP_ADDRESS, $EncodingType.BASE64, $base64EncodedIp)
$altNamesCollection.Add($altNameIp)
}

$extNames.InitializeEncode($altNamesCollection)
$Cert.X509Extensions.Add($extNames)
#endregion

#region Certificate Extensions.
# Extension code are http://msdn.microsoft.com/en-us/library/windows/desktop/aa374855(v=vs.85).aspx
# Add certificate key usage statements.
$OIDs = New-Object -ComObject X509Enrollment.CObjectIDs

# define Server authentication enhanced key usage (actual OID = 1.3.6.1.5.5.7.3.1)
$OID = New-Object -ComObject X509Enrollment.CObjectID
$OID.InitializeFromValue(“1.3.6.1.5.5.7.3.1”)
$OIDs.Add($OID)
# define Client authentication enhanced key usage (actual OID = 1.3.6.1.5.5.7.3.2)
$OID = New-Object -ComObject X509Enrollment.CObjectID
$OID.InitializeFromValue(“1.3.6.1.5.5.7.3.2”)
$OIDs.Add($OID)
# define SmartCard authentication enhanced key usage (actual OID = 1.3.6.1.4.1.311.20.2.2)
$OID = New-Object -ComObject X509Enrollment.CObjectID
$OID.InitializeFromValue(“1.3.6.1.4.1.311.20.2.2”)
$OIDs.Add($OID)
# define CodeSigning enhanced key usage (actual OID = 1.3.6.1.5.5.7.3.3) from OID
$OID = New-Object -ComObject X509Enrollment.CObjectID
$OID.InitializeFromValue(“1.3.6.1.5.5.7.3.3”)
$OIDs.Add($OID)

# now we create Enhanced Key Usage extension, add our OIDs and encode extension value
# http://msdn.microsoft.com/en-us/library/aa378132(VS.85).aspx
$EKU = New-Object -ComObject X509Enrollment.CX509ExtensionEnhancedKeyUsage
$EKU.InitializeEncode($OIDs)

$Cert.X509Extensions.Add($EKU)

# Add Key Encipherment, Data Encipherment extensions.
$keyUsageExt = New-Object -ComObject X509Enrollment.CX509ExtensionKeyUsage
$keyUsageExt.InitializeEncode(
$X509KeyUsageFlags.KEY_ENCIPHERMENT -bor `
$X509KeyUsageFlags.DATA_ENCIPHERMENT
)

$Cert.X509Extensions.Add($keyUsageExt)
#endregion

# Create Subject field in X.500 format. http://msdn.microsoft.com/en-us/library/aa377051(VS.85).aspx
$name = New-Object -ComObject X509Enrollment.CX500DistinguishedName
$name.Encode($Subject, $X500NameFlags.X500_NAME)
$Cert.Subject = $name

$Cert.Issuer = $Cert.Subject
$Cert.NotBefore = $NotBefore
$Cert.NotAfter = $NotAfter
$Cert.Encode()
#endregion

#region Process request and build end certificate.
# interface: http://msdn.microsoft.com/en-us/library/aa377809(VS.85).aspx
$enrollment = New-Object -ComObject X509Enrollment.CX509enrollment
$enrollment.InitializeFromRequest($Cert)
$endCert = $enrollment.CreateRequest($EncodingType.BASE64)

$enrollment.CertificateFriendlyName = $FriendlyName

# Install certificate.
$enrollment.InstallResponse(
$InstallResponseRestrictionFlags.AllowUntrustedRoot,
$endCert,
$EncodingType.BASE64,
“”
)
#endregion

} catch {
Write-Error (‘Failed to create web server certificate. The error was: “{0}”.’ -f $_)
}

Use the certutil utility for export the certificate
In the same PowerShell administrative session use the command:

certutil -store

for list all certificate. Look for the Serial Number of the desired certificate.
With the command:

certutil -exportPFX <Certificate Serial Number> <Certificate destination file>.pfx

the system ask for a PFX password and export the selected certificate in file <Certificate destination file>.pfx