相互 TLS を必要とする API Gateway カスタムドメイン名からの HTTP 403 禁止エラーをトラブルシューティングする方法を教えてください。
相互 Transport Layer Security (TLS) 認証が有効になっている Amazon API Gateway カスタムドメイン名で、HTTP 403 禁止エラーが返されました。なぜこれが起こるのか分かりません。
簡単な説明
**注:**API Gateway は、さまざまな理由で 403 禁止エラーを返します。この記事では、相互 TLS のみに関連する 403 禁止エラーについて説明します。他の種類の 403 禁止エラーのトラブルシューティングについては、「API Gatewayから HTTP 403 エラーをトラブルシューティングする方法を教えてください」を参照してください。
相互 TLS を必要とするカスタムドメイン名を使用して API Gateway を呼び出すには、クライアントは API リクエストで信頼できる証明書を提示する必要があります。クライアントが API を呼び出すと、API Gateway はトラストストアでクライアント証明書の発行者を探します。
次の条件があると、API Gateway は TLS 接続に失敗し、403 ステータスコードを返します。
- API Gateway は、トラストストアでクライアント証明書の発行者を見つけることができません。
- クライアント証明書は安全でない署名アルゴリズムを使用しています。
- クライアント証明書は自己署名されています。
API で Amazon CloudWatch ロギングが有効になっている場合、エラーの原因を示すエラーメッセージが実行ログに表示されます。
**重要:**ロギングが有効になった後に API リクエストで CloudWatch Logs が生成されない場合、403 禁止エラーは相互 TLS とは関係ありません。
REST API の場合
REST API 用に Amazon CloudWatch ロギングを設定した場合、実行ログには次のエラーメッセージのいずれかも表示されます。
- アクセス拒否が拒否されました。理由: 証明書の発行者が見つかりませんでした
- アクセス拒否が拒否されました。理由: クライアント証明書は安全でない署名アルゴリズムを使用しています
- アクセス拒否が拒否されました。理由:自己署名証明書
HTTP API オペレーション用
HTTP API は実行ログをサポートしていません。相互 TLS を必要とし、HTTP APIを呼び出すカスタムドメイン名によって返される 403 禁止エラーをトラブルシューティングするには、以下の手順を実行する必要があります:
- テスト専用の REST API を呼び出すカスタムドメイン名の新しい API マッピングを作成します。
**注:**テストする REST API がない場合は、サンプルの PetStore REST API を使用します。次に、サンプル API を新しいステージにデプロイし、カスタムドメイン名を使用する新しい API マッピングを作成します。 - REST API に作成した新しい API マッピングについてはこの記事の「解決策」セクションの指示に従ってください。
- カスタムドメイン名の API マッピングを HTTP API に再ルーティングします。
解決策
エラーの原因を確認する
- REST API の CloudWatch ロギングを有効にします。
- 実行とアクセスログを設定します。
注: このユースケースのアクセスログを設定する場合、次の $context 変数を使用するのがベストプラクティスです。
これらの変数は、相互 TLS を必要とするカスタムドメイン名が 403 エラーを返すときに CloudWatch ログを生成するように API Gateway に指示します。また、API オペレーションを呼び出そうとした呼び出し元を簡単に特定できます。{ "accountId":"$context.accountId", "apiId":"$context.apiId", "domainName":"$context.domainName", "domainPrefix":"$context.domainPrefix", "error.message":"$context.error.message", "error.responseType":"$context.error.responseType", "extendedRequestId":"$context.extendedRequestId", "httpMethod":"$context.httpMethod", "identity.sourceIp":"$context.identity.sourceIp", "identity.clientCert.clientCertPem":"$context.identity.clientCert.clientCertPem", "identity.clientCert.subjectDN":"$context.identity.clientCert.subjectDN", "identity.clientCert.issuerDN":"$context.identity.clientCert.issuerDN", "identity.clientCert.serialNumber":"$context.identity.clientCert.serialNumber", "identity.clientCert.validity.notBefore":"$context.identity.clientCert.validity.notBefore", "identity.clientCert.validity.notAfter":"$context.identity.clientCert.validity.notAfter", "identity.userAgent":"$context.identity.userAgent", "path":"$context.path", "protocol":"$context.protocol", "requestId":"$context.requestId", "requestTime":"$context.requestTime", "requestTimeEpoch":"$context.requestTimeEpoch", "resourceId":"$context.resourceId", "resourcePath":"$context.resourcePath", "stage":"$context.stage", "responseLatency":"$context.responseLatency", "responseLength":"$context.responseLength", "status":"$context.status" }
- CloudWatch の REST API の実行ログを表示して、エラーの原因を特定します。相互 TLS に関連する 403 禁止エラーがログに記録されると、次のようなエラーメッセージが表示されます。
Extended Request Id: {extendedRequestId} Access denied. Reason: {reason} ForbiddenException Forbidden: {requestId}
「アクセスが拒否されました。理由: Could not find issuer for certificate」エラー
API リクエストのクライアント証明書の発行者がカスタムドメイン名のトラストストアに含まれていることを確認します。
API リクエストのクライアント証明書 (client.pem) の発行者は、カスタムドメイン名のトラストストアに含まれている必要があります。発行者はまた、Amazon Simple Storage Service (Amazon S3) の証明書バンドル (bundle.pem) の一部として含まれている必要があります。
クライアント証明書の発行者が必要なトラストストアに含まれているかどうかを確認するには、次の OpenSSL コマンドを実行します。
$ openssl verify -CAfile bundle.pem client.pem
-または、-
証明書バンドルに中間認証局が含まれている場合は、次の OpenSSL コマンドを実行します。
$ openssl verify -CAfile rootCA.pem -untrusted intCA.pem client.pem
API リクエスト内のクライアント証明書の発行者が必要なトラストストアに含まれている場合、コマンドは OK 応答を返します。
クライアント証明書の発行者が必要なトラストストアに含まれていない場合、コマンドは次のエラーを返します。「error X at Y depth lookup: unable to get local issuer certificate」
カスタムドメイン名のトラストストアにあるすべてのクライアント証明書が有効であることを確認します
カスタムドメイン名のトラストストアにあるクライアント証明書のいずれかが有効でない場合、一部のクライアントが API にアクセスできない可能性があります。トラストストア内のクライアント証明書が有効であることを確認するには、次の操作を行います。
-
API Gateway コンソールを開きます。
-
左側のナビゲーションペインで、[カスタムドメイン名] を選択します。次に、相互 TLS を必要とするカスタムドメイン名を選択します。
-
「詳細」セクションで、次のエラーメッセージを確認します。 There is an invalid certificate in your truststore bundle.
-
エラーメッセージが表示されたら、トラストストア内の証明書をデコードして、どの証明書が警告を生成したかを特定します。
**注:**次の OpenSSL コマンドは、証明書の件名と内容を表示します。$ openssl x509 -in certificate.crt -text -noout
-
警告を生成した証明書を更新または削除します。次に、新しいトラストストアを Amazon S3 にアップロードします。
詳細については、「証明書警告のトラブルシューティング」を参照してください。
**注:**証明書チェーンが保存されている場合、API Gateway はルート認証局またはその他の中間認証局によって直接署名されたクライアント証明書を受け入れます。最後の中間認証局のみが署名したクライアント証明書を検証するには、リクエストパラメータベースの AWS Lambda オーソライザーを使用します。カスタム検証アルゴリズムは Lambda 関数レベルで使用できます。これを行うには、API リクエストからの入力としてクライアント証明書を受け入れます。
「アクセスが拒否されました。理由: クライアント証明書は安全でない署名アルゴリズムを使用しています」エラー
トラストストアのテキストファイルが、サポートされているハッシュアルゴリズムを使用していることを確認します。API Gateway は、トラストストアで以下のハッシュアルゴリズムをサポートしています。
- SHA-256 またはそれ以上
- RSA-2048 またはそれ以上
- ECDSA-256 またはそれ以上
トラストストアのテキストファイルがサポートされているハッシュアルゴリズムを使用していることを確認するには、次の OpenSSL コマンドを実行します。
$ openssl x509 -in client.crt -text -noout | grep 'Signature Algorithm'
コマンド応答は、トラストストアの署名アルゴリズムを返します。
詳細については、「トラストストアの設定」を参照してください。
「アクセスが拒否されました。理由:自己署名証明書」エラー
API リクエストの自己署名クライアント証明書が変更または破損していないことを確認します。クライアント証明書署名リクエスト (my_client.csr)、クライアント証明書のプライベートキー (my_client.key)、およびクライアント証明書のパブリックキー (my_client.pem) は一致する必要があります。
モジュールを比較するには、次の OpenSSL コマンドを実行します。
$ openssl rsa -noout -modulus -in my_client.csr $ openssl x509 -noout -modulus -in my_client.key $ openssl x509 -noout -modulus -in my_client.pem
**注:**比較しやすいように短いハッシュ値を生成するには、出力モジュールにパイプを使用します。次の openssl sha1 の例を参照してください。
$ openssl [operation] -noout -modulus -in [data] | openssl sha1
有効な出力例は次のようになります。
2143831a73a8bb28467860df18550c696c03fbcb2143831a73a8bb28467860df18550c696c03fbcb 2143831a73a8bb28467860df18550c696c03fbcb
データの整合性を確認するには、コンテンツレベルでデータが変更されていないことを確認します。次の diff コマンドを実行します。
$ diff client.crt bundle.crt
詳細については、「トラストストアの設定」を参照してください。
関連するコンテンツ
- 質問済み 3ヶ月前lg...
- AWS公式更新しました 2年前
- AWS公式更新しました 2年前