Skip to content

Commit

Permalink
Merge pull request #402 from versity/ben/sign_with_user_agent
Browse files Browse the repository at this point in the history
  • Loading branch information
benmcclelland authored Feb 14, 2024
2 parents 1c29fbf + 6fea34a commit 905b283
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
82 changes: 82 additions & 0 deletions s3api/utils/auth_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package utils

import (
"net"
"testing"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
"github.com/gofiber/fiber/v2"
"github.com/valyala/fasthttp/fasthttputil"
)

func TestAuthParse(t *testing.T) {
Expand Down Expand Up @@ -46,3 +53,78 @@ func TestAuthParse(t *testing.T) {
})
}
}

// 2024/02/06 21:03:28 Request headers:
// 2024/02/06 21:03:28 Host: 172.21.0.160:11000
// 2024/02/06 21:03:28 User-Agent: S3 Browser/11.5.7 (https://s3browser.com)
// 2024/02/06 21:03:28 Authorization: AWS4-HMAC-SHA256 Credential=access_key/20240206/us-east-1/s3/aws4_request,SignedHeaders=host;user-agent;x-amz-content-sha256;x-amz-date, Signature=37a35d96998d786113ad420c57c22c5433f6aca74f88f26566caa047fc3601c6
// 2024/02/06 21:03:28 X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
// 2024/02/06 21:03:28 X-Amz-Date: 20240206T210328Z
func Test_Client_UserAgent(t *testing.T) {
signedHdrs := []string{"host", "user-agent", "x-amz-content-sha256", "x-amz-date"}
access := "access_key"
secret := "secret_key"
region := "us-east-1"
host := "172.21.0.160:11000"
agent := "S3 Browser/11.5.7 (https://s3browser.com)"
expectedSig := "37a35d96998d786113ad420c57c22c5433f6aca74f88f26566caa047fc3601c6"
dateStr := "20240206T210328Z"

app := fiber.New(fiber.Config{DisableStartupMessage: true})

tdate, err := time.Parse(iso8601Format, dateStr)
if err != nil {
t.Fatal(err)
}

app.Get("/", func(c *fiber.Ctx) error {
req, err := createHttpRequestFromCtx(c, signedHdrs, int64(c.Request().Header.ContentLength()))
if err != nil {
t.Fatal(err)
}

req.Host = host
req.Header.Add("X-Amz-Content-Sha256", zeroLenSig)

signer := v4.NewSigner()

signErr := signer.SignHTTP(req.Context(),
aws.Credentials{
AccessKeyID: access,
SecretAccessKey: secret,
},
req, zeroLenSig, service, region, tdate,
func(options *v4.SignerOptions) {
options.DisableURIPathEscaping = true
})
if signErr != nil {
t.Fatalf("sign generated http request: %v", err)
}

genAuth, err := ParseAuthorization(req.Header.Get("Authorization"))
if err != nil {
return err
}

if genAuth.Signature != expectedSig {
t.Errorf("SIG: %v\nexpected: %v\n", genAuth.Signature, expectedSig)
}

return c.Send(c.Request().Header.UserAgent())
})

ln := fasthttputil.NewInmemoryListener()
go func() {
err := app.Listener(ln)
if err != nil {
panic(err)
}
}()

c := fiber.AcquireClient()
c.UserAgent = agent
a := c.Get("http://example.com")
a.HostClient.Dial = func(_ string) (net.Conn, error) { return ln.Dial() }
a.String()
fiber.ReleaseClient(c)
}
48 changes: 48 additions & 0 deletions s3api/utils/sign_hack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2023 Versity Software
// This file is licensed under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package utils

import (
"reflect"
"unsafe"
)

// This is a hack to replace the default IgnoredHeaders in the aws-sdk-go-v2
// internal/v4 package. Some AWS applications
// (e.g. AWS Java SDK v1, Athena JDBC driver, s3 browser) sign the requests
// including the User-Agent header. The aws sdk doesn't allow directly
// modifying the ignored header list. Below is a hack to replace this list
// with our own.

type Rule interface {
IsValid(value string) bool
}
type Rules []Rule

//go:linkname __ignoredHeaders github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4.IgnoredHeaders
var __ignoredHeaders unsafe.Pointer

func init() {
// Avoids "go.info.github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4.IgnoredHeaders:
// relocation target go.info.github.com/xxx/xxx/xxx.Rules not defined"
var ignoredHeaders = (*Rules)(unsafe.Pointer(&__ignoredHeaders))

// clear the map, and set just the ignored headers we want
reflect.ValueOf((*ignoredHeaders)[0]).FieldByName("Rule").Elem().Clear()
reflect.ValueOf((*ignoredHeaders)[0]).FieldByName("Rule").Elem().SetMapIndex(
reflect.ValueOf("Authorization"), reflect.ValueOf(struct{}{}))
reflect.ValueOf((*ignoredHeaders)[0]).FieldByName("Rule").Elem().SetMapIndex(
reflect.ValueOf("Expect"), reflect.ValueOf(struct{}{}))
}

0 comments on commit 905b283

Please sign in to comment.