Skip to main content

AWS Resource Verification Matrix

What CloudForge deploys to MiniStack, how it differs from the canonical AWS template, and how to verify each resource against live state.

See also: Verification layers · Template adaptations · Extended Testing


Three Sources of Truth

Every verification question maps to one of three artifacts:

┌─────────────────────────────────────────────────────────────────────────┐
│ 1. Canonical template cdk.out/<stack>.template.json │
│ What CDK would deploy to real AWS. Never modified by MiniStack. │
└───────────────────────────────┬─────────────────────────────────────────┘
│ MiniStackTemplateAdapter
┌───────────────────────────────▼─────────────────────────────────────────┐
│ 2. Adapted template cdk.out/<stack>.ministack.template.json │
│ What CloudFormation sends to MiniStack. Audit: .ministack-adaptations│
└───────────────────────────────┬─────────────────────────────────────────┘
│ MiniStackDeployer (create/update)
┌───────────────────────────────▼─────────────────────────────────────────┐
│ 3. Deployed + runtime CFN stack + service APIs + Docker + auth proxy│
│ What MiniStack recorded and what actually runs on your machine. │
└─────────────────────────────────────────────────────────────────────────┘
QuestionWhere to look
“Should this resource exist for my config?”Canonical template (Layer 6 / comprehensive-resource-validator.sh)
“Did we deploy the adapted shape?”Adapted template + adaptation report
“Did MiniStack accept and materialize it?”CFN list-stack-resources + service APIs
“Does the app actually work?”Stack outputs, HTTP, Docker, auth proxy

Always set endpoint credentials before API checks:

export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
export AWS_DEFAULT_REGION=us-east-1
export AWS_ENDPOINT_URL=http://localhost:4566
export STACK_NAME=my-jenkins # deployment-context.json stackName
export MINISTACK_STACK="${STACK_NAME}-ministack"

On ARM Macs where the host aws binary fails, use Docker:

alias aws='docker run --rm -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY \
-e AWS_DEFAULT_REGION -e AWS_ENDPOINT_URL \
--add-host=host.docker.internal:host-gateway amazon/aws-cli'
export AWS_ENDPOINT_URL=http://host.docker.internal:4566

Verification Methods (How)

MethodAWS Console equivalentWhat it proves
CFN stack statusCloudFormation → StacksCreate/update/delete succeeded
CFN resource inventoryStack → Resources tabLogical resources and physical IDs exist
CFN stack eventsStack → EventsWhich resource failed and why
CFN outputsStack → OutputsAdapter-generated local URLs
Service API describe/listEC2, ECS, ELB, Route53, etc.Emulator backend populated records
Template JSON diff— (pre-deploy)Intended add/remove/change between transitions
Adaptation report— (MiniStack-specific)Explicit local divergences from canonical
HTTP probeBrowser / curlApplication responds
Docker inspectECS task → containerReal container running with expected port/volume
Auth proxy / mock OIDC— (local substitute)OIDC flow when ALB auth is in canonical template

Rule: For infrastructure wiring (VPC, Route53 alias → ALB, Cognito pool present), trust CFN + service APIs. For user-facing reachability locally, trust stack outputs + HTTP, not public DNS or ALB forward behavior.


Resource Matrix — Jenkins Fargate (MiniStack MVP)

Legend:

ColumnMeaning
CanonicalIn cdk.out/<stack>.template.json when config enables the feature
Deployed CFNIn adapted template and expected in list-stack-resources after deploy
AdapterChange applied before deploy (none, remove, transform, local-only)
Verify viaPrimary checks (combine CFN inventory + service API where both apply)
Local fidelityHow closely runtime matches real AWS

Core networking and compute

Resource typeCanonicalDeployed CFNAdapterVerify viaLocal fidelity
AWS::EC2::VPCAlwaysYesnoneCFN inventory; aws ec2 describe-vpcsMetadata + partial networking
AWS::EC2::SubnetAlwaysYesnoneCFN; aws ec2 describe-subnetsSame
AWS::EC2::InternetGatewayAlwaysYesnoneCFN; aws ec2 describe-internet-gatewaysSame
AWS::EC2::SecurityGroupAlwaysYesnoneCFN; aws ec2 describe-security-groupsSame
AWS::EC2::SecurityGroupIngressOften (standalone)No (inlined)remove → merge into parent SGAdaptation report; parent SG rules in describe-security-groupsEquivalent rule intent, different CFN shape
AWS::ECS::ClusterAlwaysYesnoneCFN; aws ecs list-clustersSame
AWS::ECS::TaskDefinitionAlwaysYesnoneCFN; aws ecs describe-task-definitionRuns real Docker task locally
AWS::ECS::ServiceAlwaysYesnoneCFN; aws ecs describe-servicesService exists; task maps to container
AWS::IAM::RoleAlwaysYesnoneCFN; aws iam get-role (if supported)Metadata / pass-through for task
AWS::Logs::LogGroupAlwaysYesnoneCFN; aws logs describe-log-groupsLog group recorded; log delivery varies

