

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# カスタム認証と認可
<a name="custom-authentication"></a>

 AWS IoT Core では、独自のクライアントの認証と認可を管理できるように、カスタムオーソライザーを定義できます。これは、 が AWS IoT Core ネイティブにサポートしている認証メカニズム以外の認証メカニズムを使用する必要がある場合に便利です。(ネイティブでサポートされているメカニズムの詳細については、[クライアント認証](client-authentication.md) を参照してください)。  

 たとえば、 フィールドの既存のデバイスを に移行 AWS IoT Core し、これらのデバイスがカスタムベアラートークンまたは MQTT ユーザー名とパスワードを使用して認証 する場合、新しい ID をプロビジョニング AWS IoT Core しなくても に移行できます。カスタム認証は、 が AWS IoT Core サポートする任意の通信プロトコルで使用できます。 AWS IoT Core がサポートするプロトコルの詳細については、「[デバイス通信プロトコル](protocols.md)」を参照してください。

**Topics**
+ [カスタム認証ワークフローについて](custom-authorizer.md)
+ [カスタムオーソライザー (CLI) の作成と管理](config-custom-auth.md)
+ [X.509 クライアント証明書を使用したカスタム認証](custom-auth-509cert.md)
+ [カスタム認証 AWS IoT Core を使用した への接続](custom-auth.md)
+ [オーソライザーのトラブルシューティング](custom-auth-troubleshooting.md)

# カスタム認証ワークフローについて
<a name="custom-authorizer"></a>

