相互 TLS を必要とする API Gateway カスタムドメイン名からの HTTP 403 Forbidden エラーをトラブルシューティングする方法を教えてください。

所要時間3分
0

相互 Transport Layer Security (TLS) 認証が有効になっている Amazon API Gateway カスタムドメイン名は、HTTP 403 Forbidden エラーを返します。なぜこれが起こっているのかわかりません。

簡単な説明

注: API Gateway は、さまざまな理由から 403 Forbidden エラーを返すことがあります。この記事では、相互 TLS のみに関連する 403 Forbidden エラーについて説明します。他のタイプの 403 Forbidden エラーのトラブルシューティングについては、「API Gateway からの HTTP 403 Forbidden エラーをトラブルシューティングするにはどうすればよいですか?」を参照してください。

相互 TLS を必要とするカスタムドメイン名を使用して API Gateway API を呼び出すには、クライアントが API リクエストで信頼できる証明書を提示する必要があります。クライアントが API を呼び出そうとすると、API Gateway はトラストストアでクライアント証明書の発行者を探します。

次の状況により、API Gateway は TLS 接続に失敗し、403 ステータスコードを返します。

  • API Gateway は、トラストストアでクライアント証明書の発行者を見つけることができません。
  • クライアント証明書は安全でない署名アルゴリズムを使用しています。
  • クライアント証明書は自己署名されています。

API で Amazon CloudWatch のロギングが有効化されている場合、エラーの原因を示すエラーメッセージが実行ログに表示されます。

重要: ロギングがアクティブ化された後に API リクエストで CloudWatch Logs が生成されない場合、403 Forbidden エラーは相互 TLS とは関係ありません。

REST API の場合

REST API 用に Amazon CloudWatch のロギングを設定すると、次のいずれかのエラーメッセージが実行ログにも表示されます。

  • アクセスが拒否されました。理由: 証明書の発行者が見つかりませんでした
  • アクセスが拒否されました。理由: クライアント証明書が安全でない署名アルゴリズムを使用
  • アクセスが拒否されました。理由: 自己署名証明書

HTTP API オペレーション用

HTTP API は実行ログをサポートしていません。相互 TLS を必要とし、HTTP API を呼び出すカスタムドメイン名から返される 403 Forbidden エラーをトラブルシューティングするには、次の手順を実行する必要があります。

1.    テスト用に REST API を呼び出すカスタムドメイン名の新しい API マッピングを作成します。
注: テストに使用できる REST API がない場合は、PetStore REST API の例を使用してください。次に、API の例を新しいステージにデプロイして、カスタムドメイン名を使用する新しい API マッピングを作成します。

2.    REST API に作成した新しい API マッピングを使用して、この記事の [解決] セクションの手順に従います。

3.    エラーを特定して解決したら、カスタムドメイン名の API マッピングを HTTP API に再ルーティングします。

解決方法

エラーの原因を確認する

1.   REST API の CloudWatch ロギングを有効にします。次に、実行ログとアクセスログを設定します。

このユースケースでアクセスログを設定する場合は、以下の $context 変数を使用することがベストプラクティスです。これらの変数は 2 つのことを行います。

  • 相互 TLS を必要とするカスタムドメイン名が 403 Forbidden エラーを返したときに CloudWatch Logs を生成するように API Gateway に指示します。
  • CloudWatch Logs を確認するときに、API オペレーションを呼び出そうとした呼び出し元を簡単に特定することができます。

API Gateway が実行ログとアクセスログを生成できるようにする CloudWatch のアクセスロギングに推奨される $context 変数

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

2.    CloudWatch で REST API の実行ログを表示し、403 Forbidden エラーの原因を特定します。相互 TLS に関連する 403 Forbidden エラーがログに記録されると、次のようなエラーメッセージを受信します。

相互 TLS を必要とするカスタムドメイン名が 403 Forbidden エラーを返す場合の CloudWatch Logs エラーメッセージの例

Extended Request Id: {extendedRequestId} 
Access denied. Reason: {reason} 
ForbiddenException Forbidden: {requestId}