Load balancer

Resource typeCanonicalDeployed CFNAdapterVerify viaLocal fidelity
AWS::ElasticLoadBalancingV2::LoadBalancerAlwaysYesdeterministic nameCFN; aws elbv2 describe-load-balancersALB metadata; data plane via /_alb/ path
AWS::ElasticLoadBalancingV2::TargetGroupAlwaysYesnoneCFN; aws elbv2 describe-target-groupsRegistered; not used for forward
AWS::ElasticLoadBalancingV2::ListenerAlwaysYesredirect replaces forward/TLS redirectCFN; aws elbv2 describe-listenersRedirect to localhost port, not forward to ECS
AWS::ElasticLoadBalancingV2::ListenerRuleIf presentYesauth actions strippedCFN; aws elbv2 describe-rulesSame redirect/auth stripping rules

ALB behavior check:

# Listener action should be redirect → localhost:<port> in adapted template
jq '.Resources[] | select(.Type=="AWS::ElasticLoadBalancingV2::Listener") |
.Properties.DefaultActions' "cdk.out/${STACK_NAME}.ministack.template.json"

# Data-plane URL from stack outputs (redirect chain)
aws cloudformation describe-stacks --stack-name "$MINISTACK_STACK" \
--query 'Stacks[0].Outputs[?OutputKey==`MiniStackLocalUrl`].OutputValue' --output text
curl -sIL "$(aws cloudformation describe-stacks --stack-name "$MINISTACK_STACK" \
--query 'Stacks[0].Outputs[?OutputKey==`MiniStackLocalUrl`].OutputValue' --output text)" \
| grep -E '^HTTP|^Location'

Storage and scaling (adapted away)

Resource typeCanonicalDeployed CFNAdapterVerify viaLocal fidelity
AWS::EFS::FileSystemJenkins defaultNoremoveAdaptation report; absent from CFN inventoryReplaced by host bind mount
AWS::EFS::MountTargetJenkins defaultNoremoveSame
AWS::EFS::AccessPointJenkins defaultNoremoveSame
Host bind mountRuntime onlylocal-onlyOutput MiniStackHostVolume*; docker inspect mountPersists under .ministack-volumes/<stack>/
AWS::ApplicationAutoScaling::*If configuredNoremoveAdaptation report; absent from CFNNo local autoscaling
# Bind mount path from stack outputs
aws cloudformation describe-stacks --stack-name "$MINISTACK_STACK" \
--query 'Stacks[0].Outputs[?starts_with(OutputKey, `MiniStackHostVolume`)].{Key:OutputKey,Path:OutputValue}' \
--output table

docker ps --format '{{.Names}} {{.Mounts}}' | grep -i jenkins

Domain and TLS (incremental)

Resource typeCanonicalDeployed CFNAdapterVerify viaLocal fidelity
AWS::Route53::HostedZonedomain setYesnoneCFN; aws route53 list-hosted-zonesEmulator DNS only — not your laptop resolver
AWS::Route53::RecordSetdomain / subdomainYesnoneCFN; aws route53 list-resource-record-setsAlias → ALB DNS verifiable via API
AWS::CertificateManager::CertificateenableSsl: trueYesnoneCFN; aws acm list-certificatesCertificate resource exists; local HTTPS termination differs
HTTPS listener + certTLS enabledYesTLS redirect may become HTTP redirect locallyaws elbv2 describe-listenersUse outputs for browser URLs

Domain API check (source of truth — not browser DNS):

aws cloudformation list-stack-resources --stack-name "$MINISTACK_STACK" \
--query 'StackResourceSummaries[?contains(ResourceType,`Route53`)]' --output table

ZONE_ID=$(aws route53 list-hosted-zones \
--query 'HostedZones[?Name==`ministack.local.`].Id' --output text | awk '{print $1}')
aws route53 list-resource-record-sets --hosted-zone-id "$ZONE_ID" \
--query 'ResourceRecordSets[?Name==`jenkins.ministack.local.`]' --output json

See Local DNS vs API verification.

Authentication (incremental) — deferred for MiniStack MVP

Local auth runtime and browser login flow are tabled pending LocalStack evaluation. Adapter behavior and CFN inventory checks below still apply if you deploy with auth enabled; use authMode: none for MiniStack day-to-day testing.

