節前不打烊,以此小文提前預祝大家鼠年大吉。最近和小伙伴們溝通發現,經常有系統出現證書過期的問題,究其原因主要是1. 證書后台自動 renew 了但是系統並沒有及時更新 2. 因為沒有郵件提醒所以忽略的證書過期。針對上述問題,目前在 Azure 平台內大部分的 PaaS 服務都已經內置了證書自動更新的能力,但對於 IaaS 服務,應為管理界面從操作系統開始都掌握在客戶自己手上,所以操作系統內應用的證書更新需要客戶自己來完成,那么 Azure 平台有什么好的方法可以幫助客戶避免證書過期的問題。本文將介紹如何通過 Azure 平台的服務實現證書過期發現及自動更新。
證書過期預警:
Azure 平台的 Key Vault 服務提供了證書托管服務,客戶可以將自己的管理的證書上傳至 Key Vault 服務,然后通過設置 Issuance Policy,通過在其中設置 Lifetime Action Type 來實現證書過期郵件提醒,可參閱:https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates#key-vault-certificates。
證書自動更新:
Azure 平台的 Key Vault 服務支持對自簽名或支持的集成證書提供方 (DigiCert, GlobalSign) 提供自動證書 Renew 服務,借助該功能可實現無干預的證書自動續簽。但是類似虛擬機 IaaS 服務內的應用服務證書更新仍然需要用戶自己來處理完成。這部分的自動化可以通過 Event Grid + Logic App 來實現。Azure Event Grid 服務原生集成支持 Key Vault 服務的事件消息,當有證書續簽的時候會釋放證書事件消息,Logic App 通過訂閱監聽改證書事件消息可以實現后續證書更細的自動化流程。本文幫助大家更快上手選擇了 Logic App(基本上可以是零代碼),喜歡代碼解決問題的同學可以考慮使用 Function 服務。本文的例子中以更新虛擬機中 Nginx 服務其中的 SSL 證書為例,在 Logic App 中通過調用 Azure Resource Management -- Resource Update 模塊來將續簽好的證書上傳至虛擬機,這里需要強調微軟雲的 VM 原生的模板中已經支持證書屬性,該屬性可以通過指定 Azure Key Vault 中存放的證書地址實現將證書上傳至虛擬機中,這樣就實現了 Azure Resource Template 來自動上傳證書。上傳證書后再調用 Azure Resource Management -- Resource Update 來調用 VM 的 customscript extension 擴展模塊,通過執行腳本來實現將上傳好的續簽證書來自動更新 Nginx SSL 證書存放路徑的過期證書。下面我們來看一下方案的架構圖:
上圖中還引入了 Azure Table,主要是通過基礎的 KV 服務實現多應用/多主機證書自動更新的支持,在 Azure Table 中存儲 KeyVault 名稱,證書名稱和虛擬機的對應關系,這樣當 Event Grid 中 Fire 事件后,可以通過在 Table 中查詢到與該事件相關證書與什么虛擬機相關。
Logic App 里面三個模塊的具體實現這里不再做詳細的贅述,基本實現邏輯在上面已經介紹,大家可以參照下面的實例模板代碼進行導入修改。其中資源組名稱,作為初始變量,大家可以根據自己的實際環境進行調整。
Azure VM 對於 Azure Key Vault 的證書原生支持,通過在 VM 描述 Template 描述屬性中直接引用 Key Vault 證書路徑,即可實現虛擬機對證書的上傳導入, Azure Resource VM Template 示例可以參閱如下示例。
{
"osProfile": {
"secrets": [
{
"sourceVault": {
"id": "@{keyvaultid}"
},
"vaultCertificates": "@{certificate secret id}"
}
]
}
]
}
}
在 Logic App 中執行的 Custom Script Extension, 是通過執行已經預先上載在 Blob 服務中的腳本文件來實現應用證書更新的,這部分代碼邏輯是按照 Nginx SSL 證書示例來做的,大家可以按照實際自己的應用證書路徑進行修改。
#!/bin/bash secretsname=$(find /var/lib/waagent/ -name "*.prv" | cut -c -57) cp $secretsname.crt /etc/nginx/ssl/demo.cert cp $secretsname.prv /etc/nginx/ssl/demo.prv rm -f $secretsname.crt rm -f $secretsname.prv sudo service nginx restart echo $secretsname
Azure Table 中的 Schema 非常簡單,只包含一個 vmname 屬性,如果大家有更復雜的 Mapping 邏輯可以按照自己的要求定義自己的 Schema。下面供大家參考。其中 PartitionKey 采用 KeyVault Name,RowKey 采用證書名稱,該場景 entity 數量和訪問頻次都不會很多,所以這種 Partition 方式已經可以滿足要求。
好了就寫到這里啦,小伙伴們鼠年再見!