CloudFront 배포의 오리진으로 S3 웹 사이트 엔드포인트를 사용하고 있습니다. 403 액세스 거부 오류가 발생하는 이유가 무엇인가요?

최종 업데이트 날짜: 2022년 10월 12일

Amazon CloudFront 배포의 오리진으로 Amazon Simple Storage Service(S3) 버킷을 사용하고 있습니다. 403 액세스 거부 오류를 해결하려면 어떻게 해야 합니까?

간략한 설명

액세스 거부 오류를 해결하려면 먼저 배포의 오리진 도메인 이름이 S3 웹 사이트 엔드포인트인지, 아니면 S3 REST API 엔드포인트인지 확인해야 합니다. 그런 다음 배포에서 웹 사이트 엔드포인트를 사용하는 경우 문제 해결 섹션을 검토합니다.

해결 방법

배포 오리진 도메인 이름의 엔드포인트 유형 결정

1.    CloudFront 콘솔을 여십시오.

2.    CloudFront 배포를 선택합니다. 그런 다음 배포 설정(Distribution Settings)을 선택합니다.

3.    [Origins and Origin Groups] 탭을 선택합니다.

4.    오리진 도메인 이름 및 경로(Origin Domain Name and Path) 아래에서 도메인 이름을 검토합니다. 도메인 이름의 형식에 따라 엔드포인트 유형을 결정합니다.

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

DOC-EXAMPLE-BUCKET.s3.amazonaws.com

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

DOC-EXAMPLE-BUCKET.s3-website-us-east-1.amazonaws.com

참고: AWS 리전에 따라 엔드포인트 형식은 대시 형식(s3-website-Region) 또는 도트 형식(s3-website.Region)을 사용할 수 있습니다. 배포에서 REST API를 사용하는 경우 S3 REST API 엔드포인트를 CloudFront 배포의 오리진으로 사용하고 있습니다. 403 액세스 거부 오류가 발생하는 이유는 무엇인가요?를 참조하세요.

배포에서 웹 사이트 엔드포인트를 사용하는 경우 액세스 거부 오류를 방지하기 위해 다음 섹션에서 요구 사항이 충족되는지 확인합니다.

버킷의 객체가 AWS Key Management Service(AWS KMS)에 의해 암호화되지 않았는지 확인

CloudFront 배포는 AWS KMS로 암호화된 객체를 지원하지 않습니다. 배포를 사용하여 제공하려는 S3 객체에서 AWS KMS 암호화를 제거해야 합니다. AWS KMS 암호화를 사용하는 대신 AES-256을 사용하여 객체를 암호화합니다.

객체가 AWS KMS로 암호화되어 있는지 확인

버킷의 객체가 KMS로 암호화되어 있는지 확인하려면 다음을 수행합니다.

Amazon S3 콘솔을 사용하여 객체의 속성을 확인합니다. 암호화(Encryption) 대화 상자를 검토합니다. AWS-KMS를 선택한 경우 객체는 AWS KMS로 암호화됩니다.

-또는-

AWS Command Line Interface(AWS CLI)를 사용하여 head-object 명령을 실행합니다. 명령에서 aws:kmsServerSideEncryption을 반환하는 경우 객체는 AWS KMS로 암호화된 것입니다.

참고: AWS CLI 명령을 실행할 때 오류가 발생하는 경우, 최신 버전의 AWS CLI를 사용하고 있는지 확인하세요.

객체의 암호화 설정 변경

Amazon S3 콘솔을 사용하여 객체의 암호화 설정을 변경하려면 AWS KMS(SSE-KMS)를 사용하여 서버 측 암호화 지정을 참조하세요.

AWS CLI를 사용하여 객체의 암호화 설정을 변경하려면 먼저 객체의 버킷에 기본 암호화가 없는지 확인합니다. 버킷에 기본 암호화가 없으면 다음 명령을 실행하여 객체를 자체적으로 복사함으로써 객체의 암호화를 제거합니다. DOC-EXAMPLE-BUCKET을 버킷의 이름으로 바꿉니다.

aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html

경고: 객체를 자체적으로 복사하면 storage-classwebsite-redirect-location에 대한 설정도 제거됩니다. 새 객체에서 이러한 설정을 유지하려면 복사 요청에서 이러한 값을 명시적으로 지정해야 합니다.

s3:GetObject 작업에 대한 버킷 정책에 명시적인 ‘거부’가 없는지 확인

버킷 정책에는 s3:GetObject 작업에 대한 퍼블릭 읽기 액세스를 차단하는 거부 문이 없어야 합니다.

버킷 정책에서 s3:GetObject에 대한 명시적 허용 문을 포함하는 경우, 명시적 거부 문과 충돌하지 않는지 확인합니다. 명시적 거부 문은 항상 명시적 허용 문을 재정의합니다.

s3:GetObject에 대한 버킷 정책을 검토하려면 다음을 수행합니다.

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

2.    [Permissions] 탭을 선택합니다.

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

4.    버킷 정책에서 “Action”: “s3:GetObject” 또는 “Action”: “s3:*”이 포함된 문을 검토합니다.

5.    버킷 정책을 수정하여 s3:GetObject에 대한 퍼블릭 읽기 액세스를 차단하는 문을 제거하거나 편집합니다.

예를 들어 다음 정책에는 s3:GetObject에 퍼블릭 액세스를 허용하는 명시적 허용 문이 있습니다. 하지만 특정 Amazon Virtual Private Cloud(Amazon VPC)에서 요청하지 않는 한 s3:GetObject에 대한 명시적 거부 문도 포함되어 있습니다. s3:GetObject 작업을 허용하려면 이 정책을 수정해야 합니다.

{
  "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:::DOC-EXAMPLE-BUCKET/*"
      ]
    },
    {
      "Sid": "Allow-Public-Access-To-Bucket",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": [
        "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
      ]
    },
    {
      "Sid": "Access-to-specific-VPCE-only",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": [
        "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
      ],
      "Condition": {
        "StringNotEquals": {
          "aws:sourceVpce": "vpce-1a2b3c4d"
        }
      }
    }
  ]
}

버킷 정책에서 퍼블릭 읽기 액세스 권한을 부여하는 경우 버킷을 소유한 AWS 계정도 객체를 소유하는지 확인

버킷 정책에서 객체에 대한 퍼블릭 읽기 액세스를 허용하려면 버킷을 소유한 AWS 계정이 객체도 소유해야 합니다. 기본 객체 소유권 설정이 있는 기존 Amazon S3 버킷의 경우 객체 소유자는 객체를 버킷에 업로드한 AWS Identity and Access Management(IAM) 자격 증명의 AWS 계정입니다.

참고: 객체 소유권 요구 사항은 버킷 정책에 의해 부여된 퍼블릭 읽기 액세스 권한에 적용됩니다. 객체의 ACL(액세스 제어 목록)에 의해 부여된 퍼블릭 읽기 액세스 권한에는 적용되지 않습니다.

버킷과 객체의 소유자가 같은지 확인

다음 단계를 사용하여 버킷 및 객체의 소유자가 동일한지 확인합니다. Amazon S3 콘솔을 사용하여 버킷과 객체의 소유자를 확인할 수도 있습니다. 소유자는 각 버킷 또는 객체의 권한(Permissions) 탭에서 확인할 수 있습니다.

1.    다음 AWS CLI 명령을 실행하여 버킷 소유자의 S3 정식 ID를 가져옵니다.

aws s3api list-buckets --query Owner.ID

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

aws s3api list-objects --bucket DOC-EXAMPLE-BUCKET --prefix index.html

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

3.    정식 ID가 일치하지 않는 경우 버킷과 객체의 소유자가 다릅니다.

객체 소유권 업데이트

