👀

LocalStackでS3の署名付きURLが検証されなかったときに確認したこと

2023/06/07に公開

結論

ログを読もう

背景

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を検証してくれなかったり・・・?
サービスによってエミュレートレベル違うって聞いたことあるしなぁ

https://docs.localstack.cloud/user-guide/aws/feature-coverage/

う〜ん、ちゃんと実装されてそうだけどなんとも言えない。

設定で変えられるとか?

https://docs.localstack.cloud/references/configuration/#s3

ありました。如何にも怪しい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&amp;X-Amz-Credential=test%2F20230602%2Fus-east-1%2Fs3%2Faws4_request&amp;X-Amz-Date=20230602T143549Z&amp;X-Amz-Expires=3600&amp;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