forked from intelequia/letsencrypt-aw
-
Notifications
You must be signed in to change notification settings - Fork 0
/
letsencrypt-apim_v2.ps1
129 lines (100 loc) · 5.08 KB
/
letsencrypt-apim_v2.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
#######################################################################################
# Script that renews a Let's Encrypt certificate for an Azure APIM
# Pre-requirements:
# - Have a storage account in which the folder path has been created:
# '/.well-known/acme-challenge/', to put here the Let's Encrypt DNS check files
# - Add "Path-based" rule in the Application Gateway with this configuration:
# - Path: '/.well-known/acme-challenge/*'
# - Check the configure redirection option
# - Choose redirection type: permanent
# - Choose redirection target: External site
# - Target URL: <Blob public path of the previously created storage account>
# - Example: 'https://test.blob.core.windows.net/public'
# - For execution on Azure Automation: Import 'AzureRM.profile', 'AzureRM.Network'
# and 'ACMESharp' modules in Azure
#
# UPDATE 2019-11-27
# - Due to deprecation of ACMEv1, a new script is required to use ACMEv2.
# The module to use is called ACME-PS.
#
# UPDATE 2020-09-03
# - Migrated to Az modules.
# Following modules are needed now: Az.Accounts, Az.Network, Az.Storage
#
# UPDATE 2020-10-14
# - Mdified to work on Azure APIM service
# - required Az.ApiManagement module
#
#######################################################################################
Param(
[string]$domain,
[string]$EmailAddress,
[string]$STResourceGroupName,
[string]$storageName,
[string]$APIMResourceGroupName,
[string]$APIMName
)
# Ensures that no login info is saved after the runbook is done
Disable-AzContextAutosave
# Log in as the service principal from the Runbook
$connection = Get-AutomationConnection -Name AzureRunAsConnection
Login-AzAccount -ServicePrincipal -Tenant $connection.TenantID -ApplicationId $connection.ApplicationID -CertificateThumbprint $connection.CertificateThumbprint
# Create a state object and save it to the harddrive
$state = New-ACMEState -Path $env:TEMP
$serviceName = 'LetsEncrypt'
# Fetch the service directory and save it in the state
Get-ACMEServiceDirectory $state -ServiceName $serviceName -PassThru;
# Get the first anti-replay nonce
New-ACMENonce $state;
# Create an account key. The state will make sure it's stored.
New-ACMEAccountKey $state -PassThru;
# Register the account key with the acme service. The account key will automatically be read from the state
New-ACMEAccount $state -EmailAddresses $EmailAddress -AcceptTOS;
# Load an state object to have service directory and account keys available
$state = Get-ACMEState -Path $env:TEMP;
# It might be neccessary to acquire a new nonce, so we'll just do it for the sake of the example.
New-ACMENonce $state -PassThru;
# Create the identifier for the DNS name
$identifier = New-ACMEIdentifier $domain;
# Create the order object at the ACME service.
$order = New-ACMEOrder $state -Identifiers $identifier;
# Fetch the authorizations for that order
$authZ = Get-ACMEAuthorization -State $state -Order $order;
# Select a challenge to fullfill
$challenge = Get-ACMEChallenge $state $authZ "http-01";
# Inspect the challenge data
$challenge.Data;
# Create the file requested by the challenge
$fileName = $env:TMP + '\' + $challenge.Token;
Set-Content -Path $fileName -Value $challenge.Data.Content -NoNewline;
$blobName = ".well-known/acme-challenge/" + $challenge.Token
$storageAccount = Get-AzStorageAccount -ResourceGroupName $STResourceGroupName -Name $storageName
$ctx = $storageAccount.Context
Set-AzStorageBlobContent -File $fileName -Container "public" -Context $ctx -Blob $blobName
# Signal the ACME server that the challenge is ready
$challenge | Complete-ACMEChallenge $state;
# Wait a little bit and update the order, until we see the states
while($order.Status -notin ("ready","invalid")) {
Start-Sleep -Seconds 10;
$order | Update-ACMEOrder $state -PassThru;
}
# We should have a valid order now and should be able to complete it
# Therefore we need a certificate key
$certKey = New-ACMECertificateKey -Path "$env:TEMP\$domain.key.xml";
# Complete the order - this will issue a certificate singing request
Complete-ACMEOrder $state -Order $order -CertificateKey $certKey;
# Now we wait until the ACME service provides the certificate url
while(-not $order.CertificateUrl) {
Start-Sleep -Seconds 15
$order | Update-Order $state -PassThru
}
# As soon as the url shows up we can create the PFX
$password = ConvertTo-SecureString -String "Passw@rd123***" -Force -AsPlainText
Export-ACMECertificate $state -Order $order -CertificateKey $certKey -Path "$env:TEMP\$domain.pfx" -Password $password;
# Delete blob to check DNS
Remove-AzStorageBlob -Container "public" -Context $ctx -Blob $blobName
### RENEW APIM CERTIFICATE ###
$proxyCustomConfig = New-AzApiManagementCustomHostnameConfiguration -Hostname $domain -HostnameType Proxy -PfxPath "$env:TEMP\$domain.pfx" -PfxPassword $password -DefaultSslBinding
$apim = Get-AzApiManagement -ResourceGroupName $APIMResourceGroupName -Name $APIMName
$apim.ProxyCustomHostnameConfiguration = $proxyCustomConfig
Set-AzApiManagement -InputObject $apim