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