| name | hulumi-for-operations-v1-3 |
|---|---|
| created | 2026-05-01 |
| status | ideation |
| tla_required | false |
| parent_runbook | docs/slo/completed/RUNBOOK-hulumi-operations.md |
Note on origin: This doc is a scope-revised v1.3 plan. The user-proposed v1.3 list was:
EcrPullThroughCache + Ec2GoldenAmiPipeline + Ec2PatchWaves + KEV-aware severity escalation. The 2026-05-01 design diffs to v1.2 absorbedEc2PatchWaves(now M1 of v1.2) andKEV-aware severity escalation(now M2 of v1.2 via dual-route + Inspector v2 native KEV). v1.3 therefore re-fills its slate with the next layer of the patching story: the image pipeline (so new EC2s + new container images start patched on day one) and the ASG-orchestrated rolling refresh (so a critical CVE rollout drains connections cleanly without dropping in-flight requests). Both directly answer Scenarios 1 and 2 from the original sunlit-guardian feedback (critical-CVE response + evergreen-deploy-already-patched).
Sunlit (and any Hulumi consumer) lands v1.2 in production sometime in late 2026. They get detection + scheduled patching + canary waves — the foundation. Within a sprint, they hit two predictable gaps:
-
A critical CVE drops on a Tuesday afternoon. Inspector v2's KEV-route fires and pages the on-call engineer at 14:32 UTC. They have the affected instance IDs in the alert. But the next
Ec2PatchWavesMaintenance Window doesn't fire until Sunday 02:00 UTC for the dev wave — 4 days away. The on-call has to either (a) manually runaws ssm start-automation-execution AWS-RunPatchBaseline ...— at which point SSM patches in place and reboots, dropping every in-flight HTTP request to that EC2 because there's no ALB drain-then-replace orchestration; or (b) wait until Sunday, accepting 4 days of exposure. Both are bad. -
A new EC2 is launched. Auto Scaling Group spins up a fresh instance from the launch template. The launch template references an AMI baked 3 weeks ago, when the previous Ec2GoldenAmiPipeline run didn't exist. The new instance starts un-patched. Inspector v2 catches it within an hour and fires a CRITICAL alert. Now there are two un-patched instances in the fleet (the old one we knew about, plus this new one we just launched). The fleet drifts faster than the patch cadence catches up.
Same shape applies to container images. A dev pushes code Tuesday morning. CI builds a container with a base image (FROM rust:1.88) that resolves to the digest from 3 weeks ago. The image lands in ECR with the old base. Inspector v2 finds CVEs in the base layer the same day. Now ECR has a known-vulnerable image deployed to EKS — and there's no automatic rebuild path.
The pain compounds when an AI agent helps the consumer write the first cut. v1.2's Ec2PatchBaseline + DetectiveServicesEnable + AuditTrail get the consumer 70% of the way to safe patching. The remaining 30% — image pipelines + rolling refresh — is exactly the gap v1.3 fills.
- Spin up a new EC2 and have it boot from an AMI that was patched in the last 7 days, automatically — no manual AMI-rotation discipline required.
- When a critical CVE drops, trigger a rolling refresh of the affected Auto Scaling Group: build new AMI with the patch, instance-refresh with
MinHealthyPercentageand ALB drain timeout, no dropped connections — even on a Tuesday afternoon, no maintenance window required. - Pull DHI / Chainguard / Docker Hub upstream container images through a private ECR cache, signed-and-attested, so the dev's
docker pulland CI'sdocker buildgo through the same auditable path — no public-internet image dependency at build time. - Have the consumer's ECR repository auto-rebuild a container image on Inspector v2 KEV finding by triggering a GitHub
repository_dispatchwebhook — without Hulumi shipping the Lambda (the webhook is one EventBridge rule + one EventBridge API destination resource, both declarative). - Get a
/hulumi-threat-modelscenario for the "image-pipeline-stale" failure mode that walks an AI agent through the controls before they write the first cut.
- Breach (stale-AMI drift exploit): A consumer adopts
Ec2GoldenAmiPipelinewith a default rebuild cadence of "weekly on Sunday." A new ASG launches a fresh instance Wednesday morning from the AMI baked the prior Sunday. CVE-2026-XXXXX (kernel UAF, PoC public, KEV-listed) drops Wednesday afternoon. The fresh instance is exposed for ~4 days until the next AMI rebuild + ASG refresh. Adversary: opportunistic worm scanningeu-west-2for the CVE. Surface: the kernel of the fresh ASG-launched EC2. Hulumi's mitigation: tier-aware default — Sandbox = weekly rebuild, StartupHardened = daily rebuild + KEV-trigger rebuild path. The KEV-trigger means a KEV finding fromDetectiveServicesEnable(M2 of v1.2) routes through EventBridge toEc2GoldenAmiPipeline.rebuildOnKevTrigger, kicking off an out-of-cadence rebuild + instance-refresh. - Compliance fine (PCI-DSS Req 6.3.3 violation persists despite v1.2 in place): A UK fintech ships
Ec2PatchBaseline+Ec2PatchWavesfrom v1.2 but never adoptsEc2GoldenAmiPipeline. Their ASG launches new EC2s from a 6-month-old AMI. The auditor pulls the SSM Patch Compliance report and finds only in-place-patched instances are compliant; ASG-fresh instances drop to non-compliant within 12 hours of launch. Auditor reports "patch coverage drifts faster than the patch cadence" → PCI-DSS 6.3.3 finding. Mitigation:Ec2GoldenAmiPipelineis the v1.3 component that closes this gap; documented in cookbook + aO_PATCH_4policy rule (Sandbox: advisory; StartupHardened: mandatory) that requires everyaws.autoscaling.LaunchTemplateto reference an AMI taggedhulumi:ami-pipeline:source=Ec2GoldenAmiPipeline. - Prolonged outage (instance refresh takes the fleet down): A consumer adopts
AsgInstanceRefreshwith defaultMinHealthyPercentage: 50and a fleet of 4 EC2s behind an ALB. The instance-refresh terminates 2 instances simultaneously. Two seconds later, ALB target group reports 50% unhealthy, the remaining 2 instances absorb full traffic + immediately CPU-saturate, the ALB starts 5xx-ing. Who notices first: customer Slack channel within 90 seconds. Mitigation: Hulumi defaultsMinHealthyPercentageto 100 (replace one at a time) — slower but safe. Tier ladder: Sandbox = 100 (slow + safe); StartupHardened = consumer-required (fail-loud — they know their fleet shape).
- Effort: 3 person-weeks
- Wedge week 1:
EcrPullThroughCache(M1) — wrapsaws.ecr.PullThroughCacheRulefor DHI / Chainguard / Docker Hub upstreams. Trivial component, ~150 lines TS. - Subsequent:
Ec2GoldenAmiPipeline(M2) wraps EC2 Image Builder for AMIs. ASG refresh is manual viaaws autoscaling start-instance-refresh— Hulumi documents the pattern in a cookbook but ships no orchestration component. - Risks: under-delivers on Scenario 1 (critical-CVE-safe-rollout). Manual
aws autoscaling start-instance-refreshis a one-line CLI but consumers will get theMinHealthyPercentagedefault wrong. Doesn't solve the drain-before-reboot problem.
- Effort: 5 person-weeks (5 milestones — within
/slo-plancap) - Wedge: same as A, plus
AsgInstanceRefresh(M3) — wraps the ASG instance-refresh API with safe defaults (MinHealthyPercentage 100 at Sandbox; consumer-required at StartupHardened), ALB drain timeout, max-1-instance-at-a-time, and atriggerOnAmiBumpknob that auto-triggers refresh whenEc2GoldenAmiPipelinedistributes a new AMI. - M4 ships
ContainerImageRebuildTrigger— declarative EventBridge rule + API destination + IAM role that POSTs a GitHubrepository_dispatchpayload when Inspector v2 fires a KEV finding for an ECR image taggedhulumi:source-repo=<org>/<repo>. No Hulumi-shipped Lambda —aws.cloudwatch.EventApiDestinationdoes the HTTP POST natively. Consumer's GitHub Actions catches the dispatch and rebuilds. - M5 ships three new
/hulumi-threat-modelscenarios + the v1.3.0 atomic four-package release. - Risks: largest scope; the
ContainerImageRebuildTriggerGitHub PAT/App auth is the crux — consumer-supplied viaaws.secretsmanager.Secretreference, which adds a documentation burden. TheAsgInstanceRefresh.triggerOnAmiBumpcross-component wire requires carefuldependsOndiscipline.
- Effort: 1 person-week
- Wedge: ship four cookbooks (
ecr-pull-through-cache.md,ec2-golden-ami-pipeline.md,asg-instance-refresh-safe-defaults.md,container-image-rebuild-on-kev.md). Each cookbook contains the Pulumi snippet a consumer copy-pastes. No new components. - Risks: leaves ~600 lines of Pulumi to copy-paste per consumer; defeats the "Hulumi components codify the right defaults" discipline. Approach C is the v1.4 fallback if v1.3 budget collapses.
Approach B, with the same hard scope contract pinned in v1.2's runbook Rule 0: Hulumi codifies time-based defaults as IaC. The consumer's findings triage and runtime orchestration are theirs. The line between "infra pipeline" (in scope) and "orchestration runtime" (out of scope) holds — AsgInstanceRefresh wraps an existing AWS-managed orchestration (ASG instance-refresh API), not a Hulumi-authored runtime. ContainerImageRebuildTrigger uses aws.cloudwatch.EventApiDestination (declarative HTTP POST), not a Lambda.
The five-milestone shape:
| M | Surface | Closes / answers |
|---|---|---|
| M1 | EcrPullThroughCache (DHI + Chainguard + Docker Hub upstreams + auth) |
Hardened-base-images cookbook from v1.2 M5 |
| M2 | Ec2GoldenAmiPipeline (EC2 Image Builder wrapper + tier-aware rebuild cadence + KEV-trigger path) |
Scenario 2 (evergreen — new EC2 starts patched) |
| M3 | AsgInstanceRefresh (safe defaults + ALB drain + triggerOnAmiBump) |
Scenario 1 (critical-CVE-safe-rollout) |
| M4 | ContainerImageRebuildTrigger (declarative EventBridge → GitHub repository_dispatch) + O_PATCH_4 policy rule |
Container-loop sub-piece (M5 cookbook from v1.2 promoted to component) |
| M5 | Three new /hulumi-threat-model scenarios (aws-stale-ami-drift, asg-refresh-saturation, container-image-stale-base) + atomic v1.3.0 release |
v1.3 launch |
This shape — components in M1–M4, skill scenarios + release in M5 — mirrors v1.2's pattern. No new milestone discipline needed.
The dev-laptop loop pieces from the original sunlit thread (Renovate config for FROM-digest pinning, devcontainer integration) stay in cookbook-only form per Rule 0 — they're repo-level developer ergonomics, not IaC. Hulumi ships sample renovate.json5 snippets in the v1.2 M5 hardened-base-images cookbook (already on the M5 list).
aws.cloudwatch.EventApiDestinationpayload customization — how flexible is the JSON payload template the API destination sends to GitHub? Specifically: can it inject the Inspector finding's CVE ID and ECR image digest into the dispatch payload'sclient_payloadfield? This shapes M4's surface.- EC2 Image Builder cost at sunlit-shape fleet — published as $X.XX per build minute; expected monthly cost for a daily AMI rebuild + 3 distribution targets across
eu-west-2is what number? Verifies the StartupHardened daily-rebuild default is affordable for solo developers. - GitHub
repository_dispatchrate limits + retry semantics — when the API destination POSTs, does GitHub's rate limit response (429 / 403) propagate back to the EventBridge rule? Does Hulumi need to ship a dead-letter SNS subscription pattern for failed dispatches, or is API destination's built-in retry sufficient? AsgInstanceRefresh.triggerOnAmiBumpmechanism — is the cross-component trigger a PulumiOutput<string>chain (clean) or an EventBridge rule onimagebuilder.amazonaws.comevents (more decoupled, but adds an EventBridge rule per pipeline)? Default decision:Output<string>chain for tightest coupling; EventBridge rule as a v1.4 opt-in if consumers want a webhook surface.
The original sunlit thread's "container/dev-laptop loop is a separate beast" framing holds. v1.3 ships:
- v1.2 M5's
hardened-base-images.mdcookbook covers laptop ergonomics (Renovate, devcontainers, FROM-digest pinning). - v1.3 M4's
ContainerImageRebuildTriggercovers the runtime path (KEV → CI rebuild). - The CI build hygiene (Renovate auto-PR, Trivy gate in CI, SHA-pin discipline) stays in cookbook form. Hulumi does NOT ship GitHub Actions workflows or pre-commit hooks — those are repo-level concerns that don't belong in IaC.
If the dev-laptop loop turns out to need stronger Hulumi support (e.g., a DevContainerImage component that publishes a private DHI-derived image to ECR for the team's devcontainer setup to consume), that's v1.4 territory — not v1.3.
Recommended next steps, in order:
/slo-research hulumi-for-operations-v1-3— answer the four open questions, especially #1 (API destination payload) and #2 (EC2 Image Builder cost)./slo-architect hulumi-for-operations-v1-3— produce the design record + threat model. Reuse v1.2's design-doc shape./slo-plan hulumi-for-operations-v1-3— producedocs/slo/current/RUNBOOK-hulumi-operations-v1-3.md(move todocs/slo/completed/once the last milestone closes) + per-milestone lessons / completion files underdocs/slo/lessons/anddocs/slo/completion/.- Wait until v1.2 ships before kicking off v1.3 implementation — v1.3 components depend on v1.2 surfaces (especially
DetectiveServicesEnablefor the KEV trigger andEc2PatchBaselinefor the patch-compliance metric the AMI rebuild consumes).
/slo-tla is N/A — no concurrent actors / distributed-state guarantees beyond Pulumi's standard apply ordering. Mirrors v1.2's decision.