Showing posts with label CA. Show all posts
Showing posts with label CA. Show all posts

22 December 2023

Add a SAN to certificate request into additional attributes - SAN does not show in certificate

Hi, fellow certificate enthusiasts! Today I'm going to show you how to add a Subject Alternative Name (SAN) to a certificate request with certsrv and what you must do in certutil to make the CA accept the SAN. Let's get started.

First, you need to create a certificate request with certsrv. You can do this by opening a web browser and navigating to http://<your CA server>/certsrv. Then, click on "Request a certificate" and choose "advanced certificate request". On the next page, select "Submit a certificate request by using a base-64-encoded CMC or PKCS #10 file, or submit a renewal request by using a base-64-encoded PKCS #7 file". This option allows you to upload a certificate request file (.csr) that you have created with another tool, such as OpenSSL.

Now, here comes the fun part. To add a SAN to your request, you need to use the additional attributes field at the bottom of the page. This field allows you to specify any extra information that you want to include in your certificate request. To add a SAN, you need to use the following syntax:

san:dns=<your domain name>

For example, if you want to add a SAN for www.example.com, you would type:

san:dns=www.example.com

You can add multiple SANs by separating them with an ampersand ( & ) like this:

san:dns=www.example.com&dns=example.com

You can even add an ip address

san:dns=www.example.com&dns=example.com&ipaddress=10.0.0.15

Once you have entered your SANs, click on "Submit" and wait for your request to be processed.

But wait, there's more! You're not done yet. You see, by default, the CA will ignore any SANs that you have specified in your request. That's because the CA needs to be configured to accept SANs from certificate requests. To do that, you need to use certutil.

Certutil is a command-line tool that allows you to manage certificates and CAs. You can use it to enable SAN support on your CA by running the following command on your CA server:

certutil -setreg policy\EditFlags +EDITF_ATTRIBUTESUBJECTALTNAME2

This command will modify the registry value of EditFlags under the policy key of your CA configuration. It will add the flag EDITF_ATTRIBUTESUBJECTALTNAME2, which tells the CA to copy any SANs from the additional attributes field of the request to the certificate.

After running this command, you need to restart the CA service for the changes to take effect. You can do this by running:

net stop certsvc

net start certsvc

And that's it! You have successfully added a SAN to your certificate request with certsrv and enabled SAN support on your CA with certutil.



I hope you enjoyed this post and learned something new. If you have any questions or comments, feel free to leave them below.


26 May 2023

Sign certificates in Bulk - Create .PEM, .CER and .RSP certificate files from .CSR in bulk with PowerShell

Every time the intermediate certificate expires this is a recurring job.

At least 200 certificate requests need to be signed. Now I could be doing this by hand, but that would take forever would be super annoying and tedious.

So once again PowerShell to the rescue.
Put the .csr files in a directory and adjust the path in the script to match it.
Then create the output folder and adjust the patch in the script to match it.
Choose the template name for the certificate you want to request, mine was a "webserver" request.

You will be asked to click OK to select the CA for each certificate. (I know, but still beats creating them all by hand)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<#
Title         : Get-CertificateFromCSR.ps1
Version       : 1.0
Created by    : Edwin van Brenk © 2023
For           : vanbrenk.blogspot.com
Date          : 26-05-2023

.Synopsis
   Creates a certificate from a .csr file
.DESCRIPTION
   This script requests a .pem file from a .csr to the specified Certificate Authority
   Save the .csr's in the $outpath folder.
.EXAMPLE
   Just run it in a ISE window, you are prompted to select the CA.
#>



# Invoke the CertReq.exe command to sign a certificate request

# certreq -submit <Path to request file> <Path to output cert file>
# certreq -submit certRequest.req certnew.cer certnew.pfx

$CSRs = Get-ChildItem "C:\Scripts\Get-BulkCertFromCSR\CSR\2023"
$OutPath = New-Item "C:\Scripts\Get-BulkCertFromCSR\CSR\IssuedCertificates\2023" -ItemType Directory -Force

ForEach($CSR in $CSRs){
    $FileOutCER = Join-Path $OutPath "$($CSR.BaseName).cer"
    $FileOutPEM = Join-Path $OutPath "$($CSR.BaseName).pem"
    CertReq -submit -attrib "CertificateTemplate:Webserver" $CSR.FullName $FileOutCER $FileOutPEM
}

03 August 2021

Create certificates in bulk from .CSR files with PowerShell

