View a markdown version of this page

教程:为创建自定义授权方 AWS IoT Core - AWS IoT Core

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

教程:为创建自定义授权方 AWS IoT Core

本教程演示了使用 AWS CLI创建、验证和使用自定义身份验证的步骤。或者,使用本教程,您可以借助 HTTP Publish API 使用 Postman 将数据发送到 AWS IoT Core 。

本教程介绍如何创建一个示例 Lambda 函数,该函数将在启用令牌签名的情况下,借助 create-authorizer 调用实现授权和身份验证逻辑。然后使用对授权方进行验证,最后test-invoke-authorizer,您可以使用 HTTP 发布 API 向测试 MQTT 主题发送数据。 AWS IoT Core 示例请求将使用标头指定要调用的授权方,并在请求x-amz-customauthorizer-name标头x-amz-customauthorizer-signature中传递 token-key-name和。

您将在本教程中学到的内容:
  • 如何创建一个 Lambda 函数作为自定义授权方处理程序

  • 如何在启用令牌签名的情况下使用创建自定义授权方 AWS CLI

  • 如何使用 test-invoke-authorizer命令测试您的自定义授权方

  • 如何使用 Postman 发布 MQTT 主题并使用您的自定义授权方验证请求

完成本教程需要大约 60 分钟。

在开始本教程之前,请确保您具有:
  • 设置 AWS 账户

    你需要你的 AWS 账户 和 AWS IoT 主机才能完成本教程。

    当您用于本教程的账户中至少包含这些 AWS 托管策略时,账户的效果最佳:

    重要

    本教程中使用的 IAM 策略比您在生产实施中应遵循的更宽松。在生产环境中,请确保您的账户和资源策略仅授予必要的权限。

    在您为生产创建 IAM 策略时,请确定用户和角色需要的访问权限,然后设计允许他们仅执行这些任务的策略。

    有关更多信息,请参阅 IAM 安全最佳实践

  • 安装了 AWS CLI

    有关如何安装的信息 AWS CLI,请参阅安装 AWS CLI。本教程需要 AWS CLI 版本aws-cli/2.1.3 Python/3.7.4 Darwin/18.7.0 exe/x86_64或更高版本。

  • OpenSSL 工具

    本教程中的示例使用 LibreSSL 2.6.5。您还可以在本教程中使用 OpenSSL v1.1.1i 工具。

  • 查看 AWS Lambda概览

    如果您 AWS Lambda 以前从未使用过,请查看AWS Lambda开始使用 Lambda,以了解其术语和概念。

  • 回顾了如何在 Postman 中构建请求

    有关更多信息,请参阅构建请求

  • 从以前的教程中删除了自定义授权方

    一次 AWS 账户 只能配置有限数量的自定义授权方。有关如何创建和删除自定义授权方的信息,请参阅 步骤 8:清除

步骤 1:为自定义授权方创建 Lambda 函数

中的自定义身份验证 AWS IoT Core 使用您创建的授权方资源对客户端进行身份验证和授权。您将在本节中创建的函数在客户端连接和访问 AWS IoT 资源时对其进行身份验证 AWS IoT Core 和授权。

Lambda 函数执行以下操作:

  • 如果请求来自 test-invoke-authorizer,则它会返回一个带有 Deny 操作的 IAM 策略。

  • 如果请求来自使用 HTTP 的 Postman,且 actionToken 参数的值为 allow,则它会返回一个带有 Allow 操作的 IAM 策略。否则,它会返回带有 Deny 操作的 IAM 策略。

