<#  NOT FUNCTIONAL YET - WORK IN PROGRESS
.SYNOPSIS
    Update/renew any expired iLO certificates in the VMware/Synergy environment
.DESCRIPTION
    Update/renew any expired iLO certificates in the VMware/Synergy environment
.NOTES
    # retrieve all iLO from Synergy
    # find all certificates expiring in the next 3 days, or ones that do not have nd.gov in name, add to an array
    # loop through list
        ## connect to ilo
        ## generate CSR
        ## send CSR to sectigo to generate new
        ## wait for approval
        ## download new cert
        ## upload/update/set on iLO
.LINK
    
.EXAMPLE
    Test-MyTestFunction -Verbose
    Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>

[CmdletBinding()]
param (
    [Parameter(ParameterSetName = 'ByHostName')]
    [string[]]
    $HostName = $null,

    [Parameter(ParameterSetName = 'SynergyDiscovery')]
    [switch]
    $SynergyDiscovery

)
    
function Get-SectigoToken {
    Write-Verbose -Message "Retrieving Sectigo API key for VMware" -Verbose
    $SectigoCred = Get-ITDPassword -Title "Sectigo API key for VMware" -UserName "f595aa76-c26b-4664-b95d-cb805cc7ff4e"
    Write-Verbose -Message "Confirming SectigoCred is $($SectigoCred.UserName)" -Verbose
    $AuthBody = @{
        grant_type    = 'client_credentials'
        #client_id     = $Secret:sectigo_vmware.UserName
        #client_secret = $Secret:sectigo_vmware.GetNetworkCredential().Password
        client_id     = $SectigoCred.UserName
        client_secret = $SectigoCred.GetNetworkCredential().Password
    }

    $AuthBaseAPIUrl = 'https://auth.sso.sectigo.com'
    
    $tokenEndpoint = $AuthBaseAPIUrl + '/auth/realms/apiclients/protocol/openid-connect/token'
    $env:SectigoToken = (Invoke-RestMethod -Method Post -Uri $tokenEndpoint -ContentType 'application/x-www-form-urlencoded' -Body $AuthBody).access_token

    Return $env:SectigoToken
}

Write-Verbose -Message "Retrieving OneView Service Account credentials" -Verbose
$OVCred = Get-ITDPassword -Title "VMware iLO Service Account" -UserName "ndgov\svcitdvmhpe"
Write-Verbose -Message "Confirming OneView is $($OVCred.UserName)" -Verbose

Import-Module HPEiLOCmdlets -Force

Write-Verbose -Message "Gather PSUniversal Job Information" -Verbose
$PSUJobId = $UAJob.Id

Write-Verbose -Message "Set static variables" -Verbose
$RequesterEmail = 'vmware@nd.gov'
$AppName = "Infra-VMware"
$ServerTypeCode = "Linux"
$Format = "x509CO"
$OrgId = 8133 # Sectigo OrgDept ID for State of North Dakota Information Technology Department - Cloud & Infrastructure
$CertType = 2375 # Sectigo Cert Type for Standard SSL Multi-Domain

$BaseAPIUrl = 'https://admin.hard.sectigo.com'

switch ($PSCmdlet.ParameterSetName) {
    'ByHostName' {
        $AllILOServers = $HostName
    }
    'SynergyDiscovery' {
        Write-Verbose -Message "Retrieving iLO information from OneView/Synergy" -Verbose
        $OneviewServers = @('itdmdnsyncompt1.nd.gov', 'itdmdnsyncompp1.nd.gov', 'itdbissyncompp1.nd.gov')
        $AllILOServers = @()
        ForEach ($OneviewServer in $OneViewServers ) {
            Write-Verbose -Message "Connecting to OneView server $OneviewServer" -Verbose
            Connect-OVMgmt -Hostname $OneviewServer -Credential $OVCred -AuthLoginDomain nd.gov -LoginAcknowledge
            $AllILOServers += (Get-OVServer).ServerName | ForEach-Object {
                $_.split('.')[0] + "lo.nd.gov"
            }
            Disconnect-OVMgmt
        }
    }
    default {
        Write-Error -Message "Invalid parameter set."
        exit 1
    }
}

Write-Verbose -Message "Checking iLO certificates for expiration or invalid issuer/commonname" -Verbose
$AlliLOToRenew = @()
ForEach ($iLODnsName in $AllILOServers) {
    Write-Verbose -Message "Checking certificate for iLO $iLODnsName" -Verbose
    $cert = Get-SslCertificate -DNSName $iLODnsName

    If ( $cert.NotAfter.AddDays(-7) -le (Get-Date) ) {
        Write-Warning -Message "Certificate for $iLODnsName expires on $($cert.NotAfter), add to renewal list."
        $AlliLOToRenew += $iLODnsName
    }

    If ( $cert.subject -notlike "*.nd.gov*") {
        Write-Warning -Message "Certificate for $iLODnsName is not a ND.gov cert, add to renewal list."
        $AlliLOToRenew += $iLODnsName
    }
}

