Service
S3 (S3 Control API) — bucket tagging.
AWS API Action
ListTagsForResource (S3 Control API — the GET /v20180820/tags/<arn> endpoint on the account-prefixed host <account-id>.s3-control...).
This is the operation #341 added so the Terraform AWS provider v6.x can read S3 bucket tags. It is distinct from the standard S3 GetBucketTagging.
Expected behavior
For an existing bucket, S3 Control ListTagsForResource returns the bucket's tag set with HTTP 200 — an empty <Tags/> set for an untagged bucket — mirroring what the standard S3 GetBucketTagging already returns on the same bucket. This is what #341 set out to provide.
Actual behavior
floci responds with HTTP 403 and an AccessDenied body for every ListTagsForResource call, instead of returning the tags:
<?xml version="1.0" encoding="UTF-8"?>
<ErrorResponse><Error><Code>AccessDenied</Code><Message>Access Denied</Message><AccountId>000000000000</AccountId></Error><RequestId>…</RequestId><HostId>…</HostId></ErrorResponse>
(The <ErrorResponse> wrapper is correct since #557 — the problem is the AccessDenied verdict, not the envelope.)
The standard S3 GetBucketTagging on the same bucket works fine:
$ aws --endpoint-url http://floci:4566 s3api get-bucket-tagging --bucket repro
{ "TagSet": [] }
So floci serves the S3 (data-plane) tagging API but the S3 Control variant denies. Because the Terraform AWS provider v6.x reads aws_s3_bucket tags exclusively through S3 Control ListTagsForResource (AWS ABAC support), every read/refresh of a bucket fails — the bucket is created successfully but never converges.
Reproduction
Note: the AWS CLI / botocore ignores the S3 Control endpoint override (AWS_ENDPOINT_URL_S3CONTROL / --endpoint-url) and resolves S3 Control to the real *.s3-control.<region>.amazonaws.com host, so a naive aws s3control … command does not hit floci. The AWS SDK for Go v2 (which the Terraform AWS provider uses) honours BaseEndpoint, so the repro uses it.
// go.mod: github.com/aws/aws-sdk-go-v2/service/s3control
cfg, _ := config.LoadDefaultConfig(ctx,
config.WithRegion("us-east-1"),
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider("test", "test", "")),
)
// First create a bucket via the S3 client (BaseEndpoint http://floci:4566, UsePathStyle true).
// Then:
sc := s3control.NewFromConfig(cfg, func(o *s3control.Options) {
o.BaseEndpoint = aws.String("http://floci:4566")
})
_, err := sc.ListTagsForResource(ctx, &s3control.ListTagsForResourceInput{
AccountId: aws.String("000000000000"),
ResourceArn: aws.String("arn:aws:s3:::repro"),
})
// err => operation error S3 Control: ListTagsForResource, https response error
// StatusCode: 403, api error AccessDenied: Access Denied
End-to-end, this surfaces through the Crossplane Upbound provider-aws-s3 v2.6.1 (which wraps Terraform AWS provider v6): an s3.aws.m.upbound.io Bucket is created in floci, but its Observe fails forever with:
observe failed: failed to observe the resource: [{0 listing tags for S3 (Simple Storage) Bucket
(repro-…): operation error S3 Control: ListTagsForResource, https response error StatusCode: 403,
RequestID: …, HostID: …, api error AccessDenied: Access Denied []}]
so the managed resource never reaches Ready even though the bucket exists.
Environment
- Floci version / image tag:
floci/floci:latest (build 2026-06-24); also reproduced on 1.5.25 and 1.5.27.
- SDK: AWS SDK for Go v2 via Terraform AWS provider v6.x (Crossplane Upbound
provider-aws-s3:v2.6.1).
- How you're running Floci: Docker image in Kubernetes (kind), serving
http://floci:4566, account 000000000000, region us-east-1.
Related
Service
S3 (S3 Control API) — bucket tagging.
AWS API Action
ListTagsForResource(S3 Control API — theGET /v20180820/tags/<arn>endpoint on the account-prefixed host<account-id>.s3-control...).This is the operation #341 added so the Terraform AWS provider v6.x can read S3 bucket tags. It is distinct from the standard S3
GetBucketTagging.Expected behavior
For an existing bucket, S3 Control
ListTagsForResourcereturns the bucket's tag set with HTTP 200 — an empty<Tags/>set for an untagged bucket — mirroring what the standard S3GetBucketTaggingalready returns on the same bucket. This is what #341 set out to provide.Actual behavior
floci responds with HTTP 403 and an
AccessDeniedbody for everyListTagsForResourcecall, instead of returning the tags:(The
<ErrorResponse>wrapper is correct since #557 — the problem is theAccessDeniedverdict, not the envelope.)The standard S3
GetBucketTaggingon the same bucket works fine:So floci serves the S3 (data-plane) tagging API but the S3 Control variant denies. Because the Terraform AWS provider v6.x reads
aws_s3_buckettags exclusively through S3 ControlListTagsForResource(AWS ABAC support), every read/refresh of a bucket fails — the bucket is created successfully but never converges.Reproduction
Note: the AWS CLI / botocore ignores the S3 Control endpoint override (
AWS_ENDPOINT_URL_S3CONTROL/--endpoint-url) and resolves S3 Control to the real*.s3-control.<region>.amazonaws.comhost, so a naiveaws s3control …command does not hit floci. The AWS SDK for Go v2 (which the Terraform AWS provider uses) honoursBaseEndpoint, so the repro uses it.End-to-end, this surfaces through the Crossplane Upbound provider-aws-s3 v2.6.1 (which wraps Terraform AWS provider v6): an
s3.aws.m.upbound.ioBucket is created in floci, but its Observe fails forever with:so the managed resource never reaches
Readyeven though the bucket exists.Environment
floci/floci:latest(build 2026-06-24); also reproduced on1.5.25and1.5.27.provider-aws-s3:v2.6.1).http://floci:4566, account000000000000, regionus-east-1.Related
[FEAT] S3: Implement S3 Control API ListTagsForResource (used by Terraform AWS provider v6.x)(closed). This report is that the implemented handler returnsAccessDeniedrather than the tag set, so the feature does not yet unblock the provider-v6 flow it was added for.[BUG] S3 Control error responses are missing the '<ErrorResponse …>' wrapper(closed). The wrapper is now present; this is a separate, behavioural issue (the verdict, not the envelope).