github ministackorg/ministack v1.3.22

3 hours ago

What's Changed

[1.3.22] — 2026-04-30

Added

  • Cognito PreTokenGeneration Lambda triggerLambdaConfig.PreTokenGenerationConfig (V2_0) and the legacy LambdaConfig.PreTokenGeneration (V1_0) are now round-tripped through CreateUserPool / UpdateUserPool / DescribeUserPool and invoked at token-mint time. Before signing an access or id token, ministack synchronously invokes the configured Lambda with the AWS-shaped event (triggerSource, userPoolId, request.userAttributes, request.groupConfiguration, request.scopes for V2+, callerContext.clientId, etc.) and applies the Lambda's response.claimsAndScopeOverrideDetails.{accessTokenGeneration,idTokenGeneration} (V2_0: claimsToAddOrOverride, claimsToSuppress, scopesToAdd, scopesToSuppress, groupOverrideDetails) — or the legacy response.claimsOverrideDetails (V1_0, id token only). Refresh tokens are opaque in AWS and skip the trigger. Lambda errors fail open (token issued without overrides + warning logged); set MINISTACK_COGNITO_PRETOKEN_STRICT=1 to fail closed the way real AWS does. Invocation reuses the existing _resolve_name_and_qualifier_get_func_record_for_qualifier_execute_function chain in lambda_svc.py — no new handlers added. Reported by @aahoughton (#533).
  • S3 PostObject (browser-based form upload)POST /<bucket>/ with multipart/form-data is now handled. Honours key (with ${filename} substitution from the file part), Content-Type, x-amz-meta-*, x-amz-storage-class, x-amz-tagging, the object-lock headers, success_action_status (200/201/204; default 204), and success_action_redirect (303 with bucket=&key=&etag= appended). On 201 returns the <PostResponse> XML with Location/Bucket/Key/ETag. Versioning, persistence, multi-tenancy, S3 event notifications all flow through the same path as PutObject. The content-length-range policy condition is enforced — uploads under the minimum return EntityTooSmall 400 and uploads over the maximum return EntityTooLarge 400 (matches AWS error codes). Other policy conditions and the signature field are accepted but not validated — same lenient stance as ministack's presigned-URL handling. boto3's generate_presigned_post works end-to-end. Requested by @mattburton (#535).
  • Init / ready scripts: expose MINISTACK_INIT_SCRIPT_DIR and MINISTACK_INIT_SCRIPT_PATH to each script — every .sh / .py run from /docker-entrypoint-initaws.d[/ready.d] (or /etc/localstack/init/{boot,ready}.d) now sees its own directory and absolute path in the environment, so scripts can reference sibling files (aws s3 cp "${MINISTACK_INIT_SCRIPT_DIR}/data.json" s3://bucket/) without hardcoding the mount path or computing dirname "${BASH_SOURCE[0]}". Phase-level MINISTACK_INIT_BOOT_DIR / MINISTACK_INIT_READY_DIR are also set when those directories exist. Requested by @andreluiznsilva (#520).
  • EC2 Instance Metadata Service (IMDS) emulator — new imds service responds on the gateway port at /latest/api/token (IMDSv2) and /latest/meta-data/... / /latest/dynamic/instance-identity/document. Returns a credentials document under role ministack-instance-role so SDKs that fall through to the IMDS step of the default credential chain (boto3, aws-sdk-go-v2, AWS SDK Java v2) get a valid ASIA* session key + token. Both IMDSv1 (token-less) and IMDSv2 (PUT /token → GET with X-aws-ec2-metadata-token) supported; set MINISTACK_IMDS_V2_REQUIRED=1 to reject token-less requests, matching AWS hop-limit-1 IMDSv2-only instances. Point SDKs at ministack via AWS_EC2_METADATA_SERVICE_ENDPOINT=http://localhost:4566 (or ec2_metadata_service_endpoint in ~/.aws/config); we don't bind the link-local 169.254.169.254 IP — that's a per-container network-alias concern, not portable from inside ministack. Reported by @bimargulies

Fixed

  • S3 PutObject StorageClass was dropped on the floor — objects written with StorageClass=GLACIER / INTELLIGENT_TIERING / etc. came back from GetObject, HeadObject, ListObjects(V2), and ListObjectVersions as STANDARD. The header is now stored on the object record and emitted on the wire (header omitted for the default STANDARD, matching AWS). Same propagation through CopyObject (with optional override via x-amz-storage-class) and CreateMultipartUploadCompleteMultipartUpload. Unknown storage class values now return InvalidStorageClass (400). Verified against botocore/data/s3/2006-03-01/service-2.json. Reported by @JoeHale (#534).

Don't miss a new ministack release

NewReleases is sending notifications on new releases.