This is a bit of a work in progress, if anyone can help me out with the last bit.
I know it can be done with an foreach statement but haven't had the time to test it.

<#
  .Synopsis
     Request certificates from csr's
  .DESCRIPTION
     This script requests certificates from an on-premises CA
     Define you CA, PKI name, and output path
     Then copy the lines below for each certificate and fill the name between the quotes

     $name = ""
     $filename = "$name.cer"
     $status = Submit-CertificateRequest -path "C:\Scripts\Get-CertificateFromCSR\CSR\$name.csr" -CA $PKI -Attribute "CertificateTemplate:Webserver" 
     $ReqID = $status.requestid
     Get-IssuedRequest -RequestID $reqID -CertificationAuthority $PKI | Receive-Certificate -Path $OutPath\$name -Force
     cd $outpath\$name
     $item = ls
     Rename-Item -path $item -newname $filename

  .Created by
     Edwin van Brenk
  .Created for
     vanbrenk.blogspot.com
  .Date
     03-08-2021
  .Version
     1.0
  #>

# Run as Admin
Import-Module pspki

cd C:\Scripts\Get-BulkCertFromCSR\csr

$ca = Connect-CA caname.domain.lan
$PKI = "CAname.domain.lan"
$OutPath = "C:\Scripts\Get-CertificateFromCSR\IssuedCertificates\"

<#
$name = ""
$filename = "$name.cer"
$status = Submit-CertificateRequest -path "C:\Scripts\Get-CertificateFromCSR\CSR\$name.csr" -CA $PKI -Attribute "CertificateTemplate:Webserver" 
$ReqID = $status.requestid
Get-IssuedRequest -RequestID $reqID -CertificationAuthority $PKI | Receive-Certificate -Path $OutPath\$name -Force
cd $outpath\$name
$item = ls
Rename-Item -path $item -newname $filename

#>


$name = "Certificate-01"
$filename = "$name.cer"
$status = Submit-CertificateRequest -path "C:\Scripts\Get-CertificateFromCSR\CSR\$name.csr" -CA $PKI -Attribute "CertificateTemplate:Webserver"
$ReqID = $status.requestid
Get-IssuedRequest -RequestID $reqID -CertificationAuthority $PKI | Receive-Certificate -Path $OutPath\$name -Force
cd $outpath\$name
$item = ls
Rename-Item -path $item -newname $filename

$name = "Certificate-02"
$filename = "$name.cer"
$status = Submit-CertificateRequest -path "C:\Scripts\Get-CertificateFromCSR\CSR\$name.csr" -CA $PKI -Attribute "CertificateTemplate:Webserver"
$ReqID = $status.requestid
Get-IssuedRequest -RequestID $reqID -CertificationAuthority $PKI | Receive-Certificate -Path $OutPath\$name -Force
cd $outpath\$name
$item = ls
Rename-Item -path $item -newname $filename

$name = "Certificate-03"
$filename = "$name.cer"
$status = Submit-CertificateRequest -path "C:\Scripts\Get-CertificateFromCSR\CSR\$name.csr" -CA $PKI -Attribute "CertificateTemplate:Webserver"
$ReqID = $status.requestid
Get-IssuedRequest -RequestID $reqID -CertificationAuthority $PKI | Receive-Certificate -Path $OutPath\$name -Force
cd $outpath\$name
$item = ls
Rename-Item -path $item -newname $filename

30 December 2020

How to cleanup expired certificates from a Microsoft CA with PowerShell and Shrink the DB



This a shameless copy of the original post by André Gibel over at https://www.gibel.net/

The reason why I copied it is because there is very little info on this subject and even though the post is from 2014, it still applies today.

Regularly (depending on the number of issued certificates) you have to perform a clean-up of expired certificates from your CA (Certification Authority) DB and then shrink the DB to get rid of the “white space”.

You have to perform the following 3 steps in order:
1. Make a backup of your CA DB (protected with a password) to another Server / medium





- this backup also "removes" the maybe hundres of db log files (each of the has a size of 1 MB) – in my case 828



2.      Clean-up all expired certificates from all 4 categories  with my PowerShell Script


- in a first step it's the best to run the script in a "view only" modus to see which certificates would be deleted
- the script and all the details are explained 
below.

3.      Shrink your CA database to get rid of the “whitespace”

- for this you use the esentutl tool with the “/d” (= defragmentation) option

Before executing the esentutl command stop the AD Certificate service and disable it




- run the following command with the path to the .edb DB file

esentutl /d "C:\Windows\System32\CertLog\IssuingCA.edb"



