All cloud projects
LIVE us-east-1 2026
CLOUD PROJECT · 2026

Automated security scorecard

A daily read-only Lambda grades the AWS account and the live site against a fixed set of security controls — no IAM users, locked-down S3, no open security groups, the full header set, a healthy TLS cert — and publishes the graded result. Any check that flips from pass to fail pages the same SNS topic the canary uses.

LambdaIAMACMEventBridgeSNSS3CloudFrontTerraform

The problem

Security posture is easy to assert and hard to prove. Anyone can say “I follow least privilege” or “my headers are tight.” The interesting version is a system that checks itself, on a schedule, and shows its work — so the claim is a live graded artifact, not a bullet point.

The constraint is cost and honesty. AWS has a managed answer for continuous compliance — Config — but it bills per configuration item recorded and per rule evaluation, which lands around $2+/month for even a tiny account: more than the rest of this platform combined. So the design goal was a homegrown, transparent, read-only auditor that costs effectively nothing and that a reader can fully understand by looking at one Lambda.

The architecture

A daily EventBridge schedule invokes a Lambda that runs a fixed set of read-only checks and writes scorecard.json to the shared S3 data bucket, served same-origin through the existing CloudFront /data/* behavior. The /security/ page fetches it first-party and renders a grade plus per-check pass/fail badges. If any check flips from pass to fail versus the previous run, the Lambda publishes a descriptive message to the same SNS topic the observability canary uses.

EventBridgeAudit λIAM · S3 · EC2 · ACMsite headersdailyscorecard.jsonCloudFront /data/*/security/ pageSNS (on flip)pass→fail
Daily path: EventBridge → audit Lambda → read-only checks against IAM / S3 / EC2 / ACM + the live site's headers → scorecard.json in the data bucket → CloudFront /data/* → the /security/ page. A pass→fail flip publishes to 002's SNS topic.

The controls

Account — the proof that the deploy story holds up:

Live site — graded by fetching andruxa.dev exactly as a browser would:

The first run found three real things

The point of building this was to catch what I’d otherwise miss — and on its very first run it did, grading the account a D:

Fixing those took the grade to A / 100. That’s the whole value proposition: a scorecard that only ever says “all green” isn’t auditing anything. This one found real gaps the first day it ran.

Key decisions & trade-offs

Homegrown instead of AWS Config. Config is the “correct” managed answer and the right call at organizational scale — conformance packs, history, drift timelines. At this scale it’s ~$2+/mo to grade a handful of things a 120-line Lambda can check for free, and the Lambda is fully legible: the controls are the code. The trade-off is that I own the check logic and there’s no historical timeline — acceptable for a portfolio, and an honest thing to say in an interview rather than pretending Config is always the answer.

Read-only, least privilege — the auditor practices what it grades. The role gets exactly the inspection actions it needs. Most (iam:GetAccountSummary, iam:ListUsers, s3:GetAccountPublicAccessBlock, ec2:DescribeSecurityGroups) don’t support resource-level scoping, so they’re granted on *; the ones that do are pinned — acm:DescribeCertificate to the site cert, s3:PutObject/GetObject to the data/ prefix, sns:Publish to the one topic. It can read posture and nothing else; it can’t change a single resource.

Alert on the flip, not the state. A naive design pages every day a check is red, which trains you to ignore it. This Lambda compares against the previous scorecard.json and only publishes when a check goes pass → fail — a genuine regression — with a message naming exactly what broke. Steady-state red (a known, accepted finding) stays quiet.

Cost breakdown

ComponentMonthly cost
Audit Lambda (~30 invocations)~$0 (free tier)
IAM/S3/EC2/ACM read APIs$0
S3 object + CloudFront /data/*fractional cents
SNS on regression (reuses 002 topic)~$0
Total≈ $0/mo (vs ~$2+/mo for AWS Config)

What I’d do differently at scale

For a real account this graduates to AWS Config with managed + custom rules and conformance packs (CIS, PCI), Security Hub to aggregate findings across accounts, and an AWS Organizations SCP layer so the controls are enforced, not just observed — you can’t open a public bucket if the SCP forbids it. The scorecard pattern still earns its place as the public, human-readable summary on top; the enforcement moves underneath it. I’d also push findings through the same incident tooling as everything else rather than raw SNS once there’s a team to route them to.