カスタム認証を使用すると、[オーソライザーリソース](https://docs.aws.amazon.com/iot/latest/apireference/API_AuthorizerDescription.html)を使用してクライアントを認証および認可する方法を定義できます。  各オーソライザーには、カスタマー管理の Lambda 関数への参照、デバイスの認証情報を検証するためのオプションのパブリックキー、および追加の設定情報が含まれています。次の図は、 AWS IoT Coreでのカスタム認証の認可ワークフローを示しています。

![\[AWS IoT Coreでのカスタム認証のカスタム許可ワークフロー。\]](http://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/images/custom-authentication.png)


## AWS IoT Core カスタム認証と認可ワークフロー
<a name="custom-authentication-workflow"></a>

次のリストでは、カスタム認証および認可ワークフローの各ステップについて説明します。

1. デバイスは、サポートされている のいずれかを使用して、顧客の AWS IoT Core データエンドポイントに接続します[デバイス通信プロトコル](protocols.md)。デバイスは、リクエストのヘッダーフィールドまたはクエリパラメータ (HTTP Publish または MQTT over WebSocket プロトコルの場合)、または MQTT CONNECT メッセージのユーザー名とパスワードフィールド (MQTT および MQTT over WebSockets プロトコルの場合) で認証情報を渡します。

1. AWS IoT Core は、次の 2 つの条件のいずれかをチェックします。
   + 受信リクエストはオーソライザーを指定します。
   + リクエストを受信する AWS IoT Core データエンドポイントには、デフォルトのオーソライザーが設定されています。

   がこれらのいずれかの方法でオーソライザー AWS IoT Core を検出すると、 AWS IoT Core はオーソライザーに関連付けられた Lambda 関数をトリガーします。

1.  (オプション) トークン署名を有効にしている場合、 は Lambda 関数をトリガーする前に、オーソライザーに保存されている パブリックキーを使用してリクエスト署名 AWS IoT Core を検証します。検証が失敗した場合、 AWS IoT Core は Lambda 関数を呼び出さずにリクエストを停止します。  

1. Lambda 関数は、リクエスト内の認証情報と接続メタデータを受け取り、認証の可否を判断します。

1. Lambda 関数は、認証決定の結果と、接続で許可されるアクションを指定する AWS IoT Core ポリシードキュメントを返します。Lambda 関数は、Lambda 関数を呼び出してリクエスト内の認証情報 AWS IoT Core を再検証する頻度を指定する情報も返します。

1. AWS IoT Core は、Lambda 関数から受信したポリシーに対する接続のアクティビティを評価します。

1. 接続が確立され、カスタムオーソライザー Lambda が最初に呼び出された後、MQTT オペレーションなしでアイドル状態の接続では、次の呼び出しが最大 5 分間遅延する可能性があります。その後、それ以降の呼び出しはカスタムオーソライザー Lambda の更新間隔に従います。このアプローチにより、 の Lambda 同時実行数の制限を超える可能性のある過剰な呼び出しを防ぐことができます AWS アカウント。

## スケーリングに関する考慮事項
<a name="custom-authentication-scaling"></a>

 Lambda 関数はオーソライザーの認証と認可を処理するため、関数は Lambda の料金とサービスの制限 (同時実行率など) の対象となります。Lambda の料金の詳細については、「[Lambda の料金](https://aws.amazon.com/lambda/pricing/)」を参照してください。Lambda 関数の応答の `refreshAfterInSeconds` および `disconnectAfterInSeconds` パラメータを調整することで、Lambda 関数の負荷を管理できます。Lambda 関数のレスポンスの内容の詳細については、[Lambda 関数の定義](custom-auth-lambda.md) を参照してください。

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

**注記**  
カスタムオーソライザーの Lambda 関数のタイムアウト制限は 5 秒です。

# カスタムオーソライザー (CLI) の作成と管理
<a name="config-custom-auth"></a>

AWS IoT Core は、カスタムオーソライザーを使用してカスタム認証および認可スキームを実装します。カスタムオーソライザーは、特定の要件に基づいてルールとポリシーを柔軟に定義および実装できる AWS IoT Core リソースです。ステップバイステップの手順でカスタムオーソライザーを作成するには、「[チュートリアル: AWS IoT Coreのカスタムオーソライザーの作成](https://docs.aws.amazon.com//iot/latest/developerguide/custom-auth-tutorial.html)」を参照してください。

各オーソライザーは、次のコンポーネントで構成されています。
+  *名前*: オーソライザーを識別する一意のユーザー定義文字列。
+  *Lambda 関数 ARN*: 認可および認証ロジックを実装する Lambda 関数の Amazon リソースネーム (ARN)。  
+  *トークンキー名*: 署名の検証を実行するために、HTTP ヘッダー、クエリパラメータ、または MQTT CONNECT ユーザー名からトークンを抽出するために使用されるキー名。オーソライザーで署名が有効になっている場合、この値は必須です。
+  *署名無効フラグ (オプション)*: 認証情報の署名要件を無効にするかどうかを指定するブール値。これは、MQTT ユーザー名とパスワードを使用する認証スキームなど、認証情報への署名が意味をなさないシナリオで役立ちます。デフォルト値は `false` であるため、署名はデフォルトで有効になっています。
+  *トークン署名パブリックキー*: AWS IoT Core がトークン署名を検証するために使用するパブリックキー。最小長は 2,048 ビットです。オーソライザーで署名が有効になっている場合、この値は必須です。  

Lambda では、Lambda 関数の実行回数と、関数内のコードの実行にかかった時間に対する請求が発生します。Lambda の料金の詳細については、「[Lambda の料金](https://aws.amazon.com/lambda/pricing/)」を参照してください。Lambda 関数の作成の詳細については、[Lambda デベロッパーガイド](https://docs.aws.amazon.com/lambda/latest/dg/)を参照してください。

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

**注記**  
カスタムオーソライザーの Lambda 関数のタイムアウト制限は 5 秒です。

**Topics**
+ [Lambda 関数の定義](custom-auth-lambda.md)
+ [オーソライザーを作成する](custom-auth-create-authorizer.md)
+ [Lambda 関数を呼び出す AWS IoT ことを に許可する](custom-auth-authorize.md)
+ [オーソライザーのテスト](custom-auth-testing.md)
+ [カスタムオーソライザーの管理](custom-auth-manage.md)

# Lambda 関数の定義
<a name="custom-auth-lambda"></a>

 がオーソライザーを 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`: カスタム認可リクエストによって送信されるトークンの識別子として機能する英数字の文字列。値は、1～128 文字以内の英数字の文字列で、正規表現 (regex) パターン `([a-zA-Z0-9]){1,128}` と一致する必要があります。英数字以外の特殊文字は、 `principalId`では使用できません AWS IoT Core。英数字以外の特殊文字が で許可されている場合は、他の AWS サービスのドキュメントを参照してください`principalId`。
+  `policyDocuments`: JSON 形式の AWS IoT Core ポリシードキュメントのリスト AWS IoT Core ポリシーの作成の詳細については、「」を参照してください[AWS IoT Core ポリシー](iot-policies.md)。ポリシードキュメントの最大数は 10 個です。各ポリシードキュメントでは最大 2,048 文字を使用できます。
+  `disconnectAfterInSeconds`: AWS IoT Core ゲートウェイへの接続の最大期間 (秒単位) を指定する整数。最小値は 300 秒で、最大値は 86,400 秒です。デフォルト値は 86,400 です。
**注記**  
(Lambda 関数によって返される) `disconnectAfterInSeconds` の値は、接続が確立されると設定されます。この値は、後続のポリシー更新 Lambda 呼び出し中に変更することはできません。
+  `refreshAfterInSeconds`: ポリシーの更新の間隔を指定する整数。この時間間隔が経過すると、 AWS IoT Core が Lambda 関数を呼び出してポリシーの更新を許可します。最小値は 300 秒で、最大値は 86,400 秒です。

  次の JSON オブジェクトには、Lambda 関数が送信できる応答の例が含まれています。

 **\$1 "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": [       \$1         "Version": "2012-10-17",         "Statement": [            \$1               "Action": "iot:Publish",               "Effect": "Allow",               "Resource": "arn:aws:iot:us-east-1:<your\$1aws\$1account\$1id>:topic/customauthtesting"             \$1          ]        \$1     ] \$1**

 `policyDocument` 値には有効な AWS IoT Core ポリシードキュメントが含まれている必要があります。 AWS IoT Core ポリシーの詳細については、「」を参照してください[AWS IoT Core ポリシー](iot-policies.md)。  「MQTT over TLS」および「MQTT over WebSockets 接続」で、 は `refreshAfterInSeconds`フィールドの値で指定された間隔でこのポリシーを AWS IoT Core キャッシュします。HTTP 接続の場合、オーソライザーの設定時に選択するとキャッシュを有効にできる HTTP 持続的接続 (HTTP キープアライブまたは HTTP 接続の再利用とも呼ばれる) をデバイスで使用していない限り、認可リクエストごとに Lambda 関数が呼び出されます。この間隔中に、 は Lambda 関数を再度トリガーすることなく、このキャッシュされたポリシーに対して確立された接続のアクション AWS IoT Core を承認します。カスタム認証中に障害が発生した場合、 は接続 AWS IoT Core を終了します。 AWS IoT Core また、 `disconnectAfterInSeconds`パラメータで指定された値よりも長く開いている場合は接続も終了します。

 次の JavaScript には、 の値を持つ MQTT Connect メッセージ内のパスワードを検索`test`し、 という名前のクライアント AWS IoT Core を使用して に接続`myClientName`し、同じクライアント名を含むトピックに発行するアクセス許可を付与するポリシーを返すサンプル 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')); 
            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 関数は、MQTT Connect メッセージの `test` で想定されるパスワードを受け取ると、次の JSON を返します。`password` プロパティと `principalId` プロパティの値は、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
}
```

# オーソライザーを作成する
<a name="custom-auth-create-authorizer"></a>

 [CreateAuthorizer API](https://docs.aws.amazon.com/iot/latest/apireference/API_CreateAuthorizer.html) を使用してオーソライザーを作成できます。次の例は、このコマンドを示しています。

```
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 サービスに明示的に付与する必要があります。これを行う には、次のコマンドを使用します。

**注記**  
デフォルトの IoT エンドポイントは、Lambda 関数でのカスタムオーソライザーの使用をサポートしていない場合があります。その場合は、ドメイン設定を使用して新しいエンドポイントを定義し、そのエンドポイントをカスタムオーソライザーに指定できます。

```
aws lambda add-permission --function-name <lambda_function_name>
--principal iot.amazonaws.com --source-arn <authorizer_arn>
--statement-id Id-123 --action "lambda:InvokeFunction"
```

# Lambda 関数を呼び出す AWS IoT ことを に許可する
<a name="custom-auth-authorize"></a>

このセクションでは、作成したカスタムオーソライザーリソースに、Lambda 関数を実行するためのアクセス許可を付与します。アクセス許可を付与するには、[add-permission](https://docs.aws.amazon.com//cli/latest/reference/lambda/add-permission.html) CLI コマンドを使用できます。

**を使用して Lambda 関数にアクセス許可を付与する AWS CLI**

1. 値を挿入したら、次のコマンドを入力します。`statement-id` 値は一意でなければならないことに注意してください。`Id-1234` を正確な値に置き換えます。そうしないと、`ResourceConflictException` エラーが発生する可能性があります。

   ```
   aws lambda add-permission  \
   --function-name "custom-auth-function" \
   --principal "iot.amazonaws.com" \
   --action "lambda:InvokeFunction" \
   --statement-id "Id-1234" \
   --source-arn authorizerArn
   ```

1. コマンドが成功すると、この例のようなアクセス許可ステートメントが返されます。次のセクションに進んで、カスタムオーソライザーをテストできます。

   ```
   {
       "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
   ```

# オーソライザーのテスト
<a name="custom-auth-testing"></a>

 [TestInvokeAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_TestInvokeAuthorizer.html) 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` パラメータの値は署名付きトークンです。この値を取得する方法については、「[トークンへの署名](custom-auth.md#custom-auth-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
```

# カスタムオーソライザーの管理
<a name="custom-auth-manage"></a>

 次の API を使用して、オーソライザーを管理できます。
+ [ListAuthorizers](https://docs.aws.amazon.com/iot/latest/apireference/API_ListAuthorizers.html): アカウント内のすべてのオーソライザーを表示します。
+  [DescribeAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_DescribeAuthorizer.html): 指定されたオーソライザーのプロパティを表示します。これらの値には、作成日、最終更新日、およびその他の属性が含まれます。
+ [SetDefaultAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_SetDefaultAuthorizer.html): AWS IoT Core データエンドポイントのデフォルトのオーソライザーを指定します。デバイスが AWS IoT Core 認証情報を渡さず、オーソライザーを指定しない場合、 はこのオーソライザー AWS IoT Core を使用します。 AWS IoT Core 認証情報の使用の詳細については、「」を参照してください[クライアント認証](client-authentication.md)。
+ [UpdateAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_UpdateAuthorizer.html): 指定されたオーソライザーのステータス、トークンキー名、またはパブリックキーを変更します。
+  [DeleteAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_DeleteAuthorizer.html): 指定されたオーソライザーを削除します。

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

# X.509 クライアント証明書を使用したカスタム認証
<a name="custom-auth-509cert"></a>

デバイスを に接続するときは AWS IoT Core、複数の[認証タイプ](protocols.md#connection-protocol-auth-mode)を使用できます。[X.509 クライアント証明書](https://docs.aws.amazon.com//iot/latest/developerguide/x509-client-certs.html)を使用すると、クライアントとデバイス接続を認証したり、[カスタムオーソライザー](https://docs.aws.amazon.com//iot/latest/developerguide/custom-authentication.html)を定義して独自のクライアント認証と承認ロジックを管理したりできます。このトピックでは、X.509 クライアント証明書でカスタム認証を使用する方法について説明します。

X.509 証明書でカスタム認証を使用すると、X.509 証明書を使用してデバイスを既に認証していて、追加の検証とカスタム認証を実行したい場合に役立ちます。例えば、X.509 クライアント証明書にシリアル番号などのデバイスのデータを保存した場合、 AWS IoT Core が X.509 クライアント証明書を認証した後、カスタムオーソライザーを使用して、証明書の CommonName フィールドに保存されている情報に基づいて特定のデバイスを識別できます。X.509 証明書でカスタム認証を使用すると、デバイスを に接続する際のデバイスセキュリティ管理を強化 AWS IoT Core し、認証ロジックと認可ロジックをより柔軟に管理できます。 は、[MQTT](https://docs.aws.amazon.com//iot/latest/developerguide/mqtt.html) プロトコルと [HTTPS](https://docs.aws.amazon.com//iot/latest/developerguide/http.html) プロトコルの両方で動作する X.509 証明書とカスタムオーソライザー認証タイプを使用した X.509 証明書でのカスタム認証 AWS IoT Core をサポートします。 AWS IoT Core デバイスエンドポイントがサポートする認証タイプとアプリケーションプロトコルの詳細については、「[デバイス通信プロトコル](https://docs.aws.amazon.com//iot/latest/developerguide/protocols.html)」を参照してください。

**注記**  
X.509 クライアント証明書によるカスタム認証は、 AWS GovCloud (US) リージョンではサポートされていません。

**重要**  
[[ドメイン設定]](iot-custom-endpoints-configurable.md) を使用して作成されたエンドポイントを使用する必要があります。さらに、クライアントは接続時に [Server Name Indication (SNI)](https://www.rfc-editor.org/rfc/rfc3546#section-3.1) 拡張機能を提供する必要があります AWS IoT Core。

**Topics**
+ [ステップ 1: X.509 クライアント証明書を に登録する AWS IoT Core](#custom-auth-509cert-client)
+ [ステップ 2: Lambda 関数を作成する](#custom-auth-509cert-lambda)
+ [ステップ 3: カスタムオーソライザーを作成する](#custom-auth-509cert-authorizer)
+ [ステップ 4: ドメイン設定で認証タイプとアプリケーションプロトコルを設定する](#custom-auth-509cert-domainconfig)

## ステップ 1: X.509 クライアント証明書を に登録する AWS IoT Core
<a name="custom-auth-509cert-client"></a>

これをまだ実行していない場合は、[X.509 クライアント証明書](https://docs.aws.amazon.com//iot/latest/developerguide/x509-client-certs.html)を登録してアクティブ化します AWS IoT Core。それ以外の場合は、次のステップに進みます。

クライアント証明書を に登録してアクティブ化するには AWS IoT Core、次の手順に従います。

1. [でクライアント証明書を直接作成 AWS IoT](https://docs.aws.amazon.com//iot/latest/developerguide/device-certs-create.html)する場合。これらのクライアント証明書は、 に自動的に登録されます AWS IoT Core。

1. [独自のクライアント証明書を作成する](https://docs.aws.amazon.com//iot/latest/developerguide/device-certs-your-own.html)場合は、[以下の手順に従って登録します AWS IoT Core](https://docs.aws.amazon.com//iot/latest/developerguide/register-device-cert.html)。

1. クライアント証明書をアクティブ化するには、[以下の手順](https://docs.aws.amazon.com//iot/latest/developerguide/activate-or-deactivate-device-cert.html)に従います。

## ステップ 2: Lambda 関数を作成する
<a name="custom-auth-509cert-lambda"></a>

AWS IoT Core はカスタムオーソライザーを使用してカスタム認証および認可スキームを実装します。カスタムオーソライザーは、デバイスが認証されているかどうか、およびデバイスが実行できるオペレーションを決定する Lambda 関数に関連付けられます。デバイスが に接続すると AWS IoT Core、 はオーソライザー名と関連する Lambda 関数を含むオーソライザーの詳細 AWS IoT Core を取得し、Lambda 関数を呼び出します。Lambda 関数は、デバイスの X.509 クライアント証明書データを含む JSON オブジェクトを含むイベントを受信します。Lambda 関数は、このイベント JSON オブジェクトを使用して認証リクエストを評価し、実行するアクションを決定してレスポンスを送り返します。

### Lambda 関数のイベントの例
<a name="custom-auth-509cert-event"></a>

次の JSON オブジェクトの例には、含めることができるすべてのフィールドが含まれています。実際の JSON オブジェクトには、特定の接続リクエストに関連するフィールドのみが含まれます。

```
{
	"token": "aToken",
	"signatureVerified": true,
	"protocols": [
		"tls",
		"mqtt"
	],
	"protocolData": {
		"tls": {
			"serverName": "serverName",
			"x509CertificatePem": "x509CertificatePem",
			"principalId": "principalId"
		},
		"mqtt": {
			"clientId": "myClientId",
                     "username": "myUserName",
                     "password": "myPassword"
		}
	},
	"connectionMetadata": {
		"id": "UUID"
	}
}
```

`signatureVerified`  
オーソライザーの Lambda 関数を呼び出す前に、オーソライザーで設定されたトークン署名を検証するかどうかを示すブール値。オーソライザーがトークン署名を無効にするように設定されている場合、このフィールドは false になります。

`protocols`  
リクエストに期待されるプロトコルを含む配列。

`protocolData`  
接続で使用されるプロトコルの情報を含むオブジェクト。認証、承認などに役立つプロトコル固有の詳細を提供します。  
`tls` - このオブジェクトには、TLS (Transport Layer Security) プロトコルに関連する情報が含まれます。  
+ `serverName` - [[サーバー名表示 (SNI)]](https://www.rfc-editor.org/rfc/rfc3546#section-3.1) ホスト名文字列。 AWS IoT Core では、デバイスが [SNI 拡張](https://www.rfc-editor.org/rfc/rfc3546#section-3.1)を Transport Layer Security (TLS) に送信し、`host_name` フィールドに完全なエンドポイントアドレスを指定する必要があります。
+ `x509CertificatePem` - PEM 形式の X.509 証明書。TLS 接続でのクライアント認証に使用されます。
+ `principalId` - TLS 接続内のクライアントに関連付けられたプリンシパル識別子。
`mqtt` - このオブジェクトは、MQTT プロトコルに関連する情報を保持します。  
+ `clientId` - 文字列は、デバイスがこの値を送信するイベントにのみ含める必要があります。
+ `username` - MQTT Connect パケットで指定されたユーザー名。
+ `password` - MQTT Connect パケットで提供されたパスワード。

`connectionMetadata`  
接続のメタデータ。  
`id` - ログ記録とトラブルシューティングに使用できる接続 ID。

**注記**  
このイベントでは、JSON オブジェクト、`x509CertificatePem` および `principalId` はリクエスト内の 2 つの新しいフィールドです。`principalId` の値は、`certificateId` の値と同じです。詳細については、「[証明書](https://docs.aws.amazon.com//iot/latest/apireference/API_Certificate.html)」を参照してください。

### Lambda 関数のレスポンスの例
<a name="custom-auth-509cert-response"></a>

Lambda 関数は、イベント JSON オブジェクトからの情報を使用して受信接続を認証し、接続で許可されるアクションを決定する必要があります。

次の JSON オブジェクトには、Lambda 関数が送信できるレスポンスの例が含まれています。

```
{
	"isAuthenticated": true,
	"principalId": "xxxxxxxx",
	"disconnectAfterInSeconds": 86400,
	"refreshAfterInSeconds": 300,
	"policyDocuments": [
		{
			"Version": "2012-10-17",		 	 	 
			"Statement": [
				{
					"Effect": "Allow",
					"Action": "iot:Publish",
					"Resource": "arn:aws:iot:us-east-1:123456789012:topic/customauthtesting"
				}
			]
		}
	]
}
```

この例では、この関数は、次の値を含むレスポンスを送信する必要があります。

`isAuthenticated`  
リクエストが認証されるかどうかを示すブール値。

`principalId`  
カスタム認可リクエストによって送信されるトークンの識別子として機能する英数字の文字列。値は、1～128 文字以内の英数字の文字列である必要があります。ログ内の接続を識別します。`principalId` の値は、イベント JSON オブジェクト (X.509 証明書の certificateId) の `principalId` の値と同じである必要があります。

`policyDocuments`  
JSON 形式の AWS IoT Core ポリシードキュメントのリスト。値はオプションで、[モノのポリシー変数](https://docs.aws.amazon.com//iot/latest/developerguide/thing-policy-variables.html)と[証明書のポリシー変数](https://docs.aws.amazon.com//iot/latest/developerguide/cert-policy-variables.html)をサポートしています。ポリシードキュメントの最大数は 10 です。各ポリシードキュメントでは最大 2,048 文字を使用できます。クライアント証明書と Lambda 関数に複数のポリシーがアタッチされている場合、アクセス許可はすべてのポリシーのコレクションです。 AWS IoT Core ポリシーの作成の詳細については、[「 ](https://docs.aws.amazon.com//iot/latest/developerguide/iot-policies.html)ポリシー」を参照してください。

`disconnectAfterInSeconds`  
 AWS IoT Core ゲートウェイへの接続の最大時間 (秒単位) を指定する整数。最小値は 300 秒、最大値は 86,400 秒です。`disconnectAfterInSeconds` は接続の存続期間中であり、連続するポリシー更新では更新されません。

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

### Lambda 関数の例
<a name="custom-auth-509cert-js-example"></a>

次に示すのは、Node.js Lambda 関数の例です。この関数は、クライアントの X.509 証明書を調べてシリアル番号、フィンガープリント、件名などの関連情報を抽出します。抽出された情報が期待値と一致する場合、クライアントに接続するためのアクセス許可が付与されます。このメカニズムにより、有効な証明書を持つ承認されたクライアントのみが接続を確立できます。

```
const crypto = require('crypto');

exports.handler = async (event) => {
    
    // Extract the certificate PEM from the event
    const certPem = event.protocolData.tls.x509CertificatePem;
    
    // Parse the certificate using Node's crypto module
    const cert = new crypto.X509Certificate(certPem);
    
    var effect = "Deny";
    // Allow permissions only for a particular certificate serial, fingerprint, and subject
    if (cert.serialNumber === "7F8D2E4B9C1A5036DE8F7C4B2A91E5D80463BC9A1257" // This is a random serial
       && cert.fingerprint === "F2:9A:C4:1D:B5:E7:08:3F:6B:D0:4E:92:A7:C1:5B:8D:16:0F:E3:7A" // This is a random fingerprint
       && cert.subject === "allow.example.com") {
      effect = "Allow";
    }
    
    return generateAuthResponse(event.protocolData.tls.principalId, effect);
};


// Helper function to generate the authorization response.
function generateAuthResponse(principalId, effect) {
    const authResponse = {
        isAuthenticated: true,
        principalId,
        disconnectAfterInSeconds: 3600,
        refreshAfterInSeconds: 300,
        policyDocuments: [
          {
            Version: "2012-10-17",		 	 	 
            Statement: [
              {
                Action: ["iot:Connect"],
                Effect: effect,
                Resource: [
                  "arn:aws:iot:us-east-1:123456789012:client/myClientName"
                ]
              },
              {
                Action: ["iot:Publish"],
                Effect: effect,
                Resource: [
                  "arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"
                ]
              },
              {
                Action: ["iot:Subscribe"],
                Effect: effect,
                Resource: [
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/telemetry/myClientName"
                ]
              },
              {
                Action: ["iot:Receive"],
                Effect: effect,
                Resource: [
                   "arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"
                ]
              }
            ]
          }
        ]
      };

  return authResponse;
}
```

前述の Lambda 関数は、予想されるシリアル、フィンガープリント、およびサブジェクトを含む証明書を受信すると、次の JSON を返します。`x509CertificatePem` の値は、TLS ハンドシェイクで提供されるクライアント証明書になります。詳細については、「[ Lambda 関数の定義](https://docs.aws.amazon.com//iot/latest/developerguide/config-custom-auth.html#custom-auth-lambda)」を参照してください。

```
{
	"isAuthenticated": true,
	"principalId": "principalId in the event JSON object",
	"policyDocuments": [
		{
			"Version": "2012-10-17",		 	 	 
			"Statement": [
				{
					"Action": "iot:Connect",
					"Effect": "Allow",
					"Resource": "arn:aws:iot:us-east-1:123456789012:client/myClientName"
				},
				{
					"Action": "iot:Publish",
					"Effect": "Allow",
					"Resource": "arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"
				},
				{
					"Action": "iot:Subscribe",
					"Effect": "Allow",
					"Resource": "arn:aws:iot:us-east-1:123456789012:topicfilter/telemetry/myClientName"
				},
				{
					"Action": "iot:Receive",
					"Effect": "Allow",
					"Resource": "arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"
				}
			]
		}
	],
	"disconnectAfterInSeconds": 3600,
	"refreshAfterInSeconds": 300
}
```

## ステップ 3: カスタムオーソライザーを作成する
<a name="custom-auth-509cert-authorizer"></a>

[Lambda 関数 を定義した](#custom-auth-509cert-lambda)後、カスタムオーソライザーを作成して、独自のクライアント認証および承認ロジックを管理します。[ステップ 3: カスタマーオーソライザーリソースとその承認を作成する](https://docs.aws.amazon.com//iot/latest/developerguide/custom-auth-tutorial.html#custom-auth-tutorial-authorizer)の詳細な指示に従ってください。詳細については、「[オーソライザーの作成](https://docs.aws.amazon.com//iot/latest/developerguide/config-custom-auth.html)」を参照してください。

カスタムオーソライザーを作成するプロセスでは、作成後に Lambda 関数を呼び出すアクセス許可を AWS IoT に付与する必要があります。詳細な手順については、[「Lambda 関数 AWS IoT の呼び出しを許可する](custom-auth-authorize.md)」を参照してください。

## ステップ 4: ドメイン設定で認証タイプとアプリケーションプロトコルを設定する
<a name="custom-auth-509cert-domainconfig"></a>

X.509 クライアント証明書によるカスタム認証を使用してデバイスを認証するには、ドメイン設定で認証タイプとアプリケーションプロトコルを設定し、SNI 拡張機能を送信する必要があります。`authenticationType` の値は `CUSTOM_AUTH_X509` にする必要があり、`applicationProtocol` の値は `SECURE_MQTT` または `HTTPS` にすることができます。

### ドメイン設定 (CLI) で認証タイプとアプリケーションプロトコルを設定する
<a name="custom-auth-509cert-cli"></a>

ドメイン設定がない場合は、[https://docs.aws.amazon.com//cli/latest/reference/iot/create-domain-configuration.html](https://docs.aws.amazon.com//cli/latest/reference/iot/create-domain-configuration.html) コマンドを使用してドメイン設定を作成します。`authenticationType` の値は `CUSTOM_AUTH_X509` にする必要があり、`applicationProtocol` の値は `SECURE_MQTT` または `HTTPS` にすることができます。

```
aws iot create-domain-configuration \
    --domain-configuration-name domainConfigurationName \
    --authentication-type CUSTOM_AUTH_X509 \  
    --application-protocol SECURE_MQTT \ 
    --authorizer-config '{
        "defaultAuthorizerName": my-custom-authorizer
    }'
```

ドメイン設定が既にある場合は、[https://docs.aws.amazon.com//cli/latest/reference/iot/update-domain-configuration.html](https://docs.aws.amazon.com//cli/latest/reference/iot/update-domain-configuration.html) コマンドの更新 `authenticationType` と必要に応じて `applicationProtocol` を使用します。デフォルトのエンドポイント (`iot:Data-ATS`) では、認証タイプやプロトコルを変更できないことに注意してください。

```
aws iot update-domain-configuration \
    --domain-configuration-name domainConfigurationName \
    --authentication-type CUSTOM_AUTH_X509 \  
    --application-protocol SECURE_MQTT \
    --authorizer-config '{
        "defaultAuthorizerName": my-custom-authorizer
    }'
```

`domain-configuration-name`  
ドメイン構成の名前。

`authentication-type`  
ドメイン設定の認証タイプ。詳細については、「[認証タイプの選択](protocols.md#connection-protocol-auth-mode)」を参照してください。

`application-protocol`  
デバイスが AWS IoT Coreとの通信に使用するアプリケーションプロトコル。詳細については、「[アプリケーションプロトコルの選択](protocols.md#protocol-selection)」を参照してください。

`--authorizer-config`  
ドメイン設定でオーソライザー設定を指定するオブジェクト。

`defaultAuthorizerName`  
ドメイン構成のオーソライザー名。

詳細については、「*AWS IoT API リファレンス*」の「[CreateDomainConfiguration](https://docs.aws.amazon.com//iot/latest/apireference/API_CreateDomainConfiguration.html)」と「[UpdateDomainConfiguration](https://docs.aws.amazon.com//iot/latest/apireference/API_UpdateDomainConfiguration.html)」を参照してください。ドメイン設定の詳細については、「[ドメイン設定](https://docs.aws.amazon.com//iot/latest/developerguide/iot-custom-endpoints-configurable.html)」を参照してください。

# カスタム認証 AWS IoT Core を使用した への接続
<a name="custom-auth"></a>

 デバイスは、 AWS IoT Core がデバイスメッセージング用に AWS IoT Core サポートする任意のプロトコルでカスタム認証を使用して に接続できます。サポートされる通信プロトコルの詳細については、[デバイス通信プロトコル](protocols.md) を参照してください。  オーソライザーの Lambda 関数に渡す接続データは、使用するプロトコルによって異なります。オーソライザーの Lambda 関数の作成の詳細については、「[Lambda 関数の定義](custom-auth-lambda.md)」を参照してください。次のセクションでは、サポートされている各プロトコルを使用して接続して認証する方法について説明します。

## HTTPS
<a name="custom-auth-http"></a>

[HTTP Publish API](https://docs.aws.amazon.com/iot/latest/apireference/API_iotdata_Publish.html) を使用して AWS IoT Core にデータを送信するデバイスは、HTTP POST リクエストのリクエストヘッダーまたはクエリパラメータを介して認証情報を渡すことができます。デバイスは、`x-amz-customauthorizer-name` ヘッダーまたはクエリパラメータを使用して呼び出すオーソライザーを指定できます。オーソライザーでトークン署名を有効にしている場合は、リクエストヘッダーまたはクエリパラメータで `token-key-name` と `x-amz-customauthorizer-signature` を渡す必要があります。ブラウザ内から JavaScript を使用する場合、`token-signature` の値は URL エンコードする必要があります。

**注記**  
HTTPS プロトコルのカスタマーオーソライザーは、発行オペレーションのみをサポートします。HTTPS プロトコルの詳細については、「[デバイス通信プロトコル](protocols.md)」を参照してください。

次のリクエスト例は、これらのパラメータをリクエストヘッダーとクエリパラメータの両方で渡す方法を示しています。

```
//Passing credentials via headers
POST /topics/topic?qos=qos HTTP/1.1
Host: your-endpoint 
x-amz-customauthorizer-signature: token-signature
token-key-name: token-value 
x-amz-customauthorizer-name: authorizer-name

//Passing credentials via query parameters
POST /topics/topic?qos=qos&x-amz-customauthorizer-signature=token-signature&token-key-name=token-value HTTP/1.1
```

## MQTT
<a name="custom-auth-mqtt"></a>

 MQTT 接続 AWS IoT Core を使用して に接続するデバイスは、MQTT メッセージの `username` および `password`フィールドを介して認証情報を渡すことができます。`username` の値には、追加の値 (トークン、署名、オーソライザー名など) をオーソライザーに渡すクエリ文字列をオプションで含めることもできます。`username` と `password` の値の代わりにトークンベースの認証スキームを使用する場合は、このクエリ文字列を使用できます。  

**注記**  
 パスワードフィールドのデータは、 によって base64 エンコードされます AWS IoT Core。Lambda 関数はそれをデコードする必要があります。

 次の例では、トークンと署名を指定する追加のパラメータを含む `username` 文字列が含まれています。  

```
username?x-amz-customauthorizer-name=authorizer-name&x-amz-customauthorizer-signature=token-signature&token-key-name=token-value
```

オーソライザーを呼び出すには、MQTT とカスタム認証 AWS IoT Core を使用して に接続するデバイスがポート 443 に接続する必要があります。また、 の値を持つ Application Layer Protocol Negotiation (ALPN) TLS 拡張機能`mqtt`と、 AWS IoT Core データエンドポイントのホスト名を持つ Server Name Indication (SNI) 拡張機能を渡す必要があります。潜在的なエラーを回避するために、`x-amz-customauthorizer-signature` の値は URL エンコードされている必要があります。また、`x-amz-customauthorizer-name` と `token-key-name` の値も URL エンコードすることを強くお勧めします。これらの値の詳細については、「[デバイス通信プロトコル](protocols.md)」を参照してください。V2 [AWS IoT Device SDK、Mobile SDK、および AWS IoT Device Client](iot-sdks.md) は、これらの拡張の両方を設定できます。 

## MQTT over WebSockets
<a name="custom-auth-websockets"></a>

 MQTT over WebSockets AWS IoT Core を使用して に接続するデバイスは、次の 2 つの方法のいずれかで認証情報を渡すことができます。
+ HTTP UPGRADE リクエストのリクエストヘッダーまたはクエリパラメータを介して、WebSocket 接続を確立します。
+ MQTT CONNECT メッセージの `username` フィールドと `password` フィールド経由。

 MQTT 接続メッセージを介して認証情報を渡す場合、ALPN および SNI TLS 拡張が必要です。これらの拡張の詳細については、「[MQTT](#custom-auth-mqtt)」を参照してください。次の例は、HTTP Upgrade リクエストを介して認証情報を渡す方法を示しています。

```
GET /mqtt HTTP/1.1
Host: your-endpoint 
Upgrade: WebSocket 
Connection: Upgrade 
x-amz-customauthorizer-signature: token-signature
token-key-name: token-value 
sec-WebSocket-Key: any random base64 value 
sec-websocket-protocol: mqtt 
sec-WebSocket-Version: websocket version
```

## トークンへの署名
<a name="custom-auth-token-signature"></a>

`create-authorizer` 呼び出しで使用したパブリックキーとプライベートキーのペアのプライベートキーを使用してトークンに署名する必要があります。次の例では、Unix 系のコマンドと JavaScript を使用してトークン署名を作成する方法を示します。SHA-256 ハッシュアルゴリズムを使用して、署名をエンコードします。

------
#### [ Command line ]

```
echo -n TOKEN_VALUE | openssl dgst -sha256 -sign PEM encoded RSA private key | openssl base64
```

------
#### [ JavaScript ]

```
const crypto = require('crypto')

const key = "PEM encoded RSA private key"

const k = crypto.createPrivateKey(key)
let sign = crypto.createSign('SHA256')
sign.write(t)
sign.end()
const s = sign.sign(k, 'base64')
```

------

# オーソライザーのトラブルシューティング
<a name="custom-auth-troubleshooting"></a>

 このトピックでは、カスタム認証ワークフローで問題を引き起こす可能性のある一般的な問題と、それらを解決するための手順について説明します。問題を最も効果的にトラブルシューティングするには、 の CloudWatch Logs を有効に AWS IoT Core し、ログレベルを **DEBUG** に設定します。 AWS IoT Core コンソール ([https://console.aws.amazon.com/iot/](https://console.aws.amazon.com/iot/)) で CloudWatch ログを有効にできます。 AWS IoT Coreのログの有効化と設定の詳細については、「[AWS IoT ログ記録の設定](configure-logging.md)」を参照してください。

**注記**  
ログレベルを長期間 **DEBUG** のままにしておくと、CloudWatch は大量のログデータを保存する可能性があります。これにより、CloudWatch の料金が増加する可能性があります。リソースベースのログ記録を使用して、特定のモノのグループ内のデバイスのみの詳細度を高めることを検討してください。リソースベースのログ記録の詳細については、「[AWS IoT ログ記録の設定](configure-logging.md)」を参照してください。また、トラブルシューティングが完了したら、ログレベルの詳細度を引き下げます。

トラブルシューティングを開始する前に、[カスタム認証ワークフローについて](custom-authorizer.md) でカスタム認証プロセスの概要を確認してください。これは、問題の原因を見つけるのにどこを確認すればよいかを理解するのに役立ちます。

このトピックでは、調査する次の 2 つの領域について説明します。
+ オーソライザーの Lambda 関数に関連する問題。
+ デバイスに関連する問題。

## オーソライザーの Lambda 関数に問題がないか確認する
<a name="custom-auth-troubleshooting-lambda"></a>

次の手順を実行して、デバイスの接続試行が Lambda 関数を呼び出していることを確認します。

1. オーソライザーに関連付けられている Lambda 関数を確認します。

   これを行うには、[DescribeAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_DescribeAuthorizer.html) API を呼び出すか、 AWS IoT Core コンソールの [**Secure**] (安全性) セクションで目的のオーソライザーをクリックします。

1. Lambda 関数の呼び出しメトリクスを確認します。これを行うには、次の手順を実行します。

   1.  AWS Lambda コンソール ([https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)) を開き、オーソライザーに関連付けられている関数を選択します。

   1. [**Monitor**] (監視) タブを選択し、問題に関連する時間枠のメトリクスを表示します。

1. 呼び出しが表示されない場合は、 AWS IoT Core に Lambda 関数を呼び出すアクセス許可があることを確認します。呼び出しが表示された場合は、次の手順に進みます。次の手順を実行して、Lambda 関数に必要なアクセス許可があることを確認します。

   1.  AWS Lambda コンソールで 関数の**アクセス許可**タブを選択します。

   1. ページの下部にある [**Resource-based Policy**] (リソースベースのポリシー) セクションを見つけます。Lambda 関数に必要なアクセス許可がある場合、ポリシーは次の例のようになります。  
****  

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Id": "default",
        "Statement": [
          {
            "Sid": "Id123",
            "Effect": "Allow",
            "Principal": {
              "Service": "iot.amazonaws.com"
            },
            "Action": "lambda:InvokeFunction",
            "Resource": "arn:aws:lambda:us-east-1:111111111111:function:FunctionName",
            "Condition": {
              "ArnLike": {
                "AWS:SourceArn": "arn:aws:iot:us-east-1:111111111111:authorizer/AuthorizerName"
              },
              "StringEquals": {
                "AWS:SourceAccount": "111111111111"
              }
            }
          }
        ]
      }
      ```

   1. このポリシーは、関数に対する アクセス`InvokeFunction`許可を AWS IoT Core プリンシパルに付与します。表示されない場合は、[AddPermission](https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html) API を使用して追加する必要があります。次の例では、 AWS CLIを使用してこの操作を行う方法を示しています。

      ```
      aws lambda add-permission --function-name FunctionName --principal iot.amazonaws.com --source-arn AuthorizerARn --statement-id Id-123 --action "lambda:InvokeFunction"
      ```

1. 呼び出しが表示された場合は、エラーがないことを確認します。エラーは、Lambda 関数が AWS IoT Core が送信する接続イベントを適切に処理していないことを示している可能性があります。

   Lambda 関数でのイベントの処理については、[Lambda 関数の定義](custom-auth-lambda.md) を参照してください。 AWS Lambda コンソール ([https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)) のテスト機能を使用して、関数のテスト値をハードコードし、関数がイベントを正しく処理していることを確認します。

1. エラーのない呼び出しが表示されても、デバイスが接続 (またはメッセージを発行、サブスクライブ、および受信) できない場合、問題は、Lambda 関数が返すポリシーが、デバイスが実行しようとしているアクションのためのアクセス許可を付与しないことである可能性があります。関数が返すポリシーに問題があるかどうかを判断するには、次の手順を実行します。

   1. Amazon CloudWatch Logs Insights クエリを使用して、短期間にログをスキャンし、エラーがないか確認します。次のクエリ例では、イベントをタイムスタンプでソートし、エラーを探します。

      ```
      display clientId, eventType, status, @timestamp | sort @timestamp desc | filter status = "Failure"    
      ```

   1. Lambda 関数を更新して、返されるデータと関数 AWS IoT Core をトリガーするイベントをログに記録します。これらのログを使用して、関数が作成するポリシーを検査できます。

1. 呼び出しにエラーがないにもかかわらず、デバイスが接続できない (またはメッセージを発行、サブスクライブ、受信できない) 場合は、別の原因として、Lambda 関数がタイムアウト制限を超えている可能性があります。カスタムオーソライザーの Lambda 関数のタイムアウト制限は 5 秒です。関数の期間は、CloudWatch ログまたはメトリクスで確認できます。

## デバイスの問題の調査
<a name="custom-auth-troubleshooting-investigate"></a>

Lambda 関数の呼び出しに問題がない場合や、関数が返すポリシーに問題がない場合は、デバイスの接続試行に問題がないか確認してください。不正な形式の接続リクエストにより、 がオーソライザーをトリガー AWS IoT Core しない可能性があります。接続の問題は、TLS レイヤーとアプリケーションレイヤーの両方で発生する可能性があります。

**考えられる TLS レイヤーの問題:**
+ お客様は、すべてのカスタム認証リクエストで、ホスト名ヘッダー (HTTP、MQTT over WebSockets) または Server Name Indication TLS 拡張 (HTTP、MQTT over WebSockets、MQTT) を渡す必要があります。どちらの場合も、渡される値はアカウントの AWS IoT Core データエンドポイントの 1 つと一致する必要があります。これらは、次の CLI コマンドを実行したときに返されるエンドポイントです。
  + `aws iot describe-endpoint --endpoint-type iot:Data-ATS`
  + `aws iot describe-endpoint --endpoint-type iot:Data` (レガシー VeriSign エンドポイント)
+ MQTT 接続にカスタム認証を使用するデバイスは、`mqtt` の値の Application Layer Protocol Negotiation (ALPN) TLS 拡張も渡す必要があります。
+ カスタム認証は現在、ポート 443 でのみ使用できます。

**考えられるアプリケーションレイヤーの問題:**
+ 署名が有効になっている場合 (オーソライザーで `signingDisabled` フィールドが false の場合)、次の署名の問題がないかを確認します。
  + `x-amz-customauthorizer-signature` ヘッダーまたはクエリ文字列パラメータのいずれかでトークン署名を渡していることを確認してください。
  + サービスがトークン以外の値に署名していないことを確認してください。
  + オーソライザーの `token-key-name` フィールドで指定したヘッダーまたはクエリパラメータでトークンを渡すようにしてください。
+ `x-amz-customauthorizer-name` ヘッダーまたはクエリ文字列パラメータで渡すオーソライザー名が有効であること、またはアカウント用にデフォルトのオーソライザーが定義されていることを確認してください。