728x90
Boto3
에 이슈(urllib3
)가 있어서 직접AWS V4 Signiture
를 꾸역꾸역 구현Cloudflare R2
에 도메인을 붙여서 사용하고, 더불어 구현에서의 유연성을 위해 환경변수를 넣어서 설정
예제 코드
'''
%env r2_account_id = ...
%env r2_access_key_id = ...
%env r2_secret_access_key = ...
%env r2_bucket = ...
%env r2_domain = ...
!echo $r2_account_id $r2_access_key_id $r2_secret_access_key $r2_bucket $r2_domain
%%writefile sample.csv
col1, col2, col3
1, 2, 3
4, 5, 6
7, 8, 9
'''
import io
import os
import hashlib
import hmac
import datetime
import requests
from requests.auth import AuthBase
class AWSV4Auth(AuthBase):
@classmethod
def sign(cls, key, message):
return hmac.new(key, message.encode('utf-8'), hashlib.sha256).digest()
@classmethod
def get_signature_key(cls, secret_key, date_stamp, region, service):
k_date = cls.sign(('AWS4' + secret_key).encode('utf-8'), date_stamp)
k_region = cls.sign(k_date, region)
k_service = cls.sign(k_region, service)
k_signing = cls.sign(k_service, 'aws4_request')
return k_signing
def __init__(self, access_id, secret_key, region, service):
self.access_id = access_id
self.secret_key = secret_key
self.region = region
self.service = service
def __call__(self, r):
host = r.url.split('://')[1].split('/')[0]
payload_hash = hashlib.sha256(r.body or b'').hexdigest()
date_time = datetime.datetime.utcnow()
amz_date = date_time.strftime('%Y%m%dT%H%M%SZ')
date_stamp = date_time.strftime('%Y%m%d')
canonical_request = f"{r.method}\n{r.path_url}\n\nhost:{host}\nx-amz-content-sha256:{payload_hash}\nx-amz-date:{amz_date}\n\nhost;x-amz-content-sha256;x-amz-date\n{payload_hash}"
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = f"{date_stamp}/{self.region}/{self.service}/aws4_request"
string_to_sign = f"{algorithm}\n{amz_date}\n{credential_scope}\n{hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()}"
signing_key = self.get_signature_key(self.secret_key, date_stamp, self.region, self.service)
signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()
authorization_header = f"{algorithm} Credential={self.access_id}/{credential_scope}, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature={signature}"
r.headers['x-amz-content-sha256'] = payload_hash
r.headers['x-amz-date'] = amz_date
r.headers['Authorization'] = authorization_header
return r
class R2:
@classmethod
def put_file(cls, filename, obj):
aws_auth = AWSV4Auth(
access_id=os.getenv('r2_access_key_id'),
secret_key=os.getenv('r2_secret_access_key'),
region='auto', service='s3')
URL = 'https://{}.r2.cloudflarestorage.com/{}/{}'.format(
os.getenv('r2_account_id'), os.getenv('r2_bucket'), filename,
)
response = requests.put(URL, data=obj, auth=aws_auth)
return f'{os.getenv("r2_domain")}/{filename}'
filename = 'sample.csv'
with open(filename, 'rb') as f:
print(R2.put_file(filename, f.read()))
'Today_I_Learned' 카테고리의 다른 글
AWS API Gateway로 DynamoDB PutItem 메서드 구현 (23.10.13) (1) | 2023.10.14 |
---|---|
multiprocessing를 통한 병렬 처리 파이썬 코드 예제 (0) | 2023.09.30 |
네이버 증권 ETF 시세 정보 및 항목 리스트 API 조회 파이썬 코드 예제 (0) | 2023.09.30 |
장내채권 가격 데이터 조회 파이썬 코드 예제 (0) | 2023.09.29 |
TISTORY 블로그 작성 자동화 파이썬 코드 예제 (0) | 2023.09.29 |