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

6분 분량
0

상호 전송 계층 보안(TLS) 인증이 활성화된 내 Amazon API Gateway 사용자 지정 도메인 이름이 HTTP 403 Forbidden(HTTP 403 사용 권한 없음) 오류를 반환합니다. 이런 현상이 발생하는 이유가 무엇인가요?

간략한 설명

참고: 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 변수를 사용하는 것이 가장 좋습니다. 이러한 변수는 다음 두 가지 작업을 수행합니다.

  • 상호 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: unable to get local issuer certificate(Y 깊이 조회에서 X 오류: 로컬 발급자 인증서를 가져올 수 없습니다.)" 오류를 반환합니다.

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

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

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

1.    API Gateway 콘솔을 엽니다.

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

3.    Details(세부 정보) 섹션에서 There is an invalid certificate in your truststore bundle(트러스트 스토어 번들에 유효하지 않은 인증서가 있습니다.) 오류 메시지가 있는지 확인합니다.

4.    오류 메시지가 표시되면 신뢰 저장소의 인증서를 디코딩하여 경고를 생성한 인증서를 식별해야 합니다.
참고: 다음 OpenSSL 명령은 제목을 포함하는 인증서의 내용을 표시합니다.

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

5.    경고를 생성한 인증서를 업데이트 또는 제거합니다. 그런 다음 새 트러스트 스토어를 Amazon S3에 업로드합니다.

자세한 내용은 인증서 경고 문제 해결를 참조하세요.

참고: 인증서 체인이 보존된 경우 API Gateway는 루트 인증 기관 또는 다른 중간 인증 기관이 직접 서명한 클라이언트 인증서를 수락합니다. 마지막 중간 인증 기관에서만 서명한 클라이언트 인증서를 확인하려면 요청 파라미터 기반 AWS Lambda Authorizer를 사용합니다. 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)에서 전달된 클라이언트 인증서의 계수입니다.

두 계수를 비교하려면 다음 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

자세한 내용은 트러스트 스토어 구성을 참조하세요.


AWS 공식
AWS 공식업데이트됨 일 년 전