カスタムオーソライザーの作成と管理 - AWS IoT Core

カスタムオーソライザーの作成と管理

AWS IoT Core は、オーソライザーリソースを使用してカスタム認証および承認スキームを実装します。各オーソライザーは、次のコンポーネントで構成されています。

  • 名前: オーソライザーを識別する一意のユーザー定義文字列。

  • Lambda 関数 ARN: 承認および認証ロジックを実装する Lambda 関数の Amazon リソースネーム (ARN)。 

  • トークンキー名: 署名の検証を実行するために、HTTP ヘッダー、クエリパラメータ、または MQTT CONNECT ユーザー名からトークンを抽出するために使用されるキー名。オーソライザーで署名が有効になっている場合、この値は必須です。

  • 署名無効フラグ (オプション): 認証情報の署名要件を無効にするかどうかを指定するブール値。これは、MQTT ユーザー名とパスワードを使用する認証スキームなど、認証情報への署名が意味をなさないシナリオで役立ちます。デフォルト値は false であるため、署名はデフォルトで有効になっています。

  • トークン署名パブリックキー: AWS IoT Core がトークン署名を検証するために使用するパブリックキー。最小長は 2,048 ビットです。オーソライザーで署名が有効になっている場合、この値は必須です。 

Lambda では、Lambda 関数の実行回数と、関数内のコードの実行にかかった時間に対する請求が発生します。Lambda の料金の詳細については、Lambda の料金を参照してください。Lambda の作成の詳細については、AWS Lambda デベロッパーガイドを参照してください。

注記

署名を有効にしておくと、認識されないクライアントによる Lambda の過度なトリガーを防ぐことができます。オーソライザーで署名を無効にする前に、これを考慮してください。

Lambda 関数の定義

AWS IoT Core がオーソライザーを呼び出すと、次の JSON オブジェクトを含むイベントで、オーソライザーに関連付けられている Lambda をトリガーします。サンプルの 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 形式の AWS IoT Core ポリシードキュメントのリスト。 AWS IoT Core ポリシーの作成の詳細については、「 AWS IoT Core ポリシー」を参照してください。ポリシードキュメントの最大数は 10 個です。各ポリシードキュメントでは最大 2,048 文字を使用できます。

  • disconnectAfterInSeconds: AWS IoT Core ゲートウェイへの接続の最大期間 (秒単位) を指定する整数。最小値は 300 秒で、最大値は 86,400 秒です。

  • refreshAfterInSeconds: ポリシーの更新の間隔を指定する整数。この時間間隔が経過すると、 AWS IoT Core が Lambda 関数を呼び出してポリシーの更新を許可します。最小値は 300 秒で、最大値は 86,400 秒です。

 次の 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 over TLS および MQTT over WebSockets 接続では、 AWS IoT Core は refreshAfterInSeconds フィールドの値で指定された間隔でこのポリシーをキャッシュします。この間隔の間、 AWS IoT Core は、Lambda 関数を再度トリガーすることなく、このキャッシュされたポリシーに対して確立された接続内のアクションを承認します。カスタム認証中にエラーが発生した場合は、 AWS IoT Core は接続を終了します。また、disconnectAfterInSeconds パラメータで指定された値よりも長い時間開かれている場合も、 AWS IoT Core は接続を終了します。

次の JavaScript には、MQTT Connect メッセージ内で値が test のパスワードを検索し、myClientName という名前のクライアントを使用して AWS IoT Core に接続し、同じクライアント名を含むトピックに発行するためのアクセス許可を付与するポリシーを返すサンプル Node.js Lambda 関数が含まれます。想定されるパスワードが見つからない場合、これらの 2 つのアクションを拒否するポリシーを返します。

// 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 パラメータの異なる値を持つ別のカスタムオーソライザーを作成する必要があります。

署名を無効にしている場合、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"

オーソライザーのテスト

TestInvokeAuthorizer API を使用して、オーソライザーの呼び出しと戻り値をテストできます。この 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 パラメータを使用してこの情報を渡すことができます。次のタブは、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: AWS IoT Core データエンドポイントのデフォルトのオーソライザーを指定します。デバイスが AWS IoT Core 認証情報を渡さず、オーソライザを指定しない場合は、 AWS IoT Core はこのオーソライザーを使用します。 AWS IoT Core 認証情報を使用することについての詳細は、「クライアント認証」を参照してください。

  • UpdateAuthorizer: 指定されたオーソライザーのステータス、トークンキー名、またはパブリックキーを変更します。

  • DeleteAuthorizer: 指定されたオーソライザーを削除します。

注記

オーソライザーの署名要件を更新することはできません。これは、署名を必要とする既存のオーソライザーでの署名を無効にすることはできないことを意味します。また、署名を必要としない既存のオーソライザーで署名を要求することもできません。