diff --git a/config-raw.json b/config-raw.json index 4df3590d4..8e1e7d686 100644 --- a/config-raw.json +++ b/config-raw.json @@ -528,6 +528,11 @@ "key": "usepathstyle", "default_value": "false", "comment": "Whether to use path-style addressing (e.g., https://s3.amazonaws.com/bucket/key) instead of virtual-hosted-style (e.g., https://bucket.s3.amazonaws.com/key). This is commonly needed for self-hosted S3-compatible services. Some providers only support one style or the other." + }, + { + "key": "disablesigning", + "default_value": "false", + "comment": "When enabled, the S3 client will send UNSIGNED-PAYLOAD instead of computing a SHA256 hash for request signing. Some S3-compatible providers (such as Ceph RadosGW, Clever Cloud Cellar) do not correctly verify payload signatures and return XAmzContentSHA256Mismatch errors. Enabling this option works around the issue. Only applies over HTTPS." } ] } diff --git a/pkg/config/config.go b/pkg/config/config.go index 64e931893..b8d56e9ad 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -162,13 +162,14 @@ const ( FilesType Key = `files.type` // S3 Configuration - FilesS3Endpoint Key = `files.s3.endpoint` - FilesS3Bucket Key = `files.s3.bucket` - FilesS3Region Key = `files.s3.region` - FilesS3AccessKey Key = `files.s3.accesskey` - FilesS3SecretKey Key = `files.s3.secretkey` - FilesS3UsePathStyle Key = `files.s3.usepathstyle` - FilesS3TempDir Key = `files.s3.tempdir` + FilesS3Endpoint Key = `files.s3.endpoint` + FilesS3Bucket Key = `files.s3.bucket` + FilesS3Region Key = `files.s3.region` + FilesS3AccessKey Key = `files.s3.accesskey` + FilesS3SecretKey Key = `files.s3.secretkey` + FilesS3UsePathStyle Key = `files.s3.usepathstyle` + FilesS3DisableSigning Key = `files.s3.disablesigning` + FilesS3TempDir Key = `files.s3.tempdir` MigrationTodoistEnable Key = `migration.todoist.enable` MigrationTodoistClientID Key = `migration.todoist.clientid` @@ -446,6 +447,7 @@ func InitDefaultConfig() { FilesS3AccessKey.setDefault("") FilesS3SecretKey.setDefault("") FilesS3UsePathStyle.setDefault(false) + FilesS3DisableSigning.setDefault(false) FilesS3TempDir.setDefault("") // Cors CorsEnable.setDefault(true) diff --git a/pkg/files/filehandling.go b/pkg/files/filehandling.go index e47858f6d..6cd81d568 100644 --- a/pkg/files/filehandling.go +++ b/pkg/files/filehandling.go @@ -33,6 +33,7 @@ import ( "code.vikunja.io/api/pkg/modules/keyvalue" "github.com/aws/aws-sdk-go-v2/aws" + v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" awsconfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/s3" @@ -97,6 +98,9 @@ func initS3FileHandler() error { client := s3.NewFromConfig(cfg, func(o *s3.Options) { o.BaseEndpoint = aws.String(endpoint) o.UsePathStyle = config.FilesS3UsePathStyle.GetBool() + if config.FilesS3DisableSigning.GetBool() { + o.APIOptions = append(o.APIOptions, v4.SwapComputePayloadSHA256ForUnsignedPayloadMiddleware) + } }) // Initialize S3 filesystem using afero-s3