S3의 객체 잠금에 대해 알아보기

AWS S3의 객체 잠금에 대해 간략하게 알아보는 글입니다
2023.06.09

안녕하세요 클래스메소드의 수재입니다.
이번에 맡은 작업에서 [S3에 업로드하는 파일 중에 같은 이름은 파일은 업로드되지 않도록 하고 싶다] 라는 요건이 있었습니다.
이런 기능을 AWS 기능으로 해결할 수 없을지 알아보던 중 S3 의 객체 잠금 기능이 있어 한번 알아보았습니다.

착각한 내용

착각했던 내용과 그에 대한 결론부터 공유하자면

  1. 객체 잠금의 덮어쓰기를 방지를 이용해서 같은 이름의 파일 업로드를 막을 수 있다
    • 공식 문서에서 말하는 [객체 잠금은 고정된 시간 동안 또는 무기한으로 객체의 삭제 또는 덮어쓰기를 방지] 는 버전 별로 적용하며, 덮어쓰기 방지는 버전 관리를 통해서 이루어진다. 업로드 자체를 막는 기능이 아니다
  2. 객체 잠금이 활성화 된 버킷에 파일을 업로드하기 위해서는 업로드하는 유저에게 버전 관리에 대한 권한이 있어야한다
    • 파일 업로드를 위한 최소 권한에 객체 잠금 관련 권한은 필요 없다

였습니다

객체 잠금이란?

S3 객체 잠금을 사용하면 write-once-read-many(WORM) 모델을 사용하여 객체를 저장할 수 있습니다. 객체 잠금은 고정된 시간 동안 또는 무기한으로 객체의 삭제 또는 덮어쓰기를 방지하는 데 도움이 될 수 있습니다. 객체 잠금을 사용하면 WORM 스토리지가 필요한 규제 요구 사항을 충족하거나 객체 변경 및 삭제에 대한 보호 계층을 추가하는 데 도움이 됩니다. - 공식 문서

S3에 업로드 된 객체에 WORK 모델을 적용하여 관리하는 기능입니다. 일정 기간 혹은 무기한으로 객체의 삭제나 덮어쓰기를 방지할 수 있습니다.
여기서 기한과 무기한을 나누는 것이

  • 보존 기간(Retention period) : 객체 잠금의 고정 기간 설정
  • 법적 보존(Legal hold) : 만료 날짜가 없는 객체 잠금 입니다.

객체 잠금을 설정하려면 버킷을 처음 생성할 때 부터 옵션을 활성화 하여야합니다.

만약 이미 작성한 버킷의 객체 잠금을 활성화할 필요가 있다면 AWS 서포트에 문의할 필요가 있습니다.

객체 잠금에 대해 좀 더 자세히 알아보기

보존 모드(Retention modes)

S3의 객체 잠금은 2가지 보존 모드를 제공합니다.

  • 거버넌스 모드(Governance mode)
  • 규정 준수 모드(Compliance mode)

거버넌스 모드에서 특별한 권한이 없는 한 사용자는 객체 버전을 덮어쓰거나 삭제하거나 잠금 설정을 변경할 수 없습니다. - 공식 문서

덮어쓸 수 없다는 것은 객체 자체에 덮어쓸 수 없다는 것이 아니라 특정 권한이 없다면 객체의 각 버전의 메타 데이터를 수정할 수 없다는 뜻입니다.
같은 파일명(키 이름)의 객체를 업로드 막는다는 뜻이 아닙니다.
만약 객체 삭제나 기한 변경이 필요하다면 s3:BypassGovernanceRetention 권한과 삭제를 위한 다른 권한이 필요합니다.

# 삭제를 위한 정책 예
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "{sid name}",
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:ListBucketVersions",
                "s3:ListBucket",
                "s3:GetBucketObjectLockConfiguration",
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:PutObject",
                "s3:DeleteObjectVersion",
                "s3:DeleteObject",
                "s3:BypassGovernanceRetention"
            ],
            "Resource": "{target source}"
        }
    ]
}

모드를 재정의해야 하는 요청과 함께 요청 헤더로 x-amz-bypass-governance-retention:true를 명시적으로 포함해야 합니다.
콘솔에서 조작할 때에는 헤더가 자동으로 포함되어 있지만 CLI(s3api)로 이러한 조작을 하는 경우엔 --bypass-governance-retention 옵션을 추가합니다(참고)

