feat: add UNSIGNED-PAYLOAD config option for S3-compatible stores (#2205)

Adds `files.s3.disablesigning` config option that sends
`UNSIGNED-PAYLOAD` instead of computing SHA256 hashes for S3 request
signing which fixes `XAmzContentSHA256Mismatch` errors with
S3-compatible providers like Ceph RadosGW and Clever Cloud Cellar

Resolves https://github.com/go-vikunja/vikunja/issues/2181
This commit is contained in:
kolaente 2026-02-08 16:03:19 +01:00 committed by GitHub
parent eb369cf3ee
commit b6974ffcfd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 18 additions and 7 deletions

View File

@ -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."
}
]
}

View File

@ -168,6 +168,7 @@ const (
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`
@ -446,6 +447,7 @@ func InitDefaultConfig() {
FilesS3AccessKey.setDefault("")
FilesS3SecretKey.setDefault("")
FilesS3UsePathStyle.setDefault(false)
FilesS3DisableSigning.setDefault(false)
FilesS3TempDir.setDefault("")
// Cors
CorsEnable.setDefault(true)

View File

@ -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