要为自定义授权方创建 Lambda 函数:
  1. Lambda 控制台,打开函数

  2. 选择创建函数

  3. 确认 Author from scratch(从头开始编写)处于选中状态。

  4. Basic information 下:

    1. 函数名称中,输入 custom-auth-function

    2. 运行时系统中,确认 Node.js 18.x

  5. 选择创建函数

    Lambda 创建 Node.js 函数和执行角色,该角色将授予函数上载日志的权限。Lambda 函数在您调用函数时担任执行角色,并使用执行角色为 AWS SDK 创建凭证和从事件源读取数据。

  6. 要在AWS Cloud9编辑器中查看函数的代码和配置,请在设计器窗口custom-auth-function中选择,然后在编辑器的导航窗格中选择 index.js

    对于脚本语言(如 Node.js),Lambda 包含返回成功响应的基本函数。您可以使用 AWS Cloud9 编辑器来编辑您的函数,只要源码不超过 3MB 即可。

  7. 在编辑器中使用以下代码替换 index.js 代码:

    // A simple Lambda function for an authorizer. It demonstrates // How to parse a CLI and Http password to generate a response. export const handler = async (event, context, callback) => { //Http parameter to initiate allow/deny request const HTTP_PARAM_NAME='actionToken'; const ALLOW_ACTION = 'Allow'; const DENY_ACTION = 'Deny'; //Event data passed to Lambda function var event_str = JSON.stringify(event); console.log('Complete event :'+ event_str); //Read protocolData from the event json passed to Lambda function var protocolData = event.protocolData; console.log('protocolData value---> ' + protocolData); //Get the dynamic account ID from function's ARN to be used // as full resource for IAM policy var ACCOUNT_ID = context.invokedFunctionArn.split(":")[4]; console.log("ACCOUNT_ID---"+ACCOUNT_ID); //Get the dynamic region from function's ARN to be used // as full resource for IAM policy var REGION = context.invokedFunctionArn.split(":")[3]; console.log("REGION---"+REGION); //protocolData data will be undefined if testing is done via CLI. // This will help to test the set up. if (protocolData === undefined) { //If CLI testing, pass deny action as this is for testing purpose only. console.log('Using the test-invoke-authorizer cli for testing only'); callback(null, generateAuthResponse(DENY_ACTION,ACCOUNT_ID,REGION)); } else{ //Http Testing from Postman //Get the query string from the request var queryString = event.protocolData.http.queryString; console.log('queryString values -- ' + queryString); /* global URLSearchParams */ const params = new URLSearchParams(queryString); var action = params.get(HTTP_PARAM_NAME); if(action!=null && action.toLowerCase() === 'allow'){ callback(null, generateAuthResponse(ALLOW_ACTION,ACCOUNT_ID,REGION)); }else{ callback(null, generateAuthResponse(DENY_ACTION,ACCOUNT_ID,REGION)); } } }; // Helper function to generate the authorization IAM response. var generateAuthResponse = function(effect,ACCOUNT_ID,REGION) { var full_resource = "arn:aws:iot:"+ REGION + ":" + ACCOUNT_ID + ":*"; console.log("full_resource---"+full_resource); var authResponse = {}; authResponse.isAuthenticated = true; authResponse.principalId = 'principalId'; var policyDocument = {}; policyDocument.Version = '2012-10-17'; policyDocument.Statement = []; var statement = {}; statement.Action = 'iot:*'; statement.Effect = effect; statement.Resource = full_resource; policyDocument.Statement[0] = statement; authResponse.policyDocuments = [policyDocument]; authResponse.disconnectAfterInSeconds = 3600; authResponse.refreshAfterInSeconds = 600; console.log('custom auth policy function called from http'); console.log('authResponse --> ' + JSON.stringify(authResponse)); console.log(authResponse.policyDocuments[0]); return authResponse; }
  8. 选择部署

  9. Changes deployed(更改已部署)出现在编辑器上方后:

    1. 滚动到编辑器上方的 Function overview(函数概览)部分。

    2. 复制 Function ARN(函数 ARN)并保存以在本教程稍后的部分中使用。

  10. 测试 函数。

    1. 选择 Test(测试)选项卡。

    2. 使用默认测试设置,选择 Invoke(调用)。

    3. 如果测试成功,则在 Execution results(执行结果)下,打开 Details(详细信息)视图。您应该看到函数返回的策略文档。

      如果测试失败或没有看到策略文档,请查看代码以查找并更正错误。

步骤 2:为自定义授权方创建公有密钥和私有密钥对

您的自定义授权方需要公有密钥和私有密钥来对其进行身份验证。本部分中的命令使用 OpenSSL 工具来创建此密钥对。

要为自定义授权方创建公有和私有密钥对,请执行以下操作
  1. 创建私有密钥文件。

    openssl genrsa -out private-key.pem 4096
  2. 验证您刚创建的私有密钥文件。

    openssl rsa -check -in private-key.pem -noout

    如果命令未显示任何错误,则私有密钥文件是有效的。

  3. 创建公有密钥文件。

    openssl rsa -in private-key.pem -pubout -out public-key.pem
  4. 验证公有密钥文件。

    openssl pkey -inform PEM -pubin -in public-key.pem -noout

    如果命令未显示任何错误,则公有密钥文件是有效的。

步骤 3:创建自定义授权方资源及其授权

AWS IoT 自定义授权器是将前面步骤中创建的所有元素联系在一起的资源。在本部分中,您将创建一个自定义授权方资源,并授予其运行您之前创建的 Lambda 函数的权限。您可以使用 AWS IoT 控制台、或 AWS API 创建自定义授权方 AWS CLI资源。

在本教程中,您只需要创建一个自定义授权方。本节介绍如何使用 AWS IoT 控制台和进行创建 AWS CLI,以便您可以使用最方便的方法。以两种方法创建的自定义授权方资源之间没有区别。

创建自定义授权方资源

