你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
使用 BrokerListener 保护 MQTT 代理通信
重要
Azure Arc 启用的 Azure IoT 操作预览版目前处于预览状态。 不应在生产环境中使用此预览版软件。
在正式版推出后,需要部署新的 Azure IoT 操作安装。 无法升级预览版安装。
有关 beta 版、预览版或尚未正式发布的 Azure 功能所适用的法律条款,请参阅 Microsoft Azure 预览版的补充使用条款。
若要自定义网络访问和安全性,请使用 BrokerListener 资源。 侦听器对应于向网络公开中转站的网络终结点。 对于每个 Broker 资源,可以有一个或多个 BrokerListener 资源,因此可以有多个端口,每个端口具有不同的访问控制。
每个侦听器端口都可以有自己的身份验证和授权规则,这些规则定义谁可以连接到侦听器,以及他们可以在中转站上执行的操作。 可以使用 BrokerAuthentication 和 BrokerAuthorization 资源为每个侦听器指定访问控制策略。 这种灵活性使你可以根据 MQTT 客户端的需求和用例微调 MQTT 客户端的权限和角色。
提示
只能使用群集 IP、TLS 和服务帐户令牌访问默认 MQTT 代理部署。 从群集外部连接的客户端需要额外的配置,然后才能进行连接。
侦听器具有以下特征:
- 最多可以有三个侦听器。 每个服务类型(
loadBalancer
、clusterIp
或nodePort
)一个侦听器。 名为“默认”的默认 BrokerListener 的服务类型是clusterIp
。 - 每个侦听器支持多个端口
- BrokerAuthentication 和 BrokerAuthorization 引用针对每个端口
- TLS 配置因端口而异
- 服务名称必须是唯一的
- 不同侦听器的端口不会发生冲突
有关可用设置的列表,请参阅代理侦听器 API 参考。
默认 BrokerListener
部署 Azure IoT 操作预览版时,此部署还会在azure-iot-operations
命名空间中创建名为default
的BrokerListener资源。 此侦听器将链接到也在部署期间创建的名为 default
的默认 Broker 资源。 默认侦听器在启用了 TLS 和 SAT 身份验证的端口 18883 上公开中转站。 TLS 证书由证书管理器自动管理。 默认情况下禁用授权。
若要查看或编辑侦听器:
在 Azure 门户中,导航到 IoT 操作实例。
在 Azure IoT 操作资源下,选择 MQTT 代理。
从中转站侦听器列表中选择默认侦听器。
查看侦听器设置,并根据需要进行任何更改。
创建新的中转站侦听器
此示例演示如何为 Broker 资源创建名为“loadbalancer-listener”的新 BrokerListener 资源。 BrokerListener 资源定义接受来自客户端的 MQTT 连接的两个端口。
- 第一个端口侦听端口 1883,不带 TLS 且身份验证已关闭。 客户端无需加密或身份验证即可连接到中转站。
- 第二个端口侦听端口 18883,同时启用 TLS 和身份验证。 只有经过身份验证的客户端才能使用 TLS 加密连接到中转站。 TLS 字段设置为
automatic
,这意味着侦听器使用 cert-manager 来获取和续订其服务器证书。
在 Azure 门户中,导航到 IoT 操作实例。
在 Azure IoT 操作资源下,选择 MQTT 代理。
选择 LoadBalancer 的 MQTT 代理监听器>创建。 每个服务类型只能创建一个侦听器。 如果已有相同服务类型的侦听器,则可以向现有侦听器添加更多端口。
输入以下设置:
设置 说明 Name BrokerListener 资源的名称。 服务名称 与 BrokerListener 关联的 Kubernetes 服务的名称。 服务类型 代理服务的类型,例如 LoadBalancer、NodePort 或 ClusterIP。 端口 BrokerListener 侦听 MQTT 连接的端口号。 身份验证 身份验证资源参考。 授权 授权资源引用。 TLS 指示是否为安全通信启用 TLS。 可以设置为自动或手动。 选择“创建侦听器”。
使用自动证书管理配置 TLS
若要启用具有自动证书管理的 TLS,请在侦听器端口上指定 TLS 设置。
验证证书管理器安装
借助自动证书管理,可以使用证书管理器管理 TLS 服务器证书。 默认情况下,证书管理器已在azure-iot-operations
命名空间中与 Azure IoT 操作预览版一起安装。 在继续之前验证安装。
使用
kubectl
检查与证书管理器应用标签匹配的 Pod。kubectl get pods --namespace azure-iot-operations -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,则已安装证书管理器并可供使用。
提示
要进一步验证安装,请查看证书管理器文档验证安装。 请记住使用azure-iot-operations
命名空间。
为 TLS 服务器证书创建颁发者
证书管理器颁发者资源定义如何自动颁发证书。 证书管理器支持多种本机颁发者类型。 它还支持外部颁发者类型,用于将功能扩展到本机受支持的颁发者之外。 MQTT 代理可用于任何类型的证书管理器颁发者。
重要
在初始部署期间,Azure IoT 操作随 TLS 服务器证书的默认颁发者一起安装。 可以使用此颁发者进行开发和测试。 有关详细信息,请参阅Azure IoT 操作的默认根 CA 和颁发者。 只有当想要使用不同的颁发者时,才需要执行以下步骤。
创建颁发者的方法因场景而异。 以下部分列出了帮助入门的示例。
- 开发或测试
- 生产
CA 颁发者可用于开发和测试。 必须使用 Kubernetes 机密中存储的证书和私钥进行配置。
将根证书设置为 Kubernetes 机密
如果有现有的 CA 证书,请使用 CA 证书和私钥 PEM 文件创建 Kubernetes 机密。 运行以下命令,并将根证书设置为 Kubernetes 机密,并可以跳过下一部分。
kubectl create secret tls test-ca --cert tls.crt --key tls.key -n azure-iot-operations
如果没有 CA 证书,证书管理器可以为你生成根 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
证书管理器使用其默认值创建 CA 证书。 可以修改证书规范以更改此证书的属性。 有关有效选项列表,请参阅证书管理器文档。
分发根证书
前面的示例将 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
此证书必须由所有客户端分发和信任。 例如,对 mosquitto 客户端使用--cafile
标志。
基于 CA 证书创建颁发者
证书管理器需要基于在前面的步骤中生成或导入的 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 自动证书管理功能
下面是 BrokerListener 资源示例,该资源使用自动证书管理在端口 8884 上启用 TLS。
在 Azure 门户中,转到 IoT 操作实例。
在 Azure IoT 操作资源下,选择 MQTT 代理。
选择或创建侦听器。 每个服务类型只能创建一个侦听器。 如果已有相同服务类型的侦听器,则可以向现有侦听器添加更多端口。
可以通过选择现有端口上的 TLS 或添加新端口,将 TLS 设置添加到侦听器。
输入以下设置:
设置 说明 端口 BrokerListener 侦听 MQTT 连接的端口号。 必需。 身份验证 身份验证资源参考。 授权 授权资源引用。 TLS 选择“添加”按钮。 颁发者名称 cert-manager 证书颁发者的名称。 必需。 证书颁发者类型 cert-manager 证书颁发者的类型。 必需。 证书颁发者组 cert-manager 证书颁发者组。 必需。 私钥算法 私钥的算法。 私钥轮换策略 用于轮换私钥的策略。 DNS 名称 证书的 DNS 使用者备用名称。 IP 地址 证书使用者备用名称的 IP 地址。 密钥名称 包含 X.509 客户端证书的 Kubernetes 机密。 持续时间 TLS 服务器证书的总生存期默认为 90 天。 续订时间早于 开始续订证书的时间。 选择“保存”,以保存 TLS 设置。
使用 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 以进行测试的示例。
使用步骤 CLI 创建证书颁发机构
步骤是证书管理器,可在创建和管理自己的专用 CA 时快速启动并运行。
安装步骤 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
创建服务器证书
使用步骤 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)。 要通过 Internet 进行连接,请使用外部 IP添加--san
。 --no-password --insecure
标志用于测试,以跳过密码提示并禁用私钥的密码保护,因为它存储在 Kubernetes 机密中。 对于生产,请使用密码并将私钥存储在 Azure 密钥保管库等安全位置中。
证书密钥算法要求
支持 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 代理。
选择或创建侦听器。 每个服务类型只能创建一个侦听器。 如果已有相同服务类型的侦听器,则可以向现有侦听器添加更多端口。
可以通过选择现有端口上的 TLS 或添加新端口,将 TLS 设置添加到侦听器。
输入以下设置:
设置 说明 端口 BrokerListener 侦听 MQTT 连接的端口号。 必需。 身份验证 身份验证资源参考。 授权 授权资源引用。 TLS 选择“添加”按钮。 密钥名称 包含 X.509 客户端证书的 Kubernetes 机密。 选择“保存”,以保存 TLS 设置。
使用 TLS 连接到代理
若要使用 mosquitto 客户端测试 TLS 连接,请发布消息并在参数 --cafile
中传递根 CA 证书。
mosquitto_pub -d -h localhost -p 8885 -i "my-client" -t "test-topic" -m "Hello" --cafile root_ca.crt
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
添加转发端口。
注意
若要连接到代理,需要将信任根分发到客户端,也称为信任捆绑包。 在这种情况下,信任根是自签名根 CA 创建的步骤 CLI。 客户端需要分发信任根才能验证服务器证书链。 如果 MQTT 客户端是 Kubernetes 群集上的工作负载,则还需要使用根 CA 创建 ConfigMap 并将其装载到 Pod 中。
如果已启用 MQTT 代理身份验证,请记得指定用户名、密码等。
对服务器证书使用外部 IP
若要通过 TLS 在 Internet 上进行连接,MQTT 代理的服务器证书必须将其外部主机名作为 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 机密。 创建机密后,它会自动导入到侦听器。