feat: Implements signed chunk encoding with trailer in the gateway.

Closes #1159
Fixes #1161

Implements signed chunk encoding with trailers in the gateway.
The signed encoding (both with and without trailers) is now handled by the `ChunkReader`.
Fixes the `ChunkReader` implementation to validate encoding headers byte by byte.

The chunk encoding with trailers follows the general signed chunk encoding pattern, but the final chunk includes the trailing signature (`x-amz-trailing-signature`) and the checksum header (`x-amz-checksum-x`, where `x` can be `crc32`, `crc32c`, `sha1`, `sha256`, or `crc64nvme`).

Adds validation for the `X-Amz-Trailer` header.
This commit is contained in:
niksis02
2025-03-27 20:56:49 +04:00
parent 95086d70b3
commit a4b7feaa70
3 changed files with 306 additions and 96 deletions
+22 -7
View File
@@ -17,6 +17,8 @@ package utils
import (
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/gofiber/fiber/v2"
@@ -34,6 +36,14 @@ const (
payloadTypeStreamingEcdsaTrailer payloadType = "STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD-TRAILER"
)
func getPayloadTypeNotSupportedErr(p payloadType) error {
return s3err.APIError{
HTTPStatusCode: http.StatusNotImplemented,
Code: "NotImplemented",
Description: fmt.Sprintf("The chunk encoding algorithm %v is not supported.", p),
}
}
var (
specialValues = map[payloadType]bool{
payloadTypeUnsigned: true,
@@ -96,17 +106,22 @@ func NewChunkReader(ctx *fiber.Ctx, r io.Reader, authdata AuthData, region, secr
return nil, fmt.Errorf("invalid x-amz-content-sha256: %v", string(contentSha256))
}
checksumType := checksumType(ctx.Get("X-Amz-Trailer"))
if checksumType != "" && !checksumType.isValid() {
//TODO: Add proper APIError
return nil, fmt.Errorf("invalid X-Amz-Trailer: %v", checksumType)
checksumType := checksumType(strings.ToLower(ctx.Get("X-Amz-Trailer")))
if contentSha256 != payloadTypeStreamingSigned && !checksumType.isValid() {
return nil, s3err.GetAPIError(s3err.ErrTrailerHeaderNotSupported)
}
switch contentSha256 {
case payloadTypeStreamingUnsignedTrailer:
return NewUnsignedChunkReader(r, checksumType)
//TODO: Add other chunk readers
case payloadTypeStreamingSignedTrailer:
return NewSignedChunkReader(r, authdata, region, secret, date, checksumType)
case payloadTypeStreamingSigned:
return NewSignedChunkReader(r, authdata, region, secret, date, "")
// return not supported for:
// - STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD
// - STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD-TRAILER
default:
return nil, getPayloadTypeNotSupportedErr(contentSha256)
}
return NewSignedChunkReader(r, authdata, region, secret, date)
}