426 lines
14 KiB
PowerShell
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}"
|
|
}
|
|
} |