Export/Public/Add-CertificatesToKeyVault.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
function Add-CertificatesToKeyVault {
    [CmdletBinding()]
    <#
    .SYNOPSIS
        ...
    .DESCRIPTION
        ...
    #>

    param(
        [Parameter(Mandatory = $true)]
        [string]
        $ResourceGroupName,        
        [Parameter(Mandatory = $true)]
        [string]
        $ResourceLocation,
        [Parameter(Mandatory = $true)]
        $KeyVaultName,
        [Parameter(Mandatory = $true)]
        [Object[]]
        $Certificates
    )
    process {
        function Get-NewSelfSignedCertificate() {
            [CmdletBinding()]
            param
            (
                [Parameter(Mandatory = $true)]
                [string]
                $DnsName,
                [Parameter(Mandatory = $true)]
                [SecureString]
                $CertificatePassword,
                [Parameter(Mandatory = $false)]
                [string]
                $CertificateStoreLocation = "cert:\LocalMachine\My",
                [Parameter(Mandatory = $false)]
                [string]
                $TargetFilename
            )
            Write-Verbose "Generating new self-signed certificate"
            if (-not($TargetFilename)) {
                $TargetFilename = New-TemporaryFile | Rename-Item -NewName { $_ -replace 'tmp$', 'pfx' } -PassThru | Select-Object -ExpandProperty FullName
            }
            Write-Verbose "Target Filename is: $TargetFilename"
            $certificate = New-SelfSignedCertificate -DnsName $DnsName -CertStoreLocation $CertificateStoreLocation -NotAfter (Get-Date).AddYears(5)
            $fileinfo = Get-ChildItem -Path $certificate.PSPath | Export-PfxCertificate -FilePath $TargetFilename -Password $CertificatePassword

            # Remove from local storage
            Get-ChildItem -Path $certificate.PSPath | Remove-Item -Force
            $fileinfo.FullName
            
        }
        function Get-CertificateThumbprint {
            #
            # This will return a certificate thumbprint, null if the file isn't found or throw an exception.
            #
        
            param (
                [parameter(Mandatory = $true)][string] $CertificatePath,
                [parameter(Mandatory = $false)][SecureString] $CertificatePassword
            )
        
            try {
                if (!(Test-Path $CertificatePath)) {
                    return $null;
                }
        
                $certificateObject = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
                $certificateObject.Import($CertificatePath, $CertificatePassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::DefaultKeySet);
        
                return $certificateObject.Thumbprint
            }
            catch [Exception] {
                #
                # Catch accounts already added.
                throw $_;
            }
        }
        $keyVault = Get-AzKeyVault -ResourceGroupName $ResourceGroupName -VaultName $KeyVaultName -ErrorAction SilentlyContinue         
        if (-not($keyVault)) {
            Write-Verbose "KeyVault $KeyVaultName does not exists. Stopping here."
            return
        }
        $generatedCertificatePath = ""
        foreach ($certificate in $Certificates) {
            if (-not($certificate.Path)) {
                if ($generatedCertificatePath) {
                    $certificate.Path = $generatedCertificatePath
                }
            }
            if (-not($certificate.Path)) {
                if (-not($certificate.DnsName)) {
                    throw "You need to set DnsName for certificate-element if you don't provide an existing file."
                }
                $generatedCertificatePath = Get-NewSelfSignedCertificate -DnsName $certificate.DnsName -CertificatePassword (ConvertTo-SecureString -String $certificate.Password -Force -AsPlainText) -Verbose:$Verbose
                $certificate.Path = $generatedCertificatePath
            }            
            if ($generatedCertificatePath) {
                $source = "Temporary Self-Signed Certificate"
            }
            else {
                $source = "Existing Certificate"
            }
            $tags = @{
                "AddedOn"    = "$(get-date -format yyyyMMddhhmmss)"
                "FromSource" = $source
            }
            if (-not($generatedCertificatePath)) {
                $tags += @{"SourceFile" = "$(Split-Path $certificate.Path -Leaf)" }
            }            
            Write-Verbose "Checking if Certificate $($certificate.Type) already exists in KeyVault..."
            $vaultCert = Get-AzKeyVaultCertificate -VaultName $KeyVaultName -Name $certificate.Type -ErrorAction SilentlyContinue
            if ($vaultCert) {
                if ($vaultCert.Thumbprint -ne (Get-CertificateThumbprint -CertificatePath $certificate.Path -CertificatePassword (ConvertTo-SecureString -String $certificate.Password -Force -AsPlainText))) {
                    Write-Verbose "Updating Certificate $($certificate.Type) and password in KeyVault..."
                    Import-AzKeyVaultCertificate -VaultName $KeyVaultName -Name $certificate.Type -FilePath $certificate.Path -Password (ConvertTo-SecureString -String $certificate.Password -AsPlainText -Force) -Tag $tags | Out-Null
                    Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name "$($certificate.Type)-CertPassword" -SecretValue (ConvertTo-SecureString -String $certificate.Password -AsPlainText -Force) | Out-Null
                }
                else {
                    Write-Verbose "Certificate $($certificate.Type) already exists in KeyVault..."
                }
            }
            else {                
                Write-Verbose "Adding Certificate $($certificate.Type) and password to KeyVault..."
                Import-AzKeyVaultCertificate -VaultName $KeyVaultName -Name $certificate.Type -FilePath $certificate.Path -Password (ConvertTo-SecureString -String $certificate.Password -AsPlainText -Force)  -Tag $tags | Out-Null
                Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name "$($certificate.Type)-CertPassword" -SecretValue (ConvertTo-SecureString -String $certificate.Password -AsPlainText -Force) | Out-Null
            }
        }
    }
}