Skip to content

Instantly share code, notes, and snippets.

@justinyoo
Last active October 26, 2020 13:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinyoo/20017fe33f1d70fb8a6531e71c3e615c to your computer and use it in GitHub Desktop.
Save justinyoo/20017fe33f1d70fb8a6531e71c3e615c to your computer and use it in GitHub Desktop.
Updating Azure DNS and SSL Certificate on Azure Functions via Github Actions
$AppResourceGroupName = "[RESOURCE_GROUP_NAME_FOR_AZURE_FUNCTION_APP]"
AppName = "[NAME_OF_AZURE_FUNCTION_APP]"
$app = Get-AzResource `
-ResourceType Microsoft.Web/sites `
-ResourceGroupName $AppResourceGroupName `
-ResourceName $AppName
$newIp4Address = $app.Properties.inboundIpAddress
$ZoneResourceGroupName = "[RESOURCE_GROUP_NAME_FOR_AZURE_DNS]"
$ZoneName = "[NAME_OF_AZURE_DNS_ZONE]"
$rs = Get-AzDnsRecordSet `
-ResourceGroupName $ZoneResourceGroupName `
-ZoneName $ZoneName `
-Name "@" `
-RecordType A
$oldIp4Address = $rs.Records[0].Ipv4Address
if ($oldIp4Address -ne $newIp4Address) {
$rs.Records[0].Ipv4Address = $newIp4Address
$updated = Set-AzDnsRecordSet -RecordSet $rs
}
$ApiEndpoint = "[ACMEBOT_HTTP_API_ENDPOINT]"
$HostNames = "[COMMA_DELIMITED_HOST_NAMES]"
$dnsNames = $HostNames -split ","
$body = @{ DnsNames = $dnsNames }
$issued = Invoke-RestMethod `
-Method Post `
-Uri $ApiEndpoint `
-ContentType "application/json" `
-Body ($body | ConvertTo-Json)
$tokenCachedItems = (Get-AzContext).TokenCache.ReadItems()
$tokenCachedItem = $tokenCachedItems | Where-Object { $_.ClientId -eq $clientId }
$accessToken = ConvertTo-SecureString -String $tokenCachedItem.AccessToken -AsPlainText -Force
$epoch = ([DateTimeOffset](Get-Date)).ToUnixTimeMilliseconds()
$CertificateResourceGroupName = "[RESOURCE_GROUP_NAME_FOR_CERTIFICATE]"
$CertificateName = "[NAME_OF_CERTIFICATE]"
$endpoint = "https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Web/certificates/{2}" `
-f $subscriptionId, $CertificateResourceGroupName, $CertificateName
$ApiVersion = "2018-11-01"
$cert = Invoke-RestMethod -Method GET `
-Uri ("{0}?api-version={1}&_={2}" -f $endpoint, $ApiVersion, $epoch) `
-ContentType "application/json" `
-Authentication Bearer `
-Token $accessToken
$result = Invoke-RestMethod -Method PUT `
-Uri ("{0}?api-version={1}" -f $endpoint, $ApiVersion) `
-ContentType "application/json" `
-Authentication Bearer `
-Token $accessToken `
-Body ($cert | ConvertTo-Json)
# Azure PowerShell base image
FROM mcr.microsoft.com/azure-powershell:latest
ADD entrypoint.ps1 /entrypoint.ps1
RUN chmod +x /entrypoint.ps1
ENTRYPOINT ["pwsh", "-File", "/entrypoint.ps1"]
Param(
[string] [Parameter(Mandatory=$true)] $AppResourceGroupName,
[string] [Parameter(Mandatory=$true)] $AppName,
[string] [Parameter(Mandatory=$true)] $ZoneResourceGroupName,
[string] [Parameter(Mandatory=$true)] $ZoneName
)
$clientId = ($env:AZURE_CREDENTIALS | ConvertFrom-Json).clientId
$clientSecret = ($env:AZURE_CREDENTIALS | ConvertFrom-Json).clientSecret | ConvertTo-SecureString -AsPlainText -Force
$tenantId = ($env:AZURE_CREDENTIALS | ConvertFrom-Json).tenantId
$credentials = New-Object System.Management.Automation.PSCredential($clientId, $clientSecret)
$connected = Connect-AzAccount -ServicePrincipal -Credential $credentials -Tenant $tenantId
# Add/Update A Record
$app = Get-AzResource -ResourceType Microsoft.Web/sites -ResourceGroupName $AppResourceGroupName -ResourceName $AppName
$newIp4Address = $app.Properties.inboundIpAddress
$rs = Get-AzDnsRecordSet -ResourceGroupName $ZoneResourceGroupName -ZoneName $ZoneName -Name "@" -RecordType A
$oldIp4Address = $rs.Records[0].Ipv4Address
if ($oldIp4Address -eq $newIp4Address) {
Write-Output "No need to update A record"
# Set Output
Write-Output "::set-output name=updated::$false"
return
}
$rs.Records[0].Ipv4Address = $newIp4Address
$updated = Set-AzDnsRecordSet -RecordSet $rs
Write-Output "A record has been updated"
# Set Output
Write-Output "::set-output name=updated::$true"
return
Param(
[string] [Parameter(Mandatory=$true)] $ApiEndpoint,
[string] [Parameter(Mandatory=$true)] $HostNames
)
# Issue new SSL certificate
$dnsNames = $HostNames -split ","
$body = @{ DnsNames = $dnsNames }
$issued = Invoke-RestMethod -Method Post -Uri $ApiEndpoint -ContentType "application/json" -Body ($body | ConvertTo-Json)
Write-Output "New SSL certificate has been issued to $HostNames"
# Set Output
Write-Output "::set-output name=updated::$true"
Param(
[string] [Parameter(Mandatory=$true)] $CertificateResourceGroupName,
[string] [Parameter(Mandatory=$true)] $CertificateName,
[string] [Parameter(Mandatory=$false)] $ApiVersion = "2018-11-01"
)
$clientId = ($env:AZURE_CREDENTIALS | ConvertFrom-Json).clientId
$clientSecret = ($env:AZURE_CREDENTIALS | ConvertFrom-Json).clientSecret | ConvertTo-SecureString -AsPlainText -Force
$tenantId = ($env:AZURE_CREDENTIALS | ConvertFrom-Json).tenantId
$subscriptionId = ($env:AZURE_CREDENTIALS | ConvertFrom-Json).subscriptionId
$credentials = New-Object System.Management.Automation.PSCredential($clientId, $clientSecret)
$connected = Connect-AzAccount -ServicePrincipal -Credential $credentials -Tenant $tenantId
# Get Access Token
$tokenCachedItems = (Get-AzContext).TokenCache.ReadItems()
$tokenCachedItem = $tokenCachedItems | Where-Object { $_.ClientId -eq $clientId }
$accessToken = ConvertTo-SecureString -String $tokenCachedItem.AccessToken -AsPlainText -Force
# Get Existing Certificate Details
$epoch = ([DateTimeOffset](Get-Date)).ToUnixTimeMilliseconds()
$endpoint = "https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Web/certificates/{2}" -f $subscriptionId, $CertificateResourceGroupName, $CertificateName
$cert = Invoke-RestMethod -Method GET `
-Uri ("{0}?api-version={1}&_={2}" -f $endpoint, $ApiVersion, $epoch) `
-ContentType "application/json" `
-Authentication Bearer `
-Token $accessToken
$certJson = $cert | ConvertTo-Json
# Sync Certificate
$result = Invoke-RestMethod -Method PUT `
-Uri ("{0}?api-version={1}" -f $endpoint, $ApiVersion) `
-ContentType "application/json" `
-Authentication Bearer `
-Token $accessToken `
-Body $certJson
$updated = $cert.properties.thumbprint -ne $result.properties.thumbprint
# Set Output
Write-Output "::set-output name=updated::$updated"
name: Update DNS & SSL Certificate
on:
schedule:
- cron: '0/30 * * * *'
jobs:
update_dns_and_ssl_certificate:
name: 'PROD: Update DNS and SSL Certificate'
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Update A record
id: arecord
uses: ./actions/dns-update
env:
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
with:
appServiceResourceGroup: ${{ secrets.RESOURCE_GROUP_NAME_APP }}
appName: ${{ secrets.RESOURCE_NAME_FUNCTIONAPP }}
dnsZoneResourceGroup: ${{ secrets.RESOURCE_GROUP_NAME_ZONE }}
dnsZoneName: ${{ secrets.RESOURCE_NAME_ZONE }}
- name: Update SSL Certificate
if: steps.arecord.outputs.updated == 'true'
id: certificate
uses: ./actions/ssl-update
with:
apiEndpoint: ${{ secrets.SSL_RENEW_ENDPOINT }}
hostNames: ${{ secrets.SSL_HOST_NAMES }}
- name: Sync SSL Certificate
if: steps.certificate.outputs.updated == 'true'
id: sync
uses: ./actions/ssl-update
env:
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
with:
certificateResourceGroup: ${{ secrets.RESOURCE_GROUP_NAME_CERTIFICATE }}
certificateName: ${{ secrets.RESOURCE_NAME_CERTIFICATE }}
- name: Send Email Notification
if: steps.sync.outputs.updated == 'true'
uses: dawidd6/action-send-mail@v2
with:
server_address: ${{ secrets.MAIL_SMTP_SERVER }}
server_port: ${{ secrets.MAIL_SMTP_PORT }}
username: ${{ secrets.MAIL_SMTP_USERNAME }}
password: ${{ secrets.MAIL_SMTP_PASSWORD }}
subject: '[${{ secrets.SSL_HOST_NAMES }}] SSL Certificate Updated'
body: 'SSL certificate for ${{ secrets.SSL_HOST_NAMES }} has been updated'
to: ${{ secrets.MAIL_RECIPIENTS }}
from: ${{ secrets.MAIL_SENDER }}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment