본문 바로가기

WebDev

s3 sigv4

s3 sigv4

나는 내가 만든 웹앱의 저장소로 S3를 쓰고 있다. 가용성 99.999999%라는 것도 있지만 무엇보다 용량 제한 없이 편하니까.
하지만 내가 쓰고 있는 Tokyo리전은 전송속도가 너무 안나온다. 1M짜리 이미지 다운로드에 1890ms는 기다려야 할 정도 (나만 그런건지도 모르겠지만) 


그래서 이참에 새로 나온 Seoul 리전을 쓰려고 했더니 얼씨구, 되는게 없다. 커넥션이 계속해서 거부당하는 것이었다.
403에러도 떳지만, 특히 400 Bad Request에러가 죽어라 뜬다. 400까지는 좋은데, 이게 왜 발생했는지에 대한 정보를 boto가 전혀 주지 않아서 정말 파악하기 힘들었다. 


열심히 조사해 본 결과, 2014년 이후로 생성된 s3 bucket들은 반드시 AWS Signature V4를 인증 메소드로 써야 한다는 것이었다.
그럼 대체 이 인증 메소드를 어떻게 지정하는가 하고 boto문서를 열심히 뒤져봤지만, 잘 찾아지지를 않았다.
계책으로, Signature V4를 자동으로 판단하고 처리하는 boto3라이브러리를 쓰려고 했더니, 또 인터페이스도 구리고, 감춰지거나1 사라진 기능[ ^사라진기능]때문에 내 서비스에 상당한 악영향을 초래해 쓸 수가 없었다. 


결국엔 또 Stackoverflow를 한참을 뒤진 후에야, 해결 방법을 알아냈다.
그 해결 방법을 여기에 적는다.

해결 방법

해결 방법 자체는 간단하다. 내가 작성한 코드는 다음과 같다:

import boto
from boto.s3.key import Key
from django.conf import settings

BUCKET = None


def init(bucket_name=None):
    global BUCKET
    bucketname = bucket_name or getattr(settings, 'S3_FILE_BUCKET_NAME')
    boto.config.add_section('s3')
    boto.config.set('s3', 'use-sigv4', 'true')
    conn = boto.s3.connect_to_region('ap-northeast-2', host='s3.ap-northeast-2.amazonaws.com')
    BUCKET = conn.get_bucket(bucketname)

주목해야 할 것은 boto.config부분과, boto.s3.connect_to_region부분이다. 굉장히 직관적이므로 따로 추가적인 설명은 필요 없을 것이라 생각한다.

부록

부록으로 내가 쓰고 있는 aws s3 유틸리티 스크립트를 적고 글을 마친다.

import boto
from boto.s3.key import Key
from django.conf import settings

BUCKET = None


def init(bucket_name=None):
    global BUCKET
    bucketname = bucket_name or getattr(settings, 'S3_FILE_BUCKET_NAME')
    boto.config.add_section('s3')
    boto.config.set('s3', 'use-sigv4', 'true')
    conn = boto.s3.connect_to_region('ap-northeast-2', host='s3.ap-northeast-2.amazonaws.com')
    BUCKET = conn.get_bucket(bucketname)


def s3_put(key_name, stream, size=None):
    key = Key(BUCKET)
    key.key = key_name
    key.set_contents_from_file(stream, size=size)


def s3_delete(key_name):
    Key(BUCKET, key_name).delete()


def s3_get(key_name, expire_sec=300):
    return Key(BUCKET, key_name).generate_url(expires_in=expire_sec)

  1. generate_url() temporary opened private url로 아주 잘 쓰고 있는 기능인데, boto3에서 이 기능을 쓰려면 로우레벨까지 내려가야만 한다. boto3가 원하는 코딩 스타일대로는 구현할 수 없다.
    [^사라진기능]: set_contents_from_file()이 아예 없어졌다! 따라서 InMemoryFile을 파일로 사용할 수 없고, 하드디스크에 일단 저장하고, s3에 업로드 해야만 한다.


'WebDev' 카테고리의 다른 글

javascript object copy  (0) 2016.03.08
javascript string formatter  (0) 2016.03.04
AWS  (0) 2016.03.02
letsencrypt  (0) 2016.02.29
Django Foreign Key  (0) 2016.02.25