validate tags on copy object and add regex for validating tags

This commit is contained in:
Lapshin Vitaliy 2022-06-20 11:32:58 +03:00
parent aaa9938353
commit 5f5fd0bc48
4 changed files with 60 additions and 26 deletions

View file

@ -45,7 +45,11 @@ func (s3a *S3ApiServer) CopyObjectHandler(w http.ResponseWriter, r *http.Request
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidCopySource)
return
}
entry.Extended = processMetadataBytes(r.Header, entry.Extended, replaceMeta, replaceTagging)
entry.Extended, err = processMetadataBytes(r.Header, entry.Extended, replaceMeta, replaceTagging)
if err != nil {
glog.Errorf("CopyObjectHandler ValidateTags error %s: %v", r.URL, err)
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidTag)
}
err = s3a.touch(dir, name, entry)
if err != nil {
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidCopySource)
@ -252,7 +256,7 @@ func processMetadata(reqHeader, existing http.Header, replaceMeta, replaceTaggin
return
}
func processMetadataBytes(reqHeader http.Header, existing map[string][]byte, replaceMeta, replaceTagging bool) (metadata map[string][]byte) {
func processMetadataBytes(reqHeader http.Header, existing map[string][]byte, replaceMeta, replaceTagging bool) (metadata map[string][]byte, err error) {
metadata = make(map[string][]byte)
if sc := existing[s3_constants.AmzStorageClass]; len(sc) > 0 {
@ -277,16 +281,18 @@ func processMetadataBytes(reqHeader http.Header, existing map[string][]byte, rep
}
}
}
if replaceTagging {
if tags := reqHeader.Get(s3_constants.AmzObjectTagging); tags != "" {
for _, v := range strings.Split(tags, "&") {
tag := strings.Split(v, "=")
if len(tag) == 2 {
metadata[s3_constants.AmzObjectTagging+"-"+tag[0]] = []byte(tag[1])
} else if len(tag) == 1 {
metadata[s3_constants.AmzObjectTagging+"-"+tag[0]] = nil
parsedTags, err := parseTagsHeader(tags)
if err != nil {
return nil, err
}
err = validateTags(parsedTags)
if err != nil {
return nil, err
}
for k, v := range parsedTags {
metadata[s3_constants.AmzObjectTagging+"-"+k] = []byte(v)
}
}
} else {

View file

@ -367,7 +367,7 @@ func TestProcessMetadataBytes(t *testing.T) {
reqHeader := transferHToHeader(tc.request)
existing := transferHToBytesArr(tc.existing)
replaceMeta, replaceTagging := replaceDirective(reqHeader)
extends := processMetadataBytes(reqHeader, existing, replaceMeta, replaceTagging)
extends, _ := processMetadataBytes(reqHeader, existing, replaceMeta, replaceTagging)
result := transferBytesArrToH(extends)
fmtTagging(result, tc.want)

View file

@ -62,22 +62,10 @@ func (s3a *S3ApiServer) PutObjectTaggingHandler(w http.ResponseWriter, r *http.R
return
}
tags := tagging.ToTags()
if len(tags) > 10 {
glog.Errorf("PutObjectTaggingHandler tags %s: %d tags more than 10", r.URL, len(tags))
err = validateTags(tags)
if err != nil {
glog.Errorf("PutObjectTaggingHandler ValidateTags error %s: %v", r.URL, err)
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidTag)
return
}
for k, v := range tags {
if len(k) > 128 {
glog.Errorf("PutObjectTaggingHandler tags %s: tag key %s longer than 128", r.URL, k)
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidTag)
return
}
if len(v) > 256 {
glog.Errorf("PutObjectTaggingHandler tags %s: tag value %s longer than 256", r.URL, v)
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidTag)
return
}
}
if err = s3a.setTags(dir, name, tagging.ToTags()); err != nil {

View file

@ -2,6 +2,9 @@ package s3api
import (
"encoding/xml"
"fmt"
"regexp"
"strings"
)
type Tag struct {
@ -37,3 +40,40 @@ func FromTags(tags map[string]string) (t *Tagging) {
}
return
}
func parseTagsHeader(tags string) (map[string]string, error) {
var parsedTags map[string]string
for _, v := range strings.Split(tags, "&") {
tag := strings.Split(v, "=")
if len(tag) == 2 {
parsedTags[tag[0]] = tag[1]
} else if len(tag) == 1 {
parsedTags[tag[0]] = ""
}
}
return nil, nil
}
func validateTags(tags map[string]string) error {
if len(tags) > 10 {
return fmt.Errorf("validate tags: %d tags more than 10", len(tags))
}
for k, v := range tags {
if len(k) > 128 {
return fmt.Errorf("validate tags: tag key %s longer than 128", k)
}
validateKey, err := regexp.MatchString(`^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`, k)
if !validateKey && err != nil {
return fmt.Errorf("validate tags key %s error %w ", k, err)
}
if len(v) > 256 {
return fmt.Errorf("validate tags: tag value %s longer than 256", v)
}
validateValue, err := regexp.MatchString(`^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`, v)
if !validateValue && err != nil {
return fmt.Errorf("validate tags value %s error %w ", v, err)
}
}
return nil
}