Skip to content

Commit 7873e0d

Browse files
committed
Fixing Google Cloud Storage (GCS) Support
1 parent 2cb83a1 commit 7873e0d

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

server/datastore/s3/s3.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,22 @@ import (
55
"crypto/tls"
66
"errors"
77
"fmt"
8+
"strings"
89

910
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
1011
"github.com/fleetdm/fleet/v4/server/aws_common"
1112
"github.com/fleetdm/fleet/v4/server/config"
1213
"github.com/fleetdm/fleet/v4/server/fleet"
1314

1415
"github.com/aws/aws-sdk-go-v2/aws"
16+
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
1517
aws_config "github.com/aws/aws-sdk-go-v2/config"
1618
"github.com/aws/aws-sdk-go-v2/credentials"
1719
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
1820
"github.com/aws/aws-sdk-go-v2/service/s3"
1921
types "github.com/aws/aws-sdk-go-v2/service/s3/types"
22+
"github.com/aws/smithy-go/middleware"
23+
smithyhttp "github.com/aws/smithy-go/transport/http"
2024
)
2125

2226
const awsRegionHint = "us-east-1"
@@ -105,6 +109,14 @@ func newS3Store(cfg config.S3ConfigInternal) (*s3store, error) {
105109

106110
s3Client := s3.NewFromConfig(conf, func(o *s3.Options) {
107111
o.UsePathStyle = cfg.ForceS3PathStyle
112+
113+
// Apply workaround if using Google Cloud Storage (GCS) endpoint
114+
// This fixes signature issues with AWS SDK v2 when using GCS
115+
// See: https://github.com/aws/aws-sdk-go-v2/issues/1816#issuecomment-1927281540
116+
if cfg.EndpointURL != "" && strings.Contains(cfg.EndpointURL, "storage.googleapis.com") {
117+
// GCS alters the Accept-Encoding header which breaks the request signature
118+
ignoreSigningHeaders(o, []string{"Accept-Encoding"})
119+
}
108120
})
109121

110122
return &s3store{
@@ -133,3 +145,65 @@ func (s *s3store) CreateTestBucket(ctx context.Context, name string) error {
133145
}
134146
return err
135147
}
148+
149+
// GCS workaround middleware functions to fix signature issues
150+
// See: https://github.com/aws/aws-sdk-go-v2/issues/1816#issuecomment-1927281540
151+
152+
type ignoredHeadersKey struct{}
153+
154+
// ignoreSigningHeaders excludes the listed headers from the request signature
155+
// because some providers (like GCS) may alter them, causing signature mismatches.
156+
func ignoreSigningHeaders(o *s3.Options, headers []string) {
157+
o.APIOptions = append(o.APIOptions, func(stack *middleware.Stack) error {
158+
if err := stack.Finalize.Insert(ignoreHeaders(headers), "Signing", middleware.Before); err != nil {
159+
return err
160+
}
161+
162+
if err := stack.Finalize.Insert(restoreIgnored(), "Signing", middleware.After); err != nil {
163+
return err
164+
}
165+
166+
return nil
167+
})
168+
}
169+
170+
func ignoreHeaders(headers []string) middleware.FinalizeMiddleware {
171+
return middleware.FinalizeMiddlewareFunc(
172+
"IgnoreHeaders",
173+
func(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (out middleware.FinalizeOutput, metadata middleware.Metadata, err error) {
174+
req, ok := in.Request.(*smithyhttp.Request)
175+
if !ok {
176+
return out, metadata, &v4.SigningError{Err: fmt.Errorf("(ignoreHeaders) unexpected request middleware type %T", in.Request)}
177+
}
178+
179+
ignored := make(map[string]string, len(headers))
180+
for _, h := range headers {
181+
ignored[h] = req.Header.Get(h)
182+
req.Header.Del(h)
183+
}
184+
185+
ctx = middleware.WithStackValue(ctx, ignoredHeadersKey{}, ignored)
186+
187+
return next.HandleFinalize(ctx, in)
188+
},
189+
)
190+
}
191+
192+
func restoreIgnored() middleware.FinalizeMiddleware {
193+
return middleware.FinalizeMiddlewareFunc(
194+
"RestoreIgnored",
195+
func(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (out middleware.FinalizeOutput, metadata middleware.Metadata, err error) {
196+
req, ok := in.Request.(*smithyhttp.Request)
197+
if !ok {
198+
return out, metadata, &v4.SigningError{Err: fmt.Errorf("(restoreIgnored) unexpected request middleware type %T", in.Request)}
199+
}
200+
201+
ignored, _ := middleware.GetStackValue(ctx, ignoredHeadersKey{}).(map[string]string)
202+
for k, v := range ignored {
203+
req.Header.Set(k, v)
204+
}
205+
206+
return next.HandleFinalize(ctx, in)
207+
},
208+
)
209+
}

0 commit comments

Comments
 (0)