From 564d2fc0355cf7d97285dc6677e70b111ba610d5 Mon Sep 17 00:00:00 2001 From: Dmitrii Kostyrev Date: Wed, 1 Apr 2026 12:09:19 +0100 Subject: [PATCH] Introduce disable_accept_encoding flag in s3 cache. --- cache/remotecache/s3/s3.go | 104 +++++++++++++++++++++++-------------- go.mod | 2 +- 2 files changed, 65 insertions(+), 41 deletions(-) diff --git a/cache/remotecache/s3/s3.go b/cache/remotecache/s3/s3.go index 888d47ecdf9a..57b8354204b2 100644 --- a/cache/remotecache/s3/s3.go +++ b/cache/remotecache/s3/s3.go @@ -17,6 +17,7 @@ import ( "github.com/aws/aws-sdk-go-v2/feature/s3/manager" "github.com/aws/aws-sdk-go-v2/service/s3" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" + "github.com/aws/smithy-go/middleware" "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/pkg/labels" "github.com/moby/buildkit/cache/remotecache" @@ -34,36 +35,38 @@ import ( ) const ( - attrBucket = "bucket" - attrRegion = "region" - attrPrefix = "prefix" - attrManifestsPrefix = "manifests_prefix" - attrBlobsPrefix = "blobs_prefix" - attrName = "name" - attrTouchRefresh = "touch_refresh" - attrEndpointURL = "endpoint_url" - attrAccessKeyID = "access_key_id" - attrSecretAccessKey = "secret_access_key" - attrSessionToken = "session_token" - attrUsePathStyle = "use_path_style" - attrUploadParallelism = "upload_parallelism" - maxCopyObjectSize = 5 * 1024 * 1024 * 1024 + attrBucket = "bucket" + attrRegion = "region" + attrPrefix = "prefix" + attrManifestsPrefix = "manifests_prefix" + attrBlobsPrefix = "blobs_prefix" + attrName = "name" + attrTouchRefresh = "touch_refresh" + attrEndpointURL = "endpoint_url" + attrAccessKeyID = "access_key_id" + attrSecretAccessKey = "secret_access_key" + attrSessionToken = "session_token" + attrUsePathStyle = "use_path_style" + attrUploadParallelism = "upload_parallelism" + attrDisableAcceptEncoding = "disable_accept_encoding" + maxCopyObjectSize = 5 * 1024 * 1024 * 1024 ) type Config struct { - Bucket string - Region string - Prefix string - ManifestsPrefix string - BlobsPrefix string - Names []string - TouchRefresh time.Duration - EndpointURL string - AccessKeyID string - SecretAccessKey string - SessionToken string - UsePathStyle bool - UploadParallelism int + Bucket string + Region string + Prefix string + ManifestsPrefix string + BlobsPrefix string + Names []string + TouchRefresh time.Duration + EndpointURL string + AccessKeyID string + SecretAccessKey string + SessionToken string + UsePathStyle bool + UploadParallelism int + DisableAcceptEncoding bool } func getConfig(attrs map[string]string) (Config, error) { @@ -141,20 +144,30 @@ func getConfig(attrs map[string]string) (Config, error) { uploadParallelism = uploadParallelismInt } + disableAcceptEncoding := false + disableAcceptEncodingStr, ok := attrs[attrDisableAcceptEncoding] + if ok { + disableAcceptEncodingUser, err := strconv.ParseBool(disableAcceptEncodingStr) + if err == nil { + disableAcceptEncoding = disableAcceptEncodingUser + } + } + return Config{ - Bucket: bucket, - Region: region, - Prefix: prefix, - ManifestsPrefix: manifestsPrefix, - BlobsPrefix: blobsPrefix, - Names: names, - TouchRefresh: touchRefresh, - EndpointURL: endpointURL, - AccessKeyID: accessKeyID, - SecretAccessKey: secretAccessKey, - SessionToken: sessionToken, - UsePathStyle: usePathStyle, - UploadParallelism: uploadParallelism, + Bucket: bucket, + Region: region, + Prefix: prefix, + ManifestsPrefix: manifestsPrefix, + BlobsPrefix: blobsPrefix, + Names: names, + TouchRefresh: touchRefresh, + EndpointURL: endpointURL, + AccessKeyID: accessKeyID, + SecretAccessKey: secretAccessKey, + SessionToken: sessionToken, + UsePathStyle: usePathStyle, + UploadParallelism: uploadParallelism, + DisableAcceptEncoding: disableAcceptEncoding, }, nil } @@ -419,6 +432,17 @@ func newS3Client(ctx context.Context, config Config) (*s3Client, error) { options.UsePathStyle = config.UsePathStyle options.BaseEndpoint = aws.String(config.EndpointURL) } + if config.DisableAcceptEncoding { + // GCS's GFE appends "gzip(gfe)" to the Accept-Encoding header after the + // AWS SDK has signed it as "identity", causing SignatureDoesNotMatch (403). + // Removing the DisableAcceptEncodingGzip middleware prevents the header + // from being added to the request and included in the signature at all. + // See: https://github.com/moby/buildkit/issues/3749 + options.APIOptions = append(options.APIOptions, func(stack *middleware.Stack) error { + stack.Finalize.Remove("DisableAcceptEncodingGzip") + return nil + }) + } }) return &s3Client{ diff --git a/go.mod b/go.mod index 2523057f9ce3..167fdb506118 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/aws/aws-sdk-go-v2/credentials v1.19.12 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.10 github.com/aws/aws-sdk-go-v2/service/s3 v1.89.1 + github.com/aws/smithy-go v1.24.2 github.com/cespare/xxhash/v2 v2.3.0 github.com/containerd/accelerated-container-image v1.3.0 github.com/containerd/console v1.0.5 @@ -135,7 +136,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 // indirect - github.com/aws/smithy-go v1.24.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect