moto/moto/s3/exceptions.py

612 lines
16 KiB
Python

from moto.core.exceptions import RESTError
ERROR_WITH_BUCKET_NAME = """{% extends 'single_error' %}
{% block extra %}<BucketName>{{ bucket }}</BucketName>{% endblock %}
"""
ERROR_WITH_KEY_NAME = """{% extends 'single_error' %}
{% block extra %}<Key>{{ key }}</Key>{% endblock %}
"""
ERROR_WITH_ARGUMENT = """{% extends 'single_error' %}
{% block extra %}<ArgumentName>{{ name }}</ArgumentName>
<ArgumentValue>{{ value }}</ArgumentValue>{% endblock %}
"""
ERROR_WITH_UPLOADID = """{% extends 'single_error' %}
{% block extra %}<UploadId>{{ upload_id }}</UploadId>{% endblock %}
"""
ERROR_WITH_CONDITION_NAME = """{% extends 'single_error' %}
{% block extra %}<Condition>{{ condition }}</Condition>{% endblock %}
"""
ERROR_WITH_RANGE = """{% extends 'single_error' %}
{% block extra %}<ActualObjectSize>{{ actual_size }}</ActualObjectSize>
<RangeRequested>{{ range_requested }}</RangeRequested>{% endblock %}
"""
ERROR_WITH_STORAGE_CLASS = """{% extends 'single_error' %}
{% block extra %}<StorageClass>{{ storage_class }}</StorageClass>{% endblock %}
"""
class S3ClientError(RESTError):
# S3 API uses <RequestID> as the XML tag in response messages
request_id_tag_name = "RequestID"
def __init__(self, *args, **kwargs):
kwargs.setdefault("template", "single_error")
self.templates["bucket_error"] = ERROR_WITH_BUCKET_NAME
super().__init__(*args, **kwargs)
class InvalidArgumentError(S3ClientError):
code = 400
def __init__(self, message, name, value, *args, **kwargs):
kwargs.setdefault("template", "argument_error")
kwargs["name"] = name
kwargs["value"] = value
self.templates["argument_error"] = ERROR_WITH_ARGUMENT
super().__init__("InvalidArgument", message, *args, **kwargs)
class BucketError(S3ClientError):
def __init__(self, *args, **kwargs):
kwargs.setdefault("template", "bucket_error")
self.templates["bucket_error"] = ERROR_WITH_BUCKET_NAME
super().__init__(*args, **kwargs)
class BucketAlreadyExists(BucketError):
code = 409
def __init__(self, *args, **kwargs):
kwargs.setdefault("template", "bucket_error")
self.templates["bucket_error"] = ERROR_WITH_BUCKET_NAME
super().__init__(
"BucketAlreadyExists",
(
"The requested bucket name is not available. The bucket "
"namespace is shared by all users of the system. Please "
"select a different name and try again"
),
*args,
**kwargs,
)
class MissingBucket(BucketError):
code = 404
def __init__(self, *args, **kwargs):
super().__init__(
"NoSuchBucket", "The specified bucket does not exist", *args, **kwargs
)
class MissingKey(S3ClientError):
code = 404
def __init__(self, **kwargs):
kwargs.setdefault("template", "key_error")
self.templates["key_error"] = ERROR_WITH_KEY_NAME
super().__init__("NoSuchKey", "The specified key does not exist.", **kwargs)
class MissingVersion(S3ClientError):
code = 404
def __init__(self, *args, **kwargs):
super().__init__(
"NoSuchVersion", "The specified version does not exist.", *args, **kwargs
)
class InvalidVersion(S3ClientError):
code = 400
def __init__(self, version_id, *args, **kwargs):
kwargs.setdefault("template", "argument_error")
kwargs["name"] = "versionId"
kwargs["value"] = version_id
self.templates["argument_error"] = ERROR_WITH_ARGUMENT
super().__init__(
"InvalidArgument", "Invalid version id specified", *args, **kwargs
)
class ObjectNotInActiveTierError(S3ClientError):
code = 403
def __init__(self, key_name):
super().__init__(
"ObjectNotInActiveTierError",
"The source object of the COPY operation is not in the active tier and is only stored in Amazon Glacier.",
Key=key_name,
)
class InvalidPartOrder(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidPartOrder",
(
"The list of parts was not in ascending order. The parts "
"list must be specified in order by part number."
),
*args,
**kwargs,
)
class InvalidPart(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidPart",
(
"One or more of the specified parts could not be found. "
"The part might not have been uploaded, or the specified "
"entity tag might not have matched the part's entity tag."
),
*args,
**kwargs,
)
class EntityTooSmall(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"EntityTooSmall",
"Your proposed upload is smaller than the minimum allowed object size.",
*args,
**kwargs,
)
class InvalidRequest(S3ClientError):
code = 400
def __init__(self, method, *args, **kwargs):
super().__init__(
"InvalidRequest",
f"Found unsupported HTTP method in CORS config. Unsupported method is {method}",
*args,
**kwargs,
)
class IllegalLocationConstraintException(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"IllegalLocationConstraintException",
"The unspecified location constraint is incompatible for the region specific endpoint this request was sent to.",
*args,
**kwargs,
)
class MalformedXML(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"MalformedXML",
"The XML you provided was not well-formed or did not validate against our published schema",
*args,
**kwargs,
)
class MalformedACLError(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"MalformedACLError",
"The XML you provided was not well-formed or did not validate against our published schema",
*args,
**kwargs,
)
class InvalidTargetBucketForLogging(S3ClientError):
code = 400
def __init__(self, msg):
super().__init__("InvalidTargetBucketForLogging", msg)
class CrossLocationLoggingProhibitted(S3ClientError):
code = 403
def __init__(self):
super().__init__(
"CrossLocationLoggingProhibitted", "Cross S3 location logging not allowed."
)
class InvalidMaxPartArgument(S3ClientError):
code = 400
def __init__(self, arg, min_val, max_val):
error = f"Argument {arg} must be an integer between {min_val} and {max_val}"
super().__init__("InvalidArgument", error)
class InvalidMaxPartNumberArgument(InvalidArgumentError):
code = 400
def __init__(self, value, *args, **kwargs):
error = "Part number must be an integer between 1 and 10000, inclusive"
super().__init__(message=error, name="partNumber", value=value, *args, **kwargs)
class NotAnIntegerException(InvalidArgumentError):
code = 400
def __init__(self, name, value, *args, **kwargs):
error = f"Provided {name} not an integer or within integer range"
super().__init__(message=error, name=name, value=value, *args, **kwargs)
class InvalidNotificationARN(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidArgument", "The ARN is not well formed", *args, **kwargs
)
class InvalidNotificationDestination(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidArgument",
"The notification destination service region is not valid for the bucket location constraint",
*args,
**kwargs,
)
class InvalidNotificationEvent(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidArgument",
"The event is not supported for notifications",
*args,
**kwargs,
)
class InvalidStorageClass(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidStorageClass",
"The storage class you specified is not valid",
*args,
**kwargs,
)
class InvalidBucketName(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidBucketName", "The specified bucket is not valid.", *args, **kwargs
)
class DuplicateTagKeys(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidTag",
"Cannot provide multiple Tags with the same key",
*args,
**kwargs,
)
class S3AccessDeniedError(S3ClientError):
code = 403
def __init__(self, *args, **kwargs):
super().__init__("AccessDenied", "Access Denied", *args, **kwargs)
class BucketAccessDeniedError(BucketError):
code = 403
def __init__(self, *args, **kwargs):
super().__init__("AccessDenied", "Access Denied", *args, **kwargs)
class S3InvalidTokenError(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidToken",
"The provided token is malformed or otherwise invalid.",
*args,
**kwargs,
)
class S3AclAndGrantError(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidRequest",
"Specifying both Canned ACLs and Header Grants is not allowed",
*args,
**kwargs,
)
class BucketInvalidTokenError(BucketError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidToken",
"The provided token is malformed or otherwise invalid.",
*args,
**kwargs,
)
class S3InvalidAccessKeyIdError(S3ClientError):
code = 403
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidAccessKeyId",
"The AWS Access Key Id you provided does not exist in our records.",
*args,
**kwargs,
)
class BucketInvalidAccessKeyIdError(S3ClientError):
code = 403
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidAccessKeyId",
"The AWS Access Key Id you provided does not exist in our records.",
*args,
**kwargs,
)
class S3SignatureDoesNotMatchError(S3ClientError):
code = 403
def __init__(self, *args, **kwargs):
super().__init__(
"SignatureDoesNotMatch",
"The request signature we calculated does not match the signature you provided. Check your key and signing method.",
*args,
**kwargs,
)
class BucketSignatureDoesNotMatchError(S3ClientError):
code = 403
def __init__(self, *args, **kwargs):
super().__init__(
"SignatureDoesNotMatch",
"The request signature we calculated does not match the signature you provided. Check your key and signing method.",
*args,
**kwargs,
)
class NoSuchPublicAccessBlockConfiguration(S3ClientError):
code = 404
def __init__(self, *args, **kwargs):
super().__init__(
"NoSuchPublicAccessBlockConfiguration",
"The public access block configuration was not found",
*args,
**kwargs,
)
class InvalidPublicAccessBlockConfiguration(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidRequest",
"Must specify at least one configuration.",
*args,
**kwargs,
)
class WrongPublicAccessBlockAccountIdError(S3ClientError):
code = 403
def __init__(self):
super().__init__("AccessDenied", "Access Denied")
class NoSystemTags(S3ClientError):
code = 400
def __init__(self):
super().__init__(
"InvalidTag", "System tags cannot be added/updated by requester"
)
class NoSuchUpload(S3ClientError):
code = 404
def __init__(self, upload_id, *args, **kwargs):
kwargs.setdefault("template", "error_uploadid")
kwargs["upload_id"] = upload_id
self.templates["error_uploadid"] = ERROR_WITH_UPLOADID
super().__init__(
"NoSuchUpload",
"The specified upload does not exist. The upload ID may be invalid, or the upload may have been aborted or completed.",
*args,
**kwargs,
)
class PreconditionFailed(S3ClientError):
code = 412
def __init__(self, failed_condition, **kwargs):
kwargs.setdefault("template", "condition_error")
self.templates["condition_error"] = ERROR_WITH_CONDITION_NAME
super().__init__(
"PreconditionFailed",
"At least one of the pre-conditions you specified did not hold",
condition=failed_condition,
**kwargs,
)
class InvalidRange(S3ClientError):
code = 416
def __init__(self, range_requested, actual_size, **kwargs):
kwargs.setdefault("template", "range_error")
self.templates["range_error"] = ERROR_WITH_RANGE
super().__init__(
"InvalidRange",
"The requested range is not satisfiable",
range_requested=range_requested,
actual_size=actual_size,
**kwargs,
)
class InvalidContinuationToken(S3ClientError):
code = 400
def __init__(self, *args, **kwargs):
super().__init__(
"InvalidArgument",
"The continuation token provided is incorrect",
*args,
**kwargs,
)
class InvalidObjectState(BucketError):
code = 403
def __init__(self, storage_class, **kwargs):
kwargs.setdefault("template", "storage_error")
self.templates["storage_error"] = ERROR_WITH_STORAGE_CLASS
super().__init__(
error_type="InvalidObjectState",
message="The operation is not valid for the object's storage class",
storage_class=storage_class,
**kwargs,
)
class LockNotEnabled(S3ClientError):
code = 400
def __init__(self):
super().__init__("InvalidRequest", "Bucket is missing ObjectLockConfiguration")
class AccessDeniedByLock(S3ClientError):
code = 400
def __init__(self):
super().__init__("AccessDenied", "Access Denied")
class InvalidContentMD5(S3ClientError):
code = 400
def __init__(self):
super().__init__("InvalidContentMD5", "Content MD5 header is invalid")
class BucketNeedsToBeNew(S3ClientError):
code = 400
def __init__(self):
super().__init__("InvalidBucket", "Bucket needs to be empty")
class BucketMustHaveLockeEnabled(S3ClientError):
code = 400
def __init__(self):
super().__init__(
"InvalidBucketState",
"Object Lock configuration cannot be enabled on existing buckets",
)
class CopyObjectMustChangeSomething(S3ClientError):
code = 400
def __init__(self):
super().__init__(
"InvalidRequest",
"This copy request is illegal because it is trying to copy an object to itself without changing the object's metadata, storage class, website redirect location or encryption attributes.",
)
class InvalidFilterRuleName(InvalidArgumentError):
code = 400
def __init__(self, value, *args, **kwargs):
super().__init__(
"filter rule name must be either prefix or suffix",
"FilterRule.Name",
value,
*args,
**kwargs,
)
class InvalidTagError(S3ClientError):
code = 400
def __init__(self, value, *args, **kwargs):
super().__init__("InvalidTag", value, *args, **kwargs)
class ObjectLockConfigurationNotFoundError(S3ClientError):
code = 404
def __init__(self):
super().__init__(
"ObjectLockConfigurationNotFoundError",
"Object Lock configuration does not exist for this bucket",
)