使用 BrokerListener 保護 MQTT 代理程式通訊
重要
此頁面包含使用 Kubernetes 部署指令清單來管理 Azure IoT Operations 元件的指示,其處於預覽狀態。 這項功能隨附 數個限制,不應用於生產工作負載。
請參閱 Microsoft Azure 預覽版增補使用規定,以了解適用於 Azure 功能 (搶鮮版 (Beta)、預覽版,或尚未正式發行的版本) 的法律條款。
BrokerListener 對應至網路端點,該端點會透過網路向客戶端公開訊息代理程式。 您可以為每個 Broker 擁有一或多個 BrokerListener 資源,每個 Broker 都有多個埠和不同的存取控制。
每個 BrokerListener 埠可以有自己的驗證和授權規則,這些規則會定義誰可以連線到該接聽程式埠,以及他們可以在訊息代理程式上執行的動作。 您可以使用 BrokerAuthentication 和 BrokerAuthorization 資源來指定每個接聽程式埠的訪問控制原則。 此彈性可讓您根據 MQTT 用戶端的需求和使用案例,微調 MQTT 用戶端的許可權和角色。
提示
預設 MQTT 訊息代理程式部署是叢集 IP 服務,需要用戶端使用 TLS 進行連線,並使用服務帳戶令牌進行驗證。 從叢集 外部連線的用戶端需要額外的設定 ,才能連線。
Broker 接聽程式具有下列特性:
- 名稱:接聽程序的名稱。 除非覆寫,否則此名稱也是 Kubernetes 服務名稱。
- 服務類型:您最多可以有三個接聽程式,每個 服務類型一個接聽程式。 預設接 聽程式 是服務類型
ClusterIp
。 - 埠:每個接聽程式都支援 多個埠。 埠 無法與不同的接聽程式發生衝突。
- 驗證和授權參考: 每個埠都已設定 BrokerAuthentication 和 BrokerAuthorization 。
- TLS: 每個埠會套用手動 或 自動 TLS 設定。
- 通訊協定: 每個埠都可以啟用透過 WebSocket 的 MQTT。
如需所有可用設定的清單,請參閱 Broker 接聽程式 API 參考。
預設 BrokerListener
當您部署 Azure IoT 作業時,部署會建立名為 default
的 BrokerListener 資源。 此接聽程式用於 Azure IoT 作業元件之間的加密內部通訊。 默認接聽程式是預設 Broker 的一部分。
- 它會在埠 18883 上公開 ClusterIp 服務
- 它需要用戶端使用 Kubernetes 服務帳戶驗證
- 它有自動管理的 TLS 憑證
- 它不會設定任何客戶端授權原則
警告
為了避免中斷內部 Azure IoT 作業通訊,請將預設接聽程式維持不變,並專用於內部使用。 針對外部通訊, 請建立新的接聽程式。 如果您需要使用 ClusterIp 服務,請將更多埠新增至預設接聽程式,而不需要變更任何現有的設定。
若要檢視或編輯預設接聽程式:
在 Azure 入口網站 中,流覽至您的IoT作業實例。
在 [Azure IoT 作業資源] 底下,選取 [MQTT 訊息代理程式]。
從訊息代理程式接聽程式清單中,選取預設接聽程式。
檢閱接聽程式設定,但請避免修改任何現有的設定。 請改為建立新的埠,並視需要進行設定。
避免修改預設訊息代理程式接聽程式
若要防止中斷內部 Azure IoT 作業通訊,請將預設接聽程序維持不變,並專用於內部使用。 針對外部通訊, 請建立新的接聽程式。
由於預設訊息代理程式接聽程式使用服務類型 ClusterIp,而且每個服務類型只能有一個接聽程式,因此,如果您需要使用 ClusterIp 服務,請將更多埠新增至預設接聽程式,而不需要變更任何現有的設定。
建立新的訊息代理程式接聽程式
若要建立新的接聽程式,請指定下列設定:
- 名稱:接聽程序的名稱。 除非覆寫,否則此名稱也是 Kubernetes 服務名稱。
- 服務類型:Kubernetes 服務的類型。 請參閱 服務類型。
- 埠:要接聽的埠清單。 請參閱連接埠。
- (選擇性) 服務名稱:覆寫 Kubernetes 服務名稱。 請參閱 服務名稱。
範例:使用兩個埠建立新的接聽程式
此範例示範如何使用負載平衡器服務類型建立新的接聽程式。 BrokerListener 資源會定義兩個埠,以接受來自用戶端的 MQTT 連線。
- 第一個埠會在埠 1883 上接聽,而不需要 TLS 和驗證。 此設定僅適用於測試。 請勿在生產環境中使用此設定。
- 第二個埠會在埠 8883 上接聽已啟用 TLS 和驗證。 只有 具有 Kubernetes 服務帳戶令牌 的已驗證用戶端才能連線。 TLS 會設定為自動模式,使用 cert-manager 從預設簽發者管理伺服器證書。 此設定更接近生產設定。
在 Azure 入口網站 中,流覽至您的IoT作業實例。
在 [Azure IoT 作業資源] 底下,選取 [MQTT 訊息代理程式]。
針對 LoadBalancer Create 選取 MQTT 訊息代理程式接聽程式。>
輸入下列設定:
設定 描述 名稱 BrokerListener 資源的名稱。 服務名稱 Kubernetes 服務的名稱。 保留空白,以使用接聽程式名稱做為服務名稱。 服務類型 LoadBalancer 已選取。 在 [埠] 下,輸入第一個埠的下列設定:
設定 描述 連接埠 輸入 1883 驗證 選擇 [無] 授權 選擇 [無] 通訊協定 選擇 MQTT TLS 不要新增 選取 [新增埠] 專案 以新增第二個埠,然後輸入下列設定:
設定 描述 連接埠 輸入8883 驗證 選擇 預設值 授權 選擇 [無] 通訊協定 選擇 MQTT TLS 選取新增 在 [ TLS 組態 ] 窗格中,輸入下列設定:
設定 描述 TLS 模式 選擇 [自動] 簽發者名稱 輸入 azure-iot-operations-aio-certificate-issuer
簽發者種類 選擇 ClusterIssuer 將其他設定保留為預設值,然後選取 [ 套用]。
選取 [ 建立接聽程式]。
服務類型
每個 BrokerListener 都會對應至 Kubernetes 服務。 服務類型會決定訊息代理程式如何向網路公開。 支援的服務類型如下:
- ClusterIp:在叢集內部IP上公開訊息代理程式。 用戶端可以從叢集內連線到訊息代理程式。 這是預設接聽程式的預設服務類型。
- NodePort:在靜態埠上公開每個節點 IP 上的訊息代理程式。 用戶端可以從叢集外部連線到訊息代理程式。 此服務類型適用於開發和測試。
- LoadBalancer:在外部公開訊息代理程式。 服務會指派外部IP位址,用戶端可用來連線到訊息代理程式。 這是生產部署最常見的服務類型。
每個服務類型只有一個接聽程式
每個服務類型只允許一個接聽程式。 如果您需要相同服務類型的更多連線能力,請將更多埠新增至該服務類型的現有接聽程式。
服務名稱
服務名稱是與訊息代理程序相關聯的 Kubernetes 服務名稱。 如果未指定,訊息代理程式接聽程式名稱會當做服務名稱使用。 服務名稱在命名空間內必須是唯一的。
提示
若要避免管理額外負荷,建議您將服務名稱保留空白。 接聽程式名稱是唯一的,可用來識別服務。 只有在您無法在接聽程式之後為服務命名時,才使用服務名稱做為覆寫。
連接埠
每個接聽程式可以有多個埠,而且每個埠都可以有自己的驗證、授權、通訊協定和 TLS 設定。
若要針對埠使用您自己的驗證或授權設定,您必須先建立對應的資源,才能與接聽程式搭配使用。 如需詳細資訊,請參閱 設定 MQTT 訊息代理程式驗證 和 設定 MQTT 訊息代理程式授權。
若要使用 TLS,請參閱 使用自動憑證管理 設定 TLS 或使用 手動憑證管理 設定 TLS 小節。
跨接聽程式使用相同的埠
不支援跨不同接聽程式使用相同的埠號碼。 每個埠號碼都必須在 Azure IoT Operations MQTT 訊息代理程式內是唯一的。
例如,如果您有使用埠 1883 的接聽程式,則無法使用埠 1883 建立另一個接聽程式。 同樣地,預設接聽程式會使用埠 18883,因此您無法使用埠 18883 建立另一個接聽程式。
WebSocket 支援
Azure IoT Operations MQTT 訊息代理程式支援透過 WebSocket 的 MQTT。 若要開啟 WebSockets,請將連接埠的通訊協定 WebSockets
設定為 。
使用自動憑證管理設定 TLS
若要啟用具有自動憑證管理的 TLS,請在接聽程式埠上指定 TLS 設定。
確認 cert-manager 安裝
透過自動憑證管理,您可以使用 cert-manager 來管理 TLS 伺服器憑證。 根據預設,cert-manager 會與 cert-manager
命名空間中的 Azure IoT 操作預覽一起安裝。 在繼續之前,請先確認安裝。
使用
kubectl
來檢查符合 cert-manager 應用程式標記的 Pod。kubectl get pods --namespace cert-manager -l 'app in (cert-manager,cainjector,webhook)'
NAME READY STATUS RESTARTS AGE aio-cert-manager-64f9548744-5fwdd 1/1 Running 4 (145m ago) 4d20h aio-cert-manager-cainjector-6c7c546578-p6vgv 1/1 Running 4 (145m ago) 4d20h aio-cert-manager-webhook-7f676965dd-8xs28 1/1 Running 4 (145m ago) 4d20h
如果您看到顯示為就緒且正在執行的 Pod,則已安裝 cert-manager 並可供使用。
提示
若要進一步確認安裝,請檢查 cert-manager 文件確認安裝。 請記得使用 cert-manager
命名空間。
建立 TLS 伺服器憑證的簽發者
cert-manager 簽發者 資源會定義如何自動發行憑證。 Cert-manager 原生支持數種簽發者類型。 它也支援外部簽發者類型,以擴充原生支援簽發者以外的功能。 MQTT 代理程式可以搭配任何類型的 cert-manager 簽發者使用。
重要
在初始部署期間,Azure IoT 操作會隨 TLS 伺服器憑證的預設簽發者一起安裝。 您可以使用此簽發者進行開發和測試。 如需詳細資訊,請參閱使用 Azure IoT 操作的預設根 CA 和簽發者。 只有在您想使用不同的簽發者時,才需要下列步驟。
建立簽發者的方法會根據您的案例而有所不同。 下列各節列出可協助您開始使用的範例。
CA 簽發者適用於開發和測試。 它必須使用儲存在 Kubernetes 秘密中的憑證和私鑰進行設定。
將根憑證設定為 Kubernetes 秘密
如果您有現有的 CA 憑證,請使用 CA 憑證和 CA 私鑰 PEM 檔案建立 Kubernetes 秘密。 執行下列命令,將 CA 憑證匯入為 Kubernetes 秘密,並略過下一節。
kubectl create secret tls test-ca --cert tls.crt --key tls.key -n azure-iot-operations
如果您沒有 CA 憑證,cert-manager 可以為您產生 CA 憑證。 使用憑證管理員產生 CA 憑證,稱為 使用自我簽署憑證啟動載入 CA 簽發者。
從建立
ca.yaml
開始:apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: selfsigned-ca-issuer namespace: azure-iot-operations spec: selfSigned: {} --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: selfsigned-ca-cert namespace: azure-iot-operations spec: isCA: true commonName: test-ca secretName: test-ca issuerRef: # Must match Issuer name above name: selfsigned-ca-issuer # Must match Issuer kind above kind: Issuer group: cert-manager.io # Override default private key config to use an EC key privateKey: rotationPolicy: Always algorithm: ECDSA size: 256
使用下列命令建立自我簽署 CA 憑證:
kubectl apply -f ca.yaml
Cert-manager 會使用其預設值建立 CA 憑證。 您可以藉由修改憑證規格來變更此憑證的屬性。 如需有效選項的清單,請參閱 cert-manager 文件。
散發根憑證
上述範例會將 CA 憑證儲存在名為 test-ca
的 Kubernetes 秘密中。 PEM 格式的憑證可以從秘密擷取,並使用下列命令儲存在檔案 ca.crt
中:
kubectl get secret test-ca -n azure-iot-operations -o json | jq -r '.data["tls.crt"]' | base64 -d > ca.crt
此憑證必須由所有用戶端分散及信任。 例如,使用 --cafile
mosquitto 用戶端的 旗標。
根據 CA 憑證建立簽發者
cert-manager 需要根據先前步驟產生或匯入的 CA 憑證來建立一個簽發者。 將下列檔案建立為 issuer-ca.yaml
:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: my-issuer
namespace: azure-iot-operations
spec:
ca:
# Must match secretName of generated or imported CA cert
secretName: test-ca
使用下列命令建立簽發者:
kubectl apply -f issuer-ca.yaml
先前的命令會建立簽發者來發行 TLS 伺服器證書。 記下簽發者的名稱和種類。 在這裡範例中,名稱為 my-issuer
,且種類為 Issuer
。 這些值稍後會在 BrokerListener 資源中設定。
啟用埠的 TLS 自動憑證管理
以下是可在連接埠 8884 上使用自動憑證管理來啟用 TLS 的 BrokerListener 資源範例。
在 Azure 入口網站 中,移至您的 IoT 作業實例。
在 [Azure IoT 作業資源] 底下,選取 [MQTT 訊息代理程式]。
選取或建立接聽程式。 每個服務類型只能建立一個接聽程式。 如果您已經有相同服務類型的接聽程式,您可以將更多埠新增至現有的接聽程式。
您可以選取 現有埠上的 TLS 或新增埠,將 TLS 設定新增至接聽程式。
輸入下列設定:
設定 描述 名稱 BrokerListener 資源的名稱。 輸入 aio-broker-loadbalancer-tls
。連接埠 BrokerListener 接聽 MQTT 連線的埠號碼。 輸入8884。 驗證 驗證資源參考。 授權 授權 資源參考。 TLS 選取新增按鈕。 簽發者名稱 憑證管理員簽發者的名稱。 必要。 簽發者種類 憑證管理員簽發者的種類。 必要。 簽發者群組 憑證管理員簽發者的群組。 必要。 私鑰演演算法 私密金鑰的演算法。 私鑰輪替原則 輪替私鑰的原則。 DNS 名稱 憑證的 DNS 主體替代名稱。 IP 位址 憑證主體替代名稱的IP位址。 祕密名稱 包含 X.509 用戶端憑證的 Kubernetes 秘密。 期間 TLS 伺服器證書的總存留期預設為90天。 更新之前 何時開始更新憑證。 選取 [ 套用 ] 以儲存 TLS 設定。
設定 BrokerListener 資源之後,MQTT 代理程式會自動建立已啟用指定連接埠和 TLS 的新服務。
選擇性:設定伺服器憑證參數
唯一必要的參數是簽發者名稱和簽發者種類。 系統會自動選擇所產生 TLS 伺服器證書的所有其他屬性。 不過,MQTT 訊息代理程式允許遵循與憑證管理員憑證相同的語法來自定義特定屬性。 例如,您可以指定私鑰演算法和輪替原則。 這些設定位於 tls.certManagerCertificateSpec
Azure 入口網站 的或 [TLS 組態] 窗格中。
如需這些設定的完整清單,請參閱 Broker Listener CertManagerCertificateSpec API 參考。
驗證部署
使用 kubectl 檢查與 BrokerListener 資源相關聯的服務是否正在執行。 從上述範例中,服務名稱為 aio-broker-loadbalancer-tls
,而命名空間為 azure-iot-operations
。 下列命令會檢查服務狀態:
$ kubectl get service my-new-tls-listener -n azure-iot-operations
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
aio-broker-loadbalancer-tls LoadBalancer 10.X.X.X 172.X.X.X 8884:32457/TCP 33s
使用 TLS 連線到訊息代理程式
設定伺服器憑證之後,就會啟用 TLS。 若要使用 mosquitto 進行測試:
mosquitto_pub -h $HOST -p 8884 -V mqttv5 -i "test" -t "test" -m "test" --cafile ca.crt
--cafile
引數會在 mosquitto 用戶端上啟用 TLS,並指定用戶端應信任指定檔案所簽發的所有伺服器憑證。 您必須指定包含已設定 TLS 伺服器憑證簽發者的檔案。
將 $HOST
取代為適當的主機:
- 如果從同一叢集內連接,請替換為給定的服務名稱 (範例中為
my-new-tls-listener
) 或服務CLUSTER-IP
。 - 如果從叢集外部連線,服務
EXTERNAL-IP
。
請記得視需要指定驗證方法。
預設根 CA 和簽發者
為了協助您開始使用,Azure IoT 作業會使用 TLS 伺服器證書的預設「快速入門」CA 憑證和簽發者來部署。 您可以使用此簽發者進行開發和測試。 如需詳細資訊,請參閱 TLS 伺服器證書的預設根 CA 和簽發者。
針對生產環境,您必須使用來自受信任 CA 的憑證來設定 CA 簽發者,如前幾節所述。
使用手動憑證管理設定 TLS
若要手動設定 MQTT 訊息代理程式以使用特定的 TLS 憑證,請在 BrokerListener 資源中指定它,並參考 Kubernetes 秘密,並使用 kubectl 加以部署。 本文說明使用自我簽署憑證設定 TLS 以進行測試的範例。
使用 Step CLI 建立憑證授權單位
Step 是憑證管理員,可讓您在建立和管理自己的私人 CA 時快速啟動並執行。
安裝 Step CLI 並建立根憑證授權單位 (CA) 憑證和金鑰。
step certificate create --profile root-ca "Example Root CA" root_ca.crt root_ca.key
建立根 CA 簽署的中繼 CA 憑證和金鑰。
step certificate create --profile intermediate-ca "Example Intermediate CA" intermediate_ca.crt intermediate_ca.key \ --ca root_ca.crt --ca-key root_ca.key
建立伺服器憑證
使用 Step CLI 從中繼 CA 簽署的 建立伺服器憑證。
step certificate create mqtts-endpoint mqtts-endpoint.crt mqtts-endpoint.key \
--profile leaf \
--not-after 8760h \
--san mqtts-endpoint \
--san localhost \
--ca intermediate_ca.crt --ca-key intermediate_ca.key \
--no-password --insecure
在這裡,mqtts-endpoint
和 localhost
分別是 Kubernetes 和本機用戶端中 MQTT 代理程式前端的主體別名(SAN)。 若要透過因特網連線,請使用外部IP新增 --san
。 --no-password --insecure
旗標用於測試,以略過密碼提示,並停用私密金鑰的密碼保護,因為它儲存在 Kubernetes 秘密中。 針對生產環境,請使用密碼,並將私密金鑰儲存在安全的位置,例如 Azure Key Vault。
憑證金鑰演算法需求
支援 EC 和 RSA 金鑰,但鏈結中的所有憑證都必須使用相同的金鑰演算法。 如果您匯入自己的 CA 憑證,請確定伺服器證書使用與 CA 相同的密鑰演算法。
將伺服器憑證鏈結匯入為 Kubernetes 秘密
建立完整的伺服器憑證鏈結,其中憑證的順序很重要:伺服器憑證是檔案中的第一個憑證,中繼是第二個。
cat mqtts-endpoint.crt intermediate_ca.crt > server_chain.crt
使用 kubectl 建立具有伺服器憑證鏈結和伺服器金鑰的 Kubernetes 秘密。
kubectl create secret tls server-cert-secret -n azure-iot-operations \ --cert server_chain.crt \ --key mqtts-endpoint.key
啟用埠的 TLS 手動憑證管理
以下是 BrokerListener 資源的範例,可透過手動憑證管理在埠 8884 上啟用 TLS。
在 Azure 入口網站 中,流覽至您的IoT作業實例。
在 [Azure IoT 作業資源] 底下,選取 [MQTT 訊息代理程式]。
選取或建立接聽程式。 每個服務類型只能建立一個接聽程式。 如果您已經有相同服務類型的接聽程式,您可以將更多埠新增至現有的接聽程式。 若要遵循範例,請將接聽程式服務名稱指定為
mqtts-endpoint
。您可以選取 現有埠上的 TLS 或新增埠,將 TLS 設定新增至接聽程式。
輸入下列設定:
設定 描述 連接埠 BrokerListener 接聽 MQTT 連線的埠號碼。 必要。 驗證 驗證資源參考。 授權 授權 資源參考。 TLS 選取新增按鈕。 祕密名稱 包含 X.509 用戶端憑證的 Kubernetes 秘密。 選取 [ 套用 ] 以儲存 TLS 設定。
使用 TLS 連線到訊息代理程式
若要測試與 mosquitto 用戶端的 TLS 連線,請發佈訊息,並在 參數中傳遞根 CA 憑證 --cafile
。
mosquitto_pub -d -h localhost -p 8885 -i "my-client" -t "test-topic" -m "Hello" --cafile root_ca.crt
請記得在啟用 MQTT 代理程式驗證時指定使用者名稱、密碼等。
Client my-client sending CONNECT
Client my-client received CONNACK (0)
Client my-client sending PUBLISH (d0, q0, r0, m1, 'test-topic', ... (5 bytes))
Client my-client sending DISCONNECT
提示
若要使用 localhost,必須在主電腦上使用連接埠。 例如: kubectl port-forward svc/mqtts-endpoint 8885:8885 -n azure-iot-operations
。 透過 K3d 之類的某些 Kubernetes 散發套件,您可以使用 k3d cluster edit $CLUSTER_NAME --port-add 8885:8885@loadbalancer
來新增轉送連接埠。
注意
若要連線到訊息代理程式,您必須將所有用戶端散發信任根目錄,也稱為信任套件組合。 在此情況下,信任的根目錄是步驟 CLI 所建立的自我簽署根 CA。 用戶端需要散發信任根目錄,才能驗證伺服器憑證鏈結。 如果您的 MQTT 用戶端是 Kubernetes 叢集上的工作負載,您也需要使用根 CA 建立 ConfigMap,並將其掛接在您的 Pod 中。
針對伺服器憑證使用外部 IP
若要透過因特網與 TLS 連線,MQTT 訊息代理程式的伺服器證書必須具有其外部主機名或 IP 位址作為 SAN。 在生產環境中,這通常是 DNS 名稱或已知的 IP 位址。 不過,在開發/測試期間,您可能不知道在部署之前指派哪些主機名或外部 IP。 若要解決此問題,請先部署不含伺服器證書的接聽程式、使用外部IP建立伺服器證書和秘密,然後將秘密匯入接聽程式。
如果您嘗試部署範例 TLS 接聽程式 manual-tls-listener
,但參考的 Kubernetes 秘密 server-cert-secret
不存在,則會建立相關聯的服務,但 Pod 不會啟動。 因為操作員需要保留接聽程式的外部 IP,因此會建立服務。
kubectl get svc mqtts-endpoint -n azure-iot-operations
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mqtts-endpoint LoadBalancer 10.X.X.X 172.X.X.X 8885:30674/TCP 1m15s
不過,當我們匯入伺服器證書時,預期會發生此行為。 健康情況管理員記錄提到 MQTT 代理程式正在等候伺服器憑證。
kubectl logs -l app=health-manager -n azure-iot-operations
...
<6>2023-11-06T21:36:13.634Z [INFO] [1] - Server certificate server-cert-secret not found. Awaiting creation of secret.
注意
一般而言,在分散式系統中,Pod 記錄並不具決定性,而且應該謹慎使用。 這類資訊呈現的正確方式是透過 Kubernetes 事件和自訂資源狀態,也就是待辦項目。 請將上一個步驟視為暫時的因應措施。
即使前端 Pod 未啟動,但外部 IP 已可供使用。
kubectl get svc mqtts-endpoint -n azure-iot-operations
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mqtts-endpoint LoadBalancer 10.X.X.X 172.X.X.X 8885:30674/TCP 1m15s
從這裡,請遵循與先前相同的步驟,在 --san
中建立具有此外部 IP 的伺服器憑證,並以相同的方式建立 Kubernetes 秘密。 一旦建立秘密,它就會自動匯入至接聽程式。