DocsAWS 101Blog
← Back to Blog

Firehose Kinesis-source fan-out, DynamoDB conformance pass, IMDS scanner fix

May 30, 2026 · v1.3.53

One real bug fix on Firehose, a deep DynamoDB conformance pass, AWS error-type clean-up across eight more services, and a small IMDS source change so security scanners stop false-flagging. Three reported issues closed.

Firehose KinesisStreamAsSource → S3 fan-out

Delivery streams created with DeliveryStreamType=KinesisStreamAsSource and an ExtendedS3 / S3 destination now actually consume records from the source Kinesis stream and forward them to S3. Previously the KinesisStreamSourceConfiguration was stored so DescribeDeliveryStream would echo it back, but no consumer ever read the records — anything put into the source Kinesis stream was silently dropped on the Firehose side.

The fan-out fires inline from Kinesis PutRecord / PutRecords (same pattern as SNS→SQS) so it stays deterministic in tests, honors the configured Prefix, and respects DeliveryStartTimestamp — records older than the delivery-stream creation time are skipped, matching the AWS shard-iterator semantics. Delivery is best-effort: a Firehose-side problem can never break the producer's Kinesis write. Reported by @arivazhaganjeganathan-abc.

import boto3
kinesis = boto3.client("kinesis", endpoint_url="http://localhost:4566")
firehose = boto3.client("firehose", endpoint_url="http://localhost:4566")

firehose.create_delivery_stream(
    DeliveryStreamName="ingest",
    DeliveryStreamType="KinesisStreamAsSource",
    KinesisStreamSourceConfiguration={
        "KinesisStreamARN": "arn:aws:kinesis:us-east-1:000000000000:stream/events",
        "RoleARN": "arn:aws:iam::000000000000:role/firehose",
    },
    ExtendedS3DestinationConfiguration={
        "BucketARN": "arn:aws:s3:::ingest-bucket",
        "RoleARN": "arn:aws:iam::000000000000:role/firehose",
        "Prefix": "data/",
    },
)
kinesis.put_record(StreamName="events", PartitionKey="k", Data=b'{"a":1}')
# Record now lands in s3://ingest-bucket/data/YYYY/MM/DD/HH/<uuid>

DynamoDB Tier 3 conformance pass

30+ message-text fixes so the strings returned by ministack match the strings captured from real AWS by the dynamodb-conformance.org Tier 3 suite. Highlights:

Plus two functional bugs surfaced by the same run:

Error-type corrections across eight services

Each of these was emitting an exception type that doesn't exist in the corresponding botocore service model — meaning strict-deserializer SDKs (Java v2, Go v2) couldn't classify the error. All now return the canonical type per the AWS API reference:

KMS / MWAA / Inspector2 no longer leak Python exception text

Generic except Exception as e blocks were forwarding str(e) as the AWS error message on InvalidCiphertextException, InternalServerException, and InternalServerError. The new responses are opaque per AWS convention — AWS never surfaces internal exception text in 5xx responses.

IMDS instance-profile-ID literal assembled at runtime

Credential-pattern secret scanners (e.g. AquaSec) were false-flagging the literal AIPA… InstanceProfileId value in ministack/services/imds.py as a leaked AWS instance-profile ID. The 20-character wire response is unchanged — the source no longer contains a contiguous AIPA… string, so the heuristic stops matching. Reported by @diplomatic-ms.

Upgrade

docker pull ministackorg/ministack:1.3.53
docker run -d -p 4566:4566 ministackorg/ministack:1.3.53

Or pin in compose.yaml:

services:
  ministack:
    image: ministackorg/ministack:1.3.53
    ports:
      - "4566:4566"

Stay in sync

Issues and PRs welcome on GitHub. Discussion on r/ministack.