October 30, 2026 · v1.5.35
v1.5.35 adds IAM service-specific credentials and server certificates, API Gateway PutRestApi, client certificates and private domain access associations, and ELBv2 listener certificates, fixes 23 behaviours across API Gateway, AppConfig, Auth, Auto Scaling, CloudFront, EC2, ECS, ElastiCache, EventBridge, EventBridge Scheduler, KMS, Lambda, RDS, Route 53 and S3, and removes the unused Makefile.
PutRestApi. PUT /restapis/{id} answered 404, so Terraform's aws_api_gateway_rest_api with a body failed; it now imports an OpenAPI or Swagger definition (JSON or YAML) in merge mode (the default) or overwrite mode, which also removes the API's authorizers, and in both modes the API takes its name from info.title its description from info.description (removed when absent) and its version from info.version. An unknown API answers Invalid API identifier specified <account>:<id>, a body that is no definition Unable to determine OAS/Swagger version and a bad mode AWS's enum validation message. ImportRestApi now imports its definition too, where it created an empty API named unnamed. Reported by @mindsers.GenerateClientCertificate, GetClientCertificate, GetClientCertificates, UpdateClientCertificate and DeleteClientCertificate, with a 6-character id, a self-signed PEM certificate (C=US, L=Seattle, CN=ApiGateway) valid for one year, tags on the certificate's ARN, and AWS's errors: Invalid client certificate id specified (404, and 400 for a stage's /clientCertificateId patch) and Invalid patch path '<path>' specified for op '<op>'. Must be one of: [/description]. Reported by @mindsers.CreateDomainNameAccessAssociation, GetDomainNameAccessAssociations, DeleteDomainNameAccessAssociation and RejectDomainNameAccessAssociation for private custom domain names, named by their domainNameArn, with the ARN .../domainnameaccessassociations/domainname/<name>+<domainNameId>/vpcesource/<vpce> and tags on it. A duplicate, an unknown domain or a VPC endpoint EC2 doesn't hold answer 400 BadRequestException "The domain name access association between this VPC endpoint and domain name already exists.", "Domain not found" and "<vpce> is not a valid VPC endpoint id"; rejecting an association of your own, or any after the domain is deleted, answers 404 "This private custom domain name doesn't have any domain name access associations." and keeps it. Reported by @mindsers.AddListenerCertificates, DescribeListenerCertificates and RemoveListenerCertificates, as on AWS: one certificate per call, CertificateNotFound for a certificate ACM doesn't hold, the default certificate listed last with IsDefault true and never removed. Reported by @kharabasz.ListServiceSpecificCredentials or ListServerCertificates got InvalidAction. CreateServiceSpecificCredential, ListServiceSpecificCredentials, UpdateServiceSpecificCredential, ResetServiceSpecificCredential and DeleteServiceSpecificCredential now answer: a CodeCommit or Keyspaces credential is a ServiceUserName (<user>-at-<account>) and ServicePassword, a Bedrock, Claude Platform on AWS, CloudWatch or CloudWatch Logs one a ServiceCredentialAlias and ServiceCredentialSecret with the ExpirationDate from CredentialAgeDays; the password or secret is returned only on create and reset, another service answers NotSupportedService (404), and UserName may be omitted by an IAM-user caller while a non-user caller without it gets InvalidInput. UploadServerCertificate, ListServerCertificates, GetServerCertificate (with its CertificateChain), UpdateServerCertificate, DeleteServerCertificate and ListServerCertificateTags keep names unique across paths, parse Expiration from the PEM (left out on the slim image, which has no cryptography), and answer MalformedCertificate for a body that is not a certificate. Contributed by @pingedbrain.domainNameArn arn:aws:apigateway:<region>::/domainnames/<name>, certificateUploadDate and a d-<10 characters>.execute-api.<region>.amazonaws.com regional name, and responses leave out the fields AWS doesn't send for the endpoint type, empty values among them; endpointConfiguration carries ipAddressType and tags appear on GetDomainName. Reported by @cupidchan.domainNameId 1.5.34 gave a private domain had 8 characters where AWS's has 10; a private domain now also defaults ipAddressType to dualstack, and a policy statement on execute-api:/* is returned naming the domain's own execute-api ARN, as on AWS. Reported by @mindsers.KmsKeyArn is built from the identifier as given. 1.5.34 resolved an alias to its key's ARN and only reported a KmsKeyArn for a key MiniStack's KMS held; as on AWS, a key ARN or alias ARN is kept, a key id becomes arn:aws:kms:<region>:<account>:key/<id> and an alias name arn:aws:kms:<region>:<account>:alias/<name>, without checking the key exists. A hosted version created under a profile with a key carries its KmsKeyArn, and StartDeployment of such a version answers "KmsKeyIdentifier required when deploying a hosted configuration version that is encrypted with a customer managed key (CMK)" without a KmsKeyIdentifier, and KMS's messages for a key that does not exist, is disabled or is in another account. Reported by @kharabasz.ListDeployments and tag errors. deployments are listed newest first with ConfigurationProfileId and Type USER, and ListTagsForResource, TagResource and UntagResource answer AWS's errors for an ARN without an account id (400) and another account's ARN (403 AccessDeniedException). Reported by @kharabasz.:authority. with AUTH=true, a request signed with an IAM user or STS session key over HTTP/2, as the JavaScript SDK v3 does for Kinesis, Bedrock Runtime and other clients, answered SignatureDoesNotMatch: Hypercorn passes :authority to the app as host, so it was signed as empty. A signed :authority now takes the host value. Reported by @ScriptSmith.MixedInstancesPolicy. CreateAutoScalingGroup and UpdateAutoScalingGroup dropped it, so the group reported no launch template; it is now kept, in CloudFormation too, with the launch template's id and name filled in, Overrides [] when none are given and AWS's InstancesDistribution defaults, and the group then has no LaunchTemplate. A group with both a LaunchTemplate and a MixedInstancesPolicy, or with no launch source at all, answers "Valid requests must contain either LaunchTemplate, LaunchConfigurationName, InstanceId or MixedInstancesPolicy parameter." Reported by @kharabasz.LaunchTemplate with both or neither of LaunchTemplateId and LaunchTemplateName answers "Valid requests must contain either launchTemplateId or LaunchTemplateName", a version other than $Default, $Latest or a number "Invalid launch template version: either '$Default', '$Latest', or a numeric version are allowed.", and an unknown id "Malformed launch template Id: <id>" or, for a short lt- id or one in another region, "The specified launch template, with template ID <id>, does not exist.", on create and update, as on AWS. Reported by @kharabasz.UpdateFunction returns its ETag where the SDKs read it. AWS sends UpdateFunction's ETag in a header named ETtag, which is where botocore and the other SDKs read it; MiniStack sent ETag, so an SDK client got no ETag back and Terraform's aws_cloudfront_function failed to publish a code change with InvalidIfMatchVersion. Reported by @kharabasz.PublishFunction moves LIVE to its next version, with the ETag of that version number, and leaves DEVELOPMENT's ETag unchanged, where 1.5.34 copied DEVELOPMENT's ETag to LIVE. PublishFunction no longer sends an ETag header, DeleteFunction of a function a distribution uses answers 409 FunctionInUse "Cannot delete function <name>, it is in use by <n> distributions", and a stale If-Match on publish or delete answers PreconditionFailed "The request failed because it didn't meet the preconditions in one or more request-header fields." Reported by @kharabasz.<label>.cloudfront.net name; a request whose Host is one of its Aliases fell through to path-style S3 (NoSuchBucket). It is now served by the distribution that claims that name, as on AWS: the Host header chooses it, case-insensitively and ignoring the port; an exact alias beats every wildcard; *.S matches any host ending in .S, at any depth, but not S itself; and the longest matching wildcard wins, whichever distribution is newer. A host another service claims (an API Gateway custom domain, a Function URL, an S3 virtual host, an OpenSearch Serverless collection, a load balancer) still goes to that service. The viewer function sees the Host lower-cased and without its port, and a SigV4-signed API call is never treated as viewer traffic. Contributed by @skialpine.InstanceRequirements. CreateLaunchTemplate and CreateLaunchTemplateVersion dropped it, so aws_launch_template planned a change on every run; it is now returned as sent, and a template data with both InstanceType and InstanceRequirements answers InvalidParameterCombination "Either the instance type or the instance requirements can be specified in the request, but not both." Reported by @kharabasz.base. a strategy item given without base is reported with base 0 on the service and its deployments, and on the cluster's default strategy from CreateCluster, PutClusterCapacityProviders, DescribeClusters and CloudFormation, as on AWS. Reported by @kharabasz.default; the group's users now exist in the engine with their access strings and passwords, default is off unless the group holds a user named default, and an unauthenticated command answers NOAUTH Authentication required.. An iam user logs in with its token, which is not verified. Reported by @kharabasz.create-failed; ports in use are now skipped. Reported by @kharabasz.CreateUser and ModifyUser ignored AuthenticationMode, so an IAM user was reported as needing no password; users now report Authentication {"Type": "iam"} or {"Type": "password", "PasswordCount": n} and their MinimumEngineVersion, and refuse an IAM user whose name differs from its id, an IAM user with passwords and a no-password-required Valkey user with AWS's messages. ModifyUser answers modifying. Reported by @kharabasz.EventBridgeParameters are validated and an event bus target publishes as AWS does. CreateSchedule and UpdateSchedule accepted any Target.EventBridgeParameters; they now answer AWS's SerializationException for parameters or members sent as the wrong JSON type, then AWS's aggregated ValidationException for a missing or empty DetailType or Source, a DetailType over 128 or a Source over 256 characters, and a Source outside AWS's pattern (such as one starting with aws. or holding a line break), before the schedule or group is looked up and for any target type. An event a schedule puts on an event bus now has empty resources instead of the schedule ARN, and an event bus target without EventBridgeParameters no longer publishes an aws.scheduler event. Contributed by @kharabasz.PutEvents to another account's event bus. an entry whose EventBusName is the ARN of a bus another account owns in the same region failed with ResourceNotFoundException, so no other account could publish to a bus. The event is now delivered to the owner's rules and keeps the publisher's account. Under AUTH=true the bus policy (a PutPermission grant or Policy) must allow the caller, with an events:source condition checked for each entry; otherwise the whole request answers AccessDeniedException "User: <caller> is not authorized to perform: events:PutEvents on resource: <bus ARN> because no resource-based policy allows the events:PutEvents action", naming the first refusing bus in request order. A bus that does not exist refuses the same way. Contributed by @kharabasz.PutPermission with a Policy. the policy was ignored and DescribeEventBus returned a generic statement, so Terraform showed drift; it now replaces the bus's policy and is returned compact, the legacy form produces AWS's statement, and a malformed policy, a statement on another resource, or a Policy combined with Action, Principal, StatementId or Condition answer AWS's ValidationException messages. Reported by @kharabasz.NotFoundException; for the operations AWS allows across accounts it is now used from its owner's account, and with AUTH=true its key policy must allow the caller (root included), else AWS's AccessDeniedException "User: <caller> is not authorized to perform: kms:<action> on this resource because the resource does not exist in this Region, no resource-based policies allow access, or a resource-based policy explicitly denies access", the same answer as for a key that doesn't exist. Reported by @kharabasz.CreateEventSourceMapping on another account's stream now checks the stream's policy under AUTH=true: the function's role needs DescribeStream, DescribeStreamSummary, GetRecords, GetShardIterator and ListShards, and a missing stream or grant answers AWS's Cannot access stream ... message. Under AUTH=true a running mapping needs only GetRecords; without it the mapping stops and reports AWS's PROBLEM: User: ... is not authorized to perform ... result (naming DescribeStream when the whole grant is gone), and resumes when the grant returns. A mapping on a missing stream in its own account answers Stream not found. Contributed by @Jolley71717.Endpoint and Aurora PostgreSQL versions. global clusters report Endpoint <id>.global-<12 characters>.global.rds.amazonaws.com, even with no members, so aws_rds_global_cluster.endpoint is filled in; a global cluster also reports EngineLifecycleSupport, StorageEncryptionType (sse-rds, or sse-kms when encrypted) and a 16-character GlobalClusterResourceId, leaves out an empty DatabaseName, and Aurora PostgreSQL defaults to 17.9; and DescribeDBEngineVersions lists the current Aurora PostgreSQL versions, adding 14.24, 15.19, 16.15, 17.11 and 18.6. Reported by @kharabasz and @mindsers.InvalidChangeBatch messages. a duplicate CREATE and a missing DELETE answer AWS's bracketed messages, [Tried to create resource record set [name='<name.>', type='<type>'] but it already exists] and [Tried to delete resource record set [name='<name.>', type='<type>'] but it was not found]. Reported by @kharabasz.AUTH=true, the account's root credentials skipped the bucket policy, so a Deny stopped IAM users but not root; root is now refused with AWS's "with an explicit deny in a resource-based policy" message, and can still get, put and delete the bucket policy. Reported by @kharabasz.Makefile. its targets only wrapped docker build, docker run and docker compose, and nothing used it.docker pull ministackorg/ministack:1.5.35 docker run -d -p 4566:4566 ministackorg/ministack:1.5.35
Or pin in compose.yaml:
services:
ministack:
image: ministackorg/ministack:1.5.35
ports:
- "4566:4566"
Issues and PRs welcome on GitHub. Discussion on r/ministack.