functions/New-D365MSSQLSelfCert.ps1

function New-D365MSSQLSelfCert {
    <#
    .SYNOPSIS
    Creates new self signed certificates on each MS SQL database server and exports the PFX file
   .DESCRIPTION
    Creates new self signed certificates on each MS SQL database server and exports the PFX file
    .EXAMPLE
    $Certs = New-D365MSSQLSelfCert -config $Config -CertPassword 'StrongFakePass123'
   .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")) {
                    $certdir = 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")) {
                $certdir = 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 {}
}