选择以下选项之一以创建自定义授权方资源
要创建自定义授权方(控制台)
  1. 打开AWS IoT 控制台的 “自定义授权者” 页面,然后选择 “创建授权者”。

  2. 创建授权方中:

    1. 授权方名称中,输入 my-new-authorizer

    2. 授权者状态中,选中活动

    3. Authorizer function(授权方函数)中,选择您之前创建的 Lambda 函数。

    4. 令牌验证 - 可选中:

      1. 开启令牌验证

      2. 令牌密钥名称中,输入 tokenKeyName

      3. 选择添加密钥

      4. 密钥名称中,输入 FirstKey

      5. 公有密钥中,输入 public-key.pem 文件的内容。请务必包含文件中的行以及 -----BEGIN PUBLIC KEY----------END PUBLIC KEY-----,并且不要从文件内容中添加或删除任何换行符、回车符或其它字符。您输入的字符串应类似下面这个示例。

        -----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvEBzOk4vhN+3LgslvEWt sLCqNmt5Damas3bmiTRvq2gjRJ6KXGTGQChqArAJwL1a9dkS9+maaXC3vc6xzx9z QPu/vQOe5tyzz1MsKdmtFGxMqQ3qjEXAMPLEOmqyUKPP5mff58k6ePSfXAnzBH0q lg2HioefrpU5OSAnpuRAjYKofKjbc2Vrn6N2G7hV+IfTBvCElf0csalS/Rk4phD5 oa4Y0GHISRnevypg5C8n9Rrz91PWGqP6M/q5DNJJXjMyleG92hQgu1N696bn5Dw8 FhedszFa6b2x6xrItZFzewNQkPMLMFhNrQIIyvshtT/F1LVCS5+v8AQ8UGGDfZmv QeqAMAF7WgagDMXcfgKSVU8yid2sIm56qsCLMvD2Sq8Lgzpey9N5ON1o1Cvldwvc KrJJtgwW6hVqRGuShnownLpgG86M6neZ5sRMbVNZO8OzcobLngJ0Ibw9KkcUdklW gvZ6HEJqBY2XE70iEXAMPLETPHzhqvK6Ei1HGxpHsXx6BNft582J1VpgYjXha8oa /NN7l7Zbj/euAb41IVtmX8JrD9z613d1iM5L8HluJlUzn62Q+VeNV2tdA7MfPfMC 8btGYladFAnitThaz6+F0VSBJPu7pZQoLnqyEp5zLMtF+kFl2yOBmGAP0RBivRd9 JWBUCG0bqcLQPeQyjbXSOfUCAwEAAQ== -----END PUBLIC KEY-----
  3. 选择 Create Authorizer(创建授权方)。

  4. 如果创建了自定义授权方资源,您将看到自定义授权方列表,并且您的新自定义授权方应显示在列表中,然后您便可以继续下一部分展开测试了。

    如果您看到错误,请检查错误并尝试再次创建自定义授权方,然后仔细检查条目。请注意,每个自定义授权方资源必须具有唯一的名称。

要创建自定义授权方 (AWS CLI)
  1. 将您的值替换为 authorizer-function-arntoken-signing-public-keys,然后运行以下命令:

    aws iot create-authorizer \ --authorizer-name "my-new-authorizer" \ --token-key-name "tokenKeyName" \ --status ACTIVE \ --no-signing-disabled \ --authorizer-function-arn "arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function" \ --token-signing-public-keys FirstKey="-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvEBzOk4vhN+3LgslvEWt sLCqNmt5Damas3bmiTRvq2gjRJ6KXGTGQChqArAJwL1a9dkS9+maaXC3vc6xzx9z QPu/vQOe5tyzz1MsKdmtFGxMqQ3qjEXAMPLEOmqyUKPP5mff58k6ePSfXAnzBH0q lg2HioefrpU5OSAnpuRAjYKofKjbc2Vrn6N2G7hV+IfTBvCElf0csalS/Rk4phD5 oa4Y0GHISRnevypg5C8n9Rrz91PWGqP6M/q5DNJJXjMyleG92hQgu1N696bn5Dw8 FhedszFa6b2x6xrItZFzewNQkPMLMFhNrQIIyvshtT/F1LVCS5+v8AQ8UGGDfZmv QeqAMAF7WgagDMXcfgKSVU8yid2sIm56qsCLMvD2Sq8Lgzpey9N5ON1o1Cvldwvc KrJJtgwW6hVqRGuShnownLpgG86M6neZ5sRMbVNZO8OzcobLngJ0Ibw9KkcUdklW gvZ6HEJqBY2XE70iEXAMPLETPHzhqvK6Ei1HGxpHsXx6BNft582J1VpgYjXha8oa /NN7l7Zbj/euAb41IVtmX8JrD9z613d1iM5L8HluJlUzn62Q+VeNV2tdA7MfPfMC 8btGYladFAnitThaz6+F0VSBJPu7pZQoLnqyEp5zLMtF+kFl2yOBmGAP0RBivRd9 JWBUCG0bqcLQPeQyjbXSOfUCAwEAAQ== -----END PUBLIC KEY-----"
    其中:
    • authorizer-function-arn 值是您为自定义授权方创建的 Lambda 函数的 Amazon 资源名称(ARN)。

    • token-signing-public-keys 值包含密钥的名称、FirstKey 以及 public-key.pem文件的内容。请务必包含文件中的行以及 -----BEGIN PUBLIC KEY----------END PUBLIC KEY-----,并且不要从文件内容中添加或删除任何换行符、回车符或其它字符。

      注意:输入公有密钥时要非常小心,因为对公有密钥值的任何更改都会使其无法使用。

  2. 如果创建了自定义授权方,则该命令将返回新资源的名称和 ARN,如下所示。

    { "authorizerName": "my-new-authorizer", "authorizerArn": "arn:aws:iot:Region:57EXAMPLE833:authorizer/my-new-authorizer" }

    保存 authorizerArn 值,以供下一步使用。

    请记住,每个自定义授权方资源必须具有唯一的名称。

