CloudFront 배포의 오리진으로 S3 웹 사이트 엔드포인트를 사용하고 있습니다. HTTP 응답 코드 403(액세스 거부됨)이 수신되는 이유는 무엇입니까?

최종 업데이트 날짜: 2019년 5월 30일

Amazon CloudFront 배포의 오리진으로 Amazon Simple Storage Service(Amazon S3) 버킷을 사용하고 있습니다. 오리진의 도메인 이름으로는 S3 정적 웹 사이트 엔드포인트를 사용합니다. Amazon S3에서 CloudFront HTTP 응답 코드 403(액세스 거부됨)이 반환되는 이유는 무엇입니까?

간략한 설명

CloudFront 배포의 오리진으로 S3 버킷을 사용하려는 경우 오리진 도메인 이름으로 S3 정적 웹 사이트 엔드포인트 또는 S3 REST API 엔드포인트를 사용할 수 있습니다. HTTP 403(액세스 거부됨) 오류를 해결하려면 배포에서 사용 중인 엔드포인트 유형을 알아야 합니다.

다음 단계를 수행하여 엔드포인트 유형을 확인합니다.

  1. CloudFront 콘솔을 엽니다.
  2. CloudFront 배포를 선택한 후 [Distribution Settings]를 선택합니다.
  3. [Origins] 보기를 선택합니다.
  4. [Origin Domain Name and Path] 아래 도메인 이름을 검토하고 도메인 이름 형식에 기반하여 엔드포인트 유형을 확인합니다.

REST API 엔드포인트는 다음 형식을 사용합니다.

example-bucket.s3.amazonaws.com

정적 웹 사이트 엔드포인트는 다음 형식을 사용합니다. 

example-bucket.s3-website-us-east-1.amazonaws.com

배포에서 REST API를 사용하는 경우 S3 REST API 엔드포인트를 CloudFront 배포의 오리진으로 사용하고 있습니다. HTTP 응답 코드 403(액세스 거부됨)이 수신되는 이유는 무엇입니까?를 참조하십시오.

배포에서 정적 웹 사이트 엔드포인트를 사용하는 경우 HTTP 403(액세스 거부됨) 오류를 방지하기 위해 S3 구성이 다음 요구 사항을 충족하는지 확인합니다.

  • 버킷의 객체에는 퍼블릭 액세스가 가능해야 합니다.
  • 버킷의 객체는 AWS Key Management Service(AWS KMS)를 사용하여 암호화할 수 없습니다.
  • 버킷 정책에서 s3:GetObject에 대한 액세스를 허용해야 합니다.
  • 버킷을 소유한 AWS 계정이 객체도 소유해야 합니다.
  • 요청된 객체가 버킷에 존재해야 합니다.

해결 방법

버킷의 객체에 퍼블릭 액세스가 가능해야 함

S3 정적 웹 사이트 엔드포인트는 퍼블릭 액세스가 가능한 콘텐츠만 지원합니다. S3 버킷의 객체에 퍼블릭 액세스가 가능한지 확인하려면 웹 브라우저에서 S3 객체의 URL을 열거나 URL에서 curl 명령을 실행합니다.

다음은 S3 객체의 URL 예제입니다.

http://example-bucket.s3-website-us-east-1.amazonaws.com/index.html

웹 브라우저 또는 curl 명령에서 "액세스 거부됨" 오류를 반환하는 경우 해당 객체에 퍼블릭 액세스가 불가능한 것입니다.

다음 방법 중 하나로 객체에서 퍼블릭 액세스를 허용합니다.

버킷의 객체는 AWS KMS로 암호화할 수 없음

KMS로 암호화된 객체는 퍼블릭 액세스가 불가능합니다. S3 정적 웹 사이트 엔드포인트는 퍼블릭 액세스가 가능한 콘텐츠만 지원하므로 CloudFront에서는 KMS로 암호화된 객체를 지원할 수 없습니다.