Resource typeCanonicalDeployed CFNAdapterVerify viaLocal fidelity
AWS::Cognito::UserPoolauthMode: alb-oidc + auto-provisionYesnoneCFN; aws cognito-idp list-user-poolsPool exists in emulator
AWS::Cognito::UserPoolClientAuth enabledYesnoneCFN; aws cognito-idp list-user-pool-clientsSame
AWS::Cognito::UserPoolDomainAuth enabledYesnoneCFN inventorySame
ALB authenticate-oidc / authenticate-cognitoAuth enabledStripped from listenertransformAdaptation report; listener describe-listeners has no auth actionNot executed on ALB
MiniStackAuthProxy + mock OIDCRuntime onlylocal-onlycurl http://localhost:4180/_ministack/auth/health; stack output MiniStackAuthenticatedUrlSubstitutes ALB edge auth
# Cognito in stack
aws cloudformation list-stack-resources --stack-name "$MINISTACK_STACK" \
--query 'StackResourceSummaries[?contains(ResourceType,`Cognito`)]' --output table

# Auth stripped in adapted template
jq '.[] | select(.reason | contains("authenticate"))' \
"cdk.out/${STACK_NAME}.ministack-adaptations.json"

# Local auth runtime
curl -s http://localhost:4180/_ministack/auth/health

When auth is removed from config, expect Cognito resources absent from CFN inventory after update (same as AWS stack update).


By Deployment Phase

What to assert after each incremental step (matches Advanced — incremental deployments):

PhaseConfig flagsAssert in CFN inventoryAssert via service APIAssert runtime
0 — Baseno domain, no SSL, no authVPC, ALB, ECS, IAM, Logsdescribe-load-balancers, list-clustersMiniStackApplicationUrl HTTP < 500; Docker container
1 — Domaindomain, optional subdomain, createZone+ Route53 zone + recordslist-resource-record-sets alias → ALBFQDN in browser optional
2 — TLSenableSsl: true+ ACM cert, HTTPS listeneracm list-certificates, listener port 443Canonical has cert; local browser may still use output URLs
3 — AuthauthMode: alb-oidc (deferred)+ Cognito resources in CFN if deployedCognito APIsAuth proxy — not active by default
4 — Remove authauthMode: none (deferred)Cognito gone
5 — Remove domainclear domainRoute53 goneZones/records removed

No-op redeploy: identical adapted template → deployer reports no change set; CFN stack status unchanged.


Template-Level Verification (Pre- and Post-Deploy)

Compare canonical vs adapted vs deployed inventory:

cd cfc-testing

# Resource types — canonical AWS
jq -r '.Resources | to_entries[] | .value.Type' \
"cdk.out/${STACK_NAME}.template.json" | sort | uniq -c

# Resource types — adapted (what CFN receives)
jq -r '.Resources | to_entries[] | .value.Type' \
"cdk.out/${STACK_NAME}.ministack.template.json" | sort | uniq -c

# Every adapter change with reason
jq '.[] | {path, reason}' "cdk.out/${STACK_NAME}.ministack-adaptations.json"

# Deployed inventory (live)
aws cloudformation list-stack-resources --stack-name "$MINISTACK_STACK" \
--query 'StackResourceSummaries[].ResourceType' --output text | tr '\t' '\n' | sort | uniq -c

Parity rule: Deployed CFN resource types should match the adapted template (not the canonical template). Differences from canonical must appear in .ministack-adaptations.json.

For transition testing, use CloudFormationTemplateDiff (in cloudforge-ministack) between canonical templates at each config step — see Verification.


What Is Not Verified on MiniStack

These appear in canonical templates for AWS compliance/production profiles but are out of scope for MiniStack local MVP. Do not expect them in deployed CFN inventory or emulator APIs:

Resource / concernVerified on AWSMiniStack local
AWS::Config::*CDK Template.fromStack() integration testsNot deployed
AWS::CloudTrail::*SameNot deployed
AWS::GuardDuty::*SameNot deployed
AWS::WAFv2::*SameNot deployed
Compliance Config rules / audit postureCOMPLIANCE_TRUTH_TABLES.mdNot emulated
Public DNS propagationRoute53 + registrarEmulator-only Route53
ALB → ECS forwardReal target healthRedirect to localhost
ALB edge OIDC/CognitoListener authenticate actionsAuth proxy + mock OIDC
EFS NFSMount in taskHost bind mount
Application Auto ScalingCFN + ECS scalingRemoved by adapter

Quick Commands Reference

# Full stack picture
aws cloudformation describe-stacks --stack-name "$MINISTACK_STACK"
aws cloudformation list-stack-resources --stack-name "$MINISTACK_STACK" --output table
aws cloudformation describe-stacks --stack-name "$MINISTACK_STACK" \
--query 'Stacks[0].Outputs' --output table

# Built-in verify (outputs + HTTP poll)
java -cp "target/classes:target/dependency/*" \
com.cloudforgeci.ministack.MiniStackCli verify "$MINISTACK_STACK"

# Ground truth container
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' | grep -i jenkins