Direkt zum Inhalt

Wie behebe ich HTTP 403 Forbidden-Fehler von einem benutzerdefinierten API Gateway-Domainnamen, für den gegenseitiges TLS erforderlich ist?

Lesedauer: 7 Minute
0

Mein benutzerdefinierter Amazon API Gateway-Domainname, für den eine gegenseitige Transport Layer Security (TLS)-Authentifizierung aktiviert ist, verursacht HTTP 403 Forbidden-Fehler. Ich weiß nicht, warum das passiert.

Kurzbeschreibung

Hinweis: API Gateway gibt aus verschiedenen Gründen 403 Forbidden-Fehler zurück. Dieser Artikel behandelt nur 403 Forbidden-Fehler im Zusammenhang mit gegenseitigem TLS. Informationen zur Behebung anderer Arten von 403 Forbidden-Fehlern findest du unter Wie behebe ich HTTP-403-Fehler von API Gateway?

Um eine API Gateway-API mit einem benutzerdefinierten Domainnamen aufzurufen, der gegenseitiges TLS erfordert, müssen Clients in der API-Anfrage ein vertrauenswürdiges Zertifikat vorlegen. Wenn ein Client die API aufruft, sucht API Gateway in deinem Truststore nach dem Aussteller des Client-Zertifikats.

Die folgenden Bedingungen führen dazu, dass API Gateway die TLS-Verbindung fehlschlagen lässt und einen 403-Statuscode zurückgibt:

  • API Gateway kann den Aussteller des Client-Zertifikats in deinem Truststore nicht finden.
  • Das Client-Zertifikat verwendet einen unsicheren Signaturalgorithmus.
  • Das Client-Zertifikat ist selbstsigniert.

Wenn die Amazon CloudWatch-Protokollierung für deine API aktiviert ist, erscheint in deinen Ausführungsprotokollen eine Fehlermeldung, die auf die Ursache des Fehlers hinweist.

Wichtig: Wenn die API-Anfrage nach der Aktivierung der Protokollierung keine CloudWatch Logs generiert, bezieht sich der 403 Forbidden-Fehler nicht auf gegenseitiges TLS.

Für REST-APIs

Wenn du die Amazon CloudWatch-Protokollierung für deine REST-API einrichtest, erscheint eine der folgenden Fehlermeldungen in deinen Ausführungsprotokollen:

  • Access denied. Reason: Could not find issuer for certificate
  • Access denied. Reason: Client cert using an insecure Signature Algorithm
  • Access denied. Reason: self signed certificate

Für HTTP-APIs

HTTP-APIs unterstützen keine Ausführungsprotokollierung. Gehe wie folgt vor, um 403 Forbidden-Fehler zu beheben, die von einem benutzerdefinierten Domainnamen zurückgegeben werden, der gegenseitiges TLS erfordert und eine HTTP-API aufruft:

  1. Erstelle eine neue API-Zuordnung für deinen benutzerdefinierten Domainnamen, die eine REST-API nur zu Testzwecken aufruft.
    Hinweis: Wenn du keine REST-API zum Testen hast, verwende die Beispiel-PetStore-REST-API. Stelle dann die Beispiel-API in einer neuen Phase bereit und erstelle eine neue API-Zuordnung, die deinen benutzerdefinierten Domainnamen verwendet.
  2. Folge den Anweisungen im Abschnitt Lösung dieses Artikels mit der neuen API-Zuordnung, die du für deine REST-API erstellt hast.
  3. Leite die API-Zuordnung für deinen benutzerdefinierten Domainnamen zurück zu deiner HTTP-API um.

Lösung

Bestätigen der Fehlerursache

  1. Aktiviere die CloudWatch-Protokollierung für deine REST-API.

  2. Konfiguriere die Ausführungs- und Zugriffsprotokollierung. Hinweis: Wenn du die Zugriffsprotokollierung für diesen Anwendungsfall konfigurierst, verwende die folgenden $context-Variablen:

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

    Diese Zugriffsprotokollvorlage protokolliert Client-Zertifikatsinformationen, wenn gegenseitiges TLS 403-Fehler verursacht. Sie erleichtert es auch, den Aufrufer zu identifizieren, der versucht hat, deine API aufzurufen.

  3. Sieh dir die Ausführungsprotokolle deiner REST-API in CloudWatch an, um die Ursache des Fehlers zu ermitteln. Wenn ein 403 Forbidden-Fehler im Zusammenhang mit gegenseitigem TLS protokolliert wird, erhältst du eine Fehlermeldung ähnlich der folgenden:

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

Beheben von Fehlern vom Typ „Access denied. Reason: Could not find issuer for certificate“

Stelle sicher, dass der Aussteller des Client-Zertifikats in der API-Anfrage im Truststore des benutzerdefinierten Domainnamens enthalten ist

Die vollständige Zertifikatskette des Client-Zertifikats (client.pem) in der API-Anfrage muss im Truststore deines benutzerdefinierten Domainnamens enthalten sein. Der Truststore (bundle.pem) ist eine Datei, die in Amazon Simple Storage Service (Amazon S3) gespeichert ist. Führe den folgenden OpenSSL-Befehl aus, um zu überprüfen, ob der Aussteller des Client-Zertifikats im erforderlichen Truststore enthalten ist:

openssl verify -CAfile bundle.pem client.pem

Wenn das Zertifikatspaket Zwischenzertifizierungsstellen enthält, führe den folgenden OpenSSL-Befehl aus:

openssl verify -CAfile rootCA.pem -untrusted intCA.pem client.pem

