From 81a1f9a959f1815fc060f058f014f2287518f8ff Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Wed, 4 Sep 2024 16:47:53 +0300 Subject: [PATCH] [#339] Don't include additional content-length header for signing Signed-off-by: Denis Kirillov --- api/auth/center_test.go | 49 +++++++++++++++++++++------------- api/auth/signer/v4asdk2/v4a.go | 11 ++++---- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/api/auth/center_test.go b/api/auth/center_test.go index ed39123..ee95cb2 100644 --- a/api/auth/center_test.go +++ b/api/auth/center_test.go @@ -8,6 +8,7 @@ import ( "net/http" "net/http/httptest" "net/url" + "os" "strings" "testing" "time" @@ -25,6 +26,7 @@ import ( oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" credentialsv2 "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/smithy-go/logging" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" @@ -123,37 +125,48 @@ func TestSignature(t *testing.T) { } func TestSignatureV4A(t *testing.T) { - var accessKeyAddr oid.Address - err := accessKeyAddr.DecodeString("8N7CYBY74kxZXoyvA5UNdmovaXqFpwNfvEPsqaN81es2/3tDwq5tR8fByrJcyJwyiuYX7Dae8tyDT7pd8oaL1MBto") - require.NoError(t, err) - - accessKeyID := strings.ReplaceAll(accessKeyAddr.String(), "/", "0") - secretKey := "713d0a0b9efc7d22923e17b0402a6a89b4273bc711c8bacb2da1b643d0006aeb" + accessKeyID := "2XEbqH4M3ym7a3E3esxfZ2gRLnMwDXrCN4y1SkQg5fHa09sThVmVL3EE6xeKsyMzaqu5jPi41YCaVbnwbwCTF3bx1" + secretKey := "00637f53f842573aaa06c2164c598973cd986880987111416cf71f1619def537" signer := v4a.NewSigner(func(options *v4a.SignerOptions) { options.DisableURIPathEscaping = true + options.Logger = logging.NewStandardLogger(os.Stdout) + options.LogSigning = true }) credAdapter := v4a.SymmetricCredentialAdaptor{ SymmetricProvider: credentialsv2.NewStaticCredentialsProvider(accessKeyID, secretKey, ""), } - req, err := http.NewRequest("GET", "http://localhost:8084/bucket/object", nil) - require.NoError(t, err) + bodyStr := ` +1b;chunk-signature=3045022100b63692a1b20759bdabd342011823427a8952df75c93174d98ad043abca8052e002201695228a91ba986171b8d0ad20856d3d94ca3614d0a90a50a531ba8e52447b9b** +Testing with the {sdk-java} +0;chunk-signature=30440220455885a2d4e9f705256ca6b0a5a22f7f784780ccbd1c0a371e5db3059c91745b022073259dd44746cbd63261d628a04d25be5a32a974c077c5c2d83c8157fb323b9f**** +` + body := bytes.NewBufferString(bodyStr) + + req, err := http.NewRequest("PUT", "http://localhost:8084/test/tmp", body) + require.NoError(t, err) + req.Header.Set("Amz-Sdk-Invocation-Id", "ca3a3cde-7d26-fce6-ed9c-82f7a0573824") + req.Header.Set("Amz-Sdk-Request", "attempt=2; max=2") + req.Header.Set("Authorization", "AWS4-ECDSA-P256-SHA256 Credential=2XEbqH4M3ym7a3E3esxfZ2gRLnMwDXrCN4y1SkQg5fHa09sThVmVL3EE6xeKsyMzaqu5jPi41YCaVbnwbwCTF3bx1/20240904/s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-request;content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length;x-amz-region-set, Signature=30440220574244c5ff5deba388c4e3b0541a42113179b6839b3e6b4212d255a118fa9089022056f7b9b72c93f67dbcd25fe9ca67950b5913fc00bb7a62bc276c21e828c0b6c7") + req.Header.Set("Content-Length", "360") + req.Header.Set("Content-Type", "text/plain; charset=UTF-8") + req.Header.Set("X-Amz-Content-Sha256", "STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD") + req.Header.Set("X-Amz-Date", "20240904T133253Z") + req.Header.Set("X-Amz-Decoded-Content-Length", "27") + req.Header.Set("X-Amz-Region-Set", "us-east-1") + + service := "s3" + regionSet := []string{"us-east-1"} + signature := "30440220574244c5ff5deba388c4e3b0541a42113179b6839b3e6b4212d255a118fa9089022056f7b9b72c93f67dbcd25fe9ca67950b5913fc00bb7a62bc276c21e828c0b6c7" + signingTime, err := time.Parse("20060102T150405Z", "20240904T133253Z") + require.NoError(t, err) creds, err := credAdapter.RetrievePrivateKey(req.Context()) require.NoError(t, err) - signingTime := time.Now() - service := "s3" - regionSet := []string{"spb"} - - err = signer.SignHTTP(req.Context(), creds, req, "", service, regionSet, signingTime) - require.NoError(t, err) - - signature := NewRegexpMatcher(authorizationFieldV4aRegexp).GetSubmatches(req.Header.Get(AuthorizationHdr))["v4_signature"] - - err = signer.VerifySignature(creds, req, "", service, regionSet, signingTime, signature) + err = signer.VerifySignature(creds, req, "STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD", service, regionSet, signingTime, signature) require.NoError(t, err) } diff --git a/api/auth/signer/v4asdk2/v4a.go b/api/auth/signer/v4asdk2/v4a.go index 5f79859..f257ab5 100644 --- a/api/auth/signer/v4asdk2/v4a.go +++ b/api/auth/signer/v4asdk2/v4a.go @@ -16,7 +16,6 @@ import ( "net/textproto" "net/url" "sort" - "strconv" "strings" "time" @@ -464,11 +463,11 @@ func (s *httpSigner) buildCanonicalHeaders(host string, rule v4Internal.Rule, he headers = append(headers, hostHeader) signed[hostHeader] = append(signed[hostHeader], host) - const contentLengthHeader = "content-length" - if length > 0 { - headers = append(headers, contentLengthHeader) - signed[contentLengthHeader] = append(signed[contentLengthHeader], strconv.FormatInt(length, 10)) - } + //const contentLengthHeader = "content-length" + //if length > 0 { + // headers = append(headers, contentLengthHeader) + // signed[contentLengthHeader] = append(signed[contentLengthHeader], strconv.FormatInt(length, 10)) + //} for k, v := range header { if !rule.IsValid(k) {