Public/New-SelfSignedCert.ps1


#Requires -RunAsAdministrator

function New-SelfSignedCert {
    [CmdletBinding(SupportsShouldProcess = $true)]
    param(
        [Parameter(Mandatory = $true)]
        [string] $FriendlyName,
        [Parameter(Mandatory = $true)]
        [string] $DnsName,
        [Parameter(Mandatory = $true)]
        [string] $CertStoreLocation
    )

    function Set-ReadPermissionsForCert {
        param (
            [System.Security.Cryptography.X509Certificates.X509Certificate] $Cert,
            [string]$Username = $env:USERNAME
        )

        $keyPath = Join-Path $env:ProgramData 'Microsoft\Crypto\RSA\MachineKeys'
        $certUniqueKeyContainerName = $Cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
        $fullPath = Join-Path $keyPath $certUniqueKeyContainerName
        $acl = Get-Acl -Path $fullPath
        $permission = $Username,"Read","Allow"
        $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
        $acl.AddAccessRule($accessRule)
        Set-Acl $fullPath $acl
    }

# Generate a cert
    # https://docs.microsoft.com/en-us/powershell/module/pkiclient/new-selfsignedcertificate?view=win10-ps
    $cert = New-SelfSignedCertificate -FriendlyName $FriendlyName -DnsName $DnsName -CertStoreLocation $CertStoreLocation -NotAfter (Get-Date).AddYears(10) -KeyAlgorithm RSA -KeyLength 2048 -KeyExportPolicy Exportable -KeyProtection None -Provider 'Microsoft Enhanced RSA and AES Cryptographic Provider' -Verbose
    $certStoreParent = Split-Path -Path $CertStoreLocation -Parent
    $certStoreName = Split-Path $certStoreParent -Leaf

    $pfxCertPath = (Join-Path $env:TEMP "$($FriendlyName).pfx")
    $pfxCertPassword = 'test'
    $cert | Export-PfxCertificate -FilePath $pfxCertPath -Password $pfxCertPassword | Out-Null

    try
    {
        # Create the certificate
        $pfxcert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ErrorAction Stop;
        $KeyStorageFlags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable -bxor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet -bxor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet;
        Write-Verbose ('Key storage flags is: {0}' -f $KeyStorageFlags);
        $pfxcert.Import($pfxCertPath, $pfxCertPassword, $KeyStorageFlags);

        # Create the X509 store and import the certificate
        $store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList My, LocalMachine -ErrorAction Stop;
        $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite);
        $store.Add($pfxcert);
        $store.Close();

        Write-Output -InputObject $pfxcert;
    }
    catch
    {
        throw $_;
    }
    # Trust the cert
    # https://stackoverflow.com/questions/8815145/how-to-trust-a-certificate-in-windows-powershell
    $store = New-Object System.Security.Cryptography.X509Certificates.X509Store 'Root',$certStoreName
    $store.Open("ReadWrite")
    $store.Add($cert)
    $store.Close()

    Export-Certificate -Cert $cert -FilePath (Join-Path $env:TEMP "$($FriendlyName).cer")
    Set-ReadPermissionsForCert $cert
    # remove the untrusted copy of the cert
    #$cert | Remove-Item

    Write-Verbose "Created certificate $FriendlyName with thumbprint $($cert.Thumbprint)"

    return $cert
}