다음 방법 중 하나로 버킷의 객체가 KMS로 암호화되었는지 확인합니다.

  • Amazon S3 콘솔을 사용하여 객체를 확인합니다. [속성] 보기를 선택합니다. [암호화] 대화 상자를 검토합니다. [AWS-KMS]가 선택된 경우 객체는 KSM로 암호화된 것입니다. 자세한 내용은 객체의 속성을 보려면?을 참조하십시오.
  • 다음 AWS CLI(명령줄 인터페이스) 명령을 실행하여 head-object 요청을 생성합니다. 명령에서 aws:kmsServerSideEncryption을 반환하는 경우 객체는 KMS로 암호화된 것입니다.

참고: 버킷 및 키 값을 S3 버킷 및 객체에 연결된 값으로 대치해야 합니다.

aws s3api head-object --bucket example-bucket --key kms-object.html

Amazon S3 콘솔을 사용하여 객체의 암호화 설정을 변경하려면 S3 객체에 암호화를 추가하려면 어떻게 해야 합니까?를 참조하십시오.

AWS CLI(명령줄 인터페이스)를 사용하여 객체의 암호화 설정을 변경하려면 먼저 객체의 버킷에 기본 암호화가 없는지 확인해야 합니다. 버킷에 기본 암호화가 없으면 다음 AWS CLI 명령을 실행하여 객체를 자체적으로 복사합니다. 객체를 자체적으로 복사한 후에는 객체의 암호화 설정이 없음으로 구성됩니다.

경고: 객체를 자체적으로 복사하면 storage-class 및 website-redirect-location에 대한 설정도 제거됩니다. 새 객체에서 이러한 설정을 유지하려면 copy 요청에서 storage-class 또는 website-redirect-location 값을 명시적으로 지정해야 합니다. 자세한 내용은 요청 헤더를 참조하십시오.

aws s3 cp s3://example-bucket/index.html s3://example-bucket/index.html

버킷 정책에서 s3:GetObject에 대한 액세스를 허용해야 함

S3 정적 웹 사이트 엔드포인트를 사용하려면 버킷 정책은 퍼블릭 사용자를 위해 s3:GetObject 작업에 적용되는 deny 문을 포함할 수 없습니다.

버킷 정책에서 s3:GetObject에 대한 명시적인 allow 문을 포함하더라도, allow 문과 충돌하는 명시적인 deny 문을 포함하지 않아야 합니다. 명시적인 deny 문은 항상 명시적인 allow 문보다 우선됩니다.

다음 단계를 수행하여 s3:GetObject에 대한 버킷 정책을 검토합니다.

1.    Amazon S3 콘솔에서 S3 버킷을 엽니다.

2.    [권한] 보기를 선택합니다.

3.    [버킷 정책]을 선택합니다.

4.    s3:GetObject 작업과 관련된 명령문이 있는지 버킷 정책을 검토합니다.

