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

최종 업데이트 날짜: 2021년 12월 8일

상호 전송 계층 보안(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.    아직 활성화하지 않은 경우, 먼저 태스크에 대해 CloudWatch 로깅을 켭니다. 실행 및 액세스 로깅을 구성해야 합니다.

참고: 이 사용 사례에 대한 액세스 로깅을 구성할 때는 다음 $context 변수를 사용하는 것이 가장 좋습니다. 이러한 변수는 다음 두 가지 작업을 수행합니다.

  • 상호 TLS가 필요한 사용자 지정 도메인 이름이 403 Forbidden 오류를 반환하면, API Gateway에 CloudWatch Logs를 생성하도록 지시합니다.
  • 이를 통해 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 응답을 반환합니다.

클라이언트 인증서 발급자가 필요한 신뢰 저장소에 포함되어 있지 않은 경우 명령은 다음 "error X at Y depth lookup: 로컬 발급자 인증서를 가져올 수 없습니다" 오류를 반환합니다.

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

사용자 지정 도메인 이름의 신뢰 저장소에 있는 클라이언트 인증서가 유효하지 않으면 일부 클라이언트가 API에 액세스하지 못할 수 있습니다.

신뢰 저장소의 모든 클라이언트 인증서가 유효한지 확인하려면 다음을 수행합니다.

1.    API Gateway 콘솔을 엽니다.

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 요청의 자체 서명된 클라이언트 인증서가 변경 또는 손상되지 않았는지 확인합니다

다음 항목이 정확히 일치해야 합니다.

  • 개인 키(private.key)의 계수로, S3의 신뢰 저장소 내부 자체 서명 인증서(bundle.crt 또는 bundle.pem)에 서명하기 위해 사용됩니다.
  • API 요청(client.crt)에서 전달된 클라이언트 인증서의 계수입니다.

두 계수를 비교하려면 다음 OpenSSL 명령을 실행합니다.

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

참고: 보다 쉽게 비교할 수 있도록 더 짧은 해시 값을 생성하려면 출력 모듈러스를 암호화 해시 함수로 PIPE-ing할 수 있습니다. 예시: openssl sha1.

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

유효한 명령 출력 예

2143831a73a8bb28467860df18550c696c03fbcb
2143831a73a8bb28467860df18550c696c03fbcb
2143831a73a8bb28467860df18550c696c03fbcb

데이터 무결성을 확인하려면 다음 diff 명령을 실행하여 콘텐츠 수준에서 데이터가 수정되지 않았는지 확인합니다.

$ diff client.crt bundle.crt

자세한 내용은 신뢰 저장소 구성을 참조하세요.


이 문서가 도움이 되었나요?


결제 또는 기술 지원이 필요하세요?