Azure AD Application Proxy ( 後簡稱 AppProxy ) 是我真心覺得微軟非常棒的一個 Azure 服務,IT 管理者可以簡單完成串接企業內部應用程式,使用者在無 VPN 的環境下就能從 Internet 直接存取到內部系統,並且搭配 Azure AD 及 Conditional Access 提供企業強大及完整的安全防護。
一般在佈建 AppProxy 服務時,IT 管理者為方便後期快速部署,大都會使用萬用字元憑證 ( Wildcard SSL Certificate ) 進行設定。但如果遇到萬用字元憑證快到期時,已經大量部署的 AppProxy 應該沒人想一個個手動更換憑證,老闆又不是請你來做工讀生的工作 (但可能給工讀生的薪水!?),這時可以利用後述的指令進行大量更換。
本篇指令主要參考國外分享,然後將其拆分成兩段做小部改寫,因為我認為任何的直接快速大量修改都是有風險的,必須要測試及確認後才能進行變更,甚至有機會做還原動作。
開始前,請準備好
1. Azure AD PowerShell
2. 預備更新的萬用字元憑證帶私鑰 ( Private Key ) 的檔案。PFX 檔案格式,如果檔案小於 4 KB ,一般我會懷疑該檔案完全沒有含私鑰。
3. 預備更新的憑證匯入密碼
兩段的 PowerShell 程式如下,並已放在 GitHub 提供下載使用
GitHub - AskaSu - Bulk update Certificate for AAD AppProxy
第一段,產生與指定網域名稱有關的 AppProxy 資訊 CSV 報表。
藉此瞭解現有相關設定外,同時可以工人模式檢視哪些 App Proxy 真的需要進行憑證更換。
[提醒]
a. 預設產生的報表指定放入 C:\Temp 目錄中,如有其他需求請自行修改。
b. 假設這個報表主要作為憑證更新使用,可以參考程式碼中 ExternalUrl -nolike 那段進行編修,對子網域直接做過濾。主要是一般萬用字元憑證並不支援子網域 ,除非買的是 Multi-Domain 等級的憑證,不過那價格應該不是一般企業會採購的了。
執行語法範例
.\AAD_Create_AppProxy_Checking_List.ps1 -CustomDomain 網域名稱
完整指令碼
Param( [Parameter(Mandatory = $true)] [string] $CustomDomain ) $QueryDomain = "*"+ $CustomDomain + "/*" #Connect to AzureAD Write-Host 'Connecting to AzureAD' -ForegroundColor Yellow Connect-AzureAD #ExportFile $AADName = @((@((Get-AzureADDomain | Where-Object {$_.Name -like "*.onmicrosoft.com"}).Name )[0]).Split("."))[0] $ExportFilePath = "C:\Temp\" + $AADName + "_AADAppProxy_Checking_list_" + "$((Get-Date -format yyyy-MMdd).ToString()).csv" #Get all Azure AD App Proxy Proxy Applications checking the ObjectID of all apps. Write-Host 'Obtaining Azure AD App Proxy Applications for your Domain' -ForegroundColor Yellow $ProxyApps = foreach ($a in (Get-AzureADApplication -All:$true | Sort-Object DisplayName)) { try { $p = Get-AzureADApplicationProxyApplication -ObjectId $a.ObjectId [pscustomobject]@{DisplayName=$a.DisplayName; ObjectID=$a.ObjectId; ExternalUrl=$p.ExternalUrl; InternalUrl=$p.InternalUrl; AuthenticationType=$p.ExternalAuthenticationType; ServerTimeout=$p.ApplicationServerTimeout; CertSubjectName = $p.VerifiedCustomDomainCertificatesMetadata.SubjectName; CertThumbprint = $p.VerifiedCustomDomainCertificatesMetadata.Thumbprint; CertExpiryDate = $p.VerifiedCustomDomainCertificatesMetadata.ExpiryDate ; CertificateInfo=$p.VerifiedCustomDomainCertificatesMetadata} } catch { continue } } #Filter the proxy applications with the ExternalURL of your domain to askacloud.com only, and not including Jira site series, rd.askacloud.com and iot.askacloud.com etc. $AppsOnCustomDomain = $ProxyApps | Where-Object {$_.ExternalUrl -like $QueryDomain ` -and $_.ExternalUrl -notlike "*.jira*" ` -and $_.ExternalUrl -notlike "*rd.askacloud.com*" ` -and $_.ExternalUrl -notlike "*iot.askacloud.com*" ` } | Sort-Object DisPlayName Write-Host 'The following applications need to been reviewed for Certificate Update' -ForegroundColor Yellow $AppsOnCustomDomain | Out-Host #Export list for checking again and updating $AppsOnCustomDomain | Export-Csv -NoTypeInformation -Encoding UTF8 -Path $ExportFilePath
第二段,依據前面的列表作為大量更換的依據,接著進行憑證更新。
可以嘗試先將列表清單修改到僅剩下一兩項,也就是前面提到的先進行測試,確認後再進行大量部署。
[提醒]
a.本段語法假設已透過 PowerShell 完成連接 Azure AD,並且預備更新的 AppProxy 清單檔案,儲存在執行前段指令當天所產生的位置裡。
b. 執行過程如下圖會需要輸入匯入密碼,請先準備。
執行語法範例
.\AAD_Update_Cert_to_AppProxy.ps1 -PFXLocation 檔名及完整路徑
完整指令碼
Param( [Parameter(Mandatory=$True)] [String] $PFXLocation ) #Connect to AzureAD #Write-Host 'Connecting to AzureAD' -ForegroundColor Yellow #Connect-AzureAD # $PFXLocation = "C:\Temp\wildcard_askacloud_com.pfx" #Enter the PFX password Write-Host 'Enter the password for PFX file' -ForegroundColor Yellow $PFXPassword = Read-Host -AsSecureString $AADName = @((@((Get-AzureADDomain | Where-Object {$_.Name -like "*.onmicrosoft.com"}).Name )[0]).Split("."))[0] $ImportFilePath = "C:\Temp\" + $AADName + "_AADAppProxy_Checking_list_" + "$((Get-Date -format yyyy-MMdd).ToString()).csv" $AppsOnCustomDomain = Import-CSV -path $ImportFilePath Write-Host 'Are you sure you wish to change certificate on the above applications? (Y/N)' -ForegroundColor Yellow $Answer = Read-Host If ($Answer -eq 'Y'){ #Loop through the custom domain apps and upload new TLS certificate foreach ($CustomDomainApp in $AppsOnCustomDomain) { Write-Host "Setting Certificate on Application" $CustomDomainApp.DisplayName -ForegroundColor Green Set-AzureADApplicationProxyApplicationCustomDomainCertificate -ObjectId $CustomDomainApp.ObjectID -PfxFilePath $PFXLocation -Password $PFXPassword } } else { Write-Host 'Apps not approved for change' -ForegroundColor Red }
另外,我觀察測試及確認
1. 一旦完成更新與這個網域有關的憑證後,再新增加與該網域有關的 AppProxy,就會自動使用這張最新更換的。
2. 憑證匯入密碼打錯,不會做任何動作,只是會跳錯誤訊息而已。
3. 更新過程會去檢查憑證是否有對應到使用的網域名稱,如果沒有對應到,就會報錯,但不會影響該 App Proxy 的原始憑證設定,也就是不會被搞到壞掉。
舉例來說,下圖報錯的項目「AppProxy - POC - Graylog」,實際的 FQDN 為 log.app.askacloud.com 是在子網域中 ,也就是前面提及的狀況,一般萬用字元憑證無法使用到再下一層的子網域,所以報錯無法更新是正常情形,而且,錯誤訊息也很明顯地告知:
" Set-AzureADApplicationProxyApplicationCustomDomainCertificate : Error occurred while executing SetApplicationProxyApplication
Code: InvalidCertificate_HostNameMismatch
Message: Bad Certificate Request "
資料參考
Declan Turley Tech Blog - Azure AD App Proxy: Bulk Update TLS Certificate for a Custom Domain
MS Docs - Get all Azure Active Directory Application Proxy applications published with the identical certificate and replace it
發佈留言