functions/New-D365MSSQLSelfCert.ps1

function New-D365MSSQLSelfCert {
    <#
    .SYNOPSIS
 
   .DESCRIPTION
  
   .EXAMPLE
 
   .EXAMPLE
 
    .EXAMPLE
 
   .PARAMETER ComputerName
   String
   The name of the D365 LBD Server to grab the environment details; needed if a config is not specified and will default to local machine.
   .PARAMETER Config
    Custom PSObject
    Config Object created by either the Get-D365LBDConfig or Get-D365TestConfigData function inside this module
   #>

    [alias("New-MSSQLSelfCert")]
    [CmdletBinding()]
    param([Parameter(ValueFromPipeline = $True,
            ValueFromPipelineByPropertyName = $True,
            Mandatory = $false,
            HelpMessage = 'D365FO Local Business Data Server Name',
            ParameterSetName = 'NoConfig')]
        [PSFComputer]$ComputerName = "$env:COMPUTERNAME",
        [Parameter(ParameterSetName = 'Config',
            ValueFromPipeline = $True)]
        [psobject]$Config,
        [string]$CertPassword
    )
    ##Gather Information from the Dynamics 365 Orchestrator Server Config
    BEGIN {
    } 
    PROCESS {
        if (!$Config -or $Config.OrchestratorServerNames.Count -eq 0) {
            Write-PSFMessage -Level VeryVerbose -Message "Config not defined or Config is invalid. Trying to Get new config using $ComputerName"
            $Config = Get-D365LBDConfig -ComputerName $ComputerName -HighLevelOnly
        }
        ##
        <# Source: https://stackoverflow.com/questions/8423541/how-do-you-run-a-sql-server-query-from-powershell
#>

        function Invoke-SQL {
            param(
                [string] $dataSource = ".\SQLEXPRESS",
                [string] $database = "MasterData",
                [string] $sqlCommand = $(throw "Please specify a query.")
            )

            $connectionString = "Data Source=$dataSource; " +
            "Integrated Security=SSPI; " +
            "Initial Catalog=$database"

            $connection = new-object system.data.SqlClient.SQLConnection($connectionString)
            $command = new-object system.data.sqlclient.sqlcommand($sqlCommand, $connection)
            $connection.Open()
    
            $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
            $dataset = New-Object System.Data.DataSet

            $adapter.Fill($dataSet) | Out-Null
            $connection.Close()
            $dataSet.Tables
        }

        $Listener = $Config.AXDatabaseServer

        foreach ($SQLServer in $Config.DatabaseClusterServerNames) {
            try {
                $InstanceNameSQLResults = Invoke-SQL -dataSource $sqlserver -database 'master' -sqlCommand 'SELECT @@SERVICENAME as ''Servicename'' '
            }
            catch {}
            try {
                $ProductVersionSQLResults = Invoke-SQL -dataSource $sqlserver -database 'master' -sqlCommand 'SELECT SERVERPROPERTY(''Productversion'') as ''Productversion'' '
                [string]$SQLMajorVersionNumber = $($ProductVersionSQLResults | select Productversion).Productversion
                $SQLMajorVersionNumber = $SQLMajorVersionNumber.Substring(0, 2)
            }
            catch {}
            if (!$InstanceNameSQLResults) {
                Write-PSFMessage -Level Error -Message "Check SQL DB Permissions"
            }

            $InstanceName = $($InstanceNameSQLResults | Select Servicename).Servicename
            $SQLVersionandInstance = 'MSSQL' + $SQLMajorVersionNumber + '.' + $InstanceName

            try {
                $SQLCert = $null
                $SQLCert = Invoke-Command -ScriptBlock {
                    if (!$SQLVersionandInstance) {
                        $SQLVersionandInstance = $using:SQLVersionandInstance
                    }
                    $cert = Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\$SQLVersionandInstance\MSSQLSERVER\SuperSocketNetLib"
                    $cert.Certificate.ToUpper()
                } -ComputerName $SQLServer -ErrorAction Stop
            }
            catch {
                $WhoAmI = whoami
                Write-PSFMessage -Level Warning -Message "Warning: Can't Connect to $SQLServer registry with account $WhoAmI to gather SQL Certificate Encryption Details"
            }
            Write-PSFMessage -Level Verbose -Message "$SQLServer is currently using $SQLCert"

            $NewCert = Invoke-Command -ScriptBlock {
                $ComputerName = $env:COMPUTERNAME.ToLower()
                $Domain = $env:USERDNSDOMAIN.ToLower()
                $ListenerName = $using:Listener
                $NewCertInside = New-SelfSignedCertificate -Subject "$ComputerName.$Domain" -DnsName "$ListenerName.$Domain", $Listener, $ComputerName -Provider 'Microsoft Enhanced RSA and AES Cryptographic Provider'

                if (!(test-path -PathType Container "C:\certs")) {
                    mkdir "C:\certs"
                }
                $Thumbprint = $NewCertInside.Thumbprint
                $CertSecurePass = ConvertTo-SecureString -String $using:CertPassword -AsPlainText -Force
                $CertInsideLocalStore = Get-ChildItem -path Cert:\LocalMachine\My\$Thumbprint
                Export-PfxCertificate -Cert $CertInsideLocalStore -FilePath "C:\certs\$($CertInsideLocalStore.Thumbprint).pfx" -Force -Verbose -Password $CertSecurePass
                $CertInsideLocalStore
            } -ComputerName $SQLServer
            if (!(test-path -PathType Container "C:\certs")) {
                mkdir "C:\certs"
            }
            [string]$NewCertThumbprint = $($NewCert.Thumbprint)
            $NewCertThumbprint = $NewCertThumbprint.Trim()
            $Source = "\\$SqlServer\C$\certs\" + $NewCertThumbprint + ".pfx"
            $Destination = "C:\certs\" + $NewCertThumbprint + ".pfx"
            Copy-Item $Source -Destination $Destination -Verbose
        }
    }
    END {}
}