S3 버킷을 정적 호스팅용으로 사용하는 경우, 버킷을 퍼블릭으로 오픈 후, 퍼블릭하게 버킷으로 접근할 수 있도록 버킷 정책을 설정해주어야한다.
그리고 이러한 정적 호스팅 페이지를 오리진으로 하는 Cloudfront 배포를 생성해 사용하고는 한다.
이렇게 생성된 Cloudfront 배포 URL을 타고 정적 호스팅 버킷으로 접근하는 로직을 타는 것이다.
하지만, 이러한 설정에도 불구하고 여전히 정적 호스팅 버킷 URL을 통해서 직접 접근하는 것이 가능하다.
버킷 컨텐츠에 대한 직접 접근을 막기 위한 방법으로 Cloudfront의 OAI와 OAC가 존재한다.
OAI(Origin Access Identity)
Cloudfront를 통해서만 S3 오리진에 접근할 수 있도록 하는 설정
정확히는 Cloudfront가 S3 버킷에 접근할 수 있는 특수한 IAM Role을 제공하는 방식이다. 즉, Cloudfront가 버킷에 요청을 보낼 때 사용되는 가상의 사용자를 지정하는 개념이다.
그렇기에 OAI는 버킷 정책에 OAI 사용자를 명시적으로 선언해주어야한다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowLegacyOAIReadOnly",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <origin access identity ID>"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<S3 bucket name>/*"
}
]
}
OAC(Origin Access Control)
OAC는 한 마디로 차세대 OAI이라고 볼 수 있다. 현재 OAI는 Legacy로 OAC를 사용하도록 권고되고 있다.
OAC는 2022년 8월에 추가된 기능으로, 기존 OAI의 한계점을 보완한 형태의 기능을 제공한다.
Cloudfront 배포를 생성할 때, OAC를 생성하며 버킷정책에 OAI가 아닌 해당 cloudfront 배포에 대한 접근제어만 설정해주어 cloudfront만 버킷에 액세스할 수 있도록 허용한다.
더불어 OAC를 통해 버킷 오리진을 보호하는 경우, 기본적으로 Cloudfront - 버킷 간 통신은 HTTPS를 통해 이루어진다고 한다.
OAI vs OAC
OAI는 아래와 같은 한계점들이 존재한다.
- 버킷에 대한 PUT, POST, DELETE 등의 메소드를 사용하는 동적 요청 미지원
- AWS KMS를 사용하는 서버측 암호화(SSE-KMS) 미지원
OAC에서는 이러한 OAI에서의 제한사항을 해소하며 S3 오리진을 보호할 수 있다.
더불어, OAI는 2022년 이전의 리전만 사용할 수 있지만, OAC는 기존 리전과 이후 생성될 모든 리전에 대해 지원한다.
Cloudfront OAC 적용
S3 정적 호스팅 페이지를 오리진으로 하는 Cloudfront 배포를 생성하는 과정에서 OAC를 적용해보도록 한다.
먼저, S3 버킷에 정적 호스팅 페이지 설정과 퍼블릭 액세스를 차단하도록 한다.
다음으로 Cloudfront 배포를 생성한다.
오리진을 버킷으로 설정하면, 하단에 아래와 같은 버킷 오리진 설정을 볼 수 있다.
(버킷 오리진 설정 시, 웹사이트 엔드포인트를 사용하는 경우 OAI/OAC의 설정이 불가)
이후 OAC를 생성한다.
OAC 설정 중 '서명 동작'은 오리진 요청에 대해 서명 여부로 권장값을 유지한다.
OAC와 배포를 생성하면, 생성한 OAC를 배포에 연결하기 위해 해당 버킷의 정책을 수정해야한다.
앞서 생성해준 cloudfront 배포만이 버킷에 접근할 수 있도록 하는 정책을 설정하는 것이다.
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::[정적 사이트 버킷]/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "[생성한 Cloudfront 배포 ARN]"
}
}
}
]
}
이렇게 OAC와 버킷을 오리진으로 하는 cloudfront 배포를 생성한 뒤, 버킷의 object를 확인해본다.
버킷 URL로 직접 접근하면, 앞서 차단한 퍼블릭 액세스에 의해 403 Forbidden이 발생함을 볼 수 있다.
그리고 cloudfront 배포 URL을 통해 object에 접근하면, OAC를 바탕으로 object를 가져오는 것을 볼 수 있다.
버킷 보안과 제어
이러한 버킷 데이터에 직접적인 접근을 막아야하는 이유로는 버킷에 대한 보안과 제어를 위함이 있다.
Cloudfront의 캐싱된 버킷 데이터를 제공함을 통해, 사용자들은 오직 Cloudfront를 통해서만 버킷 컨텐츠에 접근할 수 있고, 외부에서 직접 접근할 수 없게 된다.
또한, 버킷 자체가 외부에 노출되지 않도록 방지하는 효과도 볼 수 있다.