授权自定义授权方资源

在本节中,您将为您刚创建的自定义授权方资源授予运行 Lambda 函数的权限。要授予权限,您可以使用 add-permission CLI 命令。

使用授予您的 Lambda 函数的权限 AWS CLI
  1. 插入您的值后,输入以下命令。请注意,statement-id 值必须唯一。如果您之前运行过本教程,或者如果您遇到了 ResourceConflictException 错误,请将 Id-1234 替换为另一个值。

    aws lambda add-permission \ --function-name "custom-auth-function" \ --principal "iot.amazonaws.com" \ --action "lambda:InvokeFunction" \ --statement-id "Id-1234" \ --source-arn authorizerArn
  2. 如果命令成功,则返回一个权限语句,如本示例。您可以继续到下一部分来测试自定义授权方。

    { "Statement": "{\"Sid\":\"Id-1234\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"iot.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function\"}}}" }

    如果命令不成功,则返回错误,如本示例。在继续操作之前,您需要查看并更正错误。

    An error occurred (AccessDeniedException) when calling the AddPermission operation: User: arn:aws:iam::57EXAMPLE833:user/EXAMPLE-1 is not authorized to perform: lambda:AddPer mission on resource: arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function

步骤 4:通过调用来测试授权者 test-invoke-authorizer

定义好所有资源后,在本节中,您将 test-invoke-authorizer从命令行调用以测试授权通行证。

请注意,在通过命令行调用授权方时,protocolData 并未定义,因此授权方将始终返回 DENY 文档。但是,此测试将确认您的自定义授权方和 Lambda 函数是否已正确配置,即使它并未完全测试 Lambda 函数。

要测试您的自定义授权方及其 Lambda 函数,请使用 AWS CLI
  1. 在包含您在上一步中创建的 private-key.pem 文件的目录中,请运行以下命令。

    echo -n "tokenKeyValue" | openssl dgst -sha256 -sign private-key.pem | openssl base64 -A

    此命令将创建要在下一步中使用的签名字符串。签名字符串如下所示:

    dBwykzlb+fo+JmSGdwoGr8dyC2qB/IyLefJJr+rbCvmu9Jl4KHAA9DG+V+MMWu09YSA86+64Y3Gt4tOykpZqn9mn VB1wyxp+0bDZh8hmqUAUH3fwi3fPjBvCa4cwNuLQNqBZzbCvsluv7i2IMjEg+CPY0zrWt1jr9BikgGPDxWkjaeeh bQHHTo357TegKs9pP30Uf4TrxypNmFswA5k7QIc01n4bIyRTm90OyZ94R4bdJsHNig1JePgnuOBvMGCEFE09jGjj szEHfgAUAQIWXiVGQj16BU1xKpTGSiTAwheLKUjITOEXAMPLECK3aHKYKY+d1vTvdthKtYHBq8MjhzJ0kggbt29V QJCb8RilN/P5+vcVniSXWPplyB5jkYs9UvG08REoy64AtizfUhvSul/r/F3VV8ITtQp3aXiUtcspACi6ca+tsDuX f3LzCwQQF/YSUy02u5XkWn+sto6KCkpNlkD0wU8gl3+kOzxrthnQ8gEajd5Iylx230iqcXo3osjPha7JDyWM5o+K EWckTe91I1mokDr5sJ4JXixvnJTVSx1li49IalW4en1DAkc1a0s2U2UNm236EXAMPLELotyh7h+flFeloZlAWQFH xRlXsPqiVKS1ZIUClaZWprh/orDJplpiWfBgBIOgokJIDGP9gwhXIIk7zWrGmWpMK9o=