创建和管理自定义授权方 - Amazon IoT Core
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

创建和管理自定义授权方

Amazon IoT Core 使用授权方资源实现自定义身份验证和授权方案。各授权方均包括以下组件:

  • 名称:用户定义的唯一字符串,用于标识授权方。

  • Lambda 函数 ARN:Lambda 函数的 Amazon Resource Name (ARN),用于实现授权和身份验证逻辑。 

  • 令牌密钥名称:用于从 HTTP 标头、查询参数或 MQTT CONNECT 用户名中提取令牌以执行签名验证的键名称。如果在授权方中启用了签名,则需要此值。

  • 签名禁用标志(可选):指定是否禁用凭证签名要求的布尔值。这对于签名凭证没有意义的情况非常有用,例如使用 MQTT 用户名和密码的身份验证方案。默认值为 false,因此预设情况下签名将处于启用状态。

  • 令牌签名公有密钥:Amazon IoT Core 用于验证令牌签名的公有密钥。其最小长度为 2048 位。如果在授权方中启用了签名,则需要此值。 

Lambda 将根据 Lambda 函数的运行次数以及函数中代码执行所需的时间向您收取费用。有关 Lambda 定价的更多信息,请参阅 Lambda 定价。有关创建 Lambda 函数的更多信息,请参阅 Lambda 开发人员指南

注意

如果启用签名,则可以防止无法识别的客户端过度触发 Lambda。在禁用授权方的签名之前,请考虑这一点。

注意

自定义授权方的 Lambda 函数超时限制为 5 秒。

定义您的 Lambda 函数

Amazon 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}。不允许使用非字母数字的特殊字符principalId在Amazon IoT Core。其他内容请参阅文档(CLY)Amazon服务,前提是允许使用非字母数字特殊字符principalId

  • policyDocuments:JSON 格式的 Amazon IoT Core 策略文档的列表。有关创建 Amazon IoT Core 策略的更多信息,请参阅 Amazon IoT Core 策略。策略文档的数量最多为 10 个。每个策略文档最多可以包含 2048 个字符。

  • disconnectAfterInSeconds:指定与 Amazon IoT Core 网关的连接的最大持续时间(以秒为单位)的整数。最小值为 300 秒,最大值为 86400 秒。

  • refreshAfterInSeconds:指定策略刷新之间间隔的整数。当此时间间隔过去时,Amazon 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 值必须包含一个有效的 Amazon IoT Core 策略文档。有关以下内容的更多信息Amazon IoT Core策略Amazon IoT Core 策略。 在 MQTT 中通过 TLS 和 MQTT 通过 WebSockets连接,Amazon IoT Core在值中指定的时间间隔内缓存此策略refreshAfterInSeconds字段。在 HTTP 连接的情况下,每个授权请求都会调用 Lambda 函数,除非您的设备使用 HTTP 持久连接(也称为 HTTP 保持活动状态或 HTTP 连接重用),否则您可以在配置授权方时选择启用缓存。在此间隔期间,Amazon IoT Core 针对此缓存策略授权已建立的连接中的操作,而不会再次触发 Lambda 函数。如果自定义身份验证过程中出现故障,则 Amazon IoT Core 将终止连接。如果连接打开的时间超过 disconnectAfterInSeconds 参数中指定的值,则 Amazon IoT Core 也会终止连接。

以下 JavaScript 包含一个示例 Node.js Lambda 函数,该函数在 MQTT Connect 消息中查找值为的密码test并返回一个授予连接权限的策略Amazon 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'));         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 函数在收到 MQTT Connect 消息中的预期密码 test 时返回以下 JSON。passwordprincipalId 属性的值将是来自 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 }

创建授权方

您可以使用创建授权者(CLY)CreateAuthorizerAPI。 以下示例描述了该命令(CLY)

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 参数具有不同值的其它自定义授权方。

如果您已禁用签名,则 tokenKeyNametokenSigningPublicKeys 参数的值是可选的。如果启用了签名,则它们是必需的值。

创建 Lambda 函数和自定义授权方后,必须明确授予 Amazon 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"

测试授权方

您可以使用TestInvokeAuthorizer用于测试授权方的调用和返回值的 API。 此 API 使您可以指定协议元数据,也可以使用授权方进行签发的验证。  

以下选项卡显示如何使用 Amazon CLI 来测试您的授权方。

Unix-like
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER \ --token TOKEN_VALUE --token-signature TOKEN_SIGNATURE
Windows CMD
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER ^ --token TOKEN_VALUE --token-signature TOKEN_SIGNATURE
Windows PowerShell
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER ` --token TOKEN_VALUE --token-signature TOKEN_SIGNATURE

token-signature 参数的值是签名令牌。要了解如何获取此值,请参阅 签名令牌

如果您的授权方使用了用户名和密码,您可以使用 --mqtt-context 参数传递此信息。以下选项卡显示如何使用 TestInvokeAuthorizer API 将包含用户名、密码和客户端名称的 JSON 对象发送到您的自定义授权方。

Unix-like
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER \ --mqtt-context '{"username": "USER_NAME", "password": "dGVzdA==", "clientId":"CLIENT_NAME"}'
Windows CMD
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER ^ --mqtt-context '{"username": "USER_NAME", "password": "dGVzdA==", "clientId":"CLIENT_NAME"}'
Windows PowerShell
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER ` --mqtt-context '{"username": "USER_NAME", "password": "dGVzdA==", "clientId":"CLIENT_NAME"}'

密码必须采用 base64 编码。以下示例说明如何在类 Unix 的环境中对密码进行编码。

echo -n PASSWORD | base64

管理自定义授权方

您可以使用以下 API 管理授权方。

  • ListAuthorizers:显示您账户中的所有授权人(CLY)

  • DescribeAuthorizer:显示指定授权者的属性(CLY) 这些值包括创建日期、上次修改日期和其它属性。

  • SetDefaultAuthorizer:为你的指定默认授权者Amazon IoT Core数据端点。Amazon IoT Core如果设备未通过,则使用此授权器Amazon IoT Core凭证且未指定授权者。有关使用 Amazon IoT Core 凭证的更多信息,请参阅 客户端身份验证

  • UpdateAuthorizer:更改指定Amazon Root CA 的状态、Toot Key Noot NA 或Root CA。

  • DeleteAuthorizer:删除指定的授权者(CLY)

注意

您无法更新授权方的签名要求。这意味着您无法禁用需要签名的现有授权方的中签名。您也不能在不需要签名的现有授权方中要求签名。