- at the end the DB - file is more than 100 MB smaller than before, depending on the size your database is.



- at this point you have to enable and start the CA Service again

Here I explain the PowerShell script in detail (the script is used in step 2)

The Microsoft Enterprise CA I’m responsible for is running on a Microsoft Windows Server 2008 Enterprise Server

- with PowerShell 2.0 installed
- no 3rd party PS modules are used
- the certutil.exe is used by the PowerShell (PS) script
- the PS script I created is "Cleanup_MSPKI_Cert_v1.1.ps1" and contains 3 functions

On this CA Server in the C:\ root drive I create a folder “_scripts “ (I don’t use PS remoting) and copy my PowerShell script “Cleanup_MSPKI_Cert_v1.1.ps1” into this folder


Per default the functions "Remove-ExpiredCertFromDB" writes the temporary files to a subfolder within C:\_scripts\PKICleanupLog.

You can change this default folder path with the parameter  “CleanedFolderLogPath”


The 3 functions I have implemented are:

A.) Get-PublishedCATemplate
B.) Get-IssuedCert
C.) Remove-ExpiredCertFromDB

A.) Get-PublishedCATemplate


When you run this function without a parameter, it displays all Templates from the "Certificate Templates" folder with it's OID. This OID is used by the other to functions to display or delete certificates issued with this certain template. In the following picture you see the corresponding templates from the PKI Snap In



function Get-PublishedCATemplate{             

    [CmdletBinding()]

    Param (

        [parameter()]

        [string]$filter   

    )      

    $FilterLen = ("msPKI-Cert-Template-OID =").length+3   

    $AllPublishedTemplates = Invoke-Expression "certutil.exe –catemplates –v | select-string msPKI-Cert-Template-OID"     

    $AllPublishedTemplates | foreach{       

        $tmp= ($_.line).Substring($FilterLen)       

        $splitarr = $tmp.split(" ",2)     

        $obj = New-Object PSObject                                     

        Add-Member -Input $obj -Name "name" -MemberType Noteproperty -Value $Splitarr[1].trim()

        Add-Member -Input $obj -Name "oid" -MemberType Noteproperty -Value $Splitarr[0].trim()              

        if ($PSBoundParameters["filter"]){  

            if ($Splitarr[1].trim() -match $filter){

                write-output $obj             

            }

        }

        else{

            write-output $obj             

        }

    }              

}

Below I run the script with the -filter parameter and so I only get templates with “SCCM” in their name



I assign the oid of ONE template (=> change filter that you get only one result)  to the variable WSTemplate

$WSTemplate = (Get-PublishedCATemplate -filter workstation).oid


B.) Get-IssuedCert

With this function  you can list the certificates  issued from all templates or a certain template (specified with it’s oid = $CertTemplate variable)  which are issued beginning at a certain date.

 function Get-IssuedCert{

  [CmdletBinding()]

  Param (

    [ValidatePattern('^([0-9\.\s])+$')]

    [string]$CertTemplate,

    [ValidatePattern('^\d\d[\./]{1}\d\d[\./]{1}\d\d\d\d$')]

    [string]$Date

  )

  if ($PSBoundParameters["CertTemplate"]){   

    Invoke-Expression "certutil.exe -view -restrict 'certificate template=$CertTemplate,disposition=20,notbefore>=$Date' -out 'Request.RequestID,Request.RequesterName,NotBefore,NotAfter,Request.Disposition'"       

  }

  else {

    # displays Certificates issued with any custom template   

    Invoke-Expression "certutil.exe -view -restrict 'disposition=20,notbefore>=$Date' -out 'Request.RequestID,Request.RequesterName,NotBefore,NotAfter,Request.Disposition'"             

  }

}

 

The following example lists all  29 certificates (from ALL templates) issued from 18 December 2014 and later …. (with this version it’s not possible to select a time range / only a “start-date”)

Get-IssuedCert  -Date 18.12.2014


The following example lists ONLY the 3 certificates which are issued with the Template $WSTemplate (OID of  “…- Workstation – Authentication Certificate”) beginning December 18. 2014

$WSTemplate = (Get-PublishedCATemplate -filter workstation).oid
Get-IssuedCert -CertTemplate $WSTemplate -Date 18.12.2014



C.) Remove-ExpiredCertFromDB

This is an advanced function and all available parameters are displayed with the get-help command

- the expired certificates to view (1st step) and then delete are in one of 4 folders


- I select this “folder” with the -state parameter


- the script creates a log file (also needed for further parsing) in a separate folder


