创建和管理自定义授权方 - AWS IoT Core

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

创建和管理自定义授权方

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

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

  • Lambda 函数 ARN:实现授权和身份验证逻辑的 Lambda 函数的亚马逊资源名称 (ARN)。 

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

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

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

Lambda 将根据 Lambda 函数的运行次数以及函数中代码执行所需的时间向您收取费用。有关 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时会返回以下内容。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 }

创建授权方

您可以使用创建授权者。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 参数具有不同值的其它自定义授权方。

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

创建 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 来测试你的授权者。

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 参数传递此信息。以下选项卡显示如何使用将TestInvokeAuthorizerAPI包含用户名、密码和客户端名称的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

管理自定义授权方

您可以使用以下APIs方法来管理您的授权者。

  • ListAuthorizers: 显示您账户中的所有授权人。

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

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

  • UpdateAuthorizer:更改指定授权方的状态、令牌密钥名称或公钥。

  • DeleteAuthorizer:删除指定的授权者。

注意

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