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.
This commit is contained in:
Harry 2026-01-30 17:34:20 +08:00
parent 3f5f893e6c
commit 40b58dfcde

View File

@ -2,7 +2,7 @@ import logging
from collections.abc import Generator from collections.abc import Generator
import boto3 import boto3
from botocore.client import Config from botocore.client import BaseClient, Config
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from configs import dify_config from configs import dify_config
@ -14,15 +14,34 @@ logger = logging.getLogger(__name__)
class AwsS3Storage(BaseStorage): class AwsS3Storage(BaseStorage):
"""Implementation for Amazon Web Services S3 storage.""" """Implementation for Amazon Web Services S3 storage."""
client: BaseClient
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.bucket_name = dify_config.S3_BUCKET_NAME 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: if dify_config.S3_USE_AWS_MANAGED_IAM:
logger.info("Using AWS managed IAM role for S3") logger.info("Using AWS managed IAM role for S3")
session = boto3.Session() session = boto3.Session()
region_name = dify_config.S3_REGION 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: else:
logger.info("Using ak and sk for S3") logger.info("Using ak and sk for S3")
@ -32,7 +51,7 @@ class AwsS3Storage(BaseStorage):
aws_access_key_id=dify_config.S3_ACCESS_KEY, aws_access_key_id=dify_config.S3_ACCESS_KEY,
endpoint_url=dify_config.S3_ENDPOINT, endpoint_url=dify_config.S3_ENDPOINT,
region_name=dify_config.S3_REGION, region_name=dify_config.S3_REGION,
config=Config(s3={"addressing_style": dify_config.S3_ADDRESS_STYLE}), config=s3_client_config,
) )
# create bucket # create bucket
try: try: