상호 TLS가 필요한 API Gateway 사용자 지정 도메인 이름에서 HTTP 403 Frobidden 오류를 해결하려면 어떻게 해야 하나요?

5분 분량
0

상호 전송 계층 보안(TLS) 인증이 활성화된 Amazon API Gateway 사용자 지정 도메인 이름이 HTTP 403 Forbidden 오류를 반환합니다. 왜 이런 일이 발생하는지 모르습니다.

간략한 설명

참고: API Gateway는 다양한 이유로 403 Forbidden 오류를 반환합니다. 이 문서에서는 상호 TLS에만 관련된 403 Forbidden 오류를 다룹니다. 다른 유형의 403 Forbidden 오류의 문제 해결에 대한 자세한 내용을 보려면 API Gateway에서 발생하는 HTTP 403 오류 문제를 해결하려면 어떻게 해야 하나요?를 참조하세요.

상호 TLS가 필요한 사용자 지정 도메인 이름을 사용하여 API Gateway API를 호출하려면 클라이언트가 API 요청에서 신뢰할 수 있는 인증서를 제시해야 합니다. 클라이언트가 API를 호출하면 API Gateway는 truststore에서 클라이언트 인증서 발급자를 찾습니다.
다음과 같은 경우 API Gateway가 TLS 연결에 실패하고 403 상태 코드를 반환합니다.

  • API Gateway는 truststore에서 클라이언트 인증서 발급자를 찾을 수 없습니다.
  • 클라이언트 인증서는 안전하지 않은 서명 알고리즘을 사용합니다.
  • 클라이언트 인증서는 자체 서명됩니다.

API에 대해 Amazon CloudWatch 로깅이 활성화되면 오류의 원인을 나타내는 오류 메시지가 실행 로그에 표시됩니다.

중요: 로깅이 활성화된 후 API 요청에서 CloudWatch 로그가 생성되지 않는 경우 403 Forbidden 오류는 상호 TLS와 관련이 없는 것입니다.

REST API의 경우

REST API에 대한 Amazon CloudWatch 로깅을 설정한 경우 실행 로그에도 다음 오류 메시지 중 하나가 표시됩니다.

  • 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

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 로깅을 활성화하세요.
  2. 실행 및 액세스 로깅을 구성합니다.
    참고: 이 사용 사례에 대한 액세스 로깅을 구성할 때는 다음과 같은 $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" }
    이러한 변수는 상호 TLS가 필요한 사용자 지정 도메인 이름이 403 오류를 반환할 때 API Gateway에 CloudWatch 로그를 생성하도록 지시합니다. 또한 API 작업을 호출하려고 시도한 호출자를 더 쉽게 식별할 수 있습니다.
  3. CloudWatch에서 REST API의 실행 로그를 확인하여 오류의 원인을 식별하세요. 상호 TLS와 관련된 403 Forbidden 오류가 기록되면 다음과 비슷한 오류 메시지가 나타납니다.
    Extended Request Id: {extendedRequestId} Access denied. Reason: {reason}
    ForbiddenException Forbidden: {requestId}

"Access denied. Reason: Could not find issuer for certificate" 오류 해결

API 요청의 클라이언트 인증서 발급자가 사용자 지정 도메인 이름의 truststore에 포함되어 있는지 확인합니다

API 요청의 클라이언트 인증서 발급자(client.pem)는 사용자 지정 도메인 이름의 truststore에 포함되어야 합니다. 또한 발급자는 Amazon Simple Storage Service(Amazon S3)의 인증서 번들 (bundle.pem)의 일부로 포함되어야 합니다.
클라이언트 인증서 발급자가 필수 truststore에 포함되어 있는지 확인하려면 다음 OpenSSL 명령을 실행합니다.

$ openssl verify -CAfile bundle.pem client.pem

-또는-

인증서 번들에 중간 인증 기관이 포함된 경우 다음 OpenSSL 명령을 실행합니다.

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

API 요청의 클라이언트 인증서 발급자가 필수 truststore에 포함된 경우 명령은 OK 응답을 반환합니다.

클라이언트 인증서 발급자가 필수 truststore에 포함되어 있지 않은 경우 명령은 “error X at Y depth lookup: unable to get local issuer certificate” 라는 오류를 반환합니다.

사용자 지정 도메인 이름의 truststore에 있는 모든 클라이언트 인증서가 유효한지 확인합니다

사용자 지정 도메인 이름의 truststore에 있는 클라이언트 인증서 중 하나가 유효하지 않은 경우 일부 클라이언트는 API에 액세스하지 못할 수 있습니다. 트러스트 스토어의 클라이언트 인증서가 유효한지 확인하려면 다음과 같이 하세요.

  1. API Gateway 콘솔을 엽니다.

  2. 왼쪽 탐색 창에서 사용자 지정 도메인 이름을 선택합니다. 그런 다음 상호 TLS가 필요한 사용자 지정 도메인 이름을 선택합니다.

  3. 세부 정보 섹션에서 다음 오류 메시지를 확인합니다. truststore 번들에 잘못된 인증서가 있습니다.

  4. 오류 메시지가 표시되면 truststore에서 인증서를 디코딩하여 경고를 생성한 인증서를 식별하세요.
    참고: 다음 OpenSSL 명령은 인증서의 제목과 내용을 표시합니다.

    $ openssl x509 -in certificate.crt -text -noout
  5. 경고를 생성한 인증서를 업데이트하거나 제거합니다. 그런 다음 Amazon S3에 새 truststore를 업로드합니다.

자세한 내용을 보려면 인증서 경고 문제 해결을 참조하세요.

참고: 인증서 체인이 보존된 경우 API Gateway는 루트 인증 기관 또는 기타 중간 인증 기관에서 직접 서명한 클라이언트 인증서를 수락합니다. 마지막 중간 인증 기관에서만 서명한 클라이언트 인증서를 검증하려면 요청 파라미터 기반 AWS Lambda authorizer를 사용하세요. Lambda 함수 수준에서 사용자 지정 검증 알고리즘을 사용할 수 있습니다. 이렇게 하려면 API 요청의 입력으로 클라이언트 인증서를 수락해야 합니다.

"Access denied. Reason: Client cert using an insecure Signature Algorithm" 오류

truststore 텍스트 파일이 지원되는 해싱 알고리즘을 사용하는지 확인하세요. API Gateway는 truststore에서 다음과 같은 해싱 알고리즘을 지원합니다.

  • SHA-256 이상
  • RSA-2048 이상
  • ECDSA-256 이상

truststore 텍스트 파일이 지원되는 해싱 알고리즘을 사용하는지 확인하려면 다음 OpenSSL 명령을 실행합니다.

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

명령 응답은 truststore의 서명 알고리즘을 반환합니다.

자세한 내용을 보려면 truststore 구성을 참조하세요.

"Access denied. Reason: self signed certificate" 오류 해결

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

자세한 내용을 보려면 truststore 구성을 참조하세요.