From 302fcb3b179dbd4bcb5f4058951cb265918b6a0d Mon Sep 17 00:00:00 2001 From: Bala FA Date: Tue, 12 Sep 2017 16:14:41 -0700 Subject: [PATCH] azure: handle encryption headers and azure InvalidMetadata error (#4893) Previously minio gateway returns invalid bucket name error for invalid meta data. This is fixed by returning BadRequest with 'Unsupported metadata' in response. Fixes #4891 --- cmd/api-errors.go | 8 ++++++++ cmd/gateway-azure.go | 20 ++++++++++++++++++++ cmd/gateway-azure_test.go | 28 ++++++++++++++++++++-------- cmd/object-api-errors.go | 7 +++++++ 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/cmd/api-errors.go b/cmd/api-errors.go index b7a95d7a3..b3e13ad6b 100644 --- a/cmd/api-errors.go +++ b/cmd/api-errors.go @@ -117,6 +117,7 @@ const ( ErrNotSupported ErrBucketAlreadyExists ErrMetadataTooLarge + ErrUnsupportedMetadata // Add new error codes here. // Bucket notification related errors. @@ -654,6 +655,11 @@ var errorCodeResponse = map[APIErrorCode]APIError{ Description: "Your metadata headers exceed the maximum allowed metadata size.", HTTPStatusCode: http.StatusBadRequest, }, + ErrUnsupportedMetadata: { + Code: "InvalidArgument", + Description: "Your metadata headers are not supported.", + HTTPStatusCode: http.StatusBadRequest, + }, // Add your error structure here. } @@ -750,6 +756,8 @@ func toAPIErrorCode(err error) (apiErr APIErrorCode) { apiErr = ErrNoSuchBucketPolicy case PartTooBig: apiErr = ErrEntityTooLarge + case UnsupportedMetadata: + apiErr = ErrUnsupportedMetadata default: apiErr = ErrInternalError } diff --git a/cmd/gateway-azure.go b/cmd/gateway-azure.go index 6f4812062..92b3b853c 100644 --- a/cmd/gateway-azure.go +++ b/cmd/gateway-azure.go @@ -45,9 +45,18 @@ const azureBlockSize = 100 * humanize.MiByte // Also replaces X-Amz-Meta prefix with X-Ms-Meta as Azure expects user // defined metadata to have X-Ms-Meta prefix. func s3ToAzureHeaders(headers map[string]string) (newHeaders map[string]string) { + gatewayHeaders := map[string]string{ + "X-Amz-Meta-X-Amz-Key": "X-Amz-Meta-x_minio_key", + "X-Amz-Meta-X-Amz-Matdesc": "X-Amz-Meta-x_minio_matdesc", + "X-Amz-Meta-X-Amz-Iv": "X-Amz-Meta-x_minio_iv", + } + newHeaders = make(map[string]string) for k, v := range headers { k = http.CanonicalHeaderKey(k) + if nk, ok := gatewayHeaders[k]; ok { + k = nk + } if strings.HasPrefix(k, "X-Amz-Meta") { k = strings.Replace(k, "X-Amz-Meta", "X-Ms-Meta", -1) } @@ -59,10 +68,19 @@ func s3ToAzureHeaders(headers map[string]string) (newHeaders map[string]string) // Prefix user metadata with "X-Amz-Meta-". // client.GetBlobMetadata() already strips "X-Ms-Meta-" func azureToS3Metadata(meta map[string]string) (newMeta map[string]string) { + gatewayHeaders := map[string]string{ + "X-Amz-Meta-x_minio_key": "X-Amz-Meta-X-Amz-Key", + "X-Amz-Meta-x_minio_matdesc": "X-Amz-Meta-X-Amz-Matdesc", + "X-Amz-Meta-x_minio_iv": "X-Amz-Meta-X-Amz-Iv", + } + newMeta = make(map[string]string) for k, v := range meta { k = "X-Amz-Meta-" + k + if nk, ok := gatewayHeaders[k]; ok { + k = nk + } newMeta[k] = v } return newMeta @@ -145,6 +163,8 @@ func azureToObjectError(err error, params ...string) error { err = BucketNameInvalid{Bucket: bucket} case "RequestBodyTooLarge": err = PartTooBig{} + case "InvalidMetadata": + err = UnsupportedMetadata{} default: switch azureErr.StatusCode { case http.StatusNotFound: diff --git a/cmd/gateway-azure_test.go b/cmd/gateway-azure_test.go index 65008e88e..b49b03628 100644 --- a/cmd/gateway-azure_test.go +++ b/cmd/gateway-azure_test.go @@ -45,14 +45,20 @@ func TestAzureToS3ETag(t *testing.T) { // Test canonical metadata. func TestS3ToAzureHeaders(t *testing.T) { headers := map[string]string{ - "accept-encoding": "gzip", - "content-encoding": "gzip", - "X-Amz-Meta-Hdr": "value", + "accept-encoding": "gzip", + "content-encoding": "gzip", + "X-Amz-Meta-Hdr": "value", + "X-Amz-Meta-X-Amz-Key": "hu3ZSqtqwn+aL4V2VhAeov4i+bG3KyCtRMSXQFRHXOk=", + "X-Amz-Meta-X-Amz-Matdesc": "{}", + "X-Amz-Meta-X-Amz-Iv": "eWmyryl8kq+EVnnsE7jpOg==", } expectedHeaders := map[string]string{ - "Accept-Encoding": "gzip", - "Content-Encoding": "gzip", - "X-Ms-Meta-Hdr": "value", + "Accept-Encoding": "gzip", + "Content-Encoding": "gzip", + "X-Ms-Meta-Hdr": "value", + "X-Ms-Meta-x_minio_key": "hu3ZSqtqwn+aL4V2VhAeov4i+bG3KyCtRMSXQFRHXOk=", + "X-Ms-Meta-x_minio_matdesc": "{}", + "X-Ms-Meta-x_minio_iv": "eWmyryl8kq+EVnnsE7jpOg==", } actualHeaders := s3ToAzureHeaders(headers) if !reflect.DeepEqual(actualHeaders, expectedHeaders) { @@ -64,10 +70,16 @@ func TestAzureToS3Metadata(t *testing.T) { // Just one testcase. Adding more test cases does not add value to the testcase // as azureToS3Metadata() just adds a prefix. metadata := map[string]string{ - "First-Name": "myname", + "First-Name": "myname", + "x_minio_key": "hu3ZSqtqwn+aL4V2VhAeov4i+bG3KyCtRMSXQFRHXOk=", + "x_minio_matdesc": "{}", + "x_minio_iv": "eWmyryl8kq+EVnnsE7jpOg==", } expectedMeta := map[string]string{ - "X-Amz-Meta-First-Name": "myname", + "X-Amz-Meta-First-Name": "myname", + "X-Amz-Meta-X-Amz-Key": "hu3ZSqtqwn+aL4V2VhAeov4i+bG3KyCtRMSXQFRHXOk=", + "X-Amz-Meta-X-Amz-Matdesc": "{}", + "X-Amz-Meta-X-Amz-Iv": "eWmyryl8kq+EVnnsE7jpOg==", } actualMeta := azureToS3Metadata(metadata) if !reflect.DeepEqual(actualMeta, expectedMeta) { diff --git a/cmd/object-api-errors.go b/cmd/object-api-errors.go index 5de2ddb02..22625be51 100644 --- a/cmd/object-api-errors.go +++ b/cmd/object-api-errors.go @@ -387,6 +387,13 @@ func (e PolicyNotFound) Error() string { return "Policy not found" } +// UnsupportedMetadata - unsupported metadata +type UnsupportedMetadata struct{} + +func (e UnsupportedMetadata) Error() string { + return "Unsupported headers in Metadata" +} + // Check if error type is IncompleteBody. func isErrIncompleteBody(err error) bool { err = errorCause(err)