mirror of
https://github.com/versity/versitygw.git
synced 2025-12-23 05:05:16 +00:00
Merge pull request #1679 from versity/sis/unsigned-streaming-upload-not-allowed
fix: rejects STREAMING-UNSIGNED-PAYLOAD-TRAILER for all actions, except for PutObject and UploadPart
This commit is contained in:
@@ -115,6 +115,11 @@ func VerifyV4Signature(root RootUserConfig, iam auth.IAMService, region string,
|
||||
if !utils.IsValidSh256PayloadHeader(hashPayload) {
|
||||
return s3err.GetAPIError(s3err.ErrInvalidSHA256Paylod)
|
||||
}
|
||||
// the streaming payload type is allowed only in PutObject and UploadPart
|
||||
// e.g. STREAMING-UNSIGNED-PAYLOAD-TRAILER
|
||||
if !streamBody && utils.IsStreamingPayload(hashPayload) {
|
||||
return s3err.GetAPIError(s3err.ErrInvalidSHA256PayloadUsage)
|
||||
}
|
||||
if streamBody {
|
||||
// for streaming PUT actions, authorization is deferred
|
||||
// until end of stream due to need to get length and
|
||||
|
||||
@@ -119,6 +119,7 @@ const (
|
||||
ErrSignatureDoesNotMatch
|
||||
ErrContentSHA256Mismatch
|
||||
ErrInvalidSHA256Paylod
|
||||
ErrInvalidSHA256PayloadUsage
|
||||
ErrUnsupportedAnonymousSignedStreaming
|
||||
ErrMissingContentLength
|
||||
ErrContentLengthMismatch
|
||||
@@ -511,6 +512,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
Description: "x-amz-content-sha256 must be UNSIGNED-PAYLOAD, STREAMING-UNSIGNED-PAYLOAD-TRAILER, STREAMING-AWS4-HMAC-SHA256-PAYLOAD, STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER, STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD, STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD-TRAILER or a valid sha256 value.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrInvalidSHA256PayloadUsage: {
|
||||
Code: "InvalidRequest",
|
||||
Description: "The value of x-amz-content-sha256 header is invalid.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrUnsupportedAnonymousSignedStreaming: {
|
||||
Code: "InvalidRequest",
|
||||
Description: "Anonymous requests don't support this x-amz-content-sha256 value. Please use UNSIGNED-PAYLOAD or STREAMING-UNSIGNED-PAYLOAD-TRAILER.",
|
||||
|
||||
@@ -1110,6 +1110,7 @@ func TestUnsignedStreaminPayloadTrailer(ts *TestState) {
|
||||
ts.Run(UnsignedStreamingPayloadTrailer_UploadPart_no_trailer_full_object)
|
||||
ts.Run(UnsignedStreamingPayloadTrailer_UploadPart_trailer_and_mp_algo_mismatch)
|
||||
ts.Run(UnsignedStreamingPayloadTrailer_UploadPart_success_with_trailer)
|
||||
ts.Run(UnsignedStreamingPayloadTrailer_not_allowed)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1765,5 +1766,6 @@ func GetIntTests() IntTests {
|
||||
"UnsignedStreamingPayloadTrailer_UploadPart_no_trailer_full_object": UnsignedStreamingPayloadTrailer_UploadPart_no_trailer_full_object,
|
||||
"UnsignedStreamingPayloadTrailer_UploadPart_trailer_and_mp_algo_mismatch": UnsignedStreamingPayloadTrailer_UploadPart_trailer_and_mp_algo_mismatch,
|
||||
"UnsignedStreamingPayloadTrailer_UploadPart_success_with_trailer": UnsignedStreamingPayloadTrailer_UploadPart_success_with_trailer,
|
||||
"UnsignedStreamingPayloadTrailer_not_allowed": UnsignedStreamingPayloadTrailer_not_allowed,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
@@ -549,3 +551,42 @@ func UnsignedStreamingPayloadTrailer_UploadPart_success_with_trailer(s *S3Conf)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func UnsignedStreamingPayloadTrailer_not_allowed(s *S3Conf) error {
|
||||
testName := "UnsignedStreamingPayloadTrailer_not_allowed"
|
||||
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
|
||||
// doesn't matter what data is sent in the body
|
||||
body := []byte("5\r\nabcde\r\n0\r\n\r\n")
|
||||
// tests a couple of bucket PUT actions, where
|
||||
// STREAMING-UNSIGNED-PAYLOAD-TRAILER is not allowed
|
||||
for i, query := range []string{
|
||||
"cors", // PutBucketCors
|
||||
"tagging", // PutBucketTagging
|
||||
"object-lock", // PutObjectLockConfiguration
|
||||
"ownershipControls", // PutBucketOwnership
|
||||
"versioning", // PutBucketVersioning
|
||||
"policy", // PutBucketPolicy
|
||||
} {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPut, fmt.Sprintf("%s/%s?%s", s.endpoint, bucket, query), bytes.NewReader(body))
|
||||
if err != nil {
|
||||
cancel()
|
||||
return fmt.Errorf("test %v failed: %w", i+1, err)
|
||||
}
|
||||
|
||||
req.Header.Set("x-amz-content-sha256", "STREAMING-UNSIGNED-PAYLOAD-TRAILER")
|
||||
req.Header.Set("x-amz-decoded-content-length", "5")
|
||||
|
||||
_, apiErr, err := sendSignedRequest(s, req, cancel)
|
||||
if err != nil {
|
||||
return fmt.Errorf("test %v failed: %w", i+1, err)
|
||||
}
|
||||
|
||||
if err := compareS3ApiError(s3err.GetAPIError(s3err.ErrInvalidSHA256PayloadUsage), apiErr); err != nil {
|
||||
return fmt.Errorf("test %v failed: %w", i+1, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user