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
master
Bala FA 7 years ago committed by Dee Koder
parent b9fc4150f6
commit 302fcb3b17
  1. 8
      cmd/api-errors.go
  2. 20
      cmd/gateway-azure.go
  3. 28
      cmd/gateway-azure_test.go
  4. 7
      cmd/object-api-errors.go

@ -117,6 +117,7 @@ const (
ErrNotSupported ErrNotSupported
ErrBucketAlreadyExists ErrBucketAlreadyExists
ErrMetadataTooLarge ErrMetadataTooLarge
ErrUnsupportedMetadata
// Add new error codes here. // Add new error codes here.
// Bucket notification related errors. // Bucket notification related errors.
@ -654,6 +655,11 @@ var errorCodeResponse = map[APIErrorCode]APIError{
Description: "Your metadata headers exceed the maximum allowed metadata size.", Description: "Your metadata headers exceed the maximum allowed metadata size.",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrUnsupportedMetadata: {
Code: "InvalidArgument",
Description: "Your metadata headers are not supported.",
HTTPStatusCode: http.StatusBadRequest,
},
// Add your error structure here. // Add your error structure here.
} }
@ -750,6 +756,8 @@ func toAPIErrorCode(err error) (apiErr APIErrorCode) {
apiErr = ErrNoSuchBucketPolicy apiErr = ErrNoSuchBucketPolicy
case PartTooBig: case PartTooBig:
apiErr = ErrEntityTooLarge apiErr = ErrEntityTooLarge
case UnsupportedMetadata:
apiErr = ErrUnsupportedMetadata
default: default:
apiErr = ErrInternalError apiErr = ErrInternalError
} }

@ -45,9 +45,18 @@ const azureBlockSize = 100 * humanize.MiByte
// Also replaces X-Amz-Meta prefix with X-Ms-Meta as Azure expects user // Also replaces X-Amz-Meta prefix with X-Ms-Meta as Azure expects user
// defined metadata to have X-Ms-Meta prefix. // defined metadata to have X-Ms-Meta prefix.
func s3ToAzureHeaders(headers map[string]string) (newHeaders map[string]string) { 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) newHeaders = make(map[string]string)
for k, v := range headers { for k, v := range headers {
k = http.CanonicalHeaderKey(k) k = http.CanonicalHeaderKey(k)
if nk, ok := gatewayHeaders[k]; ok {
k = nk
}
if strings.HasPrefix(k, "X-Amz-Meta") { if strings.HasPrefix(k, "X-Amz-Meta") {
k = strings.Replace(k, "X-Amz-Meta", "X-Ms-Meta", -1) 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-". // Prefix user metadata with "X-Amz-Meta-".
// client.GetBlobMetadata() already strips "X-Ms-Meta-" // client.GetBlobMetadata() already strips "X-Ms-Meta-"
func azureToS3Metadata(meta map[string]string) (newMeta map[string]string) { 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) newMeta = make(map[string]string)
for k, v := range meta { for k, v := range meta {
k = "X-Amz-Meta-" + k k = "X-Amz-Meta-" + k
if nk, ok := gatewayHeaders[k]; ok {
k = nk
}
newMeta[k] = v newMeta[k] = v
} }
return newMeta return newMeta
@ -145,6 +163,8 @@ func azureToObjectError(err error, params ...string) error {
err = BucketNameInvalid{Bucket: bucket} err = BucketNameInvalid{Bucket: bucket}
case "RequestBodyTooLarge": case "RequestBodyTooLarge":
err = PartTooBig{} err = PartTooBig{}
case "InvalidMetadata":
err = UnsupportedMetadata{}
default: default:
switch azureErr.StatusCode { switch azureErr.StatusCode {
case http.StatusNotFound: case http.StatusNotFound:

@ -45,14 +45,20 @@ func TestAzureToS3ETag(t *testing.T) {
// Test canonical metadata. // Test canonical metadata.
func TestS3ToAzureHeaders(t *testing.T) { func TestS3ToAzureHeaders(t *testing.T) {
headers := map[string]string{ headers := map[string]string{
"accept-encoding": "gzip", "accept-encoding": "gzip",
"content-encoding": "gzip", "content-encoding": "gzip",
"X-Amz-Meta-Hdr": "value", "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{ expectedHeaders := map[string]string{
"Accept-Encoding": "gzip", "Accept-Encoding": "gzip",
"Content-Encoding": "gzip", "Content-Encoding": "gzip",
"X-Ms-Meta-Hdr": "value", "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) actualHeaders := s3ToAzureHeaders(headers)
if !reflect.DeepEqual(actualHeaders, expectedHeaders) { 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 // Just one testcase. Adding more test cases does not add value to the testcase
// as azureToS3Metadata() just adds a prefix. // as azureToS3Metadata() just adds a prefix.
metadata := map[string]string{ 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{ 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) actualMeta := azureToS3Metadata(metadata)
if !reflect.DeepEqual(actualMeta, expectedMeta) { if !reflect.DeepEqual(actualMeta, expectedMeta) {

@ -387,6 +387,13 @@ func (e PolicyNotFound) Error() string {
return "Policy not found" 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. // Check if error type is IncompleteBody.
func isErrIncompleteBody(err error) bool { func isErrIncompleteBody(err error) bool {
err = errorCause(err) err = errorCause(err)

Loading…
Cancel
Save