你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
配置 MQTT 代理身份验证
重要
本页包含使用 Kubernetes 部署清单(目前为预览版)管理 Azure IoT 操作组件的说明。 此功能存在若干限制,不应该用于生产工作负载。
有关 beta 版本、预览版或尚未正式发布的版本的 Azure 功能所适用的法律条款,请参阅 Microsoft Azure 预览版的补充使用条款。
MQTT 代理支持客户端的多种身份验证方法,可以使用 BrokerAuthentication 资源为每个侦听器端口配置其自己的身份验证设置。 有关可用设置的列表,请参阅代理身份验证 API 参考。
链接 BrokerListener 和 BrokerAuthentication
以下规则适用于 BrokerListener 和 BrokerAuthentication 资源之间的关系:
- 每个 BrokerListener 可以有多个端口。 每个端口都可以链接到 BrokerAuthentication 资源。
- 每个 BrokerAuthentication 可以同时支持多种身份验证方法。
- 未链接 BrokerAuthentication 资源的端口已禁用身份验证。
若要将 BrokerListener 端口链接到 BrokerAuthentication 资源,请在 BrokerListener 资源的 ports
设置中指定 authenticationRef
字段。 若要了解详细信息,请参阅 BrokerListener 资源。
默认 BrokerAuthentication 资源
Azure IoT 操作部署一个名为 default
的默认 BrokerAuthentication 资源,该资源与 azure-iot-operations
命名空间中的默认侦听器相链接。 它仅使用 Kubernetes 服务帐户令牌 (SAT) 进行身份验证。
重要
Azure IoT 操作中的组件需要默认 BrokerAuthentication 资源中的服务帐户令牌 (SAT) 身份验证方法才能正常运行。 避免更新或删除默认 BrokerAuthentication 资源。
在 Azure 门户中,导航到 IoT 操作实例。
在“组件”下,选择“MQTT 代理”。
选择“身份验证”选项卡。
从身份验证策略列表中选择默认的策略名称。
若要添加新的身份验证方法,请选择“添加方法”。
身份验证流
指定身份验证方法的顺序决定了 MQTT 代理如何对客户端进行身份验证。 MQTT 代理会尝试使用第一个指定方法对客户端的凭据进行身份验证,并循环访问指定方法,直到找到匹配项或到达末尾。
对于每个方法,MQTT 代理会首先检查客户端的凭据是否与该方法相关。 例如,SAT 身份验证需要以 K8S-SAT
开头的用户名,X.509 身份验证需要客户端证书。 如果客户端的凭据相关,MQTT 代理将验证它们是否有效。 有关详细信息,请参阅“配置身份验证方法”部分。
对于自定义身份验证,MQTT 代理将无法与自定义身份验证服务器通信视为凭据不相关。 如果自定义身份验证服务器无法访问,则此行为会允许 MQTT 代理回退到其他方法。
身份验证流会在以下情况结束:
- 当以下条件之一为 true:
- 客户端的凭据对于其中一种方法相关且有效。
- 客户端的凭据与任何方法均无关。
- 客户端的凭据是相关的,但对于任何方法都无效。
- MQTT 代理会根据身份验证流的结果授予或拒绝对客户端的访问权限。
例如:
apiVersion: mqttbroker.iotoperations.azure.com/v1
kind: BrokerAuthentication
metadata:
name: default
namespace: azure-iot-operations
spec:
authenticationMethods:
- method: Custom
customSettings:
# ...
- method: ServiceAccountToken
serviceAccountTokenSettings:
# ...
前面的示例指定了自定义和 SAT。 客户端连接时,MQTT 代理会尝试按照先“自定义”、后“SAT”的顺序使用指定方法对客户端进行身份验证。
- MQTT 代理会检查客户端的凭据是否对自定义身份验证有效。 由于自定义身份验证依赖外部服务器来确定凭据的有效性,中转站会考虑与自定义身份验证相关的所有凭据,并将其转发到自定义身份验证服务器。
- 如果自定义身份验证服务器响应了
Pass
或Fail
结果,则身份验证流将结束。 但是,如果自定义身份验证服务器不可用,MQTT 代理会回退到剩余的指定方法,接下来是 SAT。 - MQTT 代理会尝试将凭据作为 SAT 凭据进行身份验证。
如果自定义身份验证服务器不可用,并且所有后续方法确定提供的凭据不相关,则代理会拒绝客户端连接。
配置身份验证方法
你可以添加身份验证方法,例如 X.509、SAT 或自定义身份验证策略。
若要向策略添加身份验证方法,请执行以下操作:
在 Azure 门户中,导航到 IoT 操作实例。
在“组件”下,选择“MQTT 代理”。
选择“身份验证”选项卡。
选择现有的身份验证策略或创建新的身份验证策略。
通过选择“添加方法”来添加新方法。
从下拉列表中选择方法类型,然后选择“添加详细信息”来配置方法。
若要详细了解每个身份验证选项,请参阅每个方法的下一部分。
有关通过配置 Azure 密钥保管库和启用工作负载标识来启用安全设置的详细信息,请参阅在 Azure IoT 操作部署中启用安全设置。
X.509
提示
有关如何配置 X.509 身份验证的端到端示例,请参阅教程:TLS、X.509 客户端身份验证和基于属性的访问控制 (ABAC) 授权。
在使用 X.509 身份验证的情况下,MQTT 代理使用受信任的 CA 证书来验证客户端证书。 此受信任的 CA 可以是根 CA 或中间 CA。 代理根据受信任的 CA 证书检查客户端证书链。 如果链有效,则客户端会通过身份验证。
若要将 X.509 身份验证与受信任的 CA 证书配合使用,必须满足以下要求:
- TLS:由于 X.509 依赖于 TLS 客户端证书,因此必须使用 X.509 身份验证为端口启用 TLS。
- 密钥算法:EC 和 RSA 密钥均受支持,但链中的所有证书都必须使用相同的密钥算法。
- 格式:CA 证书必须采用 PEM 格式。
提示
PEM 格式是证书和密钥的通用格式。 PEM 文件是 base64 编码的 ASCII 文件,其标头类似于 -----BEGIN CERTIFICATE-----
和 -----BEGIN EC PRIVATE KEY-----
。
如果证书采用另一种格式,则可以使用 OpenSSL 将其转换为 PEM。 有关详细信息,请参阅如何将证书转换为适当的格式。
获取受信任的 CA 证书
在生产设置中,CA 证书由组织的公钥基础结构 (PKI) 或公共证书颁发机构提供。
为了进行测试,请使用 OpenSSL 创建自签名 CA 证书。 例如,运行以下命令,生成具有 RSA 密钥、可分辨名称 CN=Contoso Root CA Cert
且有效期为 365 天的自签名 CA 证书:
openssl req -x509 -newkey rsa:4096 -keyout ca-key.pem -out ca.pem -days 365 -nodes -subj "/CN=Contoso Root CA Cert"
使用 Step CLI(一种用于管理证书的便捷工具)时,可生成该证书的命令是:
step certificate create "Contoso Root CA Cert" ca.pem ca-key.pem --profile root-ca --kty RSA --size 4096 --no-password --insecure
--not-after 8760h
这些命令以 PEM 格式创建 CA 证书 ca.pem
和私钥 ca-key.pem
。 CA 证书 ca.pem
可以导入到 MQTT 代理以进行 X.509 身份验证。
导入受信任的 CA 证书
若要开始使用 X.509 身份验证,请将受信任的 CA 证书导入到 azure-iot-operations
命名空间中的 ConfigMap。 若要将受信任的 CA 证书 ca.pem
导入到名为 client-ca
的 ConfigMap,请运行:
kubectl create configmap client-ca --from-file=ca.pem -n azure-iot-operations
在此示例中,CA 证书导入到密钥 ca.pem
下。 MQTT 代理信任 ConfigMap 中的所有 CA 证书,因此密钥的名称可以是任意名称。
若要检查根 CA 证书是否已正确导入,请运行 kubectl describe configmap
。 结果显示 PEM 证书文件的同一 base64 编码。
kubectl describe configmap client-ca -n azure-iot-operations
Name: client-ca
Namespace: azure-iot-operations
Data
====
ca.pem:
----
-----BEGIN CERTIFICATE-----
MIIFDjCCAvagAwIBAgIRAKQWo1+S13GTwqZSUYLPemswDQYJKoZIhvcNAQELBQAw
...
-----END CERTIFICATE-----
BinaryData
====
配置 X.509 身份验证方法
导入受信任的 CA 证书后,请通过在 BrokerAuthentication 资源中将 X.509 客户端身份验证添加为身份验证方法来启用该身份验证。 确保此资源链接到启用了 TLS 的侦听器端口。
在 Azure 门户中,导航到 IoT 操作实例。
在“组件”下,选择“MQTT 代理”。
选择“身份验证”选项卡。
选择现有的身份验证策略或创建新的身份验证策略。
通过选择“添加方法”来添加新方法。
从下拉列表中选择方法类型 X.509,然后选择“添加详细信息”来配置方法。
在“X.509 身份验证详细信息”窗格中,使用 JSON 格式指定受信任的 CA 证书 ConfigMap 名称。
{ "trustedClientCaCert": "<TRUSTED_CA_CONFIGMAP>" }
将
<TRUSTED_CA_CONFIGMAP>
替换为包含受信任 CA 证书的 ConfigMap 的名称。 例如,"trustedClientCaCert": "client-ca"
。(可选)使用 X.509 证书为客户端添加授权属性。 若要了解详细信息,请参阅用于授权的证书属性。
选择“应用”保存更改。
可选:用于授权的证书属性
可以在 BrokerAuthentication 资源中指定 X.509 属性,以基于其证书属性授权客户端。 这些属性在 authorizationAttributes
字段中定义。
例如:
在 Azure 门户中,当配置 X.509 身份验证方法时,请在“X.509 身份验证详细信息”窗格中以 JSON 格式添加授权属性。
{
"trustedClientCaCert": "<TRUSTED_CA_CONFIGMAP>",
"authorizationAttributes": {
"root": {
"subject": "CN = Contoso Root CA Cert, OU = Engineering, C = US",
"attributes": {
"organization": "contoso"
}
},
"intermediate": {
"subject": "CN = Contoso Intermediate CA",
"attributes": {
"city": "seattle",
"foo": "bar"
}
},
"smartfan": {
"subject": "CN = smart-fan",
"attributes": {
"building": "17"
}
}
}
}
在此示例中,具有可分辨名称为 CN = Contoso Root CA Cert, OU = Engineering, C = US
的根 CA或可分辨名称为 CN = Contoso Intermediate CA
的中间 CA 颁发的证书的每个客户端都会收到列出的属性。 此外,智能风扇客户端证书也会收到其特定属性。
属性的匹配始终从叶客户端证书开始,然后沿链进行。 属性分配在第一个匹配后停止。 在前面的示例中,即使 smart-fan
具有中间证书 CN = Contoso Intermediate CA
,也不会获取关联的属性。
可以使用具有这些属性的 X.509 证书将授权规则应用于客户端。 若要了解详细信息,请参阅授权使用 X.509 身份验证的客户端。
为侦听器端口启用 X.509 身份验证
导入受信任的 CA 证书并配置 BrokerAuthentication 资源后,请将其链接到启用了 TLS 的侦听器端口。 此步骤很重要,因为 X.509 身份验证依赖于 TLS 进行客户端证书验证。
若要获取启用了 TLS 的侦听器端口,请参阅为端口启用 TLS 手动证书管理和为端口启用 TLS 自动证书管理。
注意
在代理侦听器端口上启用 TLS 意味着代理使用服务器证书进行 TLS 加密。 当客户端连接到此端口时,它们必须通过在其信任存储中拥有已为服务器证书签名的 CA 证书来信任该服务器证书。 此过程称为“信任分布”或“信任捆绑”。 请务必了解服务器验证与客户端验证之间的差异:
- 客户端验证:MQTT 代理(服务器)根据
trustedClientCaCert
字段中指定的受信任 CA 证书检查客户端证书,以进行 X.509 客户端身份验证。 - 服务器验证:客户端(如 mosquitto 或 MQTTX)根据其信任存储中的受信任 CA 证书检查 MQTT 代理的服务器证书。 对于 mosquitto 客户端,请使用
--cafile
参数指定 CA 证书文件。 对于 MQTTX,请将 CA 证书添加到设置中的信任存储。
启用 X.509 身份验证后,请确保客户端通过在其信任存储中拥有服务器端 CA 证书来信任代理的服务器证书。 不要将信任服务器端 CA 证书与 trustedClientCaCert
字段中指定的用于客户端身份验证的客户端 CA 证书相混淆。
有关完整示例,请参阅教程:TLS、X.509 客户端身份验证和基于属性的访问控制 (ABAC) 授权。
使用 X.509 客户端证书将 mosquitto 客户端连接到 MQTT 代理
像 mosquitto 这样的客户端需要两个文件才能使用 TLS 和 X.509 客户端身份验证连接到 MQTT 代理。
--cert
参数指定客户端证书 PEM 文件。 此文件还应包含任何中间证书,以帮助 MQTT 代理生成完整的证书链。--key
参数指定客户端私钥 PEM 文件。
如果 MQTT 代理使用自签名 CA 证书颁发其 TLS 服务器证书,则需要 --cafile
参数。 此文件包含 mosquitto 客户端在通过 TLS 进行连接时用于验证代理服务器证书的 CA 证书(也称为“信任捆绑”)。 如果 MQTT 代理服务器证书的颁发者是系统根存储(如已知公共 CA)的一部分,则可以省略 --cafile
参数。
例如:
mosquitto_pub -q 1 -t hello -d -V mqttv5 -m world -i thermostat \
-h "<BROKER_HOST>" \
--cert thermostat_cert.pem \
--key thermostat_key.pem \
--cafile ca.pem
了解 MQTT 代理 X.509 客户端身份验证流
下面是客户端身份验证的步骤:
- 当 X.509 客户端身份验证启用时,连接客户端必须提供客户端证书和任何中间证书,以便 MQTT 代理构建一个以其配置的受信任证书之一为根的证书链。
- 负载均衡器会将通信定向到某个前端中转站。
- 前端中转站收到客户端证书后,它会尝试构建一个以配置的证书之一为根的证书链。 如果前端中转站成功生成了一个链并验证了呈现的链,它将完成 TLS 握手。 连接客户端可以通过 TLS 通道将 MQTT 数据包发送到前端。
- TLS 通道已打开,但客户端身份验证或授权尚未完成。
- 然后,客户端会将 CONNECT 数据包发送到 MQTT 代理。
- CONNECT 数据包会再次路由到前端。
- 前端会收集到目前为止提供的所有凭据,例如来自 CONNECT 数据包的身份验证数据,以及 TLS 握手期间提供的客户端证书链。
- 前端会将这些凭据发送到身份验证服务。 身份验证服务会再次检查证书链,并收集链中所有证书的使用者名称。
- 身份验证服务使用其配置的授权规则来确定连接客户端具有哪些属性。 这些属性确定客户端可以执行的操作,包括 CONNECT 数据包本身。
- 身份验证服务会将决策返回到前端中转站。
- 前端中转站知道客户端属性,以及它是否允许连接。 如果允许,则 MQTT 连接完成,客户端可以继续发送和接收由其授权规则确定的 MQTT 数据包。
Kubernetes 服务帐户令牌
Kubernetes 服务帐户令牌 (SAT) 是与 Kubernetes 服务帐户关联的 JSON Web 令牌。 客户端向 MQTT 代理提供 SAT,以自行进行身份验证。
MQTT 代理使用绑定服务帐户令牌,详细信息请参阅 GKE 用户需要了解的有关 Kubernetes 新服务账户令牌的信息帖子。 下面是帖子中的突出功能:
绑定令牌在 Kubernetes 1.13 中推出,并在 1.21 中成为默认格式,它解决了传统令牌的所有有限功能,并提供更多功能:
- 令牌本身更难窃取和滥用:它们受时间限制、受众限制和对象限制。
- 它们采用标准化格式:OpenID Connect (OIDC),具有完整的 OIDC 发现,使服务提供商更容易接受它们。
- 它们使用新的 Kubelet 预测卷类型,可以更安全地分发到 pod 中。
中转站使用 Kubernetes 令牌评审 API 验证令牌。 启用 Kubernetes TokenRequestProjection
功能以指定 audiences
(自 1.21 起为默认值)。 如果未启用此功能,则无法使用 SAT。
创建服务帐户
若要创建 SAT,请先创建服务帐户。 以下命令创建名为 mqtt-client
的服务帐户。
kubectl create serviceaccount mqtt-client -n azure-iot-operations
可选:添加用于授权的属性
通过 SAT 进行身份验证的客户端可以选择在其服务帐户上标注属性,以便与授权策略配合使用。 为了将这些批注与其他批注区分开来,这些批注以 aio-broker-auth/
前缀开头。
可以使用 kubectl annotate
来批注服务帐户:
kubectl annotate serviceaccount <SERVICE_ACCOUNT_NAME> aio-broker-auth/<ATTRIBUTE>=<VALUE> -n azure-iot-operations
或者,可以将批注添加到服务帐户清单文件:
apiVersion: v1
kind: ServiceAccount
metadata:
name: <SERVICE_ACCOUNT_NAME>
namespace: azure-iot-operations
annotations:
aio-broker-auth/<ATTRIBUTE_1>: <VALUE_1>
aio-broker-auth/<ATTRIBUTE_2>: <VALUE_2>
若要了解详细信息,请参阅授权使用 Kubernetes 服务帐户令牌的客户端。
启用服务帐户令牌 (SAT) 身份验证
修改 BrokerAuthentication 资源中的 authenticationMethods
设置,以将 ServiceAccountToken
指定为有效的身份验证方法。 audiences
指定令牌的有效访问群体列表。 选择用于标识 MQTT 代理服务的唯一值。 必须至少指定一个访问群体,并且所有 SAT 必须匹配其中一个指定访问群体。
- 在 Azure 门户中,导航到 IoT 操作实例。
- 在“组件”下,选择“MQTT 代理”。
- 选择“身份验证”选项卡。
- 选择现有的身份验证策略或创建新的身份验证策略。
- 通过选择“添加方法”来添加新方法。
- 从下拉列表中选择方法类型 Kubernetes SAT,然后选择“添加详细信息”来配置方法。
测试 SAT 身份验证
SAT 身份验证使用 MQTT v5 增强的身份验证字段。 客户端必须将增强的身份验证方法设置为 K8S-SAT
,并将增强的身份验证数据设置为令牌。
例如,使用 mosquitto(为简洁起见,省略了某些字段):
mosquitto_pub ... -D CONNECT authentication-method 'K8S-SAT' -D CONNECT authentication-data <TOKEN>
在这里,<TOKEN>
是服务帐户令牌。 若要获取测试令牌,请运行:
kubectl create token <SERVICE_ACCOUNT> -n azure-iot-operations --audience <AUDIENCE>
其中,<SERVICE_ACCOUNT>
是你创建的服务帐户的名称,<AUDIENCE>
是在 BrokerAuthentication 资源中配置的受众之一。
有关如何配置 Kubernetes Pod 以使用 SAT 身份验证的示例,请参阅连接到群集内的默认侦听器。
在 Pod 配置中,serviceAccountName
字段必须与所使用的令牌的关联服务帐户匹配,serviceAccountToken.audience
字段必须是在 BrokerAuthentication 资源中配置的 audiences
之一。
刷新服务帐户令牌
服务帐户令牌在有限的时间内有效,并配置了 expirationSeconds
。 但是,Kubernetes 会在令牌过期之前自动刷新令牌。 令牌在后台刷新,客户端无需执行任何其他操作即可再次提取令牌。
例如,如果客户端是使用装载为卷的令牌的 Pod,就像在测试 SAT 身份验证示例中那样,则会在同一路径 /var/run/secrets/tokens/broker-sat
提供最新令牌。 进行新连接时,客户端可以提取最新的令牌,并使用它进行身份验证。 客户端还应有这样一种机制:通过提取最新的令牌并重试连接来处理 MQTT 未经授权错误。
自定义身份验证
使用自定义身份验证将客户端身份验证扩展到提供的身份验证方法之外。 它是可插拔的,因为只要服务符合 API,服务就可以是任何内容。
当客户端连接到启用了自定义身份验证的 MQTT 代理时,代理会将一个带有客户端凭据的 HTTPS 请求发送到自定义身份验证服务器。 然后,服务器会以批准或拒绝(包括客户端的授权属性)做出响应。
创建自定义身份验证服务
自定义身份验证服务器由 MQTT 代理单独实现和部署。
GitHub 上提供了一个示例自定义身份验证服务器和说明。 使用此示例作为模板,以及实现自己的自定义身份验证逻辑的起点。
API
MQTT 代理和自定义身份验证服务器之间的 API 遵循用于自定义身份验证的 API 规范。 可在 GitHub 上获取 OpenAPI 规范。
需要使用 TLS 加密的 HTTPS
MQTT 代理会将包含敏感客户端凭据的请求发送到自定义身份验证服务器。 若要保护这些凭据,MQTT 代理与自定义身份验证服务器之间的通信必须使用 TLS 进行加密。
自定义身份验证服务器必须提供服务器证书,MQTT 代理必须具有受信任的根 CA 证书才能验证服务器证书。 (可选)自定义身份验证服务器可能需要 MQTT 代理提供客户端证书来对自身进行身份验证。
为侦听器启用自定义身份验证
修改 BrokerAuthentication 资源中的 authenticationMethods
设置,以将 Custom
指定为有效的身份验证方法。 然后,指定与自定义身份验证服务器通信所需的参数。
在 Azure 门户中,导航到 IoT 操作实例。
在“组件”下,选择“MQTT 代理”。
选择“身份验证”选项卡。
选择现有的身份验证策略或创建新的身份验证策略。
通过选择“添加方法”来添加新方法。
从下拉列表中选择方法类型“自定义”,然后选择“添加详细信息”来配置方法。
禁用身份验证
若要进行测试,可以对代理侦听器端口禁用身份验证。 不建议在生产环境中禁用身份验证。
- 在 Azure 门户中,导航到 IoT 操作实例。
- 在“组件”下,选择“MQTT 代理”。
- 从列表中选择要编辑的代理侦听器。
- 在要禁用身份验证的端口上,在身份验证下拉列表中选择“无”。
客户端在凭据过期后断开连接
MQTT 代理在其凭据到期后断开客户端的连接。 凭据过期后断开连接适用于连接到 MQTT 代理前端的所有客户端,包括:
- 使用 SAT 进行身份验证的客户端在 SAT 过期时断开连接
- 使用 X.509 进行身份验证的客户端在其客户端证书过期时断开连接
- 使用自定义身份验证进行身份验证的客户端根据从自定义身份验证服务器返回的到期时间断开连接。
断开连接后,客户端的网络连接将关闭。 客户端不会收到 MQTT DISCONNECT 数据包,但代理会记录一条消息,其中指出它已断开客户端连接。
使用 SAT 和自定义身份验证进行身份验证的 MQTT v5 客户端可以在其初始凭据过期之前,使用新凭据重新进行身份验证。 X.509 客户端无法重新进行身份验证,必须重新建立连接,因为身份验证是在 TLS 层完成的。
客户端可以通过发送带有原因 ReAuth
的 MQTT v5 AUTH 数据包重新进行身份验证。
SAT 客户端发送一个 AUTH 客户端,其中字段为:method: K8S-SAT
、data: <token>
。
自定义身份验证客户端根据自定义身份验证服务器的要求设置方法和数据字段。
成功重新进行身份验证后,客户端的凭据到期时间会更新为其新凭据的到期时间,代理使用 Success AUTH 数据包进行响应。 如果由于出现暂时性问题(例如自定义身份验证服务器不可用)导致身份验证失败,会导致代理使用 ContinueAuthentication AUTH 数据包进行响应。 客户端可以稍后重试。 如果出现其他身份验证失败,会导致代理发送 DISCONNECT 数据包并关闭客户端的网络连接。