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

创建和管理自定义授权方

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

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

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

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

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

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

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

注意

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

定义您的 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:字母数字字符串,它充当自定义授权请求发送的令牌的标识符。最小长度是 1 个字符。最大长度为 128 个字符。

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

  • 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 策略。在通过 TLS 的 MQTT 和通过 WebSockets 的 MQTT 连接中, Amazon IoT Core 将根据 refreshAfterInSeconds 字段中指定的间隔缓存此策略。在此间隔期间, Amazon IoT Core 针对此缓存策略授权已建立的连接中的操作,而不会再次触发 Lambda 函数。如果自定义身份验证过程中出现故障,则 Amazon IoT Core 将终止连接。如果连接打开的时间超过 disconnectAfterInSeconds 参数中指定的值,则 Amazon IoT Core 也会终止连接。

下面的 JavaScript 包含一个示例 Node.js Lambda 函数,该函数在值为 test 的 MQTT Connect 消息中查找密码,并使用名为 myClientName 的客户端返回授予权限以连接到 Amazon IoT Core 的策略,同时发布到包含相同客户端名称的主题。如果未找到预期密码,则返回拒绝这两个操作的策略。

// 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 值时返回以下值。

{ "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: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 }

创建授权方

您可以使用 CreateAuthorizer API 创建授权方。下面的示例演示了具体做法。

 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:显示您的账户中的所有授权方。

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

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

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

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

注意

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