Category Archives: PowerShell

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

Rename AD User

With this script you can rename all user in active directory.
the new name is composed using the properties LastName and FirstName and joined with a space ( space )

1. Get all user in the AD domain
We use the LDAPFilter so we retrieve only user with with FirstName (givenName) and LastName (sn) compiled
$adUsers = Get-ADUser -LDAPFilter "(&(objectCategory=person)(objectClass=user)(givenName=*)(sn=*))"
2. Rename the user
The rename process was a 2 step process. First we change the Display Name and second we change the name of the user

$adDomain = domain.local
$adUsers | Foreach-Object {
$dn = $_.Surname.Trim() + ' ' + $_.GivenName.Trim()
$_.DisplayName = $dn
Set-AdUser -Instance $_
Try {
Rename-ADObject -identity $_.DistinguishedName -Newname $dn -Server $adDomain
}
Catch {
Write-Host "$_.Name may already exist."
}
}

This script was tested on Windows Server 2008 R2 domain controller