489 lines
14 KiB
PowerShell
489 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()]
|
|
param (
|
|
# [Parameter(Mandatory = $true,
|
|
# HelpMessage = "CRC TEXT ONLY")]
|
|
# [string]
|
|
# $CSR,
|
|
# [Parameter(Mandatory = $true,
|
|
# HelpMessage = "Csr File")]
|
|
# [file]
|
|
# $CSRfile,
|
|
# [Parameter(Mandatory = $true,
|
|
# HelpMessage = "Server Type")]
|
|
# [ValidateSet('IIS','IIS_OLD','IBM','LINUX','Apache','Tomcat')]
|
|
#[string]
|
|
#$ServerType="IIS",
|
|
|
|
[Parameter(Mandatory = $true,
|
|
HelpMessage = "Email address for notifications, comma seperated")]
|
|
[string]
|
|
$RequesterEmail,
|
|
|
|
[Parameter(Mandatory = $true,
|
|
HelpMessage = "Common Name for cert")]
|
|
[string]
|
|
$CommonName,
|
|
|
|
[Parameter(Mandatory = $true,
|
|
HelpMessage = "Comma separated.")]
|
|
[string]
|
|
$SubjectAlternative,
|
|
[Parameter(Mandatory = $true,
|
|
HelpMessage = "Host for Cert Delivery")]
|
|
[string]
|
|
$DestinationServer
|
|
|
|
#[Parameter(Mandatory = $true,
|
|
#HelpMessage = "Key Type for cert")]
|
|
#[string]
|
|
#[ValidateSet("RSA")]
|
|
|
|
|
|
|
|
#[Parameter(HelpMessage = "Optional Field, will be appended to standard comments")]
|
|
#[string]
|
|
#$Comments
|
|
|
|
#[Parameter(Mandatory = $true,
|
|
# HelpMessage = "File Format")]
|
|
#[ValidateSet('x509','x509CO','base64','bin','x509IOR','pem','pemco','pemia','x509R')]
|
|
#[string]
|
|
#$Format="pem"
|
|
)
|
|
|
|
|
|
#PSU Reassignment per Zacks standards
|
|
$RequestedBy = $UAJob.Identity.Name # user that started the job
|
|
$PSUJobId = $UAJob.Id
|
|
|
|
$KeyType="RSA" #reminder this would need to be set on csr.
|
|
|
|
#Load Updated Modules
|
|
#Find-Module -Repository ITD_PwshGallery -Name ITD.Infra-Certificate-Internal.Sectigo | Update-Module
|
|
#exit
|
|
|
|
|
|
#Map script vars to ones that can be Changed for Display Only
|
|
$subjAltNames=$SubjectAlternative
|
|
$dsvEmail = $RequesterEmail
|
|
$myhost=$DestinationServer
|
|
|
|
#Set ad Default to Hide from End user.
|
|
$ServerType="IIS"
|
|
$Format="x509CO"
|
|
|
|
#Write-Verbose -Message $Secret:ndgov_svcitdpsuwin.username -Verbose
|
|
#Testing Service Now module
|
|
#Get-Command Get-ServiceNowRecord
|
|
|
|
|
|
#Block access while testing
|
|
#if ($RequestedBy -ne 'prvfjpeterson@nd.gov' -and $RequestedBy -ne 'prvnblowers@nd.gov' )
|
|
#{
|
|
# Write-Error "Check with freeman script is currenly disabled"
|
|
# exit
|
|
#}
|
|
|
|
if ($Csrfile){
|
|
$csr= [Text.Encoding]::UTF8.GetString($CSRfile.Content)
|
|
}
|
|
|
|
Write-Verbose -Message "Validate Email Address" -Verbose
|
|
$EmailAddressList = $dsvEmail -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
|
|
}
|
|
}
|
|
|
|
Write-Verbose -Message "Validate host" -Verbose
|
|
|
|
|
|
$remotehi=Invoke-Command -ComputerName $myhost -ScriptBlock {"hi"} -Credential $Secret:ndgov_svcitdpsuwin
|
|
if ($remotehi -eq "hi") {
|
|
"Connection to host Succeded"
|
|
} else {
|
|
"Connection to host failed"
|
|
exit
|
|
}
|
|
|
|
Write-Verbose -Message "Retrieve CI from ServiceNow" -Verbose
|
|
New-ITDServiceNowSession -Environment Production -Credential $Secret:snow_vmcred
|
|
$IP=(Resolve-DnsName -Name $DestinationServer).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 }
|
|
)
|
|
#done validation
|
|
|
|
#
|
|
# Do the work
|
|
#
|
|
#>
|
|
## Cert REquest
|
|
Write-Verbose -Message "Create CSR" -Verbose
|
|
$csrScriptBlock={
|
|
|
|
param ($commonName)
|
|
|
|
#######################
|
|
# Setting the variables
|
|
#######################
|
|
$UID = [guid]::NewGuid()
|
|
$files = @{}
|
|
$files['settings'] = "$($env:TEMP)\$($UID)-settings.inf";
|
|
$files['csr'] = "$($env:TEMP)\$($UID)-csr.req"
|
|
|
|
|
|
|
|
$request = @{}
|
|
$request['SAN'] = @{}
|
|
|
|
Write-Host "Provide the Subject details required for the Certificate Signing Request" -ForegroundColor Yellow
|
|
$request['CN'] = $commonName
|
|
$request['O'] = "NDIT"
|
|
$request['OU'] = "State Of North Dakota"
|
|
$request['L'] = "Bismarck"
|
|
$request['S'] = "ND"
|
|
$request['C'] = "US"
|
|
|
|
|
|
#########################
|
|
# Create the settings.inf
|
|
#########################
|
|
$settingsInf = "
|
|
[Version]
|
|
Signature=`"`$Windows NT`$
|
|
[NewRequest]
|
|
KeyLength = 2048
|
|
Exportable = TRUE
|
|
MachineKeySet = TRUE
|
|
SMIME = FALSE
|
|
RequestType = PKCS10
|
|
ProviderName = `"Microsoft RSA SChannel Cryptographic Provider`"
|
|
ProviderType = 12
|
|
HashAlgorithm = sha256
|
|
;Variables
|
|
Subject = `"CN={{CN}},OU={{OU}},O={{O}},L={{L}},S={{S}},C={{C}}`"
|
|
[Extensions]
|
|
{{SAN}}
|
|
;Certreq info
|
|
;http://technet.microsoft.com/en-us/library/dn296456.aspx
|
|
;CSR Decoder
|
|
;https://certlogik.com/decoder/
|
|
;https://ssltools.websecurity.symantec.com/checker/views/csrCheck.jsp
|
|
"
|
|
|
|
$request['SAN_string'] = & {
|
|
if ($request['SAN'].Count -gt 0) {
|
|
$san = "2.5.29.17 = `"{text}`"
|
|
"
|
|
Foreach ($sanItem In $request['SAN'].Values) {
|
|
$san += "_continue_ = `"dns="+$sanItem+"&`"
|
|
"
|
|
}
|
|
return $san
|
|
}
|
|
}
|
|
|
|
$settingsInf = $settingsInf.Replace("{{CN}}",$request['CN']).Replace("{{O}}",$request['O']).Replace("{{OU}}",$request['OU']).Replace("{{L}}",$request['L']).Replace("{{S}}",$request['S']).Replace("{{C}}",$request['C']).Replace("{{SAN}}",$request['SAN_string'])
|
|
|
|
# Save settings to file in temp
|
|
$settingsInf > $files['settings']
|
|
|
|
# Done, we can start with the CSR
|
|
#Clear-Host
|
|
|
|
#################################
|
|
# CSR TIME
|
|
#################################
|
|
|
|
# Display summary
|
|
Write-Host "Certificate information
|
|
Common name: $($request['CN'])
|
|
Organisation: $($request['O'])
|
|
Organisational unit: $($request['OU'])
|
|
City: $($request['L'])
|
|
State: $($request['S'])
|
|
Country: $($request['C'])
|
|
Subject alternative name(s): $($request['SAN'].Values -join ", ")
|
|
Signature algorithm: SHA256
|
|
Key algorithm: RSA
|
|
Key size: 2048
|
|
" -ForegroundColor Yellow
|
|
|
|
certreq -new $files['settings'] $files['csr'] > $null
|
|
|
|
# Output the CSR
|
|
$CSR = Get-Content $files['csr']
|
|
$CSR|Out-String
|
|
} #end of script block
|
|
|
|
#myhost is used as cn
|
|
$csr=Invoke-Command -ComputerName $myhost -Credential $Secret:ndgov_svcitdpsuwin -ScriptBlock $csrScriptBlock -ArgumentList $commonName
|
|
|
|
|
|
#Write-Verbose -Message "Validate CSR" -Verbose
|
|
#$TestResults=Test-SectigoCertificateRequest -csr $csr
|
|
|
|
#If ($TestResults.Valid -eq $True) {
|
|
# Write-Verbose -Message "CSR Passed Testing" -Verbose
|
|
#}
|
|
#else {
|
|
# Write-Error "You don't have a valid csr. Terminating Script"
|
|
# "CSR Content " + $csr
|
|
# exit
|
|
#}
|
|
# End of Creating csr
|
|
|
|
|
|
##
|
|
$Comments="Enrolled by PSUniversal, Job " + $UAJob.Id + ", User " + $UAJob.Identity.Name + "," + $Comments
|
|
$Comments
|
|
|
|
if ($ApplicationName)
|
|
{
|
|
$customFields = @(
|
|
@{
|
|
name = "ApplicationName"
|
|
value = $ApplicationName
|
|
}
|
|
)
|
|
}
|
|
|
|
Write-Verbose -Message "Setting up params for Enroll-SectigoCertificateRequest" -Verbose
|
|
|
|
$splat = @{
|
|
Csr=$csr
|
|
dcvEmail=$dsvEmail
|
|
Comment=$Comments
|
|
KeyType=$KeyType
|
|
subjAltNames=$subjAltNames
|
|
}
|
|
|
|
$b1 = @{
|
|
customFields = $customFields
|
|
}
|
|
|
|
if ($customFields) {
|
|
$splat = $splat+ $b1
|
|
}
|
|
|
|
|
|
#$splat2=@{
|
|
# subjAltName=$subjAltName
|
|
#}
|
|
|
|
#if ( $subjAltName) {
|
|
# $Splat = $splat + $splat2
|
|
#}
|
|
|
|
$cred=$Secret:SectigoClientSecret
|
|
$env:Sectigoclientid = $cred.UserName
|
|
$env:SectigoclientSecret = $cred.GetNetworkCredential().Password
|
|
|
|
|
|
#get-command -Module ITD.Infra-Certificate-Internal.Sectigo
|
|
#remove-module ITD.Infra-Certificate-Internal.Sectigo
|
|
Write-Verbose -Message "Enroll-SectigoCertificateRequest" -Verbose
|
|
Get-SectigoApiToken
|
|
|
|
|
|
$certRequest = Enroll-SectigoCertificateRequest @Splat
|
|
|
|
|
|
#seems to be issue with this requiring addtional wait time.
|
|
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
|
|
}
|
|
}
|
|
|
|
|
|
$tp=(Get-SectigoCertificate -OrderId $certRequest.sslid).sha1Hash
|
|
"tp: $tp"
|
|
|
|
Write-Verbose -Message "Downloading interm Certificate" -Verbose
|
|
|
|
$IntermCertRootPath="c:\psautocerts_interm\"
|
|
|
|
mkdir $IntermCertRootPath 2>$null
|
|
|
|
$IntermCertPath = (Download-SectigoCertificate -Orderid $certRequest.sslid -Format x509IOR -CertRootPath $IntermCertRootPath).FullName
|
|
ls $IntermCertPath |select FullName, LastWriteTime, Length
|
|
|
|
|
|
Write-Verbose -Message "Downloading Certificate" -Verbose
|
|
|
|
$CertRootPath="c:\psautocerts\"
|
|
mkdir $CertRootPath 2>$null
|
|
$CertPath = (Download-SectigoCertificate -Orderid $certRequest.sslid -Format $Format -CertRootPath $CertRootPath).FullName
|
|
ls $CertPath |select FullName, LastWriteTime, Length
|
|
|
|
|
|
|
|
# Define source and destination paths
|
|
$remoteCertPath = "C:\Temp\CertificateX.cer" # A temporary location on the remote machine
|
|
$IntermremoteCertPath = "C:\Temp\Interm_CertificateX.cer"
|
|
|
|
# Copy the interm certificate file to the remote machine
|
|
Copy-Item -Path $IntermCertPath -Destination $IntermremoteCertPath -ToSession (New-PSSession -ComputerName $myhost -Credential $Secret:ndgov_svcitdpsuwin)
|
|
|
|
|
|
# Copy the certificate file to the remote machine
|
|
Copy-Item -Path $CertPath -Destination $remoteCertPath -ToSession (New-PSSession -ComputerName $myhost -Credential $Secret:ndgov_svcitdpsuwin)
|
|
|
|
|
|
# Define parameters for importing the certificate
|
|
|
|
#$certPassword = "YourCertPassword" | ConvertTo-SecureString -AsPlainText -Force # If it's a PFX with a password
|
|
|
|
$IntermcertStoreLocation = "Cert:\LocalMachine\Root"
|
|
|
|
$Intermcertimport=Invoke-Command -ComputerName $myhost -Credential $Secret:ndgov_svcitdpsuwin -ScriptBlock {
|
|
param($IntermremoteCertPath, $IntermcertStoreLocation )
|
|
"Import-Certificate -FilePath -CertStoreLocation $IntermcertStoreLocation"
|
|
Import-Certificate -FilePath $IntermremoteCertPath -CertStoreLocation $IntermcertStoreLocation
|
|
if (Test-Path -Path $IntermremoteCertPath -PathType Leaf) {
|
|
Remove-Item -Path $IntermremoteCertPath -Force -Confirm:$false 2>$null
|
|
}
|
|
# Import the certificate
|
|
|
|
} -ArgumentList $IntermremoteCertPath, $IntermcertStoreLocation
|
|
|
|
if ($Intermcertimport.Thumbprint ) {
|
|
Write-Verbose -verbose "Successful Import."
|
|
$IntermThumbprint=$Intermcertimport.Thumbprint
|
|
Write-Verbose "Thumbprint: $IntermThumbprint"
|
|
|
|
if (Test-Path -Path $CertPath -PathType Leaf) {
|
|
Remove-Item -Path $IntermCertPath -Force -Confirm:$false
|
|
Write-Host "File '$IntermCertPath' deleted successfully."
|
|
} else {
|
|
Write-Host "Path '$IntermCertPath' does not exist or is not a file."
|
|
}
|
|
}
|
|
|
|
##################
|
|
$certStoreLocation = "Cert:\LocalMachine\My"
|
|
|
|
$certimport=Invoke-Command -ComputerName $myhost -Credential $Secret:ndgov_svcitdpsuwin -ScriptBlock {
|
|
param($remoteCertPath, $certStoreLocation,$CommonName )
|
|
"Import-Certificate -FilePath $remoteCertPath -CertStoreLocation $certStoreLocation"
|
|
# Import the certificate
|
|
$cert=Import-Certificate -FilePath $remoteCertPath -CertStoreLocation $certStoreLocation
|
|
$mydate=Get-Date -Format 'yyyy-MM-dd'|out-string
|
|
$FriendlyName = $CommonName + "-" +$myDate
|
|
$cert.FriendlyName = $FriendlyName
|
|
if (Test-Path -Path $remoteCertPath -PathType Leaf) {
|
|
Remove-Item -Path $remoteCertPath -Force -Confirm:$false 2>$null
|
|
}
|
|
$cert
|
|
} -ArgumentList $remoteCertPath, $certStoreLocation,$CommonName
|
|
|
|
|
|
if ($certimport.Thumbprint ) {
|
|
Write-Verbose -verbose "Successful Import."
|
|
$Thumbprint=$certimport.Thumbprint
|
|
Write-Verbose "Thumbprint: $Thumbprint" -Verbose
|
|
|
|
if (Test-Path -Path $CertPath -PathType Leaf) {
|
|
Remove-Item -Path $CertPath -Force -Confirm:$false
|
|
Write-Host "File '$CertPath' deleted successfully."
|
|
} else {
|
|
Write-Host "Path '$CertPath' does not exist or is not a file."
|
|
}
|
|
}
|
|
|
|
#
|
|
# Request Work
|
|
#
|
|
|
|
# Validate the user
|
|
$StartDateTime = (Get-Date)
|
|
$EndDateTime = $StartDateTime.AddMinutes(1)
|
|
$RequestedBy=$UAJob.Identity.Name
|
|
|
|
#$ServiceNowEnvironment = "TEST"
|
|
#TemplateName = 'NDIT-SPS-Ansible Automation Platform'
|
|
if ($certimport.Thumbprint ) {
|
|
|
|
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
|
|
$SQLStatus = "Succcess"
|
|
}
|
|
Else {
|
|
Write-Verbose -Message "Status Failure" -Verbose
|
|
$SQLStatus = "Failure"
|
|
} |