From 8ce12027dd2d89e00fa3ecfd295357471957ba3d Mon Sep 17 00:00:00 2001 From: Dawn James Date: Fri, 19 Jun 2020 11:44:43 +0100 Subject: [PATCH] Return correct error when creating a bucket with empty CreateBucketConfiguration (#3079) * Several updates to the contributor documentation with extra information. * Fix failing test by providing a region. * Create test for issue 2210. * Check if CreateBucketConfiguration is supplied and empty; raise MalformedXML error if so. --- CONTRIBUTING.md | 25 +++++++++++++++++-------- moto/s3/responses.py | 16 ++++++++++++++++ tests/test_s3/test_s3.py | 11 ++++++++++- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 941fc0624..7e54236bd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,32 +1,41 @@ -### Contributing code +# Contributing code Moto has a [Code of Conduct](https://github.com/spulec/moto/blob/master/CODE_OF_CONDUCT.md), you can expect to be treated with respect at all times when interacting with this project. ## Running the tests locally -Moto has a Makefile which has some helpful commands for getting setup. You should be able to run `make init` to install the dependencies and then `make test` to run the tests. +Moto has a [Makefile](./Makefile) which has some helpful commands for getting set up. +You should be able to run `make init` to install the dependencies and then `make test` to run the tests. + +*NB. On first run, some tests might take a while to execute, especially the Lambda ones, because they may need to download a Docker image before they can execute.* ## Linting + Run `make lint` or `black --check moto tests` to verify whether your code confirms to the guidelines. -## Is there a missing feature? +## Getting to grips with the codebase + +Moto maintains a list of [good first issues](https://github.com/spulec/moto/contribute) which you may want to look at before +implementing a whole new endpoint. + +## Missing features Moto is easier to contribute to than you probably think. There's [a list of which endpoints have been implemented](https://github.com/spulec/moto/blob/master/IMPLEMENTATION_COVERAGE.md) and we invite you to add new endpoints to existing services or to add new services. How to teach Moto to support a new AWS endpoint: -* Create an issue describing what's missing. This is where we'll all talk about the new addition and help you get it done. +* Search for an existing [issue](https://github.com/spulec/moto/issues) that matches what you want to achieve. +* If one doesn't already exist, create a new issue describing what's missing. This is where we'll all talk about the new addition and help you get it done. * Create a [pull request](https://help.github.com/articles/using-pull-requests/) and mention the issue # in the PR description. * Try to add a failing test case. For example, if you're trying to implement `boto3.client('acm').import_certificate()` you'll want to add a new method called `def test_import_certificate` to `tests/test_acm/test_acm.py`. * If you can also implement the code that gets that test passing that's great. If not, just ask the community for a hand and somebody will assist you. -# Maintainers +## Maintainers -## Releasing a new version of Moto +### Releasing a new version of Moto -You'll need a PyPi account and a Dockerhub account to release Moto. After we release a new PyPi package we build and push the [motoserver/moto](https://hub.docker.com/r/motoserver/moto/) Docker image. +You'll need a PyPi account and a DockerHub account to release Moto. After we release a new PyPi package we build and push the [motoserver/moto](https://hub.docker.com/r/motoserver/moto/) Docker image. * First, `scripts/bump_version` modifies the version and opens a PR * Then, merge the new pull request * Finally, generate and ship the new artifacts with `make publish` - diff --git a/moto/s3/responses.py b/moto/s3/responses.py index 41db43af7..d4d872a8d 100644 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -615,6 +615,19 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin): pass return False + def _create_bucket_configuration_is_empty(self, body): + if body: + try: + create_bucket_configuration = xmltodict.parse(body)[ + "CreateBucketConfiguration" + ] + del create_bucket_configuration["@xmlns"] + if len(create_bucket_configuration) == 0: + return True + except KeyError: + pass + return False + def _parse_pab_config(self, body): parsed_xml = xmltodict.parse(body) parsed_xml["PublicAccessBlockConfiguration"].pop("@xmlns", None) @@ -733,6 +746,9 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin): ): raise IllegalLocationConstraintException() if body: + if self._create_bucket_configuration_is_empty(body): + raise MalformedXML() + try: forced_region = xmltodict.parse(body)["CreateBucketConfiguration"][ "LocationConstraint" diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index 010a23d50..dbdd1b90c 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -1042,7 +1042,7 @@ def test_s3_object_in_public_bucket_using_multiple_presigned_urls(): @mock_s3 def test_streaming_upload_from_file_to_presigned_url(): - s3 = boto3.resource("s3") + s3 = boto3.resource("s3", region_name="us-east-1") bucket = s3.Bucket("test-bucket") bucket.create() bucket.put_object(Body=b"ABCD", Key="file.txt") @@ -1976,6 +1976,15 @@ def test_boto3_bucket_create_eu_central(): ) +@mock_s3 +def test_bucket_create_empty_bucket_configuration_should_return_malformed_xml_error(): + s3 = boto3.resource("s3", region_name="us-east-1") + with assert_raises(ClientError) as e: + s3.create_bucket(Bucket="whatever", CreateBucketConfiguration={}) + e.exception.response["Error"]["Code"].should.equal("MalformedXML") + e.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + + @mock_s3 def test_boto3_head_object(): s3 = boto3.resource("s3", region_name=DEFAULT_REGION_NAME)