Wenn der Aussteller des Client-Zertifikats in der API-Anfrage im erforderlichen Truststore enthalten ist, gibt der Befehl die Antwort OK zurück.

Wenn der Aussteller des Client-Zertifikats nicht im erforderlichen Truststore enthalten ist, gibt der Befehl den folgenden Fehler zurück:

error X at Y depth lookup: unable to get local issuer certificate

Um diesen Fehler zu beheben, lade einen neuen Truststore auf Amazon S3 hoch, der die vollständige Zertifikatskette für das Client-Zertifikat enthält.

Stelle sicher, dass alle Client-Zertifikate im Truststore deines benutzerdefinierten Domainnamens gültig sind

Wenn eines der Client-Zertifikate im Truststore deines benutzerdefinierten Domainnamens nicht gültig ist, können einige Clients möglicherweise nicht auf deine API zugreifen. Gehe wie folgt vor, um zu bestätigen, dass die Client-Zertifikate in deinem Truststore gültig sind:

  1. Öffne die Amazon API Gateway-Konsole.

  2. Wähle im Navigationsbereich Benutzerdefinierte Domainnamen aus. Wähle dann deinen benutzerdefinierten Domainnamen aus, der gegenseitiges TLS erfordert.

  3. Überprüfe im Abschnitt Domaindetails auf eine Warnung wie: Your truststore bundle has 1 invalid certificates.

  4. Wenn du die Warnung siehst, dekodiere die Zertifikate in deinem Truststore, um festzustellen, welches Zertifikat die Warnung ausgelöst hat. Der folgende OpenSSL-Befehl zeigt den Betreff und den Inhalt eines Zertifikats an:

    openssl x509 -in certificate.crt -text -noout
  5. Aktualisiere oder entferne die Zertifikate, die die Warnung ausgelöst haben. Lade dann einen neuen Truststore in Amazon S3 hoch.

Weitere Informationen findest du unter Troubleshooting certificate warnings (Fehlerbehebung bei Zertifikatswarnungen).

Hinweis: Wenn ihre Zertifikatskette erhalten bleibt, akzeptiert API Gateway Client-Zertifikate, die direkt von der Stammzertifizierungsstelle oder einer anderen Zwischenzertifizierungsstelle signiert wurden.Um Client-Zertifikate zu validieren, die nur von der letzten Zwischenzertifizierungsstelle signiert wurden, verwende einen auf Anforderungsparametern basierenden AWS Lambda Authorizer. Du kannst einen benutzerdefinierten Validierungsalgorithmus im anforderungsbasierten Lambda Authorizer erstellen. Das Client-Zertifikat ist in der Eingabe aus der API-Anfrage unter requestContext.identity.clienCert zu finden.

Beheben von Fehlern vom Typ „Access denied. Reason: Client cert using an insecure Signature Algorithm“

Stelle sicher, dass deine Truststore-Textdatei einen unterstützten Hashing-Algorithmus verwendet. API Gateway unterstützt die folgenden Hashing-Algorithmen im Truststore:

  • SHA-256 oder stärker
  • RSA-2048 oder stärker
  • ECDSA-256 oder stärker

Um zu bestätigen, dass deine Truststore-Textdatei einen unterstützten Hashing-Algorithmus verwendet, führe den folgenden OpenSSL-Befehl aus:

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

Die Befehlsantwort gibt den Signaturalgorithmus deines Truststores zurück. Wenn der Algorithmus nicht unterstützt wird, aktualisiere dein Client-Zertifikat, um einen unterstützten Algorithmus zu verwenden. Lade dann einen neuen Truststore in Amazon S3 hoch.

Weitere Informationen findest du unter Configuring your truststore (Konfigurieren deines Truststores).

Beheben von Fehlern vom Typ „Access denied. Reason: self signed certificate“

Stelle sicher, dass das selbstsignierte Client-Zertifikat in der API-Anfrage nicht geändert oder beschädigt ist. Die Signaturanforderung für das Client-Zertifikat (my_client.csr), der private Schlüssel des Client-Zertifikats (my_client.key) und der öffentliche Schlüssel des Client-Zertifikats (my_client.pem) müssen übereinstimmen.

Führe die folgenden OpenSSL-Befehle aus, um die Module zu vergleichen:

openssl req -noout -modulus -in my_client.csr
openssl rsa -noout -modulus -in my_client.key
openssl x509 -noout -modulus -in my_client.pem

Hinweis: Um einen kürzeren Hashwert für einen einfacheren Vergleich zu erzeugen, verwende eine Pipe beim Ausgangsmodul. Sieh dir das folgende openssl sha1 Beispiel an:

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

Ein gültiges Ausgabebeispiel sieht ähnlich wie folgt aus:

2143831a73a8bb28467860df18550c696c03fbcb
2143831a73a8bb28467860df18550c696c03fbcb
2143831a73a8bb28467860df18550c696c03fbcb

Stelle zur Bestätigung der Datenintegrität sicher, dass keine Datenänderungen auf Inhaltsebene vorliegen. Führe den folgenden diff Befehl aus:

diff client.crt bundle.crt

Wenn die Module nicht übereinstimmen oder der Befehl diff Unterschiede zurückgibt, generiere das Client-Zertifikat neu und aktualisiere deinen Truststore. Lade dann einen neuen Truststore in Amazon S3 hoch.

Weitere Informationen findest du unter Configuring your truststore (Konfigurieren deines Truststores).

Weitere Informationen

How to turn on mutual TLS authentication for your REST APIs in API Gateway (Aktivieren der gegenseitigen TLS-Authentifizierung für deine REST-APIs in API Gateway)