버킷 소유자는 S3 객체 소유권을 사용하여 객체의 소유권을 관리할 수 있습니다. 모든 새 S3 버킷에는 기본적으로 버킷 소유자 적용 설정이 켜져 있습니다. 기존 버킷을 업데이트하려면 기존 버킷에 대한 객체 소유권 설정 단원을 참조하세요. 버킷 소유자 적용 설정이 활성화되면 버킷 소유자는 버킷 내 모든 객체의 객체 소유자가 됩니다. 또한 버킷 소유자 적용 설정이 켜져 있으면 버킷 및 해당 객체의 모든 ACL이 비활성화됩니다.

버킷 소유자가 모든 버킷에 대해 버킷 소유자 적용 설정을 사용하고 IAM 및 버킷 정책을 통해 권한을 관리하는 것이 가장 좋습니다.

버킷에 대해 ACL을 제거하고 버킷의 모든 객체에 대한 소유권을 가져오려면 다음 명령을 실행합니다.

aws s3api put-bucket-ownership-controls --bucket example-bucket --ownership-controls 'Rules=[{ObjectOwnership=BucketOwnerEnforced}]'

S3 버킷에서 ACL을 끄고 싶지 않은 경우 다음 단계에 따라 객체의 소유자를 버킷 소유자로 변경할 수도 있습니다.

1.    객체 소유자의 계정에서 다음 명령을 실행하여 객체에 할당된 ACL 권한을 검색합니다.

aws s3api get-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name

2.    객체에 bucket-owner-full-control ACL 권한이 있는 경우 3단계로 건너뜁니다. 객체에 bucket-owner-full-control ACL 권한이 없는 경우 객체 소유자의 계정에서 다음 명령을 실행합니다. DOC-EXAMPLE-BUCKET을 버킷의 이름으로 바꿉니다.

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

3.    버킷 소유자 계정에서 다음 명령을 실행하여 객체 자체에 객체를 복사함으로써 객체의 소유자를 변경합니다. DOC-EXAMPLE-BUCKET을 버킷의 이름으로 바꿉니다.

aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html

요청된 객체가 버킷에 존재하는지 확인

사용자에게 S3:ListBucket 권한이 없는 경우에는 사용자에게 404 찾을 수 없음 오류 대신 누락된 객체에 대한 액세스 거부 오류가 표시됩니다. head-object AWS CLI 명령을 실행하여 버킷에 객체가 존재하는지 확인합니다.

참고: CloudFront로 전송된 객체 요청이 S3 객체 이름과 정확히 일치하는지 확인합니다. S3 객체 이름은 대/소문자를 구분합니다. 요청의 객체 이름이 올바르지 않은 경우 Amazon S3은 객체가 없는 것처럼 응답합니다. CloudFront가 Amazon S3에 요청하는 객체를 확인하려면 서버 액세스 로깅을 사용합니다.

기본 루트 객체(default root object)와 관련된 오류가 발생하는 경우 객체 이름에 추가 문자가 없는지 확인하세요. 예를 들어, 기본 루트 객체(Default Root Object) 필드에 /index.html이 아닌 index.html을 입력해야 합니다. 자세한 내용은 기본 루트 객체 지정하는 방법을 참조하세요.

버킷에 객체가 있는 경우에는 액세스 거부 오류가 404 찾을 수 없음 오류를 마스킹하지 않습니다. 액세스 거부 오류를 해결하려면 다른 구성 요구 사항을 확인합니다.

객체가 버킷에 없는 경우에는 액세스 거부 오류가 404 찾을 수 없음 오류를 마스킹하고 있는 것입니다. 누락된 객체와 관련된 문제를 해결합니다.

참고: 퍼블릭 s3:ListBucket 액세스를 활성화하는 방법은 보안상 권장하지 않습니다. 퍼블릭 s3:ListBucket 액세스를 켜면 버킷의 모든 객체를 보고 나열할 수 있습니다. 이렇게 하면 객체 다운로드 권한이 없더라도 객체 메타데이터 세부 정보(예: 키 및 크기)가 사용자에게 노출됩니다.