ForEach ($iLOToRenew in $AlliLOToRenew | Select-Object -Unique) {
    Write-Verbose -Message "Processing iLO $iLOToRenew for certificate renewal" -Verbose

    $iLOCred = $null
    switch ($iLOToRenew) {
        { $_ -like "*bis*" } { 
            Write-Verbose -Message "BIS iLO detected, getting credentials for itdbissyncompp1" -Verbose
            $iloCred = Get-ITDPassword -Title "itdbissyncompp1 iLO" -UserName "Administrator"; 
        }
        { $_ -like "*mdn*" } { 
            Write-Verbose -Message "MDN iLO detected, getting credentials for itdmdnsyncompp1" -Verbose
            $iloCred = Get-ITDPassword -Title "itdmdnsyncompp1 iLO" -UserName "Administrator"; 
        }
        { $_ -like "*test*" } { 
            Write-Verbose -Message "TEST iLO detected, getting credentials for itdmdnsyncompt1" -Verbose
            $iloCred = Get-ITDPassword -Title "itdmdnsyncompt1 iLO" -UserName "Administrator"; 
        }
        default { Write-Error -Message "No iLO credentials found for $iLOToRenew, skipping."; continue; }
    }

    try {
        Write-Verbose -Message "Establishing connection to iLO $iLOToRenew" -Verbose
        $iLOConnection = Connect-HPEiLO -Address $iLOToRenew -Credential $iLOCred -DisableCertificateAuthentication
        Write-Verbose -Message "Generating CSR on iLO $iLOToRenew" -Verbose
        Start-HPEiLOCertificateSigningRequest -Connection $iLOConnection `
            -CommonName $iLOConnection.Hostname `
            -Organization "State of North Dakota" `
            -Country US `
            -City Bismarck `
            -State "North Dakota"

        Start-Sleep -Seconds 30 ### for some reason if you check iLO for CSR too frequently it doesn't work
        
        Write-Verbose -Message "Getting CSR for $iLOToRenew"
        $CsrData = $null

        While ($null -eq $CsrData.CertificateSigningRequest) {
            try {
                $CsrData = Get-HPEiLOCertificateSigningRequest -Connection $iLOConnection
            }
            catch {
                Write-Warning -Message "CSR not ready yet for $iLOToRenew, waiting 10 seconds."
                Start-Sleep -Seconds 10
            }
        }
        Disconnect-HPEiLO -Connection $iLOConnection
        $iLOConnection = $null  

        Write-Verbose -Message "Submitting CSR to Sectigo for $iLOToRenew" -Verbose
        #Get-SectigoToken ## function above loaded into memory

        $EnrollBody = @{
            orgId             = $OrgId;
            certType          = $CertType
            term              = 365;
            comments          = "iLO Certificate Renewal for $iLOToRenew"
            serverType        = $ServerTypeCode
            csr               = $CsrData.CertificateSigningRequest
            externalRequester = "vmware@nd.gov"
            customFields      = @(
                @{
                    name  = 'ApplicationName'
                    value = 'Infra-VMware'
                }
            )
        }

        $EnrollParams = @{
            Method      = 'Post'
            Uri         = $BaseAPIUrl + "/api/ssl/v1/enroll"
            Headers     = @{
                "Authorization" = ("Bearer " + (Get-SectigoToken))
                "Content-Type"  = "application/json"
            }
            Body        = ($EnrollBody | ConvertTo-Json -Depth 10)
            ContentType = 'application/json'
        }

        $EnrollResponse = Invoke-RestMethod @EnrollParams
        $OrderId = $EnrollResponse.sslId

        Write-Verbose -Message "Waiting for certificate issuance for $iLOToRenew" -Verbose
        $Certificate = $null
        
        Start-Sleep -Seconds 15

        While ($Certificate.status -ne "Issued") {
            $ValidateUrl = "${BaseAPIUrl}/api/ssl/v1/${OrderId}"
            $ValidateSplat = @{
                Uri     = $ValidateUrl
                Method  = 'Get'
                Headers = @{
                    "Authorization" = ("Bearer " + (Get-SectigoToken))
                    "Content-Type"  = "application/json"
                }
            }

            $Certificate = Invoke-RestMethod @ValidateSplat
            If ($Certificate.status -ne "Issued") {
                Write-Warning -Message "Certificate for $iLOToRenew not issued yet, waiting 15 seconds."
                Start-Sleep -Seconds 15
            }
        }

        Write-Verbose -Message "Downloading issued certificate for $iLOToRenew" -Verbose
        $CollectUrl = $BaseAPIUrl + "/api/ssl/v1/collect/${OrderId}?format=${Format}"

        $CommonName = $Certificate.commonName

        $DownloadSplat = @{
            Uri             = $CollectUrl
            Method          = 'Get'
            Headers         = @{
                "Authorization" = ("Bearer " + (Get-SectigoToken))
                "Content-Type"  = "application/json"
            }
            UseBasicParsing = $true
        }

        Write-Verbose -Message "Downloading certificate to F:\iLO_certs\$CommonName-$OrderId-$PSUJobId.pem" -Verbose
        Invoke-WebRequest @DownloadSplat -OutFile "F:\iLO_certs\$CommonName-$OrderId-$PSUJobId.pem"

        Write-Verbose -Message "Importing new certificate to iLO $iLOToRenew" -Verbose
        $CertificateToUpload = Get-Content -Path "F:\iLO_certs\$CommonName-$OrderId-$PSUJobId.pem" -Raw
        $iLOConnection = Connect-HPEiLO -Address $iLOToRenew -Credential $iLOCred -DisableCertificateAuthentication -Verbose
        Import-HPEiLOCertificate -Certificate ($CertificateToUpload | Out-String) -Connection $iLOConnection -Force
        Disconnect-HPEiLO -Connection $iLOConnection

        Write-Verbose -Message "Disconnecting from iLO $iLOToRenew" -Verbose
    }
    catch {
        
    }
}