mirror of
https://github.com/pgsty/minio.git
synced 2026-09-19 17:08:28 +03:00
fix(replication): avoid persisting aws-chunked metadata
Signed-off-by: Mikhail Khadarenka <chodorenko@gmail.com>
This commit is contained in:
+33
-23
@@ -246,16 +246,6 @@ func extractMetadata(ctx context.Context, mimesHeader ...textproto.MIMEHeader) (
|
|||||||
|
|
||||||
// extractMetadata extracts metadata from map values.
|
// extractMetadata extracts metadata from map values.
|
||||||
func extractMetadataFromMime(ctx context.Context, v textproto.MIMEHeader, m map[string]string) error {
|
func extractMetadataFromMime(ctx context.Context, v textproto.MIMEHeader, m map[string]string) error {
|
||||||
return extractMetadataFromMimeWithReplication(ctx, v, m, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractReplicationMetadataFromMime restores replication-only metadata after the
|
|
||||||
// caller has validated that the request is a trusted replication write.
|
|
||||||
func extractReplicationMetadataFromMime(ctx context.Context, v textproto.MIMEHeader, m map[string]string) error {
|
|
||||||
return extractMetadataFromMimeWithReplication(ctx, v, m, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractMetadataFromMimeWithReplication(ctx context.Context, v textproto.MIMEHeader, m map[string]string, allowReplication bool) error {
|
|
||||||
if v == nil {
|
if v == nil {
|
||||||
bugLogIf(ctx, errInvalidArgument)
|
bugLogIf(ctx, errInvalidArgument)
|
||||||
return errInvalidArgument
|
return errInvalidArgument
|
||||||
@@ -267,18 +257,14 @@ func extractMetadataFromMimeWithReplication(ctx context.Context, v textproto.MIM
|
|||||||
nv[http.CanonicalHeaderKey(k)] = kv
|
nv[http.CanonicalHeaderKey(k)] = kv
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save all supported headers.
|
// Save ordinary object metadata. Replication-only headers are restored only
|
||||||
|
// after the request has been validated as a trusted replication write.
|
||||||
for _, supportedHeader := range supportedHeaders {
|
for _, supportedHeader := range supportedHeaders {
|
||||||
value, ok := nv[http.CanonicalHeaderKey(supportedHeader)]
|
if _, ok := replicationToInternalHeaders[supportedHeader]; ok {
|
||||||
if ok {
|
continue
|
||||||
if v, ok := replicationToInternalHeaders[supportedHeader]; ok {
|
}
|
||||||
if !allowReplication {
|
if value, ok := nv[http.CanonicalHeaderKey(supportedHeader)]; ok {
|
||||||
continue
|
m[supportedHeader] = strings.Join(value, ",")
|
||||||
}
|
|
||||||
m[v] = strings.Join(value, ",")
|
|
||||||
} else {
|
|
||||||
m[supportedHeader] = strings.Join(value, ",")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,8 +273,7 @@ func extractMetadataFromMimeWithReplication(ctx context.Context, v textproto.MIM
|
|||||||
if !stringsHasPrefixFold(key, prefix) {
|
if !stringsHasPrefixFold(key, prefix) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
value, ok := nv[http.CanonicalHeaderKey(key)]
|
if value, ok := nv[http.CanonicalHeaderKey(key)]; ok {
|
||||||
if ok {
|
|
||||||
m[key] = strings.Join(value, ",")
|
m[key] = strings.Join(value, ",")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -297,6 +282,31 @@ func extractMetadataFromMimeWithReplication(ctx context.Context, v textproto.MIM
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractReplicationMetadataFromMime restores replication-only metadata after the
|
||||||
|
// caller has validated that the request is a trusted replication write.
|
||||||
|
func extractReplicationMetadataFromMime(ctx context.Context, v textproto.MIMEHeader, m map[string]string) error {
|
||||||
|
if v == nil {
|
||||||
|
bugLogIf(ctx, errInvalidArgument)
|
||||||
|
return errInvalidArgument
|
||||||
|
}
|
||||||
|
|
||||||
|
nv := make(textproto.MIMEHeader, len(v))
|
||||||
|
for k, kv := range v {
|
||||||
|
// Canonicalize all headers, to remove any duplicates.
|
||||||
|
nv[http.CanonicalHeaderKey(k)] = kv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ordinary object metadata has already been extracted and normalized before
|
||||||
|
// replication trust is evaluated. Restoring it here would reintroduce raw
|
||||||
|
// transport headers such as Content-Encoding: aws-chunked.
|
||||||
|
for header, internalHeader := range replicationToInternalHeaders {
|
||||||
|
if value, ok := nv[http.CanonicalHeaderKey(header)]; ok {
|
||||||
|
m[internalHeader] = strings.Join(value, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Returns access credentials in the request Authorization header.
|
// Returns access credentials in the request Authorization header.
|
||||||
func getReqAccessCred(r *http.Request, region string) (cred auth.Credentials) {
|
func getReqAccessCred(r *http.Request, region string) (cred auth.Credentials) {
|
||||||
cred, _, _ = getReqAccessKeyV4(r, region, serviceS3)
|
cred, _, _ = getReqAccessKeyV4(r, region, serviceS3)
|
||||||
|
|||||||
@@ -254,6 +254,9 @@ func TestExtractMetadataFromRequestKeepsQueryCompatibility(t *testing.T) {
|
|||||||
|
|
||||||
func TestExtractReplicationMetadataHeaders(t *testing.T) {
|
func TestExtractReplicationMetadataHeaders(t *testing.T) {
|
||||||
header := http.Header{
|
header := http.Header{
|
||||||
|
"Content-Type": []string{"application/wasm"},
|
||||||
|
"Content-Encoding": []string{"aws-chunked"},
|
||||||
|
"X-Amz-Meta-Source": []string{"client"},
|
||||||
"X-Minio-Replication-Server-Side-Encryption-Sealed-Key": []string{"sealed-key"},
|
"X-Minio-Replication-Server-Side-Encryption-Sealed-Key": []string{"sealed-key"},
|
||||||
"X-Minio-Replication-Server-Side-Encryption-Seal-Algorithm": []string{"DAREv2-HMAC-SHA256"},
|
"X-Minio-Replication-Server-Side-Encryption-Seal-Algorithm": []string{"DAREv2-HMAC-SHA256"},
|
||||||
"X-Minio-Replication-Server-Side-Encryption-Iv": []string{"iv"},
|
"X-Minio-Replication-Server-Side-Encryption-Iv": []string{"iv"},
|
||||||
@@ -262,12 +265,17 @@ func TestExtractReplicationMetadataHeaders(t *testing.T) {
|
|||||||
ReplicationSsecChecksumHeader: []string{"checksum"},
|
ReplicationSsecChecksumHeader: []string{"checksum"},
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata := make(map[string]string)
|
metadata := map[string]string{
|
||||||
|
"content-type": "application/wasm",
|
||||||
|
"x-amz-meta-source": "client",
|
||||||
|
}
|
||||||
if err := extractReplicationMetadataFromMime(t.Context(), textproto.MIMEHeader(header), metadata); err != nil {
|
if err := extractReplicationMetadataFromMime(t.Context(), textproto.MIMEHeader(header), metadata); err != nil {
|
||||||
t.Fatalf("failed to extract replication metadata: %v", err)
|
t.Fatalf("failed to extract replication metadata: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := map[string]string{
|
expected := map[string]string{
|
||||||
|
"content-type": "application/wasm",
|
||||||
|
"x-amz-meta-source": "client",
|
||||||
"X-Minio-Internal-Server-Side-Encryption-Sealed-Key": "sealed-key",
|
"X-Minio-Internal-Server-Side-Encryption-Sealed-Key": "sealed-key",
|
||||||
"X-Minio-Internal-Server-Side-Encryption-Seal-Algorithm": "DAREv2-HMAC-SHA256",
|
"X-Minio-Internal-Server-Side-Encryption-Seal-Algorithm": "DAREv2-HMAC-SHA256",
|
||||||
"X-Minio-Internal-Server-Side-Encryption-Iv": "iv",
|
"X-Minio-Internal-Server-Side-Encryption-Iv": "iv",
|
||||||
@@ -279,6 +287,9 @@ func TestExtractReplicationMetadataHeaders(t *testing.T) {
|
|||||||
if !reflect.DeepEqual(metadata, expected) {
|
if !reflect.DeepEqual(metadata, expected) {
|
||||||
t.Fatalf("unexpected replication metadata: expected %#v, got %#v", expected, metadata)
|
t.Fatalf("unexpected replication metadata: expected %#v, got %#v", expected, metadata)
|
||||||
}
|
}
|
||||||
|
if _, ok := metadata["content-encoding"]; ok {
|
||||||
|
t.Fatalf("replication metadata restored transport content-encoding: %#v", metadata)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetCopyObjectMetadataFromHeaderReplication(t *testing.T) {
|
func TestGetCopyObjectMetadataFromHeaderReplication(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user