클라우드

S3 사전 서명 URL, 서명이 보증하지 않는 것

업로드 주소는 일회용 티켓이 아니에요. 사전 서명 URL의 권한과 수명, 재사용과 파일 검증을 따로 다뤄야 하는 이유를 알아봐요.

이 글의 목차서명은 누구의 권한을 담나4
  1. 서명은 누구의 권한을 담나
  2. 한 번만 쓰이는 것이 아니다
  3. 무엇을 올릴지는 통제되지 않는다
  4. 저는 무엇을 서버에 남겼나

기간이 적힌 초대장을 생각해 볼게요. 초대장이 있으면 문을 통과하지만, 그것이 보증하는 것은 딱 하나예요. 이 문을 이 기간 동안 지날 수 있다는 사실. 몇 번 지날 수 있는지, 들어가서 무엇을 하는지, 그 초대장을 누가 들고 왔는지는 별도의 이야기예요.

파일 업로드를 서버 대신 저장소로 직접 보제게 만드는 사전 서명 URL이 정확히 이 구조예요. 편의는 분명해요. 큰 파일이 서버를 거치지 않으니 서버가 대역폭과 메모리를 쓰지 않아요. 어려운 부분은 이 주소가 무엇을 보증하지 않는가를 아는 데 있어요.

서명은 누구의 권한을 담나

AWS 문서의 설명은 분명해요. 사전 서명 URL이 사용하는 자격 증명은 그 URL을 만든 주체의 것이에요. 받는 쪽은 AWS 자격 증명이 없어도 되고, 대신 만든 쪽의 권한을 그 범위만큼 빌려 써요.

여기서 첫 번째 함정이 나와요. 같은 문서는 임시 자격 증명으로 만든 주소는 그 자격 증명 자체보다 오래 유효할 수 없다고 적어요. 앞 글에서 다룬 대로 컨테이너에 붙인 역할은 임시 자격 증명을 써요. 그러면 만료 시간을 넉넉히 정해 두어도 실제로는 그 역할의 자격 증명이 만료되는 순간 함께 죽어요. 개발 환경에서 길게 잡아 두고 시험할 때는 멀쩡하다가, 배포하고 나서 짧게 끊기는 증상이 여기서 나와요.

URL에 적힌 시간보다 먼저 끝날 수 있어요

URL은 6시간, 발급 자격 증명은 2시간 뒤 만료하는 예시예요.

URL의 기한

6시간 뒤

자격 증명의 기한

2시간 뒤

임시 자격 증명으로 만든 사전 서명 URL은 URL 기한과 자격 증명의 기한 중 먼저 끝나는 쪽을 넘길 수 없어요.

가상의 기한이며 다른 정책 거부·자격 증명 취소는 없는 예시예요. 만료 전에 시작한 전송과 새 요청은 구별해요.

한 번만 쓰이는 것이 아니다

만료 전 URL 재사용에 따른 객체 교체 한 번 검증한 객체도 URL 만료 전에 같은 키로 다시 올라오면 내용이 바뀔 수 있다. 개념 도해 만료 전 URL 재사용에 따른 객체 교체 URL 사용 경로 ① URL 발급 객체 키 · 만료 시각 ② 첫 업로드 같은 객체 키 만료 전 ③ 같은 URL 재사용 같은 객체 키 ④ 만료 도달 URL 사용 종료 요청 거부 같은 키의 객체 상태 저장 내용 시간 첫 업로드 URL 재사용 URL 만료 객체 없음 첫 업로드 내용 재업로드 내용 · 현재 객체 덮어쓰기 객체 유지 한 번 검증한 객체도 URL 만료 전에 같은 키로 다시 올라오면 내용이 바뀔 수 있다. SOSHIN · DEV NOTES
한 번 쓰면 사라지는 것이 아니에요. 만료 전까지 몇 번이든 다시 쓸 수 있어요.

두 번째 함정이 더 자주 사고를 만들어요. 같은 문서가 명시하듯 사전 서명 URL은 만료 시각까지 여러 번 사용할 수 있어요. 일회용 티켓이라고 생각하고 설계하면 어긋나요. 주소가 로그나 브라우저 기록에 남았다가 나중에 다시 쓰일 수 있고, 사용자에게 전달한 주소가 그대로 다른 곳에 공유될 수도 있어요.

같은 키, 곧 같은 저장 위치로 다시 업로드하면 기존 객체를 대체할 수 있어요. 키를 예측하기 어렵게 만들어도 이미 주소를 받은 사람의 재사용은 막지 못해요. 검증한 파일을 이후에도 믿으려면 어떤 버전을 검사했는지 고정하거나 검증을 마친 파일을 별도 위치로 옮기는 식으로, 검증 뒤에 내용이 바뀌는 경로를 다뤄야 해요.

무엇을 올릴지는 통제되지 않는다

세 번째는 앞 시리즈의 이미지 편에서 이미 한 번 나온 이야기예요. 브라우저에서 줄인 파일을 올리게 만들어도 누군가는 그 화면을 거치지 않고 직접 보낼 수 있어요. 사전 서명 URL은 이 문제를 해결하지 않아요. 서명이 정하는 것은 어느 자리에 어떤 방식으로 요청할 수 있는가이지, 그 요청에 담기는 내용이 아니에요.

그래서 실무에서는 서명할 때 조건을 함께 거는 쪽으로 가요. 같은 문서에 사전 서명 URL의 능력을 제한하는 방법이 따로 정리돼 있어요. 다만 조건을 걸더라도 마지막 확인은 저장소가 아니라 내 쪽에 남아요. 올라온 뒤에 실제 내용을 확인하고, 통과한 것만 서비스에 노출하는 단계가 필요해요.

서명이 정하는 것자동으로 생기지 않는 것필요한 판단
허용한 저장 위치와 요청일회용 사용재사용과 덮어쓰기를 어떻게 다룰지
URL에 적힌 만료자격 증명보다 긴 수명실제로 유효한 종료 시각
서명에 포함한 요청 조건파일 내용의 안전성검증한 버전을 어떻게 고정할지

세 줄 모두 서명 바깥에서 해결해야 한다는 공통점이 있어요. 사전 서명 URL은 인증을 대신해 주는 물건이지 검증을 대신해 주는 물건이 아니에요.

저는 무엇을 서버에 남겼나

업로드를 직접 보제게 만들면 서버가 가벼워지는 대신 서버가 모르는 일이 늘어나요. 파일이 언제 올라왔는지, 실제로 올라오긴 했는지, 그 내용이 무엇인지를 서버가 자동으로 알지 못해요.

그래서 남겨 둔 것이 두 가지였어요. 하나는 주소를 발급한 기록이에요. 누구에게 어느 자리로 언제까지 유효한 주소를 줬는지를 남겨 두지 않으면, 나중에 이상한 파일이 올라왔을 때 추적할 실마리가 없어요. 다른 하나는 올라온 다음의 확인이에요. 저장소에 파일이 생겼다는 사실과 그 파일이 쓸 수 있는 것이라는 사실은 달라요.

돌아보면 이 기능을 이해하는 데 걸린 시간의 대부분은 무엇이 되는지가 아니라 무엇이 안 되는지를 파악하는 데 들었어요. 편의를 주는 도구일수록 그 경계가 어디까지인지 문서를 끝까지 읽어 볼 이유가 있었어요.

소신을 상징하는 까마귀 목판화 일러스트
작성자소신 · Soshin

웹과 서버를 만들고, 개발하며 배운 것들을 글로 남깁니다.

좌우로 움직여 보세요