Files
Backup/_NDGOV_WindowsTeam/ITD.Infra-Servers-PowerShellUniversal.Production/Infra-Certificate-External.Sectigo/New-SectigoPfxCertificate.ps1
T
Zack Meier 1d304511b8 update
2026-04-15 15:45:50 -05:00

426 lines
14 KiB
PowerShell

<#
.SYNOPSIS
Sectigo Certificate Creator
.DESCRIPTION
Creates a Sectigo Certificate for ITD Organization
.NOTES
Requires:
ITD.Infra-Certificate-Internal.Sectigo
.LINK
https://northdakota.service-now.com/kb_view.do?sysparm_article=KB0018128
#>
[CmdletBinding(DefaultParameterSetName = 'Windows')]
param(
# Email address for notifications, comma seperated
# [Parameter(Mandatory, ParameterSetName = 'Windows')]
# [Parameter(Mandatory, ParameterSetName = 'Cloud Service')]
# [String]$RequesterEmail,
# Common Name for cert
[Parameter(Mandatory, ParameterSetName = 'Windows')]
[Parameter(Mandatory, ParameterSetName = 'Cloud Service')]
[String]$CommonName,
# Comma separated.
[Parameter(Mandatory, ParameterSetName = 'Windows')]
[Parameter(Mandatory, ParameterSetName = 'Cloud Service')]
[String]$SubjectAlternative,
# Host for Cert Delivery, comma seperated
[Parameter(Mandatory, ParameterSetName = 'Windows')]
[String]$DestinationServer,
# Option for pfx in PasswordState
[Parameter(Mandatory, ParameterSetName = 'Windows')]
[bool]$PfxtoPasswordState,
# AppName CI in CMDB
[Parameter(Mandatory, ParameterSetName = 'Cloud Service')]
[String]$ApplicationName
)
process {
#Find-Module -Repository ITD_PwshGallery -Name ITD.Infra-Certificate-External.General|Update-Module -Scope CurrentUser
#exit
Import-Module ITD.Infra-Certificate-External.General -DisableNameChecking
Import-Module ITD.Infra-Certificate-External.JsonDB
#We reusing and breaking it up to an array for further use in script
$DestinationServerArray = $DestinationServer -split ","
#PSU Reassignment per Zacks standards
$RequestedBy = $UAJob.Identity.Name # user that started the job
$PSUJobId = $UAJob.Id
#$Test Mode
# - Blocks Access to selected users
# - Uses Test Environment for ServiceNow Change
# - Variable can be used for debugging
$ApprovedTester=@('prvfjpeterson@nd.gov','prvjdkieson@nd.gov')
if ($test) {
Write-Verbose -Message "Running in Test Mode " -Verbose
if ($ApprovedTester -contains $RequestedBy)
{
"You are allowed but others are disabled"
}
else {
Write-Error "Check with freeman script is currenly disabled"
# exit
}
}
#Set ad Default to Hide from End user.
$ServerType="IIS"
$Format="base64"
$KeyType="RSA" #reminder this would need to be set on csr.
$mydate=(Get-Date -Format 'yyyy-MM-dd'|out-string).Trim()
$FriendlyName = $CommonName + "-" +$myDate
#Write-Verbose -Message "Update Module" -Verbose
#Find-Module -Repository ITD_PwshGallery -Name ITD.Infra-Certificate-External.Sectigo |Update-Module -Scope AllUsers
if ($PSCmdlet.ParameterSetName -eq 'Windows') {
Write-Verbose -Message "Validate host" -Verbose
Foreach ($ComputerName in $DestinationServerArray) {
$remotehi=Invoke-Command -ComputerName $ComputerName -ScriptBlock {"hi"} -Credential $Secret:ndgov_svcitdpsuwin
if ($remotehi -eq "hi") {
"Connection to host $ComputerName Succeded"
} else {
"Connection to host $ComputerName failed"
exit
}
}
}
if ($PSCmdlet.ParameterSetName -eq 'Windows') {
Write-Verbose -Message "Retrieve CI from ServiceNow" -Verbose
#We are just pulling appname from first DestinationServer
New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred
$IP=(Resolve-DnsName -Name $DestinationServerArray[0]).IPAddress
$Filter= "ip_address=$ip^operational_status=1"
$Fields=("FQDN","ip_address","Location","model_id","Name","dns_domain","os_domain","Schedule","Environment","sys_class_name","u_nd_application_svc","discovery_source","support_group")
$CI= Get-ITDServiceNowRecord -Table "cmdb_ci_win_server" -Filter $Filter -Fields $Fields -First 1
$ApplicationName=$CI.u_nd_application_svc.display_value
if (!$ApplicationName) {
write-Error "CI NOT FOUND"
exit
}
$customFields = @(
[pscustomobject]@{ name = "ApplicationName"; value = $ApplicationName }
)
}
else { #ParmeterSet Not Windows
Write-Verbose -Message "Retrieve App record from ServiceNow" -Verbose
New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred
$Filter= "name=$ApplicationName"
$Fields=("name")
$CI= Get-ITDServiceNowRecord -Table "cmdb_ci_service_auto" -Filter $Filter -Fields $Fields
if ($CI.name.value -ne $ApplicationName ) {
Write-Error "Could not find $ApplicationName"
exit
}
}
#Got email address now!
$RequesterEmail=Get-ICE-Snowemail -ApplicationName $ApplicationName -Credential $Secret:snow_vmcred
Send-ICE-Mail -recipientsString $RequesterEmail -Jobid $PSUJobId -status "Started" -Message "Check job status"
Write-Verbose -Message "Validate Email Address" -Verbose
$EmailAddressList = $RequesterEmail -split ","
foreach ($e in $EmailAddressList) {
$user = Get-ADUser -Filter "Mail -eq '$e'" -Properties Mail
$group = Get-ADGroup -Filter "Mail -eq '$($e)'" -Properties Mail
if ($user -or $group) {
Write-Verbose -Message "$e Passed testing" -Verbose
}
else {
Write-Error "$e is an invalid email address. Terminating Script"
exit
}
}
$RequesterEmail=Get-ICE-Snowemail -ApplicationName $ApplicationName -Credential $Secret:snow_vmcred
#Set env prod
Set-JDEnvironment -Name prod
Write-Verbose -Verbose "Retire PreviousThumbprint"
$PreviousThumbprint=(Select-JDJson -TableName certcache -CommonName $commonname).Thumbprint
if ($PreviousThumbprint) {
$table=@("certlog","certcache")
Foreach ($t in $table) {
Set-JDJson -TableName $t `
-Where { param($row) $row.CommonName -eq $commonname } `
-Set @{ is_retired = $true; PreviousThumbprint = $PreviousThumbprint } `
-Verbose
} #end of foreach
} #end of if $Previous thumbprint
# Done validation
#
# Do the work
#
#
Write-Verbose -Message "Create CSR" -Verbose
$csr = New-ICE-CSR -commonName $commonName
Write-Verbose -Message "Test CSR" -Verbose
If (Test-ICE-CSR -csrstring $csr) {
"CSR Passed"
}
else {
Write-Error "Not A Valid CSR"
}
$Comments="Enrolled by PSUniversal, Job " + $UAJob.Id + ", User " + $UAJob.Identity.Name + "," + $Comments
if ($ApplicationName)
{
$customFields = @(
@{
name = "ApplicationName"
value = $ApplicationName
}
)
}
Write-Verbose -Message "Setting up params for Enroll-SectigoCertificateRequest" -Verbose
$splat = @{
Csr=$csr
dcvEmail=$RequesterEmail
Comment=$Comments
KeyType=$KeyType
subjAltNames=$SubjectAlternative
}
$b1 = @{
customFields = $customFields
}
if ($customFields) {
$splat = $splat+ $b1
}
$cred=$Secret:SectigoClientSecret
$env:Sectigoclientid = $cred.UserName
$env:SectigoclientSecret = $cred.GetNetworkCredential().Password
Write-Verbose -Message "Enroll-SectigoCertificateRequest" -Verbose
Get-SectigoApiToken
$certRequest = Enroll-SectigoCertificateRequest @Splat
Write-Verbose -Message "Waiting for Cert Status" -Verbose
while ($certstatus -ne "Issued") {
$certstatus=(Get-SectigoCertificate -OrderId $certRequest.sslid).status
Sleep 1
$run= $run + 1
if ($run -gt 60) {
Write-Error "Failed to get issue status after 1 minute..exiting"
exit
}
}
Write-Verbose -Message "Downloading Certificate" -Verbose
$CertRootPath="c:\psautocerts\"
mkdir $CertRootPath 2>$null
$CertPath = (Download-SectigoCertificate -Orderid $certRequest.sslid -Format $Format -CertRootPath $CertRootPath).FullName
Write-Verbose -Message "Generate Password" -Verbose
$pfxPassword= Generate-ICE-PFXPassword
$secure_pfxpassword = ConvertTo-SecureString $pfxPassword -AsPlainText -Force
$pfxCredential = [System.Management.Automation.PSCredential]::new("None", $secure_pfxpassword)
Write-Verbose -Verbose "Convert to pfx"
$results=Convert-ICE-PKS7toPfx -CertFile $CertPath -pfxCredential $pfxCredential
$pfxPath=$results.Fullname
Write-Verbose -Verbose "Load the certificate object"
$collection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$collection.Import($pfxPath, $pfxPassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet)
# Display all certificates in the chain
#$collection | Format-List Subject, Issuer, Thumbprint, NotAfter
$foundCerts = $collection.Find([System.Security.Cryptography.X509Certificates.X509FindType]::FindBySubjectName, $CommonName, $false)
$ExpiryDate = $foundCerts[0].NotAfter
$Thumbprint=$foundCerts[0].Thumbprint
if ($PSCmdlet.ParameterSetName -eq 'Cloud Service') {
$PfxtoPasswordState=$True
}
if ($PfxtoPasswordState) {
Write-Verbose -Verbose "Save to Password State"
$PasswordStateParams = @{
Title = $FriendlyName;
Description = $Comments ;
ExpiryDate = $ExpiryDate ;
APICreds = $Secret:pwdvault_WindowsCertificates ;
pfxCredential = $pfxCredential;
PfxPath = $pfxPath;
}
$PasswordStateSuccess=Send-ICE-PfxtoPasswordState @PasswordStateParams
}
#Send file to cert store windows only"
if ($PSCmdlet.ParameterSetName -eq 'Windows') {
$CertificatetoCertStore = @{
pfxPath = $pfxPath;
RemoteCertPath = "c:\temp\certificatex.pfx";
DestinationServer = $DestinationServerArray
Credential = $Secret:ndgov_svcitdpsuwin ;
pfxCredential = $pfxCredential;
CertStoreLocation = "Cert:\LocalMachine\MY";
ThumbPrint = $ThumbPrint ;
FriendlyName = $FriendlyName
}
$CertStoreResults=Send-ICE-CertificatetoCertStore @CertificatetoCertStore
$CertStoreResults
}
Write-Verbose -Verbose "Cleaning Up Temp Files"
if (Test-Path -Path $CertPath -PathType Leaf) {
Remove-Item -Path $CertPath -Force -Confirm:$false 2>$null
}
if (Test-Path -Path $pfxPath -PathType Leaf) {
Remove-Item -Path $pfxPath -Force -Confirm:$false 2>$null
}
# Validate the user
$StartDateTime = (Get-Date)
$EndDateTime = $StartDateTime.AddMinutes(1)
$RequestedBy=$UAJob.Identity.Name
if ($PSCmdlet.ParameterSetName -eq 'Cloud Service' -and $PasswordStateSuccess -eq $True ) { $Completed=$true}
if ($PSCmdlet.ParameterSetName -eq 'Windows' -and $CertStoreResults.Success -eq $True) { $Completed=$true}
if ($Completed) {
Write-Verbose -Message "Create CHG request for the work" -Verbose
$ServiceNowEnvironment = "Production" #'Production', 'Test', 'Development'
New-ITDServiceNowSession -Environment $ServiceNowEnvironment -Credential $Secret:snow_vmcred
$NewITDServiceNowChangeRequestParams = @{
TemplateName = 'NDIT-SPS-PSU Cert Automation Platform'
RequestedByUsername = $RequestedBy.split('@')[0] -replace 'prv';
Category = 'Systems Platforms - Systems';
Subcategory = 'Windows';
Impact = 3;
ShortDescription = "New Certificate Created - PSU Job Id $PSUJobId";
Description = "New Certificate Created - PSU Job Id $PSUJobId";
Justification = "Security Standards require an updated certificate";
Implementation = "PSUniversal execution";
RiskImpactAnalysis = "Low";
BackoutPlan = "Revoke Cert"
TestPlan = "n/a"
WhoIsImpacted = "Windows System Administrators";
StartTime = $StartDateTime
EndTime = $StartDateTime.AddMinutes(1);
AssignmentGroup = 'NDIT-Computer Systems Windows';
ChangeManagerUsername = 'khellman';
ChangeCoordinatorUsername = 'gpgolberg';
AssignedToUsername = $RequestedBy.split('@')[0] -replace 'prv';
}
$CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams -Verbose
$CHGNum = $CHG.Number.value
Write-Verbose -Message ("Completing Snow " + $CHG.Number.value) -Verbose
$CompleteITDServiceNowChangeRequestParams = @{
Number = $CHG.Number.value
CloseCode = "Successful"
CloseNotes = ("New Certificate" + $obj.ADDomain + "\" + $obj.SamAccountName + " created.")
}
Complete-ITDServiceNowChangeRequest @CompleteITDServiceNowChangeRequestParams -Verbose
Write-Verbose -Message "Status Success" -Verbose
$Jobstatus = "Success"
}
Else {
Write-Verbose -Message "Status Failure" -Verbose
$JobStatus = "Failure"
}
Send-ICE-Mail -recipientsString $RequesterEmail -Jobid $PSUJobId -status $Jobstatus -Message "Created Standard Change"
$log_psobject=[pscustomobject]@{
Timestamp = (Get-Date)
ParameterSetName = $ParameterSetName
RequestedBy = $RequestedBy
RequesterEmail = $RequesterEmail
CommonName = $CommonName
SubjectAlternative = $SubjectAlternative
DestinationServer = $DestinationServer
PfxtoPasswordState = $PfxtoPasswordState
ApplicationName = $ApplicationName
ExpiryDate = $ExpiryDate
Thumbprint = $Thumbprint
PreviousThumbprint = $PreviousThumbprint
is_retired = $false
}
Write-Verbose -Verbose "Log new transaction to both tables. "
#Cache table common name is the primary key so there should only be an update?
$table=@("certlog","certcache")
Foreach ($t in $table) {
$log_psobject| Add-JDJson -TableName $t -Verbose
}
###########################################
if ($PasswordStateSuccess) {
"Your new Certificate is in PasswordState at: "
" Windows/Certificates/${FriendlyName}"
}
}