What's Changed
New Contributors
- @OS-kiranmalsetty made their first contribution in #2212
[1.5.28] — 2026-10-16
Added
- RDS —
DescribeEventswith reboot events —DescribeEventsreturns theavailabilityeventDB instance restarted.once aRebootDBInstancehas finished, filtered by source, source type, category and time, paged withMarkerand kept for 14 days; other RDS lifecycle events are not recorded yet. Contributed by @jayjanssen. - S3 Control — Multi-Region Access Points —
CreateMultiRegionAccessPoint,DeleteMultiRegionAccessPoint,PutMultiRegionAccessPointPolicy,DescribeMultiRegionAccessPointOperation,GetMultiRegionAccessPoint,GetMultiRegionAccessPointPolicy,ListMultiRegionAccessPoints,GetMultiRegionAccessPointRoutesandSubmitMultiRegionAccessPointRoutes. The async operations apply at once andDescribereportsSUCCEEDED, orFAILEDwith AWS'sErrorDetailsfor a missing bucket, two buckets in one region or a name already in use. Management is served fromus-west-2and route operations fromus-east-1,us-west-2,eu-west-1,ap-northeast-1andap-southeast-2, as on AWS; other regions get301 PermanentRedirect.DeleteBucketon a member returnsBucketHasAccessPointsAttached. UnderAUTH=trueeach operation needs itss3:IAM action andx-amz-account-idmust name the caller's account. Access points fromAWS::S3::MultiRegionAccessPointappear in the API. Contributed by @fabio-andre-rodrigues. - S3 — Multi-Region Access Point failover — a request through the MRAP host goes to the member with a traffic dial of 100 that is homed in
MINISTACK_REGION, else the first active member. Setting a dial to 0 moves traffic to the other member, and an update that leaves every dial at 0 is refused. Contributed by @fabio-andre-rodrigues. - CloudFormation —
DescribeEvents— returns the validation errors of a create that fails pre-deployment validation, which the stack'sCREATE_FAILEDevent tells the caller to look up; every request member is optional. Contributed by @fabio-andre-rodrigues. - WAF v2 — regex pattern sets —
CreateRegexPatternSet,GetRegexPatternSet,UpdateRegexPatternSet,DeleteRegexPatternSetandListRegexPatternSetsnow manage regional and CloudFront-scoped regex pattern sets, with their ARN (regexpatternset), tags andLockTokenchecks on update and delete (WAFOptimisticLockExceptionfor a stale token), as AWS does. Web ACL and rule group rules are stored as sent, so aRegexPatternSetReferenceStatementpointing at a pattern set ARN round-trips; the statement is not evaluated, as MiniStack does not inspect requests. Contributed by @OS-kiranmalsetty. - IoT — job rollout rates —
jobExecutionsRolloutConfigwas stored but every execution was created at once; a job now createsmaximumPerMinuteexecutions a minute, or a rate that starts atbaseRatePerMinuteand grows byincrementFactorfor everyrateIncreaseCriteriastep of notified or succeeded things, notifies each thing when its execution is created, reportsisConcurrentuntil the last batch and stops when the job is canceled or deleted. Contributed by @iot-rocket. - Health —
authfield —/_ministack/healthreports"auth": "enabled"or"disabled", the effectiveAUTHmode. Contributed by @jgrumboe. - Auth — REST API resource policies are evaluated under
AUTH=true— an API Gateway resource policy took no part in the decision; for anexecute-api:Invokea statement naming the calling user or role now allows the call without an identity policy, a statement naming only the account still needs one, a Deny wins over an identity Allow, and a call without a SigV4 signature (none, or a bearer token) to a method without authorization passes only when the policy, if any, allows everyone, else it answersACCESS_DENIEDwith API Gateway's message. Contributed by @iot-rocket. - Auth — KMS key policies are evaluated under
AUTH=true— a key policy took no part in the decision; it now has to allow even in the key's own account: a statement naming the calling user or role allows the call without an identity policy, identity policies count only when the key policy has a statement for the account (the default key policy does), and a Deny wins over an identity Allow. Contributed by @iot-rocket. - Auth — ECR repository policies count under
AUTH=true— a repository policy took no part in the decision; a statement naming the calling user or role now allows the call without an identity policy, a statement naming only the account still needs one, and a Deny wins over an identity Allow. Contributed by @iot-rocket. - Auth — Secrets Manager resource policies count under
AUTH=true— a secret's resource policy took no part in the decision; a statement naming the calling user or role now allows the call without an identity policy, a statement naming only the account still needs one, and a Deny wins over an identity Allow. Contributed by @iot-rocket. - Auth — Lambda function policies count under
AUTH=true— anAddPermissionstatement naming the calling user or role did not let a caller without an identity policy in; it now allows the actions it names (InvokeFunction,GetFunction, ...), while a statement naming only the account still needs an identity Allow, and a call that names the function by ARN is checked against that ARN. Contributed by @iot-rocket. - Auth — bucket policies count under
AUTH=truein the owner's account — a bucket policy was consulted only for another account's requests; in the owner's account a statement naming the calling user or role now allows the request without an identity policy, a statement naming only the account still needs one, and a Deny wins over an identity Allow, CDK'saws:SecureTransportDeny on the bootstrap bucket included. Contributed by @iot-rocket. - Auth — queue and topic policies count under
AUTH=true— a queue or topic policy statement naming the calling user or role did not let a caller without an identity policy in; in the owner's account it now allows the call, a statement naming only the account still needs an identity Allow, and across accounts both have to allow. A denial answersAuthorizationErroron SNS and reportsAccessDeniedto SDKs on SQS, its message says "with an explicit deny in a resource-based policy" when the resource's policy denied, and the check reads the queue of the account theQueueUrlnames. Contributed by @iot-rocket. - IoT —
EnableTopicRuleandDisableTopicRule— both calls were missing (POST /rules/{ruleName}/enableansweredInvalid ruleName), so a rule could only be switched off by replacing it; they now setruleDisabled, whichGetTopicRuleandListTopicRulesreport and which stops the rule from acting on matching publishes and Basic Ingest until it is enabled again. Contributed by @iot-rocket. - IoT — job documents from S3 —
CreateJobandCreateJobTemplateread adocumentSource(s3://or an S3 object URL) from MiniStack's S3 once, at creation, where they stored a{"documentSource": "<url>"}placeholder. A missing bucket or object, an object that is not JSON or is over 32 KB and a URL that names no S3 host are refused with AWS's messages, andCreateJobrefusesdocumenttogether withdocumentSource. Devices get every job document re-serialized as AWS sends it, without spaces and without object members that are null, whileGetJobDocumentkeeps the stored text. Contributed by @iot-rocket. - IoT — presigned URLs in job documents — devices got
${aws:iot:s3-presigned-url:<url>}and${aws:iot:s3-presigned-url-v2:<url>}placeholders as written; theiot-jobs-dataAPI and the MQTT jobs topics now replace each with a SigV4 presigned GET URL of MiniStack's S3, signed with a session ofpresignedUrlConfig.roleArnand valid forexpiresInSec, andCreateJobandCreateJobTemplaterefuse a placeholder without a role or an S3 object URL with AWS's messages. Contributed by @iot-rocket. - IoT — fleet provisioning by claim —
CreateProvisioningClaimissues a five-minute claim certificate that the mTLS listener accepts until it expires, and a device connected with it (or with any registered certificate) gets a certificate from$aws/certificates/create/jsonand registers itself through$aws/provisioning-templates/<name>/provision/json: the template's parameters,RefandFn::Joinare resolved, the thing is created or checked against itsOverrideSettings, and the certificate is activated and attached to the thing and the template's policies, with AWS's replies and rejections on the requesting connection; withAUTH=truea claim connection is limited to the certificate topics and its own template's, as on AWS. Contributed by @iot-rocket. - IoT — pre-provisioning hook —
RegisterThingover MQTT now invokes the template'spreProvisioningHookLambda before the template is resolved and applies its answer the way AWS does:parameterOverridesare merged into the device's parameters,allowProvisioning: falseis rejected asAccessDenied, and a function that fails, answers in another shape, takes longer than six seconds or may not be invoked gets AWS'sInvocationErrororInvalidResult.CreateProvisioningTemplateandUpdateProvisioningTemplatecheck the hook like AWS (a Lambda function ARN, payload version2020-04-01, no hook on JITP templates, and an invoke permission foriot.amazonaws.comthat covers the template) and store the default payload version. Contributed by @iot-rocket. - IoT — provisioning template versions —
CreateProvisioningTemplateVersion,ListProvisioningTemplateVersions,DescribeProvisioningTemplateVersionandDeleteProvisioningTemplateVersionansweredUnsupported IoT pathandUpdateProvisioningTemplaterefused everydefaultVersionIdbut 1; a template now keeps up to five versions whose ids are never reused,setAsDefaultanddefaultVersionIdchoose the version thatDescribeProvisioningTemplatereturns andRegisterThingapplies, the default version cannot be deleted, and anAWS::IoT::ProvisioningTemplatewhoseTemplateBodychanges gets a new default version (deleting the oldest at the limit), all with AWS's errors, including its message for a body that is not JSON. Contributed by @iot-rocket. - Cognito —
UpdateUserPoolDomainandAWS::Cognito::UserPoolDomainstack updates —UpdateUserPoolDomainwas an unknown action; it now changes a domain'sManagedLoginVersionand a custom domain's certificate,CreateUserPoolDomainandDescribeUserPoolDomainreturn the version, and a second prefix domain on a pool is refused as on AWS. A stack update appliesManagedLoginVersionandCustomDomainConfigthrough it instead of running the create again, aDomainorUserPoolIdchange replaces the domain, the create keepsCustomDomainConfig,Refreturns the domain name andFn::GetAttreturnsCloudFrontDistribution. Contributed by @iot-rocket. - CloudFormation — SES configuration set updates —
AWS::SES::ConfigurationSetandAWS::SES::ConfigurationSetEventDestinationstored none of their options, tags or destinations, and a change re-ran the create; both now provision through the SES v2 calls and update in place, a removed option goes back to its default as on AWS, and only aNameorConfigurationSetNamechange replaces them. Contributed by @iot-rocket. - SES v2 — configuration set options and event destinations —
GetConfigurationSetreturned only the name and the tags given at creation; it now returns the tracking, delivery, reputation, sending, suppression, VDM and archiving options thatCreateConfigurationSetand the sevenPutConfigurationSet*Optionscalls set, and a call clears the members it leaves out, as on AWS.CreateConfigurationSetEventDestination,GetConfigurationSetEventDestinations,UpdateConfigurationSetEventDestinationandDeleteConfigurationSetEventDestinationare new.CreateConfigurationSetwith a name already in use is refused withAlreadyExistsExceptioninstead of replacing the set. Contributed by @iot-rocket. - IoT — job abort criteria — a job's
abortConfigwas stored but never acted on; once a device report, aCancelJobExecution, aDeleteJobExecutionor a timeout meets one of its criteria, the job is now canceled with reasonCodeABORT_CANCELand AWS's comment, together with itsQUEUEDexecutions.CreateJobandCreateJobTemplatestored anyabortConfig; they now refuse whatUpdateJobrefuses, and all three refuse a missing criterion member, a threshold of 0 or less or with more than two decimals, and a failure type given twice. ACancelJobwithoutforcenow reportsforceCanceledas false. Contributed by @iot-rocket.
Changed
- RDS — real instance reboot —
RebootDBInstancenow returnsrebooting, stops and starts its backing database container, and waits for SQL readiness before reportingavailable. Data and endpoint bindings are preserved. An instance that is notavailableanswersInvalidDBInstanceState, and a Docker failure reportsfailedrather than a successful reboot. Contributed by @jayjanssen.
Fixed
- CloudFront — function status follows publish and association —
DescribeFunctionandListFunctionsreported theDEVELOPMENTstage asUNPUBLISHEDeven afterPublishFunction, so Terraform'saws_cloudfront_function.status, which reads that stage, never leftUNPUBLISHED; once the current development version is published it now reportsUNASSOCIATED, orDEPLOYEDwhile a distribution's cache behavior references the function, and anUpdateFunctionmakes itUNPUBLISHEDagain until the next publish. Contributed by @fabio-andre-rodrigues. - S3 — bucket home region is enforced — a request signed for a region other than the bucket's now returns
301 PermanentRedirectwithx-amz-bucket-region, which SDKs follow; at the bucket's own regional endpoint it returns400 AuthorizationHeaderMalformedor, presigned,AuthorizationQueryParametersError, with<Region>. HEAD gets the bodiless forms.GetBucketLocation,ListBuckets,CreateBucket, unsigned, SigV2 and SigV4a requests, MRAP requests and internal callers are exempt, andCopyObjectfrom a source in another region still works. Contributed by @fabio-andre-rodrigues. - S3 —
CreateBucketlocation constraint (breaking) — a request signed for a region other thanus-east-1must name that region asLocationConstraint, or getsIllegalLocationConstraintException;LocationConstraint=us-east-1returnsInvalidLocationConstraint. Clients that created buckets in another region without a constraint now need one.BucketAlreadyOwnedByYouandBucketAlreadyExistscarry AWS's message and<BucketName>. Contributed by @fabio-andre-rodrigues. - S3 —
ListBucketsbucket-regionfilter —BucketRegionlists only that region's buckets, with pagination inside the filter; a filter for another region than the endpoint's returnsInvalidArgument. Contributed by @fabio-andre-rodrigues. - S3 — replication — delete markers replicate for V1 rules (no
Filter) and for V2 rules withDeleteMarkerReplicationenabled and no tag filter, fromDeleteObjectandDeleteObjects; version-id deletes don't. Rules withFilter.TagorFilter.And.Tagsreplicate only objects carrying those tags. Contributed by @fabio-andre-rodrigues. - SigV4a requests no longer land in region
s3— the region was read from a credential scope that SigV4a doesn't have; a single-regionX-Amz-Region-Setis used, else the default region. Contributed by @fabio-andre-rodrigues. - Lambda — S3 code from another region —
CreateFunction,UpdateFunctionCode,PublishLayerVersionand CloudFormation return AWS'sInvalidParameterValueExceptionwhen the code bucket is homed elsewhere. Contributed by @fabio-andre-rodrigues. - Resource Groups Tagging — S3 buckets by region —
GetResources,GetTagKeysandGetTagValueslist only buckets homed in the region they are called in. Contributed by @fabio-andre-rodrigues. - CloudFormation —
User Initiatedon stack events — the stack'sCREATE_IN_PROGRESSandUPDATE_IN_PROGRESSevents ofCreateStackandUpdateStackcarried no reason; they now carryUser Initiated, as AWS does. - CloudFormation —
AWS::S3::Bucketand existing names — anAWS::S3::BucketwhoseBucketNamealready exists, in this account or another, was adopted (another account's became a second bucket of that name); it now fails pre-deployment validation withNAME_CONFLICT_VALIDATION, or withDisableValidationthe resource's create with<name> already exists, as on AWS, and auto-named buckets get a new name for each stack instance.CreateStack,UpdateStackandCreateChangeSettakeDisableValidation, and an update now runs the same pre-deployment validation, ending inUPDATE_ROLLBACK_COMPLETEwithout touching a resource (a bucket the stack already owns is not a conflict). With rollback disabled, a failed validation emits AWS's secondCREATE_FAILEDevent (breaking: a stack no longer adopts a bucket left over from an earlier stack or an S3-only restore). Contributed by @fabio-andre-rodrigues. - AppSync — GraphQL requests on the API's own host — a
POST /graphqlto{apiId}.appsync-api.{region}.{host}, the endpointuris.GRAPHQLreports, was routed to AppSync Events when unsigned and found its API only byx-api-keywhen signed, so anAWS_IAMAPI could not be called there once a second API existed; the host label now selects the API (in the host's region for an unsigned request) and/graphqlon an Event API host answers404 ResourceNotFoundException, as on AWS. Contributed by @iot-rocket. - Cognito — no ID token without
openid— the/oauth2/tokenauthorization code and refresh token grants returned anid_tokenwhatever was granted; they now return one only when the grant carriesopenid, as AWS does, and a refresh token fromInitiateAuthorAdminInitiateAuthstill gets one. Contributed by @iot-rocket. - Cognito — token endpoint access tokens carry the granted scopes —
/oauth2/tokenwroteaws.cognito.signin.user.admininto every access token whatever was granted; the authorization code, client credentials and refresh token grants now write the requested scopes the app client allows (all of them when none are requested, only resource server scopes for client credentials) in the order AWS lists them, refreshed tokens keep the original scopes, and the pre token generation event'srequest.scopeslists them, so API Gateway scope checks decide as on AWS. Contributed by @iot-rocket. - S3 — object ACL grants answer another account's read — a bucket owned by another account refused every read that only the object ACL granted: the ACL was looked up under the wrong version, and a grant to the caller's canonical ID was never read. With ACLs enabled, a
READgrant to the account or a group now opensGetObjectandHeadObjectof the version it was set on,?versionId=included, andREAD_ACPopensGetObjectAcl; a grant to one account is not public, so Block Public Access leaves it in force. Contributed by @iot-rocket. - CloudWatch —
DescribeAlarmsandDescribeAlarmHistorypaging — both returned at mostMaxRecordsitems (default 100) and never aNextToken, so a paginator stopped after the first page; they now return aNextTokenwhile more items match, default to 50 items and refuse aMaxRecordsoutside 1 to 100 withValidationError.DescribeAlarmsnow lists metric and composite alarms in one name-ordered sequence thatMaxRecordscounts together, andDescribeAlarmHistorylists the newest items first unlessScanByisTimestampAscending.DescribeAlarmswithoutAlarmTypesnow returns metric alarms only, as on AWS; composite alarms needAlarmTypes=["CompositeAlarm"]. Contributed by @iot-rocket. - CloudWatch Logs — a log group's resource policy by
resourceArnalone —PutResourcePolicyandDeleteResourcePolicyrefused aresourceArnwithoutpolicyName; they now take it, store the group's policy without a name and with a countingrevisionId, and answer a request with neither field or a revision conflict with AWS's errors.AWS::Logs::LogGroupnow creates, rewrites and removes the group's own policy fromResourcePolicyDocument. Contributed by @iot-rocket. - CloudTrail — trail read-backs and recording switched on at runtime —
GetTrailandDescribeTrailsreturned the storedIsLogging,_StartedAtand_StoppedAtkeys and emptyS3KeyPrefixandSnsTopicNamemembers, andGetTrailStatusleft out the six deprecated string members and movedStopLoggingTimewhen a stopped trail was stopped again; they now answer in AWS's shapes, with the start and stop times in milliseconds, and keep the last stop time. Recording switched on through/_ministack/configbegan only after the first CloudTrail API call and now starts with the next request. Contributed by @iot-rocket. - ACM / Signer — certificate key and in-use refusals —
ImportCertificateaccepted a call without aPrivateKeyand now answers AWS'sValidationException;DeleteCertificateremoved a certificate an Active Signer signing profile uses and now answersResourceInUseException, with those profiles listed inDescribeCertificate'sInUseBy;CancelSigningProfileanswered 200 with{}and now answers 204 with an empty body, as on AWS. Contributed by @iot-rocket. - IoT — not-found messages match AWS — a call naming a thing, thing type, thing group, certificate, CA certificate, principal, policy, policy version, job, job execution, job target or provisioning template that does not exist answered
ResourceNotFoundExceptionwith a generic<Resource> '<name>' not found, and the device jobs plane (HTTP and MQTT/rejected) withNo job execution found for thing … and job …; each now carries the wording AWS uses for that operation, with the same error code and status. Contributed by @iot-rocket. - IoT Jobs — terminal job executions on the device plane — a device's
DescribeJobExecution(HTTP and the MQTTgettopic) of a SUCCEEDED, FAILED, REJECTED, TIMED_OUT, CANCELED or REMOVED execution answered with the execution; it now answersTerminalStateException(410) andTerminalStateReachedover MQTT, as AWS does.UpdateJobExecutionandCancelJobExecutionof a terminal execution now refuse with AWS's messages (over MQTTInvalidStateTransitionwith theexecutionState), a refused status such as QUEUED is checked first, and a device that reports SUCCEEDED or FAILED straight from QUEUED now stampsstartedAt. Contributed by @iot-rocket. - IoT / CloudFormation — stack tags and provisioning templates — stack-level tags never reached IoT resources; they now reach thing types, thing groups, policies, topic rules, CA certificates and provisioning templates without the
aws:cloudformation:tags (job templates get none, as on AWS), and an update that only changes tags no longer adds a policy version. AnAWS::IoT::ProvisioningTemplateEnabledof"false"from a parameter or the template enabled the template; it now disables it.CreateProvisioningTemplateand the CloudFormation type accepted any certificate resource; they now refuse one without aStatusofActiveorInactive(any case) or whoseCertificateIdis not a reference toAWS::IoT::Certificate::Id, a second certificate resource and a resource withoutProperties, with AWS's messages. Contributed by @iot-rocket. - IoT — device certificates take the mode of their CA — a device certificate registered under a CA in
SNI_ONLYmode, with or withoutcaCertificatePem, or created by just-in-time registration reportedcertificateModeDEFAULT; it now takes its CA's mode, and RegisterCertificateWithoutCA staysSNI_ONLY. Contributed by @iot-rocket. - IoT — deletes of unknown resources and
DeleteThingexpectedVersion—DeleteThing,DeleteThingType,DeleteThingGroup,RemoveThingFromThingGroupwith an unknown group andDetachPolicywith an unknown policy answeredResourceNotFoundException, andDeleteThingignoredexpectedVersion; they now answer 200 as AWS does, andDeleteThingrefuses a wrongexpectedVersionwithVersionConflictExceptionbefore the attached-principal check. Contributed by @iot-rocket. - CloudFormation — IoT policy and thing type deletes check what still uses them — a stack delete removed an
AWS::IoT::PolicyorAWS::IoT::ThingTypedirectly, even while a certificate outside the stack had the policy attached or a thing used the type; the policy delete now removes the non-default versions and then callsDeletePolicy, the thing type delete deprecates the type and then callsDeleteThingType, so a resource still in use fails its delete with the service's message and the stack ends inDELETE_FAILED, as on AWS. Contributed by @iot-rocket. - IoT — MQTT 5 message expiry — the broker forwarded the Message Expiry Interval unchanged and never expired a message; a subscriber now receives the seconds left (60 arrives as 59, 0 counts as 1, intervals above seven days are capped at 604800), an expired retained message is no longer replayed to new subscribers or returned by
GetRetainedMessageandListRetainedMessages, and a QoS 1 message queued for an offline persistent session is dropped once it expires (the queue also keeps the MQTT 5 properties now). Contributed by @iot-rocket. - IoT — HTTP
Publishkeeps the MQTT 5 properties and a literal%in the topic —PublishignoreduserProperties,payloadFormatIndicator,contentType,responseTopic,correlationDataandmessageExpiry, so MQTT 5 subscribers got none of them andGetRetainedMessagereturned nouserProperties; they now reach subscribers and the retained message, and invalid values are refused with AWS'sInvalidRequestExceptionmessages.Publish,GetRetainedMessageand theAUTH=truetopic ARN decoded the topic a second time, sop%41qbecamepAq; the topic is now kept as sent./_ministack/resetkept messages retained over MQTT when no iot-data call had loaded that module; it now clears them. Contributed by @iot-rocket. - IoT Core — MQTT 5 PUBACK reports Success without subscribers — a QoS 1 PUBLISH that no subscriber matched (including a topic only a rule reads, Basic Ingest and a retained publish) was acknowledged with reason code
0x10No matching subscribers; it now gets0x00Success, as AWS IoT answers over both MQTT over TLS and MQTT over WebSocket. Contributed by @iot-rocket. - CloudFormation — AppSync data sources and resolvers keep their configuration —
AWS::AppSync::DataSourcedroppedDescription,HttpConfigandEventBridgeConfigand storedDynamoDBConfigandLambdaConfigin the template's PascalCase, andAWS::AppSync::ResolverdroppedKind,Runtime,Code,PipelineConfigandMaxBatchSize, so a DynamoDB resolver from a stack answerednulland anAPPSYNC_JSresolver never ran; both now go throughCreateDataSourceandCreateResolverand read back as on AWS, and a new data sourceNameor resolverTypeNameorFieldNameis reported as a replacement.GetDataSourceandGetResolverleave out a description, service role or mapping template that was never set, a DynamoDB data source reportsuseCallerCredentialsandversioned, an EventBridge one keepseventBridgeConfig, and a resolver reportsmaxBatchSize. Contributed by @iot-rocket. - CloudFormation —
AWS::AutoScaling::LifecycleHookupdates — a stack update ran the create again, so a member dropped from the template went back to its default and a hook with a generated name moved to another group stayed on the old group too; the hook now updates in place and keeps a dropped member, and anAutoScalingGroupNameorLifecycleHookNamechange replaces it.NotificationMetadatais stored and returned byDescribeLifecycleHooks, and a group deleted by its stack takes its lifecycle hooks along. Contributed by @iot-rocket. - IoT — mTLS refusals close without a CONNACK under
AUTH=true— withAUTH=truethe mTLS listener closes the connection of an unknown, inactive, revoked or doubly-registered client certificate after its CONNECT without sending a CONNACK, as AWS does on MQTT 3.1.1 and 5; withoutAUTHit still answers a "not authorized" CONNACK, and the log names the reason either way. Contributed by @iot-rocket. - IoT —
AttachPolicyto a target that does not exist —AttachPolicyandAttachPrincipalPolicyaccepted any target string; they now answerResourceNotFoundExceptionfor an unknown certificate or thing group,InvalidRequestExceptionfor anything else that is not a certificate, a thing group (AttachPolicyonly) or a Cognito identity id, andAccessDeniedExceptionfor another account's certificate, which also fails anAWS::IoT::PolicyPrincipalAttachmentnaming such a principal. Contributed by @iot-rocket. - IoT —
SetDefaultPolicyVersion— the call was missing (PATCH /policies/{policyName}/version/{policyVersionId}answeredUnsupported policy path), so onlyCreatePolicyVersionwithsetAsDefaultcould move a policy's default version; it now sets the default thatGetPolicy,GetPolicyVersion,ListPolicyVersionsand the MQTT policy evaluation underAUTH=trueuse, deleting the default version answersDeleteConflictException(409) instead of 400, andListPolicyVersionslists the newest version first. Contributed by @iot-rocket. - STS — session policies and
GetFederationToken—AssumeRoleignoredPolicyandPolicyArnsandGetFederationTokenansweredInvalidAction; underAUTH=truea role session now gets only what both the role and its session policies allow, aDenyin them denies, andAssumeRolerejects a malformed policy withMalformedPolicyDocumentand an unknown policy ARN withValidationError.GetFederationTokenis added: its federated user gets the calling user's permissions within the session policies (none without one) and itsTags, not the user's tags, asaws:PrincipalTag/*; it checks itsName, policies and tags, and underAUTH=truea temporary caller answersAccessDenied. Contributed by @iot-rocket. - IAM — permissions boundaries are enforced — the boundaries of users and roles were stored and never applied; under
AUTH=truea boundary now limits what the identity policies allow and aDenyin it denies, a boundary must name a known managed policy (ValidationErrorfor a malformed ARN, CloudFormationAWS::IAM::Userincluded), deleting an absent boundary answersNoSuchEntity, and a policy in use as a boundary cannot be deleted.ListUsersandListRolesleave the boundary out,ListEntitiesForPolicylists boundary users and roles and honoursPolicyUsageFilter, and a managed policy reportsPermissionsBoundaryUsageCount. Contributed by @iot-rocket. - API Gateway —
GetExportincludes Lambda authorizers — a REST API export had no security scheme for aTOKENorREQUESTauthorizer and nosecurityfield on its methods, so tools such as Swagger UI showed no "Authorize" button. Each authorizer that aCUSTOMmethod uses is now a scheme incomponents.securitySchemes(OAS 3.0) orsecurityDefinitions(Swagger 2.0), and the method hassecurity. Withextensions=authorizersorextensions=apigateway, the scheme also has thex-amazon-apigateway-authorizerblock. Checked against a real AWS export and thex-amazon-apigateway-authorizerdocs. Contributed by @mishukdutta-cz. - STS — trust policies see principal tags, session tags and web identities under
AUTH=true—AssumeRoletrust conditions had noaws:PrincipalTag/*, aServiceprincipal matched any IAM user whose ARN contained the service name,Tagspassed withoutsts:TagSessionin the trust policy, andAssumeRoleWithWebIdentityskipped the trust policy; trust conditions now see the caller's keys and the session tags asaws:RequestTag/*andaws:TagKeys, aServiceprincipal no longer matches an IAM user, session tags needsts:TagSession, and a web identity needs aFederatedprincipal naming its issuer, with<issuer>:aud,:suband:amrevaluated. UnderAUTH=truesession tag keys that differ only in case answerInvalidParameterValue. Contributed by @iot-rocket. - IAM —
aws:ResourceTag/*underAUTH=true— the key was always absent outside CloudWatch Logs, so a tag-scoped grant denied every request; a request on an existing SQS queue, SNS topic, DynamoDB table, Lambda function, IAM user or role, SSM parameter, Secrets Manager secret or KMS key now sees that resource's tags. Contributed by @iot-rocket. - IAM —
aws:RequestTag/*andaws:TagKeysunderAUTH=true— only CloudWatch Logs filled them; a call whose API takesTagsorTagKeys(create, tag and untag calls such asCreateQueue,CreateTable,CreateUser,PutParameter,CreateSecret,CreateKey) now carries the tags it sets and the keys it names,aws:TagKeysis absent on a call that names none, and LambdaTagResource,UntagResourceandListTagsare authorized against the ARN in the path instead of skipped. Contributed by @iot-rocket. - IAM — caller and transport condition keys under
AUTH=true— identity policies saw none of the caller's keys and a fixed127.0.0.1over plain HTTP; they now seeaws:username,aws:userid,aws:PrincipalTag/*(the user's or role's tags,AssumeRolesession tags taking precedence; inrds-db:connecttoo), for temporary credentialsaws:MultiFactorAuthPresentandaws:TokenIssueTime, the client's address asaws:SourceIpandaws:SecureTransportastrueover HTTPS or behind a proxy that sendsX-Forwarded-Proto: https, andAssumedRoleIdstarts with the role'sRoleIdwith or withoutAUTH. Contributed by @iot-rocket. - S3 — requests without credentials are anonymous under
AUTH=true— an unsigned request (noAuthorizationheader, presigned query or POST form credential) ran as the root key, so a private bucket in the caller's own account answered 200 to anyone; it is now anonymous, and only the owner's public grants let it in: anAllUsersACL grant or a bucket policy that allows*, unless Public Access Block shuts them off. Anything else answers 403AccessDenied. Apublic-readobject ACL is now also found for an unversioned object, which the grant check missed for cross-account callers too. WithoutAUTHnothing changes. Contributed by @prandogabriel. - Cognito —
InboundFederationuserName— the trigger received<provider>_<NameID>for SAML and<provider>_<sub>for OIDC; it now receives the bare SAMLNameIDor OIDCsub. Contributed by @kjdev. - S3 Tables —
CreateTablekeeps Iceberg column types — aschemaorschemaV2field type other thanstring,int,long,boolean,date,timestamp,floatordoublewas stored asstring, andtimestampastimestamptz; every Iceberg v2 type, nestedlist,structandmapincluded, is now stored as AWS stores it (lowercase,decimal(P, S)), and any other type answersBadRequestExceptionThe specified metadata is not valid. Reported by @anatollius. - S3 Tables — the Iceberg REST catalog takes the table bucket prefix — a request without the
{prefix}searched every table bucket, so two buckets with the same namespace and table name answered with the first one; such a request now answers 404<UnknownOperationException/>,GET /v1/configwithout a table bucket ARNwarehouseanswers 400The specified table bucket ARN is not valid., and the url-encoded ARN comes back asprefixindefaults.