-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCSRtoCER.ps1
280 lines (229 loc) · 13.5 KB
/
CSRtoCER.ps1
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
<#PSScriptInfo
.VERSION 1.32
.GUID 134de175-8fd8-4938-9812-053ba39eed83
.AUTHOR [email protected]
.COMPANYNAME
.COPYRIGHT
.TAGS
.LICENSEURI
.PROJECTURI
.ICONURI
.EXTERNALMODULEDEPENDENCIES
.REQUIREDSCRIPTS
.EXTERNALSCRIPTDEPENDENCIES
.RELEASENOTES
.PRIVATEDATA
#>
<#
.DESCRIPTION
CSRtoCER.ps1 is used to view the information from a CSR file and generate the certificate based on the CSR file. This PowerShell will grab the information such as "Subject", "Key Length", "SANs", "Template" from the CSR file. If the SANs is not empty in the CSR file, the script will use the CSR file’s setting. If there's no SANs in CSR file, script will use “CN” as the SANs. The script will also list the Template that used in the CSR file, If there's no Template in the CSR file, script will list all the available Certificate Templates from your AD, when you pick up one, script will list the CA Server which has the Template you picked up.
Version: 1.32
Creation Date: <07/04/2022>
Purpose/Change: Fix the bug that when the CSR file contains duplicated CN.
Version: 1.31
Creation Date: <02/25/2021>
Purpose/Change: Fix the bug that when the CSR file contains SANs can't generate SANs in Certificate correctly.
Version: 1.30
Creation Date: <01/29/2020>
Purpose/Change: Add the feature that can manually input SANS. If the SANs not contain CN the script will auto add it.
Version: 1.20
Creation Date: <10/08/2019>
Purpose/Change: Fix the CertUtil version compare issue
Before you run the script Install the PSPKI module in your PowerShell running environment.
https://www.powershellgallery.com/packages/PSPKI/3.4.1.0
<Install-Module -Name PSPKI>
#>
<#
.SYNOPSIS
<>
.DESCRIPTION
<>
.PARAMETER <Parameter_Name>
<>
.INPUTS
<>
.OUTPUTS
<>
.NOTES
<>
.EXAMPLE
This PowerShell passed the test in PowerShell version 5.1
PS H:\>host
Check the PowerShell version.
PS H:\>CSRtoCER.ps1 csrfilename
Output the Certificate Template and the other information which is in the CSR file.
PS H:\>CSRtoCER.ps1 csrfilename -cert
Generate the Certificate by using the CSR file.
#>
cls
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#variables
$CSRfile = $Args[0]
$ENV = $Args[1]
Import-Module PSPKI
if ( Test-Path -Path TemplatePropCommonName.csv ) { Clear-Content TemplatePropCommonName.csv }else{ New-Item -Name TemplatePropCommonName.csv -ItemType File }
if ( Test-Path -Path TemplateOID.csv ) { Clear-Content TemplateOID.csv }else{ New-Item -Name TemplateOID.csv -ItemType File }
if ( Test-Path -Path TemplateMenu.csv) { Clear-Content TemplateMenu.csv }else{ New-Item -Name TemplateMenu.csv -ItemType File }
if ( Test-Path -Path CAServers.csv ) { Clear-Content CAServers.csv }else{ New-Item -Name CAServers.csv -ItemType File }
if ( ([string]::IsNullOrEmpty($CSRfile)) ){
Write-Output "Sorry, missing the CSR file! Please input the CSR file name and try again."
Write-Output "---USAGE: CSRtoCER.ps1 csrfilename [-cert]---"
}else {
if ( Test-Path -Path $CSRfile ) {
$CSRfileOID = certutil.exe -dump .\$CSRfile | findstr "Template=" | %{ $_.Split('=')[1]; }
$CSRfileSubject = ((certutil.exe -dump .\$CSRfile) | select-string '^\s{4}[A-Z]{1,2}=[0-9a-zA-Z*]' -AllMatches) | foreach{ $_.ToString().Trim() }
$CSRfileCN = (certutil.exe -dump .\$CSRfile) | findstr "CN" | %{ $_.Split('=')[1]; } | foreach{ $_.ToString().Trim() } | sort -u
$CSRfileSAN = certutil.exe -dump .\$CSRfile | findstr "DNS" | %{ $_.Split('=')[1]; } | sort -u
$CSRfileKeyLength = (certutil.exe -dump .\$CSRfile | findstr "Public\ Key\ Length:" | %{ $_.Split(':')[1]; }).Trim()
$DistinguishedNameLength = (((get-addomain | findstr "DistinguishedName" | foreach{ $_.ToString() } | %{ $_.Split(':')[1]; }).Trim()).Split(',')).count
$ForestLength = (((get-addomain | findstr "^Forest" | foreach{ $_.ToString() } | %{ $_.Split(':')[1]; }).Trim()).Split('.')).count
$Delta = $DistinguishedNameLength-$ForestLength
$ForestDC = ((get-addomain | findstr "DistinguishedName" | foreach{ $_.ToString() } | %{ $_.Split(':')[1]; }).Trim()).Split(',')[$Delta..$($DistinguishedNameLength-1)] -join ","
$CertutilVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo("c:\windows\system32\certutil.exe").FileVersion | %{ $_.Split('(')[0]; } | foreach{ $_.ToString().Trim() }
Write-Output "CSR file $CSRfile Subject = "$CSRfileSubject
Write-Output ""
Write-Output "CSR file $CSRfile Key Length = $($CSRfileKeyLength)"
Write-Output ""
Write-Output "CSR file $CSRfile SANs = "$CSRfileSAN
Write-Output ""
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#Generate all the Certificate Templates Name List from every CA Server export into TemplatePropCommonName.csv.
#certutil.exe -Template | findstr "TemplatePropCommonName" | %{ $_.Split('=')[1]; } | %{$_.Substring(1)} > .\TemplatePropCommonName.csv
if ( [version]$CertutilVersion -ge [version]"10.0.16299.15" ){ certutil.exe | findstr "Config" | %{ $_.Split(':')[1]; } | foreach{ $_.ToString().Trim() } > CAServers.csv }
else{ certutil.exe | findstr "Config" | %{ $_.Split('`')[1]; } | %{$_.Substring(0, $_.length - 1) } > CAServers.csv }
foreach($line in Get-Content .\CAServers.csv) {
$CA = certutil.exe -config $line -CATemplates | findstr "Auto-Enroll" | %{ $_.Split(':')[0]; }
$COUNT = $CA.count
for (($i = 0); $i -lt $COUNT; $i++){
write-output "$($line),$($CA[$i])" >> .\TemplatePropCommonName.csv
}
}
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#Generate all the Certificate Templates OID List export into Template-OID.csv
foreach($line in Get-Content .\TemplatePropCommonName.csv) {
$TemplateName = $line | %{ $_.Split(',')[1]; }
$Parameter = "CN="+$TemplateName+",CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,"+$ForestDC
$TemplateOID = Get-ADObject $Parameter -Properties msPKI-Cert-Template-OID | findstr "msPKI-Cert-Template-OID" | %{ $_.Split(':')[1]; } | %{$_.Substring(1)}
write-output "$($TemplateName)=$($TemplateOID)" >> TemplateOID.csv
}
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#Find out which Certificate Template is used in the CSR file and which CA Server has the Template and generate the CA Server List menu
if ( $CSRfileOID ){
$CSRTemplateOID = Select-String -Path .\TemplateOID.csv -Pattern $CSRfileOID | foreach{ $_.ToString() } | %{ $_.Split(':')[3]; } | select-object -First 1
$CSRTemplateName = Select-String -Path .\TemplateOID.csv -Pattern $CSRfileOID | foreach{ $_.ToString() } | %{ $_.Split(':')[3]; } | %{ $_.Split('=')[0]; } | select-object -First 1
if ( ([string]::IsNullOrEmpty($CSRTemplateName)) ){
write-host "This Certificate Template doesn't exist in the CA Servers! Need to re-generate the CSR file or check the Domain Forest!"
exit
}else {
Write-Output "CSR file $($CSRfile) uses Certificate Template:"
Write-output $CSRTemplateOID
Write-Output ""
$i = 1
$menu = @{}
write-output "------------------------------------------------------------------------------------------------------"
write-output "Following CA Servers have this Certificate Template:"
foreach($line in Get-Content .\CAServers.csv) {
$result = certutil.exe -config $line -CATemplates | findstr $CSRTemplateName":"
if ( $result ){
Write-Host "$i. $line"
$menu.Add($i, ($line))
$i++
}
}
}
}else {
write-output "------------------------------------------------------------------------------------------------------"
Write-Output "CSR file $($CSRfile) doesn't use the Certificate Template. Please choose one Template from the following list:"
get-content -Path .\TemplateOID.csv | %{ $_.Split('=')[0]; } | Sort-Object | Get-Unique > TemplateMenu.csv
$i = 1
$menu = @{}
foreach($line in Get-Content .\TemplateMenu.csv) {
Write-Host "$i. $line"
$menu.Add($i, ($line))
$i++
}
[int]$ans = Read-Host "Please select the CA server to gnenerate the Certificate [ 1 - $($i-1) ]"
$selection = $menu.Item($ans)
if ( ([string]::IsNullOrEmpty($selection)) ){
write-output "------------------------------------------------------------------------------------------------------"
Write-Output "Selection Wrong, Please correct it and try again."
}else { $CSRTemplateName = $selection }
write-output "------------------------------------------------------------------------------------------------------"
write-output "Following CA Servers have this Certificate Template:"
$i = 1
$menu = @{}
foreach($line in Get-Content .\CAServers.csv) {
$result = certutil.exe -config $line -CATemplates | findstr ^$CSRTemplateName":"
if ( $result ){
Write-Host "$i. $line"
$menu.Add($i, ($line))
$i++
}
}
}
# ------------------------------------------------------------------------------------------------------------------------------------------------------
#Generate the Certificate.
if ( $ENV -eq "-cert" ){
[int]$ans = Read-Host "Please select the CA server to gnenerate the Certificate [ 1 - $($i-1) ]"
$selection = $menu.Item($ans)
if ( ([string]::IsNullOrEmpty($selection)) ){
write-output "------------------------------------------------------------------------------------------------------"
Write-Output "Selection Wrong, Please correct it and try again."
}else{
if ( ([string]::IsNullOrEmpty($CSRfileSAN)) ){
if ( $CSRfileCN -match "\*") { $CERFILENAME = $CSRfileCN -replace "\*", "wildcard" } else{ $CERFILENAME = $CSRfileCN }
[string[]] $SANArray = @()
$SANArray = Read-Host "Please input the SANs [ Example: 192.168.0.1,www.example.com,test.example.com ] (Use comma "," as Delimiter)"
$SANArray = $SANArray.Split(',').Split(' ')
if ( ([string]::IsNullOrEmpty($SANArray)) ){
$CSRfileSAN = $CSRfileCN
$RequestIdOutPut = certreq -f -q -Submit -Attrib "CertificateTemplate:$CSRTemplateName\nSAN:dns=$CSRfileSAN" -config $selection .\$CSRfile "$($CERFILENAME).cer"
} else{
if ( $SANArray.contains($CSRfileCN) ){
$CSRfileSAN = "SAN:dns="+$SANArray[0]
for ($i=1;$i -lt $SANArray.length;$i++){ $CSRfileSAN = $CSRfileSAN+"&dns="+$SANArray[$i] }
}else{
$CSRfileSAN = "SAN:dns="+$CSRfileCN
for ($i=0;$i -lt $SANArray.length;$i++){ $CSRfileSAN = $CSRfileSAN+"&dns="+$SANArray[$i] }
}
$RequestIdOutPut = certreq -f -q -Submit -Attrib "CertificateTemplate:$CSRTemplateName\n$CSRfileSAN" -config $selection .\$CSRfile "$($CERFILENAME).cer"
}
$RequestId = $RequestIdOutPut[0] | %{ $_.Split(':')[1]; } | foreach{ $_.ToString().Trim() }
$CAServer = $selection | %{ $_.Split('\')[0]; } | foreach{ $_.ToString().Trim() }
write-output "This Request Id is $($RequestId)"
if ( Test-Path -Path "$($CERFILENAME).cer" ) { write-Output "Certificate $($CERFILENAME).cer generate successfully!" }else{ Get-PendingRequest -CA $CAServer -RequestID $RequestId | Approve-CertificateRequest
$CertPath = Get-Location
Get-IssuedRequest -CA $CAServer -RequestId $RequestId | Receive-Certificate -Path "$CertPath"
Rename-Item -Path "RequestID_$RequestId.cer" -NewName "$CERFILENAME.cer"
}
}else{
if ( $CSRfileCN -match "\*") { $CERFILENAME = $CSRfileCN -replace "\*", "wildcard" } else{ $CERFILENAME = $CSRfileCN }
if ( !$($CSRfileSAN.contains($CSRfileCN)) ) {
$SANArray = @($CSRfileSAN)
$CSRfileSAN = "SAN:dns="+$CSRfileCN
for ($i=0;$i -lt $SANArray.length;$i++){ $CSRfileSAN = $CSRfileSAN+"&dns="+$SANArray[$i] }
$RequestIdOutPut = certreq -f -q -Submit -Attrib "CertificateTemplate:$CSRTemplateName\n$CSRfileSAN" -config $selection .\$CSRfile "$($CERFILENAME).cer"
}else { $RequestIdOutPut = certreq -f -q -Submit -Attrib "CertificateTemplate:$CSRTemplateName" -config $selection .\$CSRfile "$($CERFILENAME).cer" }
$RequestId = $RequestIdOutPut[0] | %{ $_.Split(':')[1]; } | foreach{ $_.ToString().Trim() }
$CAServer = $selection | %{ $_.Split('\')[0]; } | foreach{ $_.ToString().Trim() }
write-output "This Request Id is $($RequestId)"
if ( Test-Path -Path "$($CERFILENAME).cer" ) {
write-Output "Certificate $($CERFILENAME).cer generate successfully!"
}else{
Get-PendingRequest -CA $CAServer -RequestID $RequestId | Approve-CertificateRequest
$CertPath = Get-Location
Get-IssuedRequest -CA $CAServer -RequestId $RequestId | Receive-Certificate -Path "$CertPath"
Rename-Item -Path "RequestID_$RequestId.cer" -NewName "$CERFILENAME.cer"
}
}
}
}else{
write-output "------------------------------------------------------------------------------------------------------"
Write-Output "If need generate the Certificate, please use the Verbs <-cert>"
Write-Output "---USAGE: CSRtoCER.ps1 csrfilename [-cert]---"
}
}else {
Write-Output "Sorry, $($CSRfile) doesn't exist. Please correct it and try again."
Write-Output "---USAGE: CSRtoCER.ps1 csrfilename [-cert]---"
}
}