Skip to content

v1.4.15

Latest

Choose a tag to compare

@Nahuel990 Nahuel990 released this 10 Aug 20:29

What's Changed

New Contributors

[1.4.15] — 2026-08-10

Added

  • RDS — ManageMasterUserPassword wires Aurora clusters to Secrets ManagerCreateDBCluster(ManageMasterUserPassword=true) previously ignored the flag: no secret was created, no MasterUserSecret was returned, and code paths that resolve database credentials from Secrets Manager (the common production pattern) could not be rehearsed locally. The flag now generates a random master password, stores it in MiniStack's own Secrets Manager as {"username", "password"} under the AWS naming convention (rds!cluster-<uuid>), and returns MasterUserSecret (SecretArn, SecretStatus, KmsKeyId) from create/describe/modify. ModifyDBCluster(RotateMasterUserPassword=true, ApplyImmediately=true) rotates the real database login through the same path as an explicit password change — including the pending-rotation behavior for stopped compute — and promotes the new credentials to AWSCURRENT (previous ones stay readable as AWSPREVIOUS); a rotation whose managed secret was deleted out from under RDS fails with InvalidDBClusterStateFault and flips SecretStatus to impaired, as on AWS. DeleteDBCluster deletes the managed secret with the cluster (and only when the delete actually succeeds). AWS-exact rejections: ManageMasterUserPassword + explicit MasterUserPassword at create, explicit password against a managed cluster, RotateMasterUserPassword without a managed secret or without ApplyImmediately, and explicit password + rotate flag in one request — validated before anything mutates. The RDS↔Secrets Manager seam is in-process and one-directional (rds → secretsmanager), reusing the emulator's existing stage-promotion and replica-sync internals. Contributed by @Kiran01bm.
  • EventBridge — API destination targets are now invoked over HTTP on PutEvents — API destinations and connections were control-plane stubs: a matching rule with an api-destination target logged "unsupported event target ARN" and dropped the event, so webhook-style pipelines (EventBridge → HTTPS endpoint) could not be tested locally. Matching events now POST (or the destination's configured method) to the InvocationEndpoint with the input-selected payload (Input / InputPath / InputTransformer apply as for other targets). Connection authorization is honored: BASIC populates Authorization: Basic …, API_KEY sends the configured header, and OAUTH_CLIENT_CREDENTIALS exchanges the client ID/secret at the authorization endpoint (OAuthHttpParameters merged in, grant_type=client_credentials defaulted), caches the token per connection and invalidates it when the connection is deleted, re-authorized, or deauthorized (a connection recreated under a reused name never inherits its predecessor's token), refreshes proactively when it expires within 60 seconds, and refreshes + retries once on a 401/407 response — matching documented AWS behavior. Connection InvocationHttpParameters and target HttpParameters are merged with connection values taking precedence (per the HttpParameters API reference), PathParameterValues populate * path wildcards, and body parameters fold into JSON-object bodies. Requests carry the AWS default headers (User-Agent: Amazon/EventBridge/ApiDestinations and Range non-overridable, Content-Type defaulting to application/json; charset=utf-8), strip the headers real EventBridge removes, and time out after 5 seconds (the documented maximum client execution timeout). Delivery runs on a background thread mirroring the SNS HTTP(S) path. Not modeled, mirroring the cross-region FailedInvocations policy: the 24h/185-attempt retry pipeline, Retry-After, DLQs, and InvocationRateLimitPerSecond — retryable statuses (401, 407, 409, 429, 5xx) are logged and dropped. Contributed by @t-rech.
  • KMS — HMAC keys, GenerateMac, and VerifyMac — the four HMAC key specs (HMAC_224/HMAC_256/HMAC_384/HMAC_512) with KeyUsage=GENERATE_VERIFY_MAC, RFC 2104 HMAC generation and constant-time verification (KMSInvalidMacException on mismatch), MacAlgorithms in the key metadata, and DryRun. HMAC keys are rejected by Encrypt / Decrypt / Sign / Verify / GenerateDataKey*, and automatic key rotation follows AWS: EnableKeyRotation and DisableKeyRotation reject them with UnsupportedOperationException, while GetKeyRotationStatus succeeds and reports KeyRotationEnabled: false. Contributed by @nafdev.
  • Lambda — LAMBDA_KEEPALIVE_MS=0 forces a per-invocation cold start — a LocalStack-compat lever (not an AWS behavior): for Docker RIE runtimes (Ruby/Java/.NET), LAMBDA_KEEPALIVE_MS=0 tears the warm container down after each invocation so the next invoke re-runs INIT, giving deterministic cold-start isolation for test suites. Unset or any non-zero value keeps the warm-pool behavior. Reported by @mayankgupta57.

