diff --git a/api/auth/center.go b/api/auth/center.go index 09733738..fdb3b25c 100644 --- a/api/auth/center.go +++ b/api/auth/center.go @@ -40,6 +40,9 @@ var ( postPolicyCredentialRegexp = regexp.MustCompile(`(?P[^/]+)/(?P[^/]+)/(?P[^/]*)/(?P[^/]+)/aws4_request`) ) +// need for tests. +var timeNow = time.Now + type ( Center struct { reg *RegexpSubmatcher @@ -470,7 +473,7 @@ func (c *Center) checkSign(ctx context.Context, authHeader *AuthHeader, box *acc } func checkPresignedDate(authHeader *AuthHeader, signatureDateTime time.Time) error { - now := time.Now() + now := timeNow() if signatureDateTime.Add(authHeader.Expiration).Before(now) { return fmt.Errorf("%w: expired: now %s, signature %s", apierr.GetAPIError(apierr.ErrExpiredPresignRequest), now.Format(time.RFC3339), signatureDateTime.Format(time.RFC3339)) diff --git a/api/auth/center_test.go b/api/auth/center_test.go index 94936c21..0b9f9cc7 100644 --- a/api/auth/center_test.go +++ b/api/auth/center_test.go @@ -182,6 +182,71 @@ func TestSignatureV4(t *testing.T) { require.Equal(t, signature, signatureComputed, "signature mismatched") } +func TestSignExpectHeader(t *testing.T) { + timeNow = func() time.Time { + return time.Date(2025, 3, 10, 11, 0, 0, 0, time.UTC) + } + t.Cleanup(func() { + timeNow = time.Now + }) + + ctx := context.Background() + key, err := keys.NewPrivateKey() + require.NoError(t, err) + + cfg := &cache.Config{ + Size: 10, + Lifetime: 24 * time.Hour, + Logger: zaptest.NewLogger(t), + } + + gateData := []*accessbox.GateData{{ + BearerToken: &bearer.Token{}, + GateKey: key.PublicKey(), + }} + + accessBox, _, err := accessbox.PackTokens(gateData, []byte("0a85c05b993e7663bdd245aa780569ee8abbdc1d9d9a9e185395ff87dffb0105"), true) + require.NoError(t, err) + data, err := accessBox.Marshal() + require.NoError(t, err) + + var obj object.Object + obj.SetPayload(data) + var addr oid.Address + err = addr.DecodeString("2t6v52sJdxN2NV2bFfYnuTSQiYkbcDQ2yMKHfGSsjHiv/HbUvXKFK7meCQWoo1Es3oGSMQFbFK7Np82JVEMbCM48d") + require.NoError(t, err) + + frostfs := newFrostFSMock() + frostfs.objects[getAccessKeyID(addr)] = &obj + + tknCfg := tokens.Config{ + FrostFS: frostfs, + Key: key, + CacheConfig: cfg, + } + creds := tokens.New(tknCfg) + cntr := New(creds, nil, ¢erSettingsMock{}) + + body := bytes.NewBufferString("") + + req, err := http.NewRequest("PUT", "http://localhost:8184/test/tmp.txt", body) + require.NoError(t, err) + req.Header.Set("Authorization", "AWS4-HMAC-SHA256 Credential=2t6v52sJdxN2NV2bFfYnuTSQiYkbcDQ2yMKHfGSsjHiv0HbUvXKFK7meCQWoo1Es3oGSMQFbFK7Np82JVEMbCM48d/20250310/us-east-2/s3/aws4_request, SignedHeaders=expect;host;x-amz-content-sha256;x-amz-date, Signature=966bda3d22213ae3f10d82b302041d2fc1c18804e8c02ca7d9bd35b6bcb8c161") + req.Header.Set("Expect", "100-continue") + req.Header.Set("X-Amz-Content-Sha256", UnsignedPayload) + req.Header.Set("X-Amz-Date", "20250310T082808Z") + + _, err = cntr.Authenticate(ctx, req) + require.NoError(t, err) + + req2, err := http.NewRequest("PUT", "http://localhost:8184/test/tmp.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=2t6v52sJdxN2NV2bFfYnuTSQiYkbcDQ2yMKHfGSsjHiv0HbUvXKFK7meCQWoo1Es3oGSMQFbFK7Np82JVEMbCM48d%2F20250310%2Fru%2Fs3%2Faws4_request&X-Amz-Date=20250310T083436Z&X-Amz-Expires=43200&X-Amz-SignedHeaders=expect%3Bhost&X-Amz-Signature=42c3dbe45842fdfd62d78632e135f5460e3f709ab6b949e257de30168946859b", body) + require.NoError(t, err) + req2.Header.Set("Expect", "100-continue") + + _, err = cntr.Authenticate(ctx, req2) + require.NoError(t, err) +} + func TestCheckFormatContentSHA256(t *testing.T) { defaultErr := errors.GetAPIError(errors.ErrContentSHA256Mismatch) diff --git a/api/auth/signer/v4sdk2/signer/internal/v4/headers.go b/api/auth/signer/v4sdk2/signer/internal/v4/headers.go index 46e220ce..f0e12826 100644 --- a/api/auth/signer/v4sdk2/signer/internal/v4/headers.go +++ b/api/auth/signer/v4sdk2/signer/internal/v4/headers.go @@ -1,6 +1,7 @@ // This is https://github.com/aws/aws-sdk-go-v2/blob/a2b751d1ba71f59175a41f9cae5f159f1044360f/aws/signer/internal/v4/header.go // with changes: // * drop User-Agent header from ignored +// * drop Expect header from ignored package v4 @@ -11,7 +12,7 @@ var IgnoredPresignedHeaders = Rules{ "Authorization": struct{}{}, "User-Agent": struct{}{}, "X-Amzn-Trace-Id": struct{}{}, - "Expect": struct{}{}, + //"Expect": struct{}{}, }, }, } @@ -24,7 +25,7 @@ var IgnoredHeaders = Rules{ "Authorization": struct{}{}, //"User-Agent": struct{}{}, "X-Amzn-Trace-Id": struct{}{}, - "Expect": struct{}{}, + //"Expect": struct{}{}, }, }, } diff --git a/api/auth/signer/v4sdk2/signer/internal/v4/headers_test.go b/api/auth/signer/v4sdk2/signer/internal/v4/headers_test.go index bb386599..5476a635 100644 --- a/api/auth/signer/v4sdk2/signer/internal/v4/headers_test.go +++ b/api/auth/signer/v4sdk2/signer/internal/v4/headers_test.go @@ -1,4 +1,6 @@ // This is https://github.com/aws/aws-sdk-go-v2/blob/a2b751d1ba71f59175a41f9cae5f159f1044360f/aws/signer/internal/v4/header_test.go +// with changes: +// * drop Expect header from ignored package v4 @@ -41,10 +43,10 @@ func TestIgnoredHeaders(t *testing.T) { Header string ExpectIgnored bool }{ - "expect": { - Header: "Expect", - ExpectIgnored: true, - }, + //"expect": { + // Header: "Expect", + // ExpectIgnored: true, + //}, "authorization": { Header: "Authorization", ExpectIgnored: true,