규정 준수 모드(Compliance mode)에서는 객체나 버킷에 대한 권한이 있더라도 처음에 정한 기간 동안에 수정이나 삭제 등을 할 수 없습니다.
따라서 개발 환경에서 거버넌스 모드로 검증을 끝낸 후 운용 환경에서는 규정 준수 모드로 운용하는 것을 추천합니다.

보존 기간에 대해

기본적으로 처음 버킷을 생성하고 설정할 때 보존 기간을 정할 수 있습니다.
콘솔에서 파일을 업로드할 때는 기간 변경이 불가능하지만 그 외의 방법으로 업로드할 때는 객체별로(정확히는 업로드되는 버전) 기간을 정할 수 있습니다.

예를 들어 보관 기간이 15~30일인 객체가 있고 보관 기간이 60일인 동일한 이름의 객체를 Amazon S3에 PUT한다고 가정합니다. 이 경우 PUT이 성공하면 Amazon S3에서는 보관 기간이 60일인 새 버전의 객체를 생성합니다. 이전 버전은 원래 보관 기간을 유지하고 15일 후에 삭제할 수 있게 됩니다.

보존 기간은 필요에 따라 수정할 수 있습니다.
물론 위에서 설명한 적절한 권한이 필요합니다.

법적 보존(Legal hold)

무기한으로 해당 객체의 잠금을 설정하는 옵션입니다.
이미 업로드 된 파일에 대해 법적 보존을 설정할 수 있습니다.

이렇게 설정한 객체는 보존 기간이 지나더라도 객체 잠금이 유지됩니다.

필요한 권한

객체 잠금에 관한 정책은 다음과 같으며 작업에 따라 필요한 권한이 다릅니다.

  • s3:BypassGovernanceRetention
    • 거버넌스 모드에서 파일의 수정을 위해 필요한 권한
  • s3:GetBucketObjectLockConfiguration
    • 버킷에 대한 객체 잠금 구성을 확인하기 위해 필요한 권한
    • CLI에서 파일을 조작한다면 없어도 되는 권한이지만 콘솔에서 파일을 조작하는 경우에는 이 권한이 필요합니다
  • s3:GetObjectLegalHold
    • 객체의 법적 보존 적용 여부를 확인하는데 필요한 권한
  • s3:GetObjectRetention
    • 객체의 보존 기간을 확인하는데 필요한 권한
  • s3:PutBucketObjectLockConfiguration
    • 버킷의 잠금 구성을 변경하기 위해 필요한 권한
  • s3:PutObjectLegalHold
    • 객체의 법적 보존 적용을 변경하는데 필요한 권한
  • s3:PutObjectRetention
    • 객체의 보존 기간을 변경하는데 필요한 권한
    • 객체의 업로드에 객체 별 기간 변경이 필요하지 않다면 이 권한이 없어도 업로드 할 수 있습니다

(부록) 그럼 문제 해결은 어떻게 했는가?

S3에는 객체의 키 이름에 따라 업로드를 막는 기능은 없습니다.
따라서 이번에는 다음과 같은 선택지가 있었습니다.

  • 파일을 업로드할 때 DynamoDB에 파일의 키 이름을 검색한 후, 해당 키 이름이 없다면 업로드. 해당 키 이름이 있다면 에러 발생하는 코드를 어플리케이션 레이어에서 구현
  • 업로드하는 객체의 키 이름에 중복이 발생하지 않도록 유니크한 문자열이나 타임 스탬프 등을 지정
  • 업로드는 버전 관리를 유효화하고, 파일을 다운로드 할 때는 단순히 키 이름이 아닌 객체의 버전을 제대로 구분해서 다운로드

어느 방법도 장단점이 있기 때문에 도입 전에 제대로 된 검토를 한 후 작업할 필요가 있었습니다.

마무리

S3의 객체 잠금에 대해 간략하게 알아보았습니다.
법적 보존을 운용 환경에 도입할 때는 거버넌스 모드에서 확실하게 검증을 한 후 사용하여야 하며 콘솔과 CLI에서 조작할 때 필요한 권한이 조금 달라진다는 점만 주의하면 사용하는데는 큰 문제가 없는 기능이라고 생각되었습니다.

긴 글 읽어주셔서 감사합니다!
오탈자나 내용 피드백은 must01940 지메일로 보내주시면 감사합니다!