← Back to writing
2026-06-09

Building a NIS2-Compliant AWS Landing Zone — Week 0: Why I'm Doing This

AWSNIS2CloudSecurityComplianceLandingZoneIaCTerraformDevSecOpsProjectKickoff

NIS2 came into force across the EU in October 2024. Companies in banking, healthcare, energy, and telecom now have a legal obligation to implement the security measures in Article 21 — encryption, incident handling, access control, ongoing risk management. The deadline has already passed, and the fines go up to €10M or 2% of global turnover.

But if you search "AWS landing zone Terraform" today, almost nothing mentions NIS2. There's plenty mapped to CIS or NIST. The framework that actually creates legal obligations for EU companies is mostly absent from public infrastructure-as-code.

So that's what I'm building: an open-source AWS landing zone in Terraform where each module maps to a specific NIS2 Article 21 measure and ISO 27001:2022 control. I'm doing it in public, one module at a time, over six weeks — including the parts that don't go smoothly.

the plan

Three decisions that shape the project

Two frameworks, mapped properly. NIS2 is the legal requirement; ISO 27001:2022 is the set of controls EU teams use to show they meet it. I left out CIS and NIST on purpose — I'd rather map two frameworks properly than four superficially. Every resource is tagged with the measure and control it satisfies, so the compliance mapping comes straight from the infrastructure instead of a separate spreadsheet that goes stale.

LocalStack to build, real AWS to prove it. I develop and test everything on LocalStack Pro at zero cost, so anyone can clone the repo and run it without an AWS account. Then one cost-controlled run on real AWS in Week 6 captures the evidence an emulator can't produce — real GuardDuty findings, real Security Hub output — for under €15.

Track the risk instead of hiding it. A lot of "secure infrastructure" demos aim for a scanner dashboard with everything green and every finding suppressed. I don't think that proves much. A real setup has open findings; what matters is that each one was looked at, judged, and recorded with a reason. That record is the part I'd actually show an auditor. The green badge is just what's left over once you've done that honestly.

Building in public

The repo is public from the start — rough commits, work-in-progress branches, bot PRs and all. Every significant choice gets a short Architecture Decision Record, and every scanner finding gets a written disposition. This series is the running commentary: six posts, one per week, each picking up where the last left off.

I'm writing it as a build journal, not a set of tutorials, because a finished repo hides the decisions that went into it. You can't tell what was obvious from the start and what took three tries to get right. Going week by week keeps that visible, which is the part I'd have found useful to read myself.

Next in the series

Post 2 is Week 1: the first two modules — a KMS key and a locked-down S3 bucket, wired together through a clean interface — plus native terraform test and a CI pipeline behind branch protection. By the end of that week the repo has two modules, nine tests, seven checks running on every pull request, and a green badge that actually means something.

Repo Link: github.com/olanak/aws-nis2-baseline