Fixed incorrect authentication error handling in S3.
This commit is contained in:
parent
1b8179992e
commit
95799b99bc
@ -3,7 +3,6 @@ from __future__ import unicode_literals
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
import six
|
import six
|
||||||
from werkzeug.exceptions import HTTPException
|
|
||||||
|
|
||||||
from moto.core.utils import str_to_rfc_1123_datetime
|
from moto.core.utils import str_to_rfc_1123_datetime
|
||||||
from six.moves.urllib.parse import parse_qs, urlparse, unquote
|
from six.moves.urllib.parse import parse_qs, urlparse, unquote
|
||||||
@ -119,13 +118,10 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
def should_autoescape(self):
|
def should_autoescape(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def all_buckets(self, headers):
|
def all_buckets(self):
|
||||||
try:
|
self.data["Action"] = "ListAllMyBuckets"
|
||||||
self.data["Action"] = "ListAllMyBuckets"
|
self._authenticate_s3_action()
|
||||||
self._authenticate_s3_action()
|
|
||||||
except HTTPException as http_error:
|
|
||||||
response = http_error.code, headers, http_error.description
|
|
||||||
return self._send_response(response)
|
|
||||||
# No bucket specified. Listing all buckets
|
# No bucket specified. Listing all buckets
|
||||||
all_buckets = self.backend.get_all_buckets()
|
all_buckets = self.backend.get_all_buckets()
|
||||||
template = self.response_template(S3_ALL_BUCKETS)
|
template = self.response_template(S3_ALL_BUCKETS)
|
||||||
@ -219,7 +215,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
bucket_name = self.parse_bucket_name_from_url(request, full_url)
|
bucket_name = self.parse_bucket_name_from_url(request, full_url)
|
||||||
if not bucket_name:
|
if not bucket_name:
|
||||||
# If no bucket specified, list all buckets
|
# If no bucket specified, list all buckets
|
||||||
return self.all_buckets(headers)
|
return self.all_buckets()
|
||||||
|
|
||||||
self.data["BucketName"] = bucket_name
|
self.data["BucketName"] = bucket_name
|
||||||
|
|
||||||
@ -236,15 +232,15 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
body = u'{0}'.format(body).encode('utf-8')
|
body = u'{0}'.format(body).encode('utf-8')
|
||||||
|
|
||||||
if method == 'HEAD':
|
if method == 'HEAD':
|
||||||
return self._bucket_response_head(bucket_name, headers)
|
return self._bucket_response_head(bucket_name)
|
||||||
elif method == 'GET':
|
elif method == 'GET':
|
||||||
return self._bucket_response_get(bucket_name, querystring, headers)
|
return self._bucket_response_get(bucket_name, querystring)
|
||||||
elif method == 'PUT':
|
elif method == 'PUT':
|
||||||
return self._bucket_response_put(request, body, region_name, bucket_name, querystring, headers)
|
return self._bucket_response_put(request, body, region_name, bucket_name, querystring)
|
||||||
elif method == 'DELETE':
|
elif method == 'DELETE':
|
||||||
return self._bucket_response_delete(body, bucket_name, querystring, headers)
|
return self._bucket_response_delete(body, bucket_name, querystring)
|
||||||
elif method == 'POST':
|
elif method == 'POST':
|
||||||
return self._bucket_response_post(request, body, bucket_name, headers)
|
return self._bucket_response_post(request, body, bucket_name)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Method {0} has not been impelemented in the S3 backend yet".format(method))
|
"Method {0} has not been impelemented in the S3 backend yet".format(method))
|
||||||
@ -255,7 +251,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
querystring = parse_qs(parsed_url.query, keep_blank_values=True)
|
querystring = parse_qs(parsed_url.query, keep_blank_values=True)
|
||||||
return querystring
|
return querystring
|
||||||
|
|
||||||
def _bucket_response_head(self, bucket_name, headers):
|
def _bucket_response_head(self, bucket_name):
|
||||||
try:
|
try:
|
||||||
self.backend.get_bucket(bucket_name)
|
self.backend.get_bucket(bucket_name)
|
||||||
except MissingBucket:
|
except MissingBucket:
|
||||||
@ -266,14 +262,9 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
return 404, {}, ""
|
return 404, {}, ""
|
||||||
return 200, {}, ""
|
return 200, {}, ""
|
||||||
|
|
||||||
def _bucket_response_get(self, bucket_name, querystring, headers):
|
def _bucket_response_get(self, bucket_name, querystring):
|
||||||
self._set_action("BUCKET", "GET", querystring)
|
self._set_action("BUCKET", "GET", querystring)
|
||||||
|
self._authenticate_s3_action()
|
||||||
try:
|
|
||||||
self._authenticate_s3_action()
|
|
||||||
except HTTPException as http_error:
|
|
||||||
response = http_error.code, headers, http_error.description
|
|
||||||
return self._send_response(response)
|
|
||||||
|
|
||||||
if 'uploads' in querystring:
|
if 'uploads' in querystring:
|
||||||
for unsup in ('delimiter', 'max-uploads'):
|
for unsup in ('delimiter', 'max-uploads'):
|
||||||
@ -502,17 +493,12 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
next_continuation_token = None
|
next_continuation_token = None
|
||||||
return result_keys, is_truncated, next_continuation_token
|
return result_keys, is_truncated, next_continuation_token
|
||||||
|
|
||||||
def _bucket_response_put(self, request, body, region_name, bucket_name, querystring, headers):
|
def _bucket_response_put(self, request, body, region_name, bucket_name, querystring):
|
||||||
if not request.headers.get('Content-Length'):
|
if not request.headers.get('Content-Length'):
|
||||||
return 411, {}, "Content-Length required"
|
return 411, {}, "Content-Length required"
|
||||||
|
|
||||||
self._set_action("BUCKET", "PUT", querystring)
|
self._set_action("BUCKET", "PUT", querystring)
|
||||||
|
self._authenticate_s3_action()
|
||||||
try:
|
|
||||||
self._authenticate_s3_action()
|
|
||||||
except HTTPException as http_error:
|
|
||||||
response = http_error.code, headers, http_error.description
|
|
||||||
return self._send_response(response)
|
|
||||||
|
|
||||||
if 'versioning' in querystring:
|
if 'versioning' in querystring:
|
||||||
ver = re.search('<Status>([A-Za-z]+)</Status>', body.decode())
|
ver = re.search('<Status>([A-Za-z]+)</Status>', body.decode())
|
||||||
@ -612,14 +598,9 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
template = self.response_template(S3_BUCKET_CREATE_RESPONSE)
|
template = self.response_template(S3_BUCKET_CREATE_RESPONSE)
|
||||||
return 200, {}, template.render(bucket=new_bucket)
|
return 200, {}, template.render(bucket=new_bucket)
|
||||||
|
|
||||||
def _bucket_response_delete(self, body, bucket_name, querystring, headers):
|
def _bucket_response_delete(self, body, bucket_name, querystring):
|
||||||
self._set_action("BUCKET", "DELETE", querystring)
|
self._set_action("BUCKET", "DELETE", querystring)
|
||||||
|
self._authenticate_s3_action()
|
||||||
try:
|
|
||||||
self._authenticate_s3_action()
|
|
||||||
except HTTPException as http_error:
|
|
||||||
response = http_error.code, headers, http_error.description
|
|
||||||
return self._send_response(response)
|
|
||||||
|
|
||||||
if 'policy' in querystring:
|
if 'policy' in querystring:
|
||||||
self.backend.delete_bucket_policy(bucket_name, body)
|
self.backend.delete_bucket_policy(bucket_name, body)
|
||||||
@ -647,7 +628,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
S3_DELETE_BUCKET_WITH_ITEMS_ERROR)
|
S3_DELETE_BUCKET_WITH_ITEMS_ERROR)
|
||||||
return 409, {}, template.render(bucket=removed_bucket)
|
return 409, {}, template.render(bucket=removed_bucket)
|
||||||
|
|
||||||
def _bucket_response_post(self, request, body, bucket_name, headers):
|
def _bucket_response_post(self, request, body, bucket_name):
|
||||||
if not request.headers.get('Content-Length'):
|
if not request.headers.get('Content-Length'):
|
||||||
return 411, {}, "Content-Length required"
|
return 411, {}, "Content-Length required"
|
||||||
|
|
||||||
@ -655,22 +636,12 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
|
|
||||||
if self.is_delete_keys(request, path, bucket_name):
|
if self.is_delete_keys(request, path, bucket_name):
|
||||||
self.data["Action"] = "DeleteObject"
|
self.data["Action"] = "DeleteObject"
|
||||||
|
self._authenticate_s3_action()
|
||||||
|
|
||||||
try:
|
return self._bucket_response_delete_keys(request, body, bucket_name)
|
||||||
self._authenticate_s3_action()
|
|
||||||
except HTTPException as http_error:
|
|
||||||
response = http_error.code, headers, http_error.description
|
|
||||||
return self._send_response(response)
|
|
||||||
|
|
||||||
return self._bucket_response_delete_keys(request, body, bucket_name, headers)
|
|
||||||
|
|
||||||
self.data["Action"] = "PutObject"
|
self.data["Action"] = "PutObject"
|
||||||
|
self._authenticate_s3_action()
|
||||||
try:
|
|
||||||
self._authenticate_s3_action()
|
|
||||||
except HTTPException as http_error:
|
|
||||||
response = http_error.code, headers, http_error.description
|
|
||||||
return self._send_response(response)
|
|
||||||
|
|
||||||
# POST to bucket-url should create file from form
|
# POST to bucket-url should create file from form
|
||||||
if hasattr(request, 'form'):
|
if hasattr(request, 'form'):
|
||||||
@ -707,7 +678,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
path = request.full_path if hasattr(request, 'full_path') else path_url(request.url)
|
path = request.full_path if hasattr(request, 'full_path') else path_url(request.url)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def _bucket_response_delete_keys(self, request, body, bucket_name, headers):
|
def _bucket_response_delete_keys(self, request, body, bucket_name):
|
||||||
template = self.response_template(S3_DELETE_KEYS_RESPONSE)
|
template = self.response_template(S3_DELETE_KEYS_RESPONSE)
|
||||||
|
|
||||||
keys = minidom.parseString(body).getElementsByTagName('Key')
|
keys = minidom.parseString(body).getElementsByTagName('Key')
|
||||||
@ -813,21 +784,16 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
elif method == 'HEAD':
|
elif method == 'HEAD':
|
||||||
return self._key_response_head(bucket_name, query, key_name, headers=request.headers)
|
return self._key_response_head(bucket_name, query, key_name, headers=request.headers)
|
||||||
elif method == 'DELETE':
|
elif method == 'DELETE':
|
||||||
return self._key_response_delete(bucket_name, query, key_name, headers)
|
return self._key_response_delete(bucket_name, query, key_name)
|
||||||
elif method == 'POST':
|
elif method == 'POST':
|
||||||
return self._key_response_post(request, body, bucket_name, query, key_name, headers)
|
return self._key_response_post(request, body, bucket_name, query, key_name)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Method {0} has not been implemented in the S3 backend yet".format(method))
|
"Method {0} has not been implemented in the S3 backend yet".format(method))
|
||||||
|
|
||||||
def _key_response_get(self, bucket_name, query, key_name, headers):
|
def _key_response_get(self, bucket_name, query, key_name, headers):
|
||||||
self._set_action("KEY", "GET", query)
|
self._set_action("KEY", "GET", query)
|
||||||
|
self._authenticate_s3_action()
|
||||||
try:
|
|
||||||
self._authenticate_s3_action()
|
|
||||||
except HTTPException as http_error:
|
|
||||||
response = http_error.code, headers, http_error.description
|
|
||||||
return self._send_response(response)
|
|
||||||
|
|
||||||
response_headers = {}
|
response_headers = {}
|
||||||
if query.get('uploadId'):
|
if query.get('uploadId'):
|
||||||
@ -864,12 +830,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
|
|
||||||
def _key_response_put(self, request, body, bucket_name, query, key_name, headers):
|
def _key_response_put(self, request, body, bucket_name, query, key_name, headers):
|
||||||
self._set_action("KEY", "PUT", query)
|
self._set_action("KEY", "PUT", query)
|
||||||
|
self._authenticate_s3_action()
|
||||||
try:
|
|
||||||
self._authenticate_s3_action()
|
|
||||||
except HTTPException as http_error:
|
|
||||||
response = http_error.code, headers, http_error.description
|
|
||||||
return self._send_response(response)
|
|
||||||
|
|
||||||
response_headers = {}
|
response_headers = {}
|
||||||
if query.get('uploadId') and query.get('partNumber'):
|
if query.get('uploadId') and query.get('partNumber'):
|
||||||
@ -1237,14 +1198,9 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
config = parsed_xml['AccelerateConfiguration']
|
config = parsed_xml['AccelerateConfiguration']
|
||||||
return config['Status']
|
return config['Status']
|
||||||
|
|
||||||
def _key_response_delete(self, bucket_name, query, key_name, headers):
|
def _key_response_delete(self, bucket_name, query, key_name):
|
||||||
self._set_action("KEY", "DELETE", query)
|
self._set_action("KEY", "DELETE", query)
|
||||||
|
self._authenticate_s3_action()
|
||||||
try:
|
|
||||||
self._authenticate_s3_action()
|
|
||||||
except HTTPException as http_error:
|
|
||||||
response = http_error.code, headers, http_error.description
|
|
||||||
return self._send_response(response)
|
|
||||||
|
|
||||||
if query.get('uploadId'):
|
if query.get('uploadId'):
|
||||||
upload_id = query['uploadId'][0]
|
upload_id = query['uploadId'][0]
|
||||||
@ -1265,14 +1221,9 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
raise InvalidPartOrder()
|
raise InvalidPartOrder()
|
||||||
yield (pn, p.getElementsByTagName('ETag')[0].firstChild.wholeText)
|
yield (pn, p.getElementsByTagName('ETag')[0].firstChild.wholeText)
|
||||||
|
|
||||||
def _key_response_post(self, request, body, bucket_name, query, key_name, headers):
|
def _key_response_post(self, request, body, bucket_name, query, key_name):
|
||||||
self._set_action("KEY", "POST", query)
|
self._set_action("KEY", "POST", query)
|
||||||
|
self._authenticate_s3_action()
|
||||||
try:
|
|
||||||
self._authenticate_s3_action()
|
|
||||||
except HTTPException as http_error:
|
|
||||||
response = http_error.code, headers, http_error.description
|
|
||||||
return self._send_response(response)
|
|
||||||
|
|
||||||
if body == b'' and 'uploads' in query:
|
if body == b'' and 'uploads' in query:
|
||||||
metadata = metadata_from_headers(request.headers)
|
metadata = metadata_from_headers(request.headers)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user