다음 예제 정책에는 s3:GetObject에 퍼블릭 액세스를 허용하는 명시적인 allow 문이 있습니다. 그러나 모든 사용자에게 S3 객체 액세스를 차단하는 s3:GetObject에 대한 명시적인 deny 문도 있습니다.

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "Allow-OAI-Access-To-Bucket",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EAF5XXXXXXXXX"
            },
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::example-bucket/*"
            ]
        },
        {
            "Sid": "Allow-Public-Access-To-Bucket",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::example-bucket/*"
            ]
        },
        {
            "Sid": "Access-to-specific-VPCE-only",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::example-bucket/*"
            ],
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpce": "vpce-1a2b3c4d"
                }
            }
        }
    ]
  }

s3:GetObject에 대한 액세스를 허용하도록 버킷 정책을 업데이트하는 방법에 대한 지침은 S3 버킷 정책을 추가하려면 어떻게 해야 합니까?를 참조하십시오.

참고: CloudFront는 HTTP 403(액세스 거부됨) 오류의 결과를 최대 5분 동안 캐시에 저장합니다. 버킷 정책에서 deny 문을 제거한 후에 캐시에서 객체를 제거하려면 배포에서 무효화를 실행해야 할 수도 있습니다.

버킷을 소유하는 AWS 계정이 객체도 소유해야 함

버킷 정책에서 객체에 대한 퍼블릭 액세스를 허용하려면 버킷을 소유한 AWS 계정이 객체도 소유해야 합니다. 버킷 또는 객체 소유권은 해당 버킷 또는 객체를 생성한 AWS Identity and Access Management(IAM) 사용자 또는 역할의 AWS 계정에 기반합니다.

다음 단계를 수행하여 버킷 및 객체의 소유자가 동일한지 확인합니다.

1.    다음 AWS CLI 명령을 실행하여 AWS 계정의 S3 정식 ID를 가져옵니다.

aws s3api list-buckets --query Owner.ID

2.    다음 명령을 실행하여 객체 소유자의 S3 정식 ID를 가져옵니다.

참고: 이 명령 예제에서는 단일 객체를 보여주지만, 여러 객체를 확인하기 위해 list 명령을 사용할 수도 있습니다.

aws s3api list-objects --bucket example-bucket --prefix index.html

3.    정식 ID가 일치하지 않으면 버킷 및 객체의 소유자는 서로 다릅니다.

참고: Amazon S3 콘솔을 사용하여 버킷 및 객체 소유자를 확인할 수도 있습니다. 소유자는 각 버킷 또는 객체의 [권한] 보기에서 확인할 수 있습니다.

다음 단계를 수행하여 객체의 소유자를 버킷 소유자로 변경합니다.

1.    객체 소유자의 AWS 계정에서 다음 명령을 실행하여 객체에 할당된 ACL(액세스 제어 목록) 권한을 검색합니다.

aws s3api get-object-acl --bucket bucket-name --key object-name

2.    객체에 bucket-owner-full-control ACL 권한이 있는 경우 3단계로 건너뜁니다. 객체에 bucket-owner-full-control ACL 권한이 없는 경우 객체 소유자의 AWS 계정에서 다음 명령을 실행하여 버킷 소유자 ACL 권한을 할당합니다.

aws s3api put-object-acl --bucket bucket-name --key object-name --acl bucket-owner-full-control

3.    다음 명령을 통해 객체를 자체적으로 복사하여 객체의 소유자를 변경합니다.

aws s3 cp s3://example-bucket/index.html s3://example-bucket/index.html

요청된 객체가 버킷에 존재해야 함

요청된 객체가 버킷에 없고 요청자에게 s3:ListBucket 액세스 권한이 없으면 요청자는 HTTP 404(찾을 수 없음) 오류 대신, HTTP 403(액세스 거부됨) 오류를 수신합니다.

HTTP 403 오류 때문에 HTTP 404 오류가 숨겨진 것인지 확인하려면 먼저 Amazon S3 콘솔에서 또는 head-object AWS CLI 명령을 실행하여 버킷을 열고 버킷에 객체가 존재하는지 확인합니다.

참고: S3 객체 이름에 대한 참조는 대소문자를 구분합니다. CloudFront로 전송된 객체 요청은 객체 이름과 정확히 일치해야 합니다. CloudFront가 Amazon S3에서 요청하는 객체를 식별하려면 서버 액세스 로깅을 사용합니다.

객체가 버킷에서 사용 가능하면 HTTP 403 오류는 HTTP 404 오류를 숨기지 않으며, HTTP 403 오류를 해결하기 위해 다른 S3 구성 요구 사항을 확인해야 합니다.

객체가 버킷에서 사용 불가능하면 HTTP 403 오류가 HTTP 404 오류를 숨긴 것이므로, 누락된 객체와 관련된 문제를 해결해야 합니다.

참고: 퍼블릭 s3:ListBucket 액세스는 활성화하지 않는 것이 좋습니다. 보안 모범 사례가 아니기 때문입니다.


이 문서가 도움이 되었습니까?

AWS에서 개선해야 할 부분이 있습니까?


도움이 필요하십니까?