DevOps
I Wrote a Security Policy, Then Made Myself Break It
Okikiola Ashiru Dev.to (EN Zone)
3 views
A guardrail you haven't tried to violate is just documentation with better formatting.
That's the premise behind aws-boundary: an AWS multi-account setup using AWS Organizations, where a management account defines security guardrails and a separate member account operates under full administrator access, yet remains strictly bound by policies it cannot edit, bypass, or disable.
The setup
One management account defines two Service Control Policies attached to a workloads organizational unit:
a region lock (deny anything outside us-east-1, with exemptions for global services like IAM and STS) and
CloudTrail immutability (deny stopping, deleting, or modifying the audit trail, from anyone, including administrators).
A member account, dev-workload, gets native AdministratorAccess inside its own boundary. Access is brokered exclusively through short-lived STS AssumeRole sessions, zero static IAM user access keys allowed.
The experiment focuses on the gap between what AdministratorAccess implies on paper and what an SCP actually enforces at the API evaluation layer underneath it.
Proving it, not just configuring it
I assumed the admin role in the member account and tried to do exactly the things the guardrails are supposed to prevent, from inside the account that's supposed to be blocked:
Permitted Control Test (us-east-1): Created an SQS queue in the allowed region. Succeeded with HTTP 200, confirming the boundary doesn't break legitimate operations.
Violation 1 (Region Lock Breach): Attempted to create an SQS queue in eu-west-1. Failed with an explicit deny:
User: ... is not authorized to perform: sqs:CreateQueue ...
with an explicit deny in a service control policy: arn:aws:organizations::...:policy/.../p-oajpewkp
Violation 2 (Audit Tampering): Attempted cloudtrail:StopLogging against the organization trail. Denied immediately with AccessDeniedException.
Violation 3 (Audit Destruction): Attempted cloudtrail:DeleteTrail. Denied immediately with AccessDeniedException.
Four tests, four expected outcomes. The same explicit denial triggered inside the AWS Management Console UI, rendering an unbypassable red banner when attempting to switch regions.
What actually went wrong along the way
None of this worked on the first attempt, and the failures were more useful than the eventual pass.
Attaching the SCPs initially failed with PolicyTypeNotEnabledException, because feature_set = "ALL" makes SCPs available at the organization level, but the policy type still has to be explicitly enabled on the root container separately, a distinction that isn't obvious until Terraform tells you no.
Tearing the environment down surfaced two more: an OU can't be deleted while a suspended account is still parented under it, AWS holds closed accounts in a 30-day suspended state, and an organization itself can't be dissolved while any suspended account exists anywhere inside it. The actual fix for the second one was uncomfortable: leave the empty organization shell in place at zero cost, and remove it from Terraform state rather than fight AWS's retention policy.
Why the region-lock exemption list matters more than it looks
The region-lock SCP isn't a blanket deny. It explicitly exempts global control-plane services, IAM, STS, Organizations itself, Route 53. Get that exemption list wrong and you don't get a stricter guardrail, you get an account that can't authenticate or manage its own identity, which is a worse failure mode than the one you were trying to prevent. A security control that locks you out of fixing itself isn't a security control, it's an incident.
What this project didn't try to be
This isn't a full landing-zone framework, and two accounts under one OU is a small fraction of what a real multi-account AWS environment looks like at scale, more OUs, more granular SCPs, config aggregators, security hub integration. What it does prove is narrow and specific: that a policy attached at the organization level actually holds against an administrator trying to work around it from inside a member account, verified by trying, not by reading the policy and assuming it's correct.
Repo: github.com/aashiruu/aws-boundary
Read original: https://dev.to/0xkikiola/i-wrote-a-security-policy-then-made-myself-break-it-4ho3
← Previous
The Clean Server Passed. My Laptop Was Loading sitecustomize.py First.
Next →
Change-Intent Governance: The Missing Layer
Related
I Wrapped My x402 Pay-Per-Call APIs in an MCP Server — and Got Into the Official Registry Without GitHub
DevOps
0
Dev.to (EN Zone)
🛡️ IMDSv1 vs IMDSv2 en EC2: SSRF, métricas, riesgos y una migración segura
DevOps
0
Dev.to (EN Zone)
If you're just about to switch to Linux, read this.
DevOps
1
DEV Community
Your containers are not a security boundary, and CVE-2026-53362 just proved it
DevOps
2
DEV Community
Comments0
No comments yet — be the first