버킷에 대해 Amazon S3 블록 퍼블릭 액세스가 해제되어 있는지 확인

버킷에 Amazon S3 퍼블릭 액세스 차단 설정이 적용되지 않았는지 확인합니다. 이러한 설정은 퍼블릭 읽기 액세스를 허용하는 권한을 재정의할 수 있습니다. Amazon S3 퍼블릭 액세스 차단 설정은 개별 버킷 또는 AWS 계정에 적용될 수 있습니다.

버킷의 객체에 공개적으로 액세스할 수 있는지 확인

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

예시:

http://DOC-EXAMPLE-BUCKET.s3-website-us-east-1.amazonaws.com/index.html

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

퍼블릭 읽기 액세스를 허용하려면 다음을 수행합니다.

버킷의 모든 객체에 대한 퍼블릭 읽기 액세스를 허용하는 버킷 정책을 생성합니다.

-또는-

Amazon S3 콘솔을 사용하여 객체에 대한 퍼블릭 읽기 액세스를 허용합니다.

요청자 지불이 켜진 경우 요청에 request-payer 파라미터가 포함되어 있는지 확인

버킷에 요청자 지불이 켜진 경우 버킷에 대한 익명 액세스가 허용되지 않습니다. 다른 계정의 사용자는 버킷에 요청을 보낼 때 request-payer 파라미터를 지정해야 합니다. 지정하지 않는 경우, 해당 사용자에게 액세스 거부 오류가 표시됩니다.

Referer 헤더를 사용하여 CloudFront에서 S3 오리진으로의 액세스를 제한하는 경우 사용자 지정 헤더를 검토합니다.

Referer 헤더를 사용하여 CloudFront에서 S3 웹 사이트 엔드포인트 오리진으로의 액세스를 제한하는 경우 S3 버킷 정책에 설정된 보안 암호 값 또는 토큰을 확인하십시오. 그런 다음 보안 암호 값 또는 토큰이 CloudFront 오리진 사용자 정의 헤더의 값과 일치하는지 확인합니다.

버킷 정책에서 명시적 거부 문을 사용하는 경우 Referer 헤더를 기반으로 액세스를 부여하는 허용 문도 있는지 확인합니다. 명시적 거부 문으로만 액세스 권한을 부여할 수 없습니다.

예를 들어, 다음 버킷 정책은 요청에 다음 문자열이 있는 경우 S3 오리진에 대한 액세스 권한을 부여합니다. "aws:Referer":"MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER"
CloudFront 오리진 사용자 지정 헤더는 다음과 같아야 합니다.

  • Header: Referer
  • Value: MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER
{
  "Version":"2012-10-17",
  "Id":"http referer policy example",
  "Statement":[
    {
      "Sid":"Allow get requests originating from my CloudFront with referer header",
      "Effect":"Allow",
      "Principal":"*",
      "Action":"s3:GetObject",
      "Resource":"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
      "Condition":{
        "StringLike":{"aws:Referer":"MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER"}
      }
    }
  ]
}

참고: 예시 버킷 정책은 보안 주체가 와일드카드 값("Principal":"*")이므로 버킷에 대한 퍼블릭(익명) 액세스 권한을 부여합니다. 그러나 조건문 때문에 요청에 Referer 헤더가 포함되어 있고 헤더 값이 버킷 정책의 값과 일치하는 경우에만 S3 오리진에 대한 액세스가 부여됩니다.

조직의 관리 계정에 연결된 명시적 “거부” 서비스 제어 정책(SCP)이 없는지 확인

서비스 제어 정책(SCP)은 조직의 권한을 관리하는 데 사용할 수 있는 조직 정책 유형입니다. AWS Organizations에서 조직의 관리 계정을 사용하여 조직 루트, 조직 단위(OU) 또는 AWS 계정에 직접 연결된 거부 정책(s3:GetObject 작업에 대한)이 있는지 확인합니다.