Fixed

  • S3 — POST Object no longer misreads form fields as the object body — a multipart part was classified as the object content when its name was file or it carried a filename attribute, but browsers and HTTP libraries (Python requests' files=) set filename on ordinary form fields, so every field looked like the body, no key field survived, and the upload was rejected with InvalidArgument. Only the field literally named file is the body now, matching S3. Reported by @gaul.
  • S3 — GetObject with partNumber returns the requested part — the partNumber parameter was dropped, so a client fetching an N-part object in parallel received N full copies. A completed multipart object now returns the requested part as 206 Partial Content with a Content-Range and x-amz-mp-parts-count, matching S3. Reported by @gaul.
  • S3 — ListObjectVersions returns continuation markers when truncated — a truncated response set IsTruncated=true but emitted neither NextKeyMarker nor NextVersionIdMarker, and the incoming version-id-marker was ignored, so a paginating client looped on page one or (as boto3 does) rejected KeyMarker=None. The markers are now emitted and version-id-marker resumes within key-marker. Reported by @gaul.
  • S3 — CompleteMultipartUpload returns 400 MalformedXML for an unparseable body — an empty or malformed body raised an unguarded ParseError that escaped as a 500 with a JSON document no S3 SDK can parse, so clients treated it as a transient fault and retried. It now returns 400 MalformedXML, as XML. Reported by @gaul.
  • S3 — CompleteMultipartUpload is idempotent — the upload record was dropped on the first call, so a retry (how a client recovers from a lost response) returned NoSuchUpload. The completed response is now retained and replayed for a repeat call with the same upload id, without minting a second object version, matching S3. Reported by @gaul.
  • S3 — object owner id is consistent between listings and ACLsListBuckets / ListObjects / ListObjectVersions / ListParts hard-coded the owner id owner-id while GetObjectAcl / GetBucketAcl used the account id, so a client matching an object's owner against an ACL grantee always got a mismatch. All of them now use the account id. Reported by @gaul.
  • S3 — presigned URLs are rejected once expiredX-Amz-Date + X-Amz-Expires were never compared against the current time, so a URL minted with a one-second lifetime served the object indefinitely. An expired presigned URL now returns 403 AccessDenied (Request has expired), matching S3. Reported by @gaul.
  • S3 — conditional deletes honour If-MatchDeleteObject ignored the If-Match header and DeleteObjects ignored a per-object ETag, so a delete carrying a stale ETag removed the object anyway (and the batch reported it under Deleted). DeleteObject now returns 412 PreconditionFailed on an ETag mismatch, and DeleteObjects reports the key under Error (PreconditionFailed) instead of deleting it, matching S3's compare-and-swap delete. Reported by @gaul.
  • CloudWatch Logs — ARN-based tag operations resolve vended-delivery resourcesTagResource, UntagResource, and ListTagsForResource only resolved log-group ARNs, so the AWS provider's read-after-create on aws_cloudwatch_log_delivery_source / aws_cloudwatch_log_delivery_destination / aws_cloudwatch_log_delivery failed with ResourceNotFoundException and broke terraform apply of any stack using EventBridge bus logging (the community EventBridge module ≥ v4.1 provisions the trio). All three operations now resolve the delivery records' tags. Contributed by @t-rech.
  • Route 53 — ChangeResourceRecordSets DELETE now requires the values provided to match the current values — a DELETE matched only on name, type, and set identifier, so a delete carrying a stale TTL or stale record values silently removed the live record. Real Route 53 requires the values in a DELETE to match the current record exactly and rejects the whole batch with InvalidChangeBatch otherwise — the compare-and-swap semantics that guarded-delete workflows (delete only if the record still holds the values I last observed) rely on to detect concurrent modification, which the emulator's silent success defeated. A mismatched DELETE now fails the batch atomically with the AWS-shaped message (Tried to delete resource record set [name='…', type='…'] but the values provided do not match the current values); record values are compared as an unordered set, so the same values in a different order still match. Contributed by @jayjanssen.
  • S3 — CopyObject and HeadObject honour the source versionId — a ?versionId= on the copy source (and on HeadObject) was discarded, so both operated on the current object instead of the requested version. CopyObject now copies the exact version and echoes x-amz-copy-source-version-id, HeadObject returns that version's metadata, and a non-existent version is rejected with NoSuchVersion. Reported by @Kaphaalor.
  • SQS — FIFO deduplication holds for the full 5-minute window — the dedup entry was cleared when a message was deleted (including the Lambda event-source-mapping consume path), so a duplicate sent seconds after the original was consumed was delivered again. A MessageDeduplicationId is now retained for its full 5-minute window from send time regardless of receive/delete, matching AWS FIFO semantics. Reported by @giannimassi.
  • S3 — NewerNoncurrentVersions survives the lifecycle configuration round-tripNoncurrentVersionExpiration and NoncurrentVersionTransition dropped NewerNoncurrentVersions on the PUT/GET round-trip, so terraform-provider-aws never converged and terraform apply of a lifecycle configuration timed out. The field is now emitted and parsed on both rules. Contributed by @sac-outsystems.
  • Step Functions — aws-sdk integration preserves query-protocol singleton lists — the query-XML to JSON converter collapsed a known list wrapper with an irregular item name (e.g. VpcSecurityGroups to VpcSecurityGroupMembership) into an object when it held a single item, so SDK consumers expecting a stable list shape broke. Known wrappers now decode to a list for zero, one, or multiple items. Contributed by @Areson.
  • CodeBuild — a timed-out build reports TIMED_OUT — a build stopped by timeoutInMinutes was labelled FAILED instead of TIMED_OUT, so BatchGetBuilds could not distinguish a timeout from a genuine build failure. It now reports the TIMED_OUT build status, matching AWS.
  • RDS Data API — requests that AWS rejects no longer succeed through permissive fallbacks — the Data API accepted calls that real AWS refuses, so a local integration passed where the equivalent AWS request would fail. A cluster whose HTTP endpoint is not enabled now returns HttpEndpointNotEnabledException (SQL runs only after EnableHttpEndpoint); a secret that is absent, scheduled for deletion, or missing a password returns SecretsErrorException / InvalidSecretException, and this validation now applies in stub mode too. CommitTransaction / RollbackTransaction now require resourceArn and secretArn (AWS marks both required), and a transaction is bound to its originating cluster: a mismatched or unknown transaction returns TransactionNotFoundException (404) from ExecuteStatement / BatchExecuteStatement and NotFoundException (404) from CommitTransaction / RollbackTransaction, matching AWS's per-operation error model. Statement timeouts surface as StatementTimeoutException and unmodeled stub-mode SQL as BadRequestException instead of a fabricated success. Contributed by @Areson.