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) {
|
if !utils.IsValidSh256PayloadHeader(hashPayload) {
|
||||||
return s3err.GetAPIError(s3err.ErrInvalidSHA256Paylod)
|
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 {
|
if streamBody {
|
||||||
// for streaming PUT actions, authorization is deferred
|
// for streaming PUT actions, authorization is deferred
|
||||||
// until end of stream due to need to get length and
|
// until end of stream due to need to get length and
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ const (
|
|||||||
ErrSignatureDoesNotMatch
|
ErrSignatureDoesNotMatch
|
||||||
ErrContentSHA256Mismatch
|
ErrContentSHA256Mismatch
|
||||||
ErrInvalidSHA256Paylod
|
ErrInvalidSHA256Paylod
|
||||||
|
ErrInvalidSHA256PayloadUsage
|
||||||
ErrUnsupportedAnonymousSignedStreaming
|
ErrUnsupportedAnonymousSignedStreaming
|
||||||
ErrMissingContentLength
|
ErrMissingContentLength
|
||||||
ErrContentLengthMismatch
|
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.",
|
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,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
|
ErrInvalidSHA256PayloadUsage: {
|
||||||
|
Code: "InvalidRequest",
|
||||||
|
Description: "The value of x-amz-content-sha256 header is invalid.",
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
},
|
||||||
ErrUnsupportedAnonymousSignedStreaming: {
|
ErrUnsupportedAnonymousSignedStreaming: {
|
||||||
Code: "InvalidRequest",
|
Code: "InvalidRequest",
|
||||||
Description: "Anonymous requests don't support this x-amz-content-sha256 value. Please use UNSIGNED-PAYLOAD or STREAMING-UNSIGNED-PAYLOAD-TRAILER.",
|
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_no_trailer_full_object)
|
||||||
ts.Run(UnsignedStreamingPayloadTrailer_UploadPart_trailer_and_mp_algo_mismatch)
|
ts.Run(UnsignedStreamingPayloadTrailer_UploadPart_trailer_and_mp_algo_mismatch)
|
||||||
ts.Run(UnsignedStreamingPayloadTrailer_UploadPart_success_with_trailer)
|
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_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_trailer_and_mp_algo_mismatch": UnsignedStreamingPayloadTrailer_UploadPart_trailer_and_mp_algo_mismatch,
|
||||||
"UnsignedStreamingPayloadTrailer_UploadPart_success_with_trailer": UnsignedStreamingPayloadTrailer_UploadPart_success_with_trailer,
|
"UnsignedStreamingPayloadTrailer_UploadPart_success_with_trailer": UnsignedStreamingPayloadTrailer_UploadPart_success_with_trailer,
|
||||||
|
"UnsignedStreamingPayloadTrailer_not_allowed": UnsignedStreamingPayloadTrailer_not_allowed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package integration
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
@@ -549,3 +551,42 @@ func UnsignedStreamingPayloadTrailer_UploadPart_success_with_trailer(s *S3Conf)
|
|||||||
return nil
|
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