「アクセスが拒否されました。理由: 証明書の発行者が見つかりませんでした」というエラーを解決するには

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 のレスポンスを返します。

クライアント証明書の発行者が必要なトラストストアに含まれていない場合には、コマンドは次のエラーを返します。「深さ Y のルックアップでエラー X: ローカル発行者証明書を取得できません」

カスタムドメイン名のトラストストアにあるすべてのクライアント証明書が有効であることを確認する

カスタムドメイン名のトラストストアにあるクライアント証明書の 1 つが有効でない場合、一部のクライアントが API にアクセスできないことがあります。

トラストストア内のすべてのクライアント証明書が有効かどうかを確認するには、次の手順を実行します。

1.    API Gateway Console にログインします。

2.    左側のナビゲーションペインで、[カスタムドメイン名] を選択します。次に、相互 TLS を必要とするカスタムドメイン名を選択します。

3.    [詳細] セクションで、「トラストストアバンドルに無効な証明書があります」というエラーメッセージが表示されていることを確認します。

4.    このエラーメッセージが表示された場合は、トラストストア内の証明書をデコードして、警告を生成した証明書を特定する必要があります。
注: 次の OpenSSL コマンドは、サブジェクトを含む証明書の内容を表示します。

$ openssl x509 -in certificate.crt -text -noout

5.    警告を生成した証明書を更新または削除します。次に、新しいトラストストアを Amazon S3 にアップロードします。

詳細については、「証明書の警告のトラブルシューティング」を参照してください。

注: 証明書チェーンが保持されている場合、API Gateway は、ルート認証局またはその他の中間認証局によって直接署名されたクライアント証明書を受け入れます。最後の中間認証局によってのみ署名されたクライアント証明書を検証するには、リクエストパラメータベースの AWS Lambda オーソライザーを使用しますAPI リクエストからの入力としてクライアント証明書を受け入れることで、Lambda 関数レベルでカスタム検証アルゴリズムを使用できます。

「アクセスが拒否されました。理由: 安全でない署名アルゴリズムを使用したクライアント証明書」というエラーを解決するには

トラストストアのテキストファイルが、サポートされているハッシュアルゴリズムを使用していることを確認する

API Gateway は、トラストストアで次のハッシュアルゴリズムをサポートしています。

  • SHA-256 またはより強力
  • RSA-2048 またはより強力
  • ECDSA-256 またはより強力

トラストストアテキストファイルが、サポートされているハッシュアルゴリズムを使用しているかどうかを確認するには、次の OpenSSL コマンドを実行します。

$ openssl x509 -in client.crt -text -noout | grep 'Signature Algorithm'

コマンドのレスポンスによって、トラストストアの署名アルゴリズムが返されます。

詳細については、トラストストアの設定を参照してください。

「アクセスが拒否されました。理由: 自己署名証明書」というエラーを解決するには

API リクエストの自己署名クライアント証明書が変更または破損していないことを確認する

次の項目は正確に一致する必要があります。

  • S3 のトラストストア内の自己署名証明書 (bundle.crt または bundle.pem) の署名に使用されるプライベートキー (private.key) のモジュ―ル。
  • API リクエスト (client.crt) で渡されたクライアント証明書のモジュ―ル。

2 つのモジュールを比較するには、次の OpenSSL コマンドを実行します。

$ openssl rsa -noout -modulus -in private.key
$ openssl x509 -noout -modulus -in bundle.crt
$ openssl x509 -noout -modulus -in client.crt

注: 比較しやすいように短いハッシュ値を生成するには、出力モジュ―ルを暗号化ハッシュ関数に PIPE 処理します。次の openssl sha1 の例を参照してください。

$ openssl [operation] -noout -modulus -in [data] | openssl sha1

有効なコマンドの出力例

2143831a73a8bb28467860df18550c696c03fbcb
2143831a73a8bb28467860df18550c696c03fbcb
2143831a73a8bb28467860df18550c696c03fbcb

データの整合性を確認するには、次の diff コマンドを実行して、コンテンツレベルでデータが変更されていないことを確認します。

$ diff client.crt bundle.crt

詳細については、トラストストアの設定を参照してください。


コメントはありません

関連するコンテンツ