~bigbes/core-go

c2c2f3848fa9a88d96952ff08f886483f8b9d1f7 — bigbes 30 days ago 71b2787 master
objects: force UnsignedPayload for S3 uploads (phoebe-lab patch)

Carried production patch from the phoebe-lab SourceHut deployment
(patches/core-go-checksum.patch). Fixes streaming PutObject to a
non-AWS S3 backend (Garage) over plain HTTP, where the AWS SDK's
dynamic payload middleware only uses UnsignedPayload over HTTPS and
otherwise falls through to ComputePayloadSHA256, which seeks the
non-seekable request body (pages Publish tarball, builds artifact
stream) and fails. Force UnsignedPayload unconditionally and pin the
sigv4 signing region so the endpoint resolver does not reset it.

Not upstreamed.
1 files changed, 15 insertions(+), 1 deletions(-)

M objects/middleware.go
M objects/middleware.go => objects/middleware.go +15 -1
@@ 7,9 7,11 @@ import (
	"net/http"

	"github.com/aws/aws-sdk-go-v2/aws"
	v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
	"github.com/aws/aws-sdk-go-v2/credentials"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/aws/smithy-go/endpoints"
	smithymw "github.com/aws/smithy-go/middleware"
	"github.com/vaughan0/go-ini"

	"git.sr.ht/~sircmpwn/core-go/config"


@@ 87,7 89,19 @@ func NewClient(conf ini.File) (*s3.Client, error) {
	return s3.NewFromConfig(aws.Config{
		Region:      region,
		Credentials: creds,
	}, func(opts *s3.Options) {
	}, s3.WithSigV4SigningRegion(region), func(opts *s3.Options) {
		// Patched (phoebe-lab): pages Publish + builds artifact upload pass
		// non-seekable bodies (tar.Reader, io.LimitReader) to PutObject. The
		// SDK's default dynamic-payload middleware only uses UnsignedPayload
		// over HTTPS; over HTTP (s3-insecure=true to internal Garage) it
		// falls through to ComputePayloadSHA256, which seeks the body and
		// fails. Force UnsignedPayload unconditionally. The above
		// WithSigV4SigningRegion pins the sigv4 region so the V1 endpoint
		// resolver doesn't override it back to "default".
		opts.APIOptions = append(opts.APIOptions, func(stack *smithymw.Stack) error {
			_, err := stack.Finalize.Swap("ComputePayloadHash", &v4.UnsignedPayload{})
			return err
		})
		opts.BaseEndpoint = aws.String(scheme + upstream)
		opts.EndpointResolverV2 = &S3Resolver{
			conf,