👀
LocalStackでS3の署名付きURLが検証されなかったときに確認したこと
結論
ログを読もう
背景
S3の署名付きURLを使ったアップロードの検証を行うため、LocalStackを使用していた。
署名付きURLを発行してアップロードはできたが、なぜかURLに含まれるkeyを変更しても普通にアップロードされてしまう。
期待値としては、invalid的なエラーが返ってきてほしいのだが・・・
署名発行スクリプト
import boto3
from botocore.client import Config
# Configure your LocalStack endpoint
localstack_endpoint = 'http://localhost:4566'
aws_access_key_id = 'test'
aws_secret_access_key = 'test'
region_name = 'us-east-1' # LocalStack default region
# Create an S3 client
s3_client = boto3.client(
's3',
endpoint_url=localstack_endpoint,
aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key,
region_name=region_name,
config=Config(signature_version='s3v4')
)
# Generate a pre-signed URL for upload
bucket_name = 'sample-bucket'
object_key = 'YOUR_OBJECT_KEY' # e.g., 'example.jpg'
expires_in_seconds = 3600 # URL expiration time in seconds
url = s3_client.generate_presigned_url(
'put_object',
Params={'Bucket': bucket_name, 'Key': object_key},
ExpiresIn=expires_in_seconds,
)
print('Pre-signed URL for upload:', url)
バケットの作成
awslocal s3api create-bucket --bucket sample-bucket
{
"Location": "/sample-bucket"
}
URL発行
python presign.py
Pre-signed URL for upload: http://localhost:4566/sample-bucket/YOUR_OBJECT_KEY?X-Amz-Algorithm=AWS4-HMAC-SHA256&~...
アップロード
curl -X PUT --upload-file ~/Downloads/cat.png "http://localhost:4566/sample-bucket/YOUR_OBJECT_KEY?X-Amz-Algorithm=AWS4-HMAC-SHA256&~..."
awslocal s3 ls sample-bucket
2023-06-02 23:27:54 5813191 YOUR_OBJECT_KEY
これは期待通り
URLを改竄してアップロード
curl -X PUT --upload-file ~/Downloads/cat.png "http://localhost:4566/sample-bucket/YOUR_OBJECT_KEYeeeeeeee?X-Amz-Algorithm=AWS4-HMAC-SHA256&~..."
awslocal s3 ls sample-bucket
2023-06-02 23:28:11 5813191 YOUR_OBJECT_KEYeeeeeeee
何故か普通にアップロードされてしまった。これでは署名付きURLを使っている意味がない。
困ったときの公式ドキュメント
LocalStackって実は署名付きURLを検証してくれなかったり・・・?
サービスによってエミュレートレベル違うって聞いたことあるしなぁ
う〜ん、ちゃんと実装されてそうだけどなんとも言えない。
設定で変えられるとか?
ありました。如何にも怪しいS3_SKIP_SIGNATURE_VALIDATION
という値がデフォルトで有効化されているようです。
設定してみる
環境変数で設定できるようなので試してみます。
docker run \
--rm -it \
-p 4566:4566 \
-p 4510-4559:4510-4559 \
-e S3_SKIP_SIGNATURE_VALIDATION=0 \
localstack/localstack
再びURLを改竄してアップロード
curl -X PUT --upload-file ~/Downloads/cat.png "http://localhost:4566/sample-bucket/YOUR_OBJECT_KEYeeeeeeee?X-Amz-Algorithm=AWS4-HMAC-SHA256&~..."
awslocal s3 ls sample-bucket
<?xml version='1.0' encoding='utf-8'?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><RequestId>8c6b6e08-3184-45e4-8fcb-91aaaf8a5028</RequestId><AWSAccessKeyId>test</AWSAccessKeyId><CanonicalRequest>PUT
/sample-bucket/YOUR_OBJECT_KEYeeeeeeee
X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=test%2F20230602%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230602T143549Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host
host:localhost:4566
ちゃんとエラーになりました。
ところでLocalStack側にはどう出力されているんだろう
2023-06-02T14:36:20.768 INFO --- [ asgi_gw_1] localstack.request.aws : AWS s3.PutObject => 403 (SignatureDoesNotMatch)
ちゃんとエラーログが出てますね。
・・・おや?
2023-06-02T14:32:01.053 WARN --- [ asgi_gw_0] l.s.s3.presigned_url : Signatures do not match, but not raising an error, as S3_SKIP_SIGNATURE_VALIDATION=1
いや、WARNログ出とるやないか〜い
最後に
回り道を減らすためにもログはちゃんと読みましょう。
Discussion