Skip to content

AWS parity E2E audit: bugs, gaps & enhancements across all 30 services #319

Description

@thzgajendra

AWS parity E2E audit — bugs & enhancements (issue draft)

Method. Ran the standalone binary cloudemu serve --providers aws --aws-port 4566 and drove real aws-sdk-go-v2 clients (BaseEndpoint=http://127.0.0.1:4566) through dependency-ordered lifecycles per resource family — create → describe (with field assertions) → modify/associate → list → tag → sub-resources → delete → error paths. Every non-pass was hand-verified to separate real defects from bad test inputs.

Coverage. All 30 AWS service handlers exercised E2E (~250 operation calls): ec2, s3, iam, sts, dynamodb, lambda, rds, redshift, sqs, sns, eventbridge, secretsmanager, ssm, cloudwatch, cloudwatchlogs, ecr, ecs, eks, elbv2, elasticache, memorydb, keyspaces, route53, networkfirewall, resourcegroupstaggingapi, sagemaker, bedrock, bedrockagent, bedrockagentruntime, resourceexplorer2. Depth = representative dependency-ordered lifecycle per service (not literally every one of each service's SDK operations; EC2 additionally got a full 150-action reachability sweep). Runtime data-planes (model inference) not exercised.
Overall the emulator is strong — the vast majority of core CRUD + error paths pass, and it correctly enforces dependency violations, resource state, and CIDR overlaps.

Parity coverage vs full AWS API (implemented ops ÷ total SDK ops)

High-level breadth (denominator = the entire AWS API for the service, incl. many niche ops an emulator need not cover, so low % is expected for large services):

Service impl/SDK Service impl/SDK Service impl/SDK
ec2 150/773 rds 79/168 sagemaker 113/403
iam 39/176 ecs 37/77 memorydb 33/45
keyspaces 18/19 elbv2 18/51 dynamodb 15/57
eventbridge 14/57 cloudwatch 10/46 elasticache 10/75
sns 9/42 redshift 9/141 cloudwatchlogs 9/118
ssm 11/152 sqs 7/23 secretsmanager 7/23
ecr 7/58 networkfirewall 20/84 resourcegroupstaggingapi 9/9
s3 / lambda / route53 / eks / bedrock* path/target-dispatch (subset)

Thinnest relative to common usage: redshift, cloudwatchlogs, ssm, elasticache, ecr, resourceexplorer2.


Cross-cutting themes (fix these first — highest leverage)

A. Tagging is systemically missing/inconsistent

The tag operations users rely on for every IaC tool are absent across many services:

  • ec2 CreateTags / DeleteTagsInvalidAction
  • dynamodb TagResourceUnknownOperationException
  • sns TagResourceInvalidAction
  • secretsmanager TagResourceUnknownOperationException
  • ssm AddTagsToResourceUnknownOperationException
  • sqs TagQueueUnknownOperationException
  • lambda TagResource405 + non-JSON body (SDK can't deserialize → wire bug)

Impact: Terraform/CloudFormation/CDK tag nearly everything; tag-on-create or post-create tagging fails. A shared tagging surface would close most of these at once.

B. Set*/Modify* attribute operations commonly missing

  • sqs GetQueueAttributes / SetQueueAttributesHigh: GetQueueAttributes is how you read a queue ARN (event-source mappings, DLQ wiring, S3→SQS notifications). Its absence breaks many real flows.
  • sqs PurgeQueue
  • sns SetTopicAttributes
  • elasticache ModifyCacheCluster
  • redshift CreateClusterParameterGroup
  • cloudwatchlogs PutRetentionPolicy
  • cloudwatch SetAlarmState
  • secretsmanager UpdateSecretHigh: updating a secret's metadata is a routine op

D. Unimplemented REST/JSON paths return a 405 HTML page (breaks SDK error handling) — Med

Some unimplemented operations on REST/JSON services return an HTTP 405 + an HTML error body instead of a structured JSON API error. The SDK then fails to deserialize the response (invalid character '<') rather than surfacing a clean "operation not supported". Seen on: lambda TagResource, resourceexplorer2 CreateIndex / GetDefaultView. Users get an opaque parse error instead of an actionable API error.

C. EC2 Describe* by nonexistent ID returns empty success (systemic) — High

Describe{Vpcs,Instances,Volumes,SecurityGroups} with an explicit missing ID returns an empty set with no error, where real AWS returns Invalid*.NotFound. Confirmed across 4 resource types → almost certainly the shared EC2 ID-filter path. Breaks existence checks, Terraform refresh/drift, and "wait-until-deleted" polls. One shared fix likely covers all EC2 types.


Per-service findings

Service Operation(s) Type Sev Note
ec2 Describe{Vpcs,Instances,Volumes,SecurityGroups}(missing id) BUG High no Invalid*.NotFound (theme C)
ec2 CreateTags / DeleteTags GAP High tagging (theme A)
ec2 CreateNetworkInterface GAP Med ENI describe/detach/delete exist; create missing
ec2 MonitorInstances / DescribeInstanceStatus GAP Med common instance ops
ec2 DescribeRegions / DescribeInstanceTypes GAP Med bootstrap/validation calls
s3 HeadBucket (existing & missing) BUG Med HTTP HEAD /bucket verb not routed → 405; breaks bucket-exists check
s3 PutBucketTagging (PUT /bucket?tagging) BUG Med ?tagging subresource mis-routed to CreateBucket (BucketAlreadyOwnedByYou)
sqs GetQueueAttributes / SetQueueAttributes GAP High queue ARN/config (theme B)
sqs PurgeQueue / TagQueue GAP Med
sqs GetQueueUrl(missing) ENH Low code QueueDoesNotExist vs AWS AWS.SimpleQueueService.NonExistentQueue
sns SetTopicAttributes / TagResource GAP Med
lambda UpdateFunctionConfiguration / PublishVersion / CreateAlias / AddPermission GAP High 404 "unsupported Lambda path" — versioning/alias/permission/config
lambda TagResource BUG-WIRE Med 405 + HTML body → SDK deserialize error
dynamodb TagResource / DescribeTimeToLive GAP Med
iam PutRolePolicy GAP Med inline role policies
secretsmanager UpdateSecret / TagResource GAP High/Med
ssm AddTagsToResource GAP Med
ecr GetAuthorizationToken GAP High required for image push/pull auth (docker login)
ecr SetRepositoryPolicy GAP Low
elasticache ModifyCacheCluster GAP Med
redshift CreateClusterParameterGroup GAP Med
cloudwatchlogs PutRetentionPolicy GAP Med
cloudwatch SetAlarmState GAP Low also returns UnknownError message
cloudwatch PutMetricData (empty MetricData) BUG Low rejects (correct) but message InvalidParameterValue: UnknownError unhelpful
resourceexplorer2 CreateIndex / GetDefaultView BUG-WIRE Med 405 + HTML body → SDK deserialize error (theme D); Search/ListViews/ListIndexes/ListResources work
bedrock / bedrockagent / bedrockagentruntime list/get/create + Retrieve all passed (ListFoundationModels, GetFoundationModel, guardrails, CreateAgent, ListKnowledgeBases, Retrieve)

Verified-correct behavior (NOT bugs — excluded)

  • ec2 DeleteSubnet/DeleteVpcDependencyViolation (I hadn't removed ENI/NAT) ✔ good FK enforcement
  • ec2 ModifyInstanceAttribute (type) on a running instance → IncorrectInstanceState ✔ correct
  • ec2 CreateVpcPeeringConnection self-peer → CIDR-overlap rejection ✔ correct
  • s3 DeleteBucket on non-empty bucket → BucketNotEmpty ✔ correct
  • eks DeleteCluster with a live nodegroup → InvalidRequestException ✔ correct

Passed cleanly (solid)

rds (instances/snapshots/clusters/param+subnet groups), ecs (cluster/task-def/service/run-task), sagemaker (model/endpoint-config/endpoint/notebook/training-job), dynamodb data-plane (put/get/query/scan/update/batch), s3 object data-plane, iam roles/users/policies/instance-profiles/groups, route53 zones+record sets, keyspaces, memorydb, eks cluster+nodegroup, elbv2 LB/target-group/listener/register, redshift cluster lifecycle, bedrock list ops, and all non-EC2 missing-resource error paths (proper *NotFound).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions