<# .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}" } }