What's Changed
New Contributors
- @CSandyHub made their first contribution in #359
- @Baptiste-Garcin made their first contribution in #356
- @fzonneveld made their first contribution in #302
[1.2.20] — 2026-04-17
Added
- EKS service with k3s backend — CreateCluster, DescribeCluster, ListClusters, DeleteCluster, CreateNodegroup, DescribeNodegroup, ListNodegroups, DeleteNodegroup, TagResource, UntagResource, ListTagsForResource.
CreateClusterspawns a real k3s Docker container (75 MB) providing a full Kubernetes API server.kubectl, Helm, and any K8s tooling work out of the box. Cascading delete removes nodegroups and k3s container. CloudFormationAWS::EKS::ClusterandAWS::EKS::Nodegroupprovisioners included. - Lambda layer S3 support —
PublishLayerVersionnow acceptsS3Bucket/S3Keyin Content, matching real AWS behavior. Contributed by @Baptiste-Garcin (#356) - Lambda Docker executor rewritten with AWS RIE —
LAMBDA_EXECUTOR=dockernow uses official AWS Lambda Runtime Interface Emulator images (public.ecr.aws/lambda/*) for all runtimes (Python, Node.js, provided). Events are POSTed to the RIE HTTP endpoint on port 8080, matching exact AWS Lambda execution semantics. Containers are kept warm between invocations and reused when the same function+code is invoked again. Cleaned up onreset()and shutdown. Addednodejs22.x,nodejs24.x,python3.14runtimes. Contributed by @fzonneveld (#302) - Lambda Windows compatibility — replaced
select.select()stderr polling with cross-platform background thread + queue. Fixes Lambda warm worker execution on Windows. Contributed by @davidtme (#350) - Lambda ESM poller on CFN create and state restore — event source mappings created via CloudFormation or restored from persisted state now correctly start the background poller. Contributed by @davidtme (#350)
Fixed
AWS Compliance (21 fixes from full-codebase audit)
- KMS
Verifyerror handling — invalid signatures now raiseKMSInvalidSignatureException(HTTP 400) instead of returningSignatureValid: falsewith HTTP 200, matching real AWS behavior. - KMS
Decrypt/GenerateDataKey/Sign/Verify/EncryptresponseKeyId— all KMS crypto operations now return the full key ARN in theKeyIdfield instead of the bare UUID, matching real AWS. - KMS
PendingDeletionstate check —Encrypt,Decrypt,Sign,Verify, andGenerateDataKeynow returnKMSInvalidStateExceptionwhen called on a key scheduled for deletion or disabled. Previously these operations silently succeeded. - EC2
TerminateInstances/StopInstances/StartInstancesunknown instance IDs — now returnInvalidInstanceID.NotFounderror instead of silently succeeding with an empty response. - EC2 VPC
cidrBlockAssociationSetmissing —CreateVpcandDescribeVpcsresponses now include<cidrBlockAssociationSet>with the primary CIDR association. Fixes Terraform AWS provider v6 crash (index out of range [0]). Reported by @mspiller (#331) - SQS FIFO
DeduplicationScope: messageGroup— content-based deduplication now correctly scopes per message group whenDeduplicationScopeismessageGroup. Previously, two messages with the same body but differentMessageGroupIdvalues were incorrectly deduplicated. Contributed by @CSandyHub (#359) - SNS
ListSubscriptionsXML escaping — endpoint URLs containing&or other XML special characters are now properly escaped, preventing malformed XML responses. - DynamoDB
DescribeTableLatestStreamArnstability — stream ARN and label are now set once whenStreamSpecificationis enabled instead of regenerated on everyDescribeTablecall. Fixes CDK drift detection and ESM setup failures. - SSM
GetParametersByPathroot path —GetParametersByPathwithPath=/andRecursive=falsenow correctly returns only top-level parameters instead of all parameters in the store. - ElastiCache
AutomaticFailover/MultiAZvalues —CreateReplicationGroupandModifyReplicationGroupnow returnenabled/disabledenum values instead of rawtrue/falsestrings, matching the AWS API contract. - Transfer Family pagination off-by-one —
ListServersandListUsersno longer re-serve the token item when paginating, fixing duplicate entries across pages. - ECS
PutAccountSettingDefaultinconsistency — now stores a plain string value likePutAccountSetting, fixingListAccountSettingsresponse shape when both endpoints were used. - IAM user inline policy persistence — restructured
_user_inline_policiesfrom tuple keys(user, policy)to nested dict{user: {policy: doc}}. Tuple keys silently broke JSON serialization, causing all user inline policies to be lost on restart withPERSIST_STATE=1. - Route53
reset()multi-tenancy —reset()now calls.clear()on existingAccountScopedDictinstances instead of replacing them with plaindictobjects, preserving multi-tenant isolation after reset. - STS
AssumeRoleWithWebIdentityprovider —Providerfield now uses the caller-suppliedProviderIdinstead of hardcodedaccounts.google.com. - EKS state persistence —
get_state()now savesport_counterand strips Docker container IDs.restore_state()restores port counter and marks clusters asFAILED(k3s containers don't survive restart).
Architecture & Safety
- Persistence
eval()replaced withast.literal_eval— deserialization ofAccountScopedDictkeys no longer useseval(), closing a code injection vector via crafted state files. Contributed by @AdigaAkhil - RDS
_wait_for_portno longer blocks event loop — container port wait now runs in a background thread. Previously aCreateDBInstancewith Docker could block the entire ASGI server for up to 60 seconds. - RDS
get_state()multi-account persistence —get_state()now serializes instances as a fullAccountScopedDict, capturing all accounts instead of only the default account at shutdown time. - RDS
_port_counterthread safety — port allocation now uses athreading.Lock, preventing potential duplicate ports under concurrent requests. - Lambda ESM poller account context — background SQS/Kinesis/DynamoDB Streams pollers now iterate
_esms._datadirectly and set the correct account context per ESM. Previously, event source mappings created under non-default accounts were silently never polled.
Also Fixed
- EC2 SecurityGroup duplicate detection ignoring Description —
AuthorizeSecurityGroupIngressduplicate check andRevokeSecurityGroupIngressnow compare rules without theDescriptionfield, matching AWS behavior. - CloudWatch DeleteDashboards error — deleting a nonexistent dashboard returned 500 InternalError instead of 404 DashboardNotFoundError.
- Athena ListNamedQueries empty —
ListNamedQuerieswithout aWorkGroupfilter now returns all queries instead of only "primary" workgroup. - ElastiCache CreateCacheSubnetGroup missing Subnets — response XML now includes
<Subnets>element. - Cognito OAuth2 lazy loading — OAuth2 endpoints now use lazy module loading, fixing crash when Cognito module wasn't pre-imported.
- Cognito OAuth2 persistence —
_authorization_codesand_refresh_tokensnow included in state persistence. - Lambda warm worker stuck after init failure — broken workers are now invalidated so the next invocation gets a fresh process. Reported by @Baptiste-Garcin
- Docker image missing
boto3— Lambda functions importingboto3now work out of the box. Real AWS Lambda runtimes pre-installboto3; the Docker image only hadbotocore(viaawscli). Reported by @xPTM1219 (#362)