NTS.Tools.MSADCS.psm1
function Start-Certutil { <# .Description A Function to start certuil via parameters .Parameter Parameters string for the certutil parameters, these must be separated with " " .Example # executes the certutil command with parameter view and out Start-Certutil -Parameters "-view -out SerialNumber" .NOTES this function is just a wrapper for cerutil #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $Parameters ) $SuccessPattern = "command completed successfully" try { Write-Verbose "executing certutil with parameters '$($Parameters)'" $CertutilMessage = & certutil.exe $Parameters.Split(" ") if ($null -eq ($CertutilMessage | Select-String -Pattern $SuccessPattern)) { throw $CertutilMessage } else { return $CertutilMessage } } catch { throw $PSItem.Exception.Message } } function Set-CAConfig { <# .Description This function kann be used to set some settings on the certification authority by using certutil. .Parameter CAType Type of CA .Parameter Domain_DistinguishedName Distinguished name of domain .Parameter WebServer_URL FQDN of web server that will host the crl .Parameter ValidityPeriodUnits units of validity period for certificate .Parameter ValidityPeriod type of validity period for certificate .Parameter CRLPeriod type of validity period for crl .Parameter CRLPeriodUnits units of validity period for crl .Parameter CRLDeltaPeriod type of validity period for delta crl .Parameter CRLDeltaPeriodUnits units of validity period for delta crl .Example # configures the local ca with specified values Set-CAConfig -CAType "RootCA" ` -Domain_DistinguishedName $Domain_DistinguishedName ` -WebServer_URL $WebServer_URL ` -ValidityPeriodUnits $RootCA_RenewalValidityPeriodUnits ` -ValidityPeriod $RootCA_RenewalValidityPeriod ` -CRLPeriod $RootCA_CRLPeriod ` -CRLPeriodUnits $RootCA_CRLPeriodUnits ` -CRLDeltaPeriod $RootCA_CRLDeltaPeriod ` -CRLDeltaPeriodUnits $RootCA_CRLDeltaPeriodUnits .NOTES this function is just a wrapper for cerutil #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateSet("RootCA", "SubCA")] [string] $CAType, [Parameter(Mandatory = $true)] [string] $Domain_DistinguishedName, [Parameter(Mandatory = $true)] [string] $WebServer_URL, [Parameter(Mandatory = $false)] [string] $ValidityPeriodUnits, [Parameter(Mandatory = $false)] [string] $ValidityPeriod, [Parameter(Mandatory = $false)] [string] $CRLPeriod, [Parameter(Mandatory = $false)] [string] $CRLPeriodUnits, [Parameter(Mandatory = $false)] [string] $CRLDeltaPeriod, [Parameter(Mandatory = $false)] [string] $CRLDeltaPeriodUnits ) if ($CAType -eq "RootCA") { if ($ValidityPeriodUnits -eq "" -or $null -eq $ValidityPeriodUnits) { $ValidityPeriodUnits = "10" } if ($ValidityPeriod -eq "" -or $null -eq $ValidityPeriod) { $ValidityPeriod = "years" } if ($CRLPeriod -eq "" -or $null -eq $CRLPeriod) { $CRLPeriod = "weeks" } if ($CRLPeriodUnits -eq "" -or $null -eq $CRLPeriodUnits) { $CRLPeriodUnits = "26" } if ($CRLDeltaPeriod -eq "" -or $null -eq $CRLDeltaPeriod) { $CRLDeltaPeriod = "hours" } if ($CRLDeltaPeriodUnits -eq "" -or $null -eq $CRLDeltaPeriodUnits) { $CRLDeltaPeriodUnits = "0" } } elseif ($CAType -eq "SubCA") { if ($ValidityPeriodUnits -eq "" -or $null -eq $ValidityPeriodUnits) { $ValidityPeriodUnits = "5" } if ($ValidityPeriod -eq "" -or $null -eq $ValidityPeriod) { $ValidityPeriod = "years" } if ($CRLPeriod -eq "" -or $null -eq $CRLPeriod) { $CRLPeriod = "days" } if ($CRLPeriodUnits -eq "" -or $null -eq $CRLPeriodUnits) { $CRLPeriodUnits = "3" } if ($CRLDeltaPeriod -eq "" -or $null -eq $CRLDeltaPeriod) { $CRLDeltaPeriod = "days" } if ($CRLDeltaPeriodUnits -eq "" -or $null -eq $CRLDeltaPeriodUnits) { $CRLDeltaPeriodUnits = "0" } } try { Write-Output "$($env:COMPUTERNAME): configuring ca setting" Start-Certutil -Parameters "-setreg CA\DSConfigDN `"CN=Configuration,$($Domain_DistinguishedName)`"" Start-Certutil -Parameters "-setreg CA\ValidityPeriodUnits $($ValidityPeriodUnits)" Start-Certutil -Parameters "-setreg CA\ValidityPeriod $($ValidityPeriod)" Start-Certutil -Parameters "-setreg CA\CRLPeriodUnits $($CRLPeriod)" Start-Certutil -Parameters "-setreg CA\CRLPeriod $($CRLPeriodUnits)" Start-Certutil -Parameters "-setreg CA\CRLDeltaPeriodUnits $($CRLDeltaPeriodUnits)" Start-Certutil -Parameters "-setreg CA\CRLDeltaPeriod $($CRLDeltaPeriod)" Start-Certutil -Parameters "-setreg CA\CRLPublicationURLs `"1:$($env:windir)\system32\CertSrv\CertEnroll\%3%8%9.crl\n2:http://$($WebServer_URL)/CertEnroll/%3%8%9.crl\n10:LDAP:///CN=%3%8,CN=%3,CN=CDP,CN=Public Key Services,CN=Services,%6%10`"" Start-Certutil -Parameters "-setreg CA\CACertPublicationURLs `"1:$($env:windir)\system32\CertSrv\CertEnroll\%3.crt\n2:http://$($WebServer_URL)/CertEnroll/%3%4.crt\n2:LDAP:///CN=%3,CN=AIA,CN=Public Key Services,CN=Services,%6%11`"" Start-Certutil -Parameters "-setreg CA\AuditFilter 127" Start-Certutil -Parameters "-setreg CA\forceteletex +0x20" Start-Certutil -Parameters "-setreg policy\EditFlags -EDITF_ADDOLDKEYUSAGE" Restart-Service -Name certsvc | Out-Null Start-Sleep -Seconds 5 } catch { throw "error configuring ca settings - $($PSItem.Exception.Message)" } } function Set-CAPolicyInfFile { <# .Description Creates a CAPolicy.inf file at $($env:SystemDrive)\Windows\ with specified values .Parameter RootCA use this switch to configure a rootca capolicy.inf file .Parameter SubCA use this switch to configure a subca capolicy.inf file .Parameter Renewalkeylength length of key for renewal .Parameter RenewalValidityPeriodUnits unit of key for renewal .Parameter RenewalValidityPeriod type of key for renewal .Parameter CRLPeriod type of validity period for crl .Parameter CRLPeriodUnits units of validity period for crl .Parameter CRLDeltaPeriod type of validity period for delta crl .Parameter CRLDeltaPeriodUnits units of validity period for delta crl .Parameter DiscreteSignatureAlgorithm DiscreteSignatureAlgorithm .Example # creates a capolicy.inf for a root ca Set-CAPolicyInfFile -RootCA ` -Renewalkeylength $RootCA_Key_Length ` -RenewalValidityPeriod $RootCA_Key_ValidityPeriod ` -RenewalValidityPeriodUnits $RootCA_Key_ValidityPeriodUnits ` -CRLPeriod $RootCA_CRL_Period ` -CRLPeriodUnits $RootCA_CRL_PeriodUnits ` -CRLDeltaPeriod $RootCA_CRLDelta_Period ` -CRLDeltaPeriodUnits $RootCA_CRLDelta_PeriodUnits ` -DiscreteSignatureAlgorithm $RootCA_DiscreteSignatureAlgorithm .NOTES this used some predefined values #> param ( [Parameter(ParameterSetName = 'RootCA', Mandatory = $false)] [switch] $RootCA, [Parameter(ParameterSetName = 'SubCA', Mandatory = $false)] [switch] $SubCA, [Parameter(ParameterSetName = 'RootCA', Mandatory = $false)] [Parameter(ParameterSetName = 'SubCA', Mandatory = $false)] [string] $Renewalkeylength, [Parameter(ParameterSetName = 'RootCA', Mandatory = $false)] [Parameter(ParameterSetName = 'SubCA', Mandatory = $false)] [string] $RenewalValidityPeriodUnits, [Parameter(ParameterSetName = 'RootCA', Mandatory = $false)] [Parameter(ParameterSetName = 'SubCA', Mandatory = $false)] [string] $RenewalValidityPeriod, [Parameter(ParameterSetName = 'RootCA', Mandatory = $false)] [string] $CRLPeriod, [Parameter(ParameterSetName = 'RootCA', Mandatory = $false)] [string] $CRLPeriodUnits, [Parameter(ParameterSetName = 'RootCA', Mandatory = $false)] [string] $CRLDeltaPeriod, [Parameter(ParameterSetName = 'RootCA', Mandatory = $false)] [string] $CRLDeltaPeriodUnits, [Parameter(ParameterSetName = 'RootCA', Mandatory = $false)] [string] $DiscreteSignatureAlgorithm ) $ErrorActionPreference = 'Stop' # define default values if ($RootCA) { if ($Renewalkeylength -eq "") { $Renewalkeylength = "4096" } if ($RenewalValidityPeriod -eq "") { $RenewalValidityPeriod = "years" } if ($RenewalValidityPeriodUnits -eq "") { $RenewalValidityPeriodUnits = "10" } if ($CRLPeriod -eq "") { $CRLPeriod = "weeks" } if ($CRLPeriodUnits -eq "") { $CRLPeriodUnits = "26" } if ($CRLDeltaPeriodUnits -eq "") { $CRLDeltaPeriodUnits = "0" } if ($DiscreteSignatureAlgorithm -eq "") { $DiscreteSignatureAlgorithm = "1" } $CAPolicy_Value = "[Version] Signature= `"`$Windows NT$`" [certsrv_server] renewalkeylength = $($renewalkeylength) RenewalValidityPeriodUnits = $($RenewalValidityPeriodUnits) RenewalValidityPeriod = $($RenewalValidityPeriod) CRLPeriod = $($CRLPeriod) CRLPeriodUnits = $($CRLPeriodUnits) CRLDeltaPeriod = $($CRLDeltaPeriod) CRLDeltaPeriodUnits = $($CRLDeltaPeriodUnits) DiscreteSignatureAlgorithm = $($DiscreteSignatureAlgorithm) [CRLDistributionPoint] Empty = true [AuthorityInformationAccess] Empty = true [Extensions] 2.5.29.15 = AwIBBg== Critical = 2.5.29.15 " } elseif ($SubCA) { if ($Renewalkeylength -eq "") { $Renewalkeylength = "4096" } if ($RenewalValidityPeriod -eq "") { $RenewalValidityPeriod = "years" } if ($RenewalValidityPeriodUnits -eq "") { $RenewalValidityPeriodUnits = "5" } $CAPolicy_Value = "[Version] Signature = `"`$Windows NT`$`" [Extensions] 2.5.29.15 = AwIBBg== Critical = 2.5.29.15 [certsrv_server] RenewalKeyLength = $($Renewalkeylength) RenewalValidityPeriodUnits = $($RenewalValidityPeriodUnits) RenewalValidityPeriod = $($RenewalValidityPeriod) LoadDefaultTemplates=0 [PolicyStatementExtension] Policies = AllIssuancePolicy [AllIssuancePolicy] OID = 2.5.29.32.0 " } else { throw "no ca type was selected" } try { $CAPolicy_Path = "$($env:SystemDrive)\Windows\CAPolicy.inf" Write-Output "$($env:COMPUTERNAME): creating $($CAPolicy_Path)" New-ItemIfNotExists -Path $CAPolicy_Path -ItemType File Set-Content -Path $CAPolicy_Path -Value $CAPolicy_Value } catch { throw "error creating $($CAPolicy_Path) - $($psitem.Exception.Message)" } } function New-CACRL { <# .Description runs certutil -CRL .Example # creates a new crl New-CACRL .NOTES #> #region crl try { Write-Output "$($env:COMPUTERNAME): creating crl" Start-Certutil -Parameters "-CRL" } catch { throw "error creating crl - $($PSItem.Exception.Message)" } #endregion } function Install-CACert { <# .Description installs the certificate of a sub ca to activate it .Parameter CerFilePath path to certificate file to install for ca .Example # this will install the certificate of the local ca Install-CACert -CerFilePath $SubCA_CerFilePath .NOTES should only be run on an enterprise subca #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $CerFilePath ) $ServiceName = "CertSvc" try { Write-Output "$($env:COMPUTERNAME): installing ca cert to activate ca" Start-Process -FilePath GPUpdate -ArgumentList "/force" -Wait -WindowStyle Hidden Start-Certutil -Parameters "-installCert $($CerFilePath)" Start-Service -Name $ServiceName | Out-Null Restart-Service -Name $ServiceName | Out-Null } catch { throw $PSItem.Exception.Message } } function Publish-CACRLToAD { <# .Description runs certutil -dspublish -f $CRLPath .Parameter CRLPath path to crl file .Example # published the certificate revocation list to ad Publish-CACRLToAD -CRLPath $BaseCRLPath .NOTES #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $CRLPath ) try { if (Test-Path -Path $CRLPath) { Start-Certutil -Parameters "-dspublish -f $($CRLPath)" } else { throw "cannot find $($CRLPath)" } } catch { throw "error publishing crl - $($PSItem.Exception.Message)" } } function Enable-ScheduledTaskForCRLCreation { <# .Description Creates a script and a scheduled task to automate crl creation .Parameter SMBSharePath smb share path .Parameter CACommonName CA Name .Parameter CAServerName CA Server Name .Parameter ScriptName Name of the script .Parameter ScriptFolder path to the script, it will be created there .Example # creates the script and scheduled task Enable-ScheduledTaskForCRLCreation -SMBSharePath "\\$($WEB_Obj.Name).$($env:USERDNSDOMAIN)\CertEnroll" ` -CACommonName $SubCA_Initial_CACommonName ` -CAServerName $SubCA_Obj.Name .NOTES Scheduled Task Properties $Trigger = New-JobTrigger -Daily -At "4:00 AM" -DaysInterval 1 $User = "NT AUTHORITY\SYSTEM" $Action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File $($Script_FilePath)" #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $SMBSharePath, [Parameter(Mandatory = $true)] [string] $CACommonName, [Parameter(Mandatory = $true)] [string] $CAServerName, [Parameter(Mandatory = $false)] [string] $ScriptName = "Publish-DailyCRL", [Parameter(Mandatory = $false)] [string] $ScriptFolder = "$($env:ProgramData)\NTS\CertSrv" ) try { $Script_FilePath = "$($ScriptFolder)\$($ScriptName).ps1" $ScriptContent = "Start-Process -FilePath certutil -ArgumentList `"-CRL`" -Wait -WindowStyle Hidden Copy-Item -Path `"$($env:windir)\system32\certsrv\certenroll\*`" -Destination `"$($SMBSharePath)`" -Force `$Path = `"$($SMBSharePath)\$($CAServerName).$($env:USERDNSDOMAIN)_$($CACommonName).crt`" if(Test-Path -Path `$Path) { if(Test-Path -Path `"$($SMBSharePath)\$($CACommonName).crt`") { Remove-Item -Path `"$($SMBSharePath)\$($CACommonName).crt`" -Force } Rename-Item -Path `$Path -NewName `"$($CACommonName).crt`" } " Write-Output "$($env:COMPUTERNAME): creating scheduled task to publish crl on a daily basis" try { New-ItemIfNotExists -Path $ScriptFolder -ItemType Directory New-Item -Path $Script_FilePath -ItemType File -Force | Out-Null Set-Content -Path $Script_FilePath -Value $ScriptContent -Force } catch { throw "$($env:COMPUTERNAME): error creating files: $($PSItem.Exception.Message)" } try { $Trigger = New-JobTrigger -Daily -At "4:00 AM" -DaysInterval 1 $User = "NT AUTHORITY\SYSTEM" $Action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File $($Script_FilePath)" Register-ScheduledTask -TaskName $ScriptName -Trigger $Trigger -User $User -Action $Action -RunLevel Highest -Force | Out-Null } catch { throw "$($env:COMPUTERNAME): error creating task: $($PSItem.Exception.Message)" } Write-Output "$($env:COMPUTERNAME): starting task" Start-ScheduledTask -TaskName $ScriptName } catch { throw "error creating task - $($PSItem.Exception.Message)" } #endregion } function Complete-CertRequest { <# .Description this function can be used to sign a certificate request using the local ca .Parameter CertReqFilePath path to the certificate request .Parameter CAName name of the local ca .Example # completes the request Complete-CertRequest -CertReqFilePath $CertReqFilePath -CAName $CAName .NOTES #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $CertReqFilePath, [Parameter(Mandatory = $true)] [string] $CAName ) Write-Output "$($env:COMPUTERNAME): trying to sign the subca cert req" if (Test-Path -Path $CertReqFilePath) { $SubCA_CerFilePath = $CertReqFilePath.Replace(".req", ".cer") # load req into cert authority try { Write-Output "$($env:COMPUTERNAME): loading subca request into ca" $ImportResult = certreq -submit -q -config - "$($CertReqFilePath)" "$($SubCA_CerFilePath)" if ($ImportResult -like "*ERROR_FILE_EXISTS*" ) { Remove-Item -Path "$($CertReqFilePath.Replace(".req",".rsp"))" -Force } $ReqID = ($ImportResult -like "*RequestId: *")[0].Replace("RequestId: ", "") } catch { throw "error importing ca req file - $($PSItem.Exception.Message)" } # sign req Write-Output "$($env:COMPUTERNAME): submitting subca request" $SubmitResult = Start-Certutil -Parameters "-config $($CAName) -resubmit $($ReqID)" if ($SubmitResult[-1] -notlike "*command completed successfully*") { throw "$($env:COMPUTERNAME): submit was not successful:`n$($SubmitResult)" } # export cer to file Write-Output "$($env:COMPUTERNAME): exporting signed subca cert" $ExportResult = Start-Certutil -Parameters "-config $($CAName) -view -restrict requestid=$($ReqID) -out rawcertificate" if ($ExportResult[-1] -like "*command completed successfully*") { $FirstFilterString = "-----BEGIN CERTIFICATE-----" $SecondFilterString = "-----END CERTIFICATE-----" $RegexPattern = "$($FirstFilterString)(.*?)$($SecondFilterString)" #Perform the opperation $CertFileValue = $firstString + "`n" + ([regex]::Match($ExportResult, $RegexPattern).Groups[1].Value) + "`n" + $secondString New-Item -Path $SubCA_CerFilePath -ItemType File -Force | Out-Null Set-Content -Path $SubCA_CerFilePath -Value $CertFileValue | Out-Null } else { throw "$($env:COMPUTERNAME): file could not be created:`n$($ExportResult)" } } else { throw "$($env:COMPUTERNAME): cert req file could not be found at $($CertReqFilePath)" } } |