These folders are created automatically if they don’t exist yet.
In a first step always run the cmdlet without the "-delete" parameter so nothing is really deleted.
I also recommend the ISE instead of the shell.
And I also always run this cmdlet with the “-verbose” parameter.

The following example displays all issued (and expired) certificates till 18.12.2014  --- they are not really deleted yet.

Remove-ExpiredCertFromDB -State issued -Date 18.12.2014  -Verbose 


Without the -delete switch parameter the log file has "-ViewOnly" in it’s name

Below is the output from the example above / 396 entries “would be” deleted from the “issued folder” (or category) if you run the cmdlet with “-delete”


The following example lists / deletes  certificates from a certain (workstation authentication) template expired up to 18 december 2014

$WSTemplate = (Get-PublishedCATemplate -filter workstation).oid
Remove-ExpiredCertFromDB -State issued -CertTemplate $WSTemplate -Date 18.12.2014 -Verbose


With the added-delete switch parameter you really delete the entries
T
his step can take some time if there are a lot of entries.

$WSTemplate = (Get-PublishedCATemplate -filter workstation).oid
Remove-ExpiredCertFromDB -State issued -CertTemplate $WSTemplate -Date 18.12.2014 -Verbose -delete


The output at the end (and the log file)


When  you run the same cmdlet again, you see that there aren’t any entries to delete from the DB



The latest (full) version of this script with the 3 functions you can download from the Microsoft Script Gallery: go to download

DirectDownload link

Since TechNet is retired and will be taken offline any time soon a backup can be downloaded here:

Cleanup_MSPKI_Cert_v1.2.ps1







04 June 2020

How to create key file and certificate file from pfx - Openssl

Install the Windows version of Openssl from:
https://slproweb.com/download/Win64OpenSSL-3_6_0.msi
https://slproweb.com/download/Win64ARMOpenSSL-3_6_0.msi

Open a command prompt window in c:\Program Files\OpenSSL\Bin
(or even better, add Openssl to your Path)

Then type:

For the key file:
openssl pkcs12 -in [yourfile.pfx] -nocerts -out [keyfile-encrypted.key]
Example:
openssl pkcs12 -in c:\temp\mycertificate.pfx -nocerts -out c:\temp\keyfile-mycertificate.key

You will be asked for the pfx password (import password), and then asked to enter a password for the .key file (PEM pass phrase)

For the certificate:
openssl pkcs12 -in [yourfile.pfx] -clcerts -nokeys -out [certificate.crt]
Example:
openssl pkcs12 -in c:\temp\mycertificate.pfx -clcerts -nokeys -out c:\temp\certificate-mycertificate.crt

You will only be asked for the pfx password (import password) since the private key will not be exported.

And for .pfx to .pem

openssl pkcs12 -in file.pfx -out file.nokey.pem -nokeys 

openssl pkcs12 -in file.pfx -out file.withkey.pem

Convert x509 to PEM

openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem



Convert PEM to DER

openssl x509 -outform der -in certificatename.pem -out certificatename.der



Convert DER to PEM

openssl x509 -inform der -in certificatename.der -out certificatename.pem

Convert PEM to P7B

Note: The PKCS#7 or P7B format is stored in Base64 ASCII format and has a file extension of .p7b or .p7c.
A P7B file only contains certificates and chain certificates (Intermediate CAs), not the private key. The most common platforms that support P7B files are Microsoft Windows and Java Tomcat.

openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer



Convert PKCS7 to PEM

openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem



Convert pfx to PEM

Note: The PKCS#12 or PFX format is a binary format for storing the server certificate, intermediate certificates, and the private key in one encryptable file. PFX files usually have extensions such as .pfx and .p12. PFX files are typically used on Windows machines to import and export certificates and private keys.

openssl pkcs12 -in certificatename.pfx -out certificatename.pem



Convert PFX to PKCS#8
Note: This requires 2 commands

STEP 1: Convert PFX to PEM

openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem



STEP 2: Convert PEM to PKCS8

openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8



Convert P7B to PFX
Note: This requires 2 commands

STEP 1: Convert P7B to CER

openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer



STEP 2: Convert CER and Private Key to PFX

openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile  cacert.cer
Or:
openssl pkcs12 -export -out domain.name.pfx -inkey domain.name.key -in domain.name.crt
Or with intermediate and root:
openssl pkcs12 -export -out domain.name.pfx -inkey domain.name.key -in domain.name.crt -in intermediate.crt -in rootca.crt