Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions localstack-core/localstack/services/s3/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,9 +492,11 @@ def create_bucket(
if not is_bucket_name_valid(bucket_name):
raise InvalidBucketName("The specified bucket is not valid.", BucketName=bucket_name)

# TODO: support `Tags` in `CreateBucketConfiguration`
create_bucket_configuration = request.get("CreateBucketConfiguration") or {}
bucket_region = create_bucket_configuration.get("LocationConstraint")
bucket_tags = create_bucket_configuration.get("Tags")
if bucket_tags:
validate_tag_set(bucket_tags, type_set="create-bucket")
if bucket_region:
if context.region == AWS_REGION_US_EAST_1:
if bucket_region in ("us-east-1", "aws-global"):
Expand Down Expand Up @@ -522,8 +524,9 @@ def create_bucket(
if existing_bucket_owner != context.account_id:
raise BucketAlreadyExists()

# if the existing bucket has the same owner, the behaviour will depend on the region
if bucket_region != "us-east-1":
# if the existing bucket has the same owner, the behaviour will depend on the region and if the request has
# tags
if bucket_region != AWS_REGION_US_EAST_1 or bucket_tags:
raise BucketAlreadyOwnedByYou(
"Your previous request to create the named bucket succeeded and you already own it.",
BucketName=bucket_name,
Expand All @@ -542,6 +545,7 @@ def create_bucket(
# see https://docs.aws.amazon.com/AmazonS3/latest/API/API_Owner.html
owner = get_owner_for_account_id(context.account_id)
acl = get_access_control_policy_for_new_resource_request(request, owner=owner)

s3_bucket = S3Bucket(
name=bucket_name,
account_id=context.account_id,
Expand All @@ -554,6 +558,11 @@ def create_bucket(

store.buckets[bucket_name] = s3_bucket
store.global_bucket_map[bucket_name] = s3_bucket.bucket_account_id
if bucket_tags:
store.TAGS.tag_resource(
arn=s3_bucket.bucket_arn,
tags=bucket_tags,
)
self._cors_handler.invalidate_cache()
self._storage_backend.create_bucket(bucket_name)

Expand Down
21 changes: 16 additions & 5 deletions localstack-core/localstack/services/s3/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -841,13 +841,20 @@ def parse_tagging_header(tagging_header: TaggingHeader) -> dict:
)


def validate_tag_set(tag_set: TagSet, type_set: Literal["bucket", "object"] = "bucket"):
def validate_tag_set(
tag_set: TagSet, type_set: Literal["bucket", "object", "create-bucket"] = "bucket"
):
keys = set()
for tag in tag_set:
if set(tag) != {"Key", "Value"}:
raise MalformedXML()

key = tag["Key"]
value = tag["Value"]

if key is None or value is None:
raise MalformedXML()

if key in keys:
raise InvalidTag(
"Cannot provide multiple Tags with the same key",
Expand All @@ -857,21 +864,25 @@ def validate_tag_set(tag_set: TagSet, type_set: Literal["bucket", "object"] = "b
if key.startswith("aws:"):
if type_set == "bucket":
message = "System tags cannot be added/updated by requester"
else:
elif type_set == "object":
message = "Your TagKey cannot be prefixed with aws:"
else:
message = 'User-defined tag keys can\'t start with "aws:". This prefix is reserved for system tags. Remove "aws:" from your tag keys and try again.'
raise InvalidTag(
message,
TagKey=key,
# weirdly, AWS does not return the `TagKey` field here, but it does if the TagKey does not match the
# regex in the next step
TagKey=key if type_set != "create-bucket" else None,
)

if not TAG_REGEX.match(key):
raise InvalidTag(
"The TagKey you have provided is invalid",
TagKey=key,
)
elif not TAG_REGEX.match(tag["Value"]):
elif not TAG_REGEX.match(value):
raise InvalidTag(
"The TagValue you have provided is invalid", TagKey=key, TagValue=tag["Value"]
"The TagValue you have provided is invalid", TagKey=key, TagValue=value
)

keys.add(key)
Expand Down
Loading
Loading