From 40b58dfcdec8f12ed7978e1d77e975dcffc1ead5 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 30 Jan 2026 17:34:20 +0800 Subject: [PATCH] feat(storage): enhance AWS S3 client configuration for presigned URLs - Updated the AWS S3 client initialization to enforce SigV4 for presigned URLs, ensuring consistent header signing behavior across S3-compatible providers. - Introduced a dedicated configuration for the S3 client to manage addressing styles and signature versions more effectively. --- api/extensions/storage/aws_s3_storage.py | 25 +++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/api/extensions/storage/aws_s3_storage.py b/api/extensions/storage/aws_s3_storage.py index 3fdfde2372..04d75a0f67 100644 --- a/api/extensions/storage/aws_s3_storage.py +++ b/api/extensions/storage/aws_s3_storage.py @@ -2,7 +2,7 @@ import logging from collections.abc import Generator import boto3 -from botocore.client import Config +from botocore.client import BaseClient, Config from botocore.exceptions import ClientError from configs import dify_config @@ -14,15 +14,34 @@ logger = logging.getLogger(__name__) class AwsS3Storage(BaseStorage): """Implementation for Amazon Web Services S3 storage.""" + client: BaseClient + def __init__(self): super().__init__() self.bucket_name = dify_config.S3_BUCKET_NAME + + # NOTE: + # Some S3-compatible providers (e.g. MinIO) are strict about presigned request + # signature calculation. If the client sends a `Content-Type` header while the + # server generates a SigV2 presigned URL (or otherwise signs an empty Content-Type), + # the request may be rejected with 403 (signature mismatch). + # + # Enforce SigV4 for presigned URLs to avoid accidental SigV2 fallback and to keep + # header signing behavior consistent across providers. + s3_client_config = Config( + signature_version="s3v4", + s3={"addressing_style": dify_config.S3_ADDRESS_STYLE}, + ) if dify_config.S3_USE_AWS_MANAGED_IAM: logger.info("Using AWS managed IAM role for S3") session = boto3.Session() region_name = dify_config.S3_REGION - self.client = session.client(service_name="s3", region_name=region_name) + self.client = session.client( + service_name="s3", + region_name=region_name, + config=s3_client_config, + ) else: logger.info("Using ak and sk for S3") @@ -32,7 +51,7 @@ class AwsS3Storage(BaseStorage): aws_access_key_id=dify_config.S3_ACCESS_KEY, endpoint_url=dify_config.S3_ENDPOINT, region_name=dify_config.S3_REGION, - config=Config(s3={"addressing_style": dify_config.S3_ADDRESS_STYLE}), + config=s3_client_config, ) # create bucket try: