本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
创建和管理自定义授权方
AWS IoT Core 使用授权方资源实现自定义身份验证和授权方案。各授权方均包括以下组件:
-
名称:用户定义的唯一字符串,用于标识授权方。
-
Lambda 函数 ARN:实现授权和身份验证逻辑的 Lambda 函数的亚马逊资源名称 (ARN)。
-
令牌密钥名称:用于从HTTP标题、查询参数或MQTTCONNECT用户名中提取令牌以执行签名验证的密钥名称。如果在授权方中启用了签名,则需要此值。
-
签名禁用标志(可选):一个布尔值,用于指定是否禁用对凭据的签名要求。 这对于签名凭据没有意义的场景很有用,例如使用MQTT用户名和密码的身份验证方案。 默认值为
false
,因此默认情况下签名处于启用状态。 -
令牌签名公钥:公钥 AWS IoT Core 用于验证令牌签名。其最小长度为 2048 位。如果在授权方中启用了签名,则需要此值。
Lambda 将根据 Lambda 函数的运行次数以及函数中代码执行所需的时间向您收取费用。有关 Lambda 定价的更多信息,请参阅 Lambda 定价
注意
如果启用签名,则可以防止无法识别的客户端过度触发 Lambda。在禁用授权方的签名之前,请考虑这一点。
注意
自定义授权方的 Lambda 函数超时限制为 5 秒。
定义您的 Lambda 函数
时间 AWS IoT Core 调用您的授权方,它会使用包含以下对象的事件触发与授权方关联的 Lambda。JSON示例JSON对象包含所有可能的字段。不包括与连接请求无关的任何字段。
{ "token" :"aToken", "signatureVerified": Boolean, // Indicates whether the device gateway has validated the signature. "protocols": ["tls", "http", "mqtt"], // Indicates which protocols to expect for the request. "protocolData": { "tls" : { "serverName": "serverName" // The server name indication (SNI)
host_name
string. }, "http": { "headers": { "#{name}": "#{value}" }, "queryString": "?#{name}=#{value}" }, "mqtt": { "username": "myUserName", "password": "myPassword", // A base64-encoded string. "clientId": "myClientId" // Included in the event only when the device sends the value. } }, "connectionMetadata": { "id": UUID // The connection ID. You can use this for logging. }, }
Lambda 函数应使用此信息对传入连接进行身份验证,并决定允许在连接中执行哪些操作。函数应发送包含以下值的响应。
-
isAuthenticated
:一个布尔值,指示是否已对请求进行身份验证。 -
principalId
:字母数字字符串,它充当自定义授权请求发送的令牌的标识符。该值必须是包含至少一个字符且不超过 128 个字符的字母数字字符串,并与此正则表达式(正则表达式)模式匹配:([a-zA-Z0-9]){1,128}
。不允许在 in 中使用非字母数字的特殊字符principalId
AWS IoT Core。 有关其他,请参阅文档 AWS 服务,前提是允许使用非字母数字特殊字符。principalId
-
policyDocuments
: 格式JSON化列表 AWS IoT Core 政策文档有关创建的更多信息 AWS IoT Core 策略,请参阅AWS IoT Core 策略。策略文档的数量最多为 10 个。每个策略文档最多可以包含 2048 个字符。 -
disconnectAfterInSeconds
: 一个整数,它指定与的连接的最大持续时间(以秒为单位) AWS IoT Core 网关。最小值为 300 秒,最大值为 86400 秒。默认值为 86,400。注意
的值
disconnectAfterInSeconds
(由 Lambda 函数返回)是在连接建立时设置的。在后续的策略刷新 Lambda 调用过程中,无法修改此值。 -
refreshAfterInSeconds
:指定策略刷新之间间隔的整数。当这个间隔过去时, AWS IoT Core 调用 Lambda 函数以允许策略刷新。最小值为 300 秒,最大值为 86400 秒。
以下JSON对象包含您的 Lambda 函数可以发送的响应示例。
{ "isAuthenticated":true, //A Boolean that determines whether client can connect. "principalId": "xxxxxxxx", //A string that identifies the connection in logs. "disconnectAfterInSeconds": 86400, "refreshAfterInSeconds": 300, "policyDocuments": [ { "Version": "2012-10-17", "Statement": [ { "Action": "iot:Publish", "Effect": "Allow", "Resource": "arn:aws:iot:us-east-1:<your_aws_account_id>:topic/customauthtesting" } ] } ] }
该policyDocument
值必须包含有效的 AWS IoT Core 政策文件。有关 AWS IoT Core 策略,请参阅AWS IoT Core 策略。 在一MQTT遍TLS又一MQTT遍的 WebSockets连接中, AWS IoT Core 在refreshAfterInSeconds
字段值中指定的时间间隔内缓存此策略。对于HTTP连接,每个授权请求都会调用 Lambda 函数,除非您的设备使用的是HTTP永久连接(也称为HTTP保持活动状态或HTTP连接重用),您可以在配置授权方时选择启用缓存。在这段时间里, AWS IoT Core 授权在已建立的连接中针对此缓存策略执行操作,而无需再次触发您的 Lambda 函数。如果在自定义身份验证期间出现故障, AWS IoT Core 终止连接。 AWS IoT Core 如果连接的打开时间超过disconnectAfterInSeconds
参数中指定的值,也会终止连接。
以下内容 JavaScript 包含一个 Node.js Lambda 函数示例,该函数在 Conn MQTT ect 消息中查找值为的密码test
并返回一个授予连接权限的策略 AWS IoT Core 使用名为的客户端,myClientName
并发布到包含相同客户机名称的主题。如果未找到预期密码,则返回拒绝这两个操作的策略。
// A simple Lambda function for an authorizer. It demonstrates // how to parse an MQTT password and generate a response. exports.handler = function(event, context, callback) { var uname = event.protocolData.mqtt.username; var pwd = event.protocolData.mqtt.password; var buff = new Buffer(pwd, 'base64'); var passwd = buff.toString('ascii'); switch (passwd) { case 'test': callback(null, generateAuthResponse(passwd, 'Allow')); break; default: callback(null, generateAuthResponse(passwd, 'Deny')); } }; // Helper function to generate the authorization response. var generateAuthResponse = function(token, effect) { var authResponse = {}; authResponse.isAuthenticated = true; authResponse.principalId = 'TEST123'; var policyDocument = {}; policyDocument.Version = '2012-10-17'; policyDocument.Statement = []; var publishStatement = {}; var connectStatement = {}; connectStatement.Action = ["iot:Connect"]; connectStatement.Effect = effect; connectStatement.Resource = ["arn:aws:iot:us-east-1:123456789012:client/myClientName"]; publishStatement.Action = ["iot:Publish"]; publishStatement.Effect = effect; publishStatement.Resource = ["arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"]; policyDocument.Statement[0] = connectStatement; policyDocument.Statement[1] = publishStatement; authResponse.policyDocuments = [policyDocument]; authResponse.disconnectAfterInSeconds = 3600; authResponse.refreshAfterInSeconds = 300; return authResponse; }
前面的 Lambda 函数在 Conn MQTT ect 消息test
中收到预期的密码JSON时会返回以下内容。password
和principalId
属性的值将是 MQTT Connect 消息中的值。
{ "password": "
password
", "isAuthenticated": true, "principalId": "principalId
", "policyDocuments": [ { "Version": "2012-10-17", "Statement": [ { "Action": "iot:Connect", "Effect": "Allow", "Resource": "*" }, { "Action": "iot:Publish", "Effect": "Allow", "Resource": "arn:aws:iot:region
:accountId
:topic/telemetry/${iot:ClientId}" }, { "Action": "iot:Subscribe", "Effect": "Allow", "Resource": "arn:aws:iot:region
:accountId
:topicfilter/telemetry/${iot:ClientId}" }, { "Action": "iot:Receive", "Effect": "Allow", "Resource": "arn:aws:iot:region
:accountId
:topic/telemetry/${iot:ClientId}" } ] } ], "disconnectAfterInSeconds": 3600, "refreshAfterInSeconds": 300 }
创建授权方
您可以使用创建授权者。CreateAuthorizerAPI 以下示例描述了该命令。
aws iot create-authorizer --authorizer-name MyAuthorizer --authorizer-function-arn arn:aws:lambda:us-west-2:<account_id>:function:MyAuthorizerFunction //The ARN of the Lambda function. [--token-key-name MyAuthorizerToken //The key used to extract the token from headers. [--token-signing-public-keys FirstKey= "-----BEGIN PUBLIC KEY----- [...insert your public key here...] -----END PUBLIC KEY-----" [--status ACTIVE] [--tags <value>] [--signing-disabled | --no-signing-disabled]
您可以使用 signing-disabled
参数选择退出适用于授权方的每次调用的签名验证。除有必要,否则我们强烈建议您不要禁用签名。签名验证可防止来自未知设备的 Lambda 函数过多调用。您无法在创建授权方后更新其 signing-disabled
状态。要更改此行为,您必须创建 signing-disabled
参数具有不同值的其它自定义授权方。
如果您已禁用签名,则 tokenKeyName
和 tokenSigningPublicKeys
参数的值是可选的。如果启用了签名,则它们是必需的值。
创建 Lambda 函数和自定义授权方后,您必须明确授予 AWS IoT Core 代表您调用该函数的服务权限。 您可以使用以下命令执行此操作。
aws lambda add-permission --function-name <lambda_function_name>
--principal iot.amazonaws.com --source-arn <authorizer_arn>
--statement-id Id-123 --action "lambda:InvokeFunction"
测试授权方
您可以使用TestInvokeAuthorizerAPI来测试授权方的调用和返回值。 这API使您能够在授权者中指定协议元数据并测试签名验证。
以下选项卡显示了如何使用 AWS CLI 来测试你的授权者。
token-signature
参数的值是签名令牌。要了解如何获取此值,请参阅 签名令牌。
如果您的授权方使用了用户名和密码,您可以使用 --mqtt-context
参数传递此信息。以下选项卡显示如何使用将TestInvokeAuthorizer
API包含用户名、密码和客户端名称的JSON对象发送给您的自定义授权者。
密码必须采用 base64 编码。以下示例说明如何在类 Unix 的环境中对密码进行编码。
echo -n
PASSWORD
| base64
管理自定义授权方
您可以使用以下APIs方法来管理您的授权者。
-
ListAuthorizers: 显示您账户中的所有授权人。
-
DescribeAuthorizer:显示指定授权者的属性。这些值包括创建日期、上次修改日期和其它属性。
-
SetDefaultAuthorizer:为你的指定默认授权者 AWS IoT Core 数据端点。 AWS IoT Core 如果设备未通过,则使用此授权器 AWS IoT Core 凭证且未指定授权者。有关使用的更多信息 AWS IoT Core 证书,请参阅客户端身份验证。
-
UpdateAuthorizer:更改指定授权方的状态、令牌密钥名称或公钥。
-
DeleteAuthorizer:删除指定的授权者。
注意
您无法更新授权方的签名要求。这意味着您无法禁用需要签名的现有授权方的中签名。您也不能在不需要签名的现有授权方中要求签名。