Add PostObject Checksum (#17244)

This commit is contained in:
Klaus Post 2023-05-23 07:58:33 -07:00 committed by GitHub
parent ef54200db7
commit 5677f73794
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 11 deletions

View File

@ -1018,6 +1018,20 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
writeErrorResponse(ctx, w, apiErr, r.URL) writeErrorResponse(ctx, w, apiErr, r.URL)
return return
} }
checksum, err := hash.GetContentChecksum(formValues)
if err != nil {
apiErr := errorCodes.ToAPIErr(ErrMalformedPOSTRequest)
apiErr.Description = fmt.Sprintf("%s (%v)", apiErr.Description, fmt.Errorf("Invalid checksum: %w", err))
writeErrorResponse(ctx, w, apiErr, r.URL)
return
}
if checksum != nil && checksum.Type.Trailing() {
// Not officially supported in POST requests.
apiErr := errorCodes.ToAPIErr(ErrMalformedPOSTRequest)
apiErr.Description = fmt.Sprintf("%s (%v)", apiErr.Description, errors.New("Trailing checksums not available for POST operations"))
writeErrorResponse(ctx, w, apiErr, r.URL)
return
}
formValues.Set("Bucket", bucket) formValues.Set("Bucket", bucket)
if fileName != "" && strings.Contains(formValues.Get("Key"), "${filename}") { if fileName != "" && strings.Contains(formValues.Get("Key"), "${filename}") {
@ -1073,6 +1087,13 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
return return
} }
if checksum != nil && checksum.Valid() {
err = hashReader.AddChecksum(r, false)
if err != nil {
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
return
}
}
// Handle policy if it is set. // Handle policy if it is set.
if len(policyBytes) > 0 { if len(policyBytes) > 0 {
@ -1167,6 +1188,13 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
return return
} }
if checksum != nil && checksum.Valid() {
err = hashReader.AddChecksum(r, true)
if err != nil {
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
return
}
}
pReader, err = pReader.WithEncryption(hashReader, &objectEncryptionKey) pReader, err = pReader.WithEncryption(hashReader, &objectEncryptionKey)
if err != nil { if err != nil {
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
@ -1226,6 +1254,11 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
return return
} }
// Add checksum header.
if checksum != nil && checksum.Valid() {
hash.AddChecksumHeader(w, checksum.AsMap())
}
// Decide what http response to send depending on success_action_status parameter // Decide what http response to send depending on success_action_status parameter
switch successStatus { switch successStatus {
case "201": case "201":

View File

@ -291,7 +291,7 @@ func putOpts(ctx context.Context, r *http.Request, bucket, object string, metada
metadata = make(map[string]string) metadata = make(map[string]string)
} }
wantCRC, err := hash.GetContentChecksum(r) wantCRC, err := hash.GetContentChecksum(r.Header)
if err != nil { if err != nil {
return opts, InvalidArgument{ return opts, InvalidArgument{
Bucket: bucket, Bucket: bucket,
@ -377,7 +377,7 @@ func completeMultipartOpts(ctx context.Context, r *http.Request, bucket, object
} }
} }
} }
opts.WantChecksum, err = hash.GetContentChecksum(r) opts.WantChecksum, err = hash.GetContentChecksum(r.Header)
if err != nil { if err != nil {
return opts, InvalidArgument{ return opts, InvalidArgument{
Bucket: bucket, Bucket: bucket,

View File

@ -341,7 +341,7 @@ func (c *Checksum) AsMap() map[string]string {
// TransferChecksumHeader will transfer any checksum value that has been checked. // TransferChecksumHeader will transfer any checksum value that has been checked.
// If checksum was trailing, they must have been added to r.Trailer. // If checksum was trailing, they must have been added to r.Trailer.
func TransferChecksumHeader(w http.ResponseWriter, r *http.Request) { func TransferChecksumHeader(w http.ResponseWriter, r *http.Request) {
c, err := GetContentChecksum(r) c, err := GetContentChecksum(r.Header)
if err != nil || c == nil { if err != nil || c == nil {
return return
} }
@ -375,8 +375,8 @@ func AddChecksumHeader(w http.ResponseWriter, c map[string]string) {
// GetContentChecksum returns content checksum. // GetContentChecksum returns content checksum.
// Returns ErrInvalidChecksum if so. // Returns ErrInvalidChecksum if so.
// Returns nil, nil if no checksum. // Returns nil, nil if no checksum.
func GetContentChecksum(r *http.Request) (*Checksum, error) { func GetContentChecksum(h http.Header) (*Checksum, error) {
if trailing := r.Header.Values(xhttp.AmzTrailer); len(trailing) > 0 { if trailing := h.Values(xhttp.AmzTrailer); len(trailing) > 0 {
var res *Checksum var res *Checksum
for _, header := range trailing { for _, header := range trailing {
var duplicates bool var duplicates bool
@ -402,7 +402,7 @@ func GetContentChecksum(r *http.Request) (*Checksum, error) {
return res, nil return res, nil
} }
} }
t, s := getContentChecksum(r) t, s := getContentChecksum(h)
if t == ChecksumNone { if t == ChecksumNone {
if s == "" { if s == "" {
return nil, nil return nil, nil
@ -418,21 +418,21 @@ func GetContentChecksum(r *http.Request) (*Checksum, error) {
// getContentChecksum returns content checksum type and value. // getContentChecksum returns content checksum type and value.
// Returns ChecksumInvalid if so. // Returns ChecksumInvalid if so.
func getContentChecksum(r *http.Request) (t ChecksumType, s string) { func getContentChecksum(h http.Header) (t ChecksumType, s string) {
t = ChecksumNone t = ChecksumNone
alg := r.Header.Get(xhttp.AmzChecksumAlgo) alg := h.Get(xhttp.AmzChecksumAlgo)
if alg != "" { if alg != "" {
t |= NewChecksumType(alg) t |= NewChecksumType(alg)
if t.IsSet() { if t.IsSet() {
hdr := t.Key() hdr := t.Key()
if s = r.Header.Get(hdr); s == "" { if s = h.Get(hdr); s == "" {
return ChecksumNone, "" return ChecksumNone, ""
} }
} }
return t, s return t, s
} }
checkType := func(c ChecksumType) { checkType := func(c ChecksumType) {
if got := r.Header.Get(c.Key()); got != "" { if got := h.Get(c.Key()); got != "" {
// If already set, invalid // If already set, invalid
if t != ChecksumNone { if t != ChecksumNone {
t = ChecksumInvalid t = ChecksumInvalid

View File

@ -170,7 +170,7 @@ func (r *Reader) SetExpectedMax(expectedMax int64) {
// https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html // https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
// Returns ErrInvalidChecksum if a problem with the checksum is found. // Returns ErrInvalidChecksum if a problem with the checksum is found.
func (r *Reader) AddChecksum(req *http.Request, ignoreValue bool) error { func (r *Reader) AddChecksum(req *http.Request, ignoreValue bool) error {
cs, err := GetContentChecksum(req) cs, err := GetContentChecksum(req.Header)
if err != nil { if err != nil {
return ErrInvalidChecksum return ErrInvalidChecksum
} }
@ -181,6 +181,16 @@ func (r *Reader) AddChecksum(req *http.Request, ignoreValue bool) error {
if cs.Type.Trailing() { if cs.Type.Trailing() {
r.trailer = req.Trailer r.trailer = req.Trailer
} }
return r.AddNonTrailingChecksum(cs, ignoreValue)
}
// AddNonTrailingChecksum will add a checksum to the reader.
// The checksum cannot be trailing.
func (r *Reader) AddNonTrailingChecksum(cs *Checksum, ignoreValue bool) error {
if cs == nil {
return nil
}
r.contentHash = *cs
if ignoreValue { if ignoreValue {
// Do not validate, but allow for transfer // Do not validate, but allow for transfer
return nil return nil