Enforcing Security Using Cedar, SCPs, and OPA
"Security should not depend on memory. It should depend on policy."
A few years ago, a cloud engineering team at a fintech startup faced a nightmare.
One junior engineer accidentally deployed an S3 bucket with public access enabled. Nobody noticed for two days.
No malicious attack happened.
But it could have.
The security team started asking difficult questions:
- Why was the engineer even allowed to create public buckets?
- Why did nobody stop the deployment?
- Why were security rules written in PDFs instead of code?
- Why did governance depend on manual reviews?
That incident led them toward something powerful:
Policy-as-Code (PaC)
Instead of writing security guidelines in documentation, they started writing machine-enforced policies.
Policies became:
- version-controlled,
- tested,
- reviewed,
- automated,
- and continuously enforced.
This blog is about that journey.
We'll learn how modern AWS environments use:
- AWS Organizations SCPs
- OPA (Open Policy Agent)
- Cedar Policy Language
- Infrastructure-as-Code integration
- CI/CD enforcement
- Runtime governance
By the end, you'll understand how enterprise-grade governance actually works in modern cloud platforms
What is Policy-as-Code?
Policy-as-Code means:
Defining and enforcing rules using code instead of manual processes.
Instead of saying:
❌ "Developers should not create public S3 buckets."
You write:
{
"Effect": "Deny",
"Action": "s3:PutBucketPublicAccessBlock",
"Resource": "*"
}Or:
deny[msg] {
input.resource.public == true
msg := "Public S3 buckets are not allowed"
}The policy becomes:
- executable,
- testable,
- repeatable,
- enforceable automatically.
Why Policy-as-Code Matters
In traditional environments:

Modern cloud environments move too fast for manual governance.
A single Terraform deployment can create:
- 100 EC2 instances,
- 20 IAM roles,
- 15 S3 buckets,
- multiple databases,
- cross-account trust policies.
Humans cannot review everything manually.
Policy-as-Code solves this.
The Three Layers of AWS Governance
Think of cloud governance like airport security.
Layer 1 — SCPs (The Airport Rules)
SCPs define what is globally forbidden.
Example:
- Nobody can disable CloudTrail.
- Nobody can leave the organization.
- Nobody can create resources outside approved regions.
SCPs are organization-wide guardrails.
Layer 2 — OPA (The Security Inspector)
OPA validates infrastructure before deployment.
Example:
- Terraform cannot create public resources.
- Kubernetes manifests must include limits.
- IAM policies cannot contain
"Action": "*".
OPA acts during CI/CD.
Layer 3 — Cedar (Application Authorization)
Cedar controls fine-grained application access.
Example:
- Which user can access which document?
- Which tenant can modify which API resource?
- Which engineer can approve production changes?
Cedar handles modern authorization logic.
High-Level Architecture
┌─────────────────────┐
│ Developer Commits │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ CI/CD Pipeline │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ OPA Check │
│ Terraform Policies │
└──────────┬──────────┘
│
PASS │ FAIL
───────────────┼────────────────
│
▼
┌─────────────────────┐
│ Deploy to AWS │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ AWS SCP Enforcement │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Cedar Authorization │
│ Inside Applications │
└─────────────────────┘Understanding AWS SCPs
What are SCPs?
Service Control Policies (SCPs) are part of AWS Organizations.
They define the maximum permissions available in accounts.
Even if an IAM user has:
"Action": "*"An SCP can still deny actions.
Real-World SCP Example
Imagine your company only operates in:
- us-east-1
- ap-south-1
You want to block all other regions.
SCP Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUnapprovedRegions",
"Effect": "Deny",
"NotAction": [
"iam:*",
"organizations:*",
"route53:*"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestedRegion": [
"us-east-1",
"ap-south-1"
]
}
}
}
]
}What This Policy Does
If someone tries:
aws ec2 run-instances --region eu-west-1AWS immediately blocks it.
Even admins cannot bypass it.
That's the power of SCPs.
Another Enterprise SCP Example
Prevent disabling CloudTrail.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ProtectCloudTrail",
"Effect": "Deny",
"Action": [
"cloudtrail:StopLogging",
"cloudtrail:DeleteTrail"
],
"Resource": "*"
}
]
}This is common in:
- banks,
- healthcare,
- enterprise security,
- SOC2 environments.
SCP Best Practices

Introducing OPA (Open Policy Agent)
Now let's move to CI/CD security.
SCPs work after deployment attempts.
OPA works before deployment.
What is OPA?
OPA is a universal policy engine.
It evaluates:
- Terraform,
- Kubernetes,
- APIs,
- CI/CD pipelines,
- Docker configs,
- JSON/YAML documents.
OPA uses a language called Rego.
Real Problem OPA Solves
Suppose a developer writes:
resource "aws_s3_bucket" "public_bucket" {
bucket = "my-public-data"
acl = "public-read"
}Without policy enforcement:
- this reaches production,
- becomes internet accessible,
- creates a data exposure risk.
OPA can stop it instantly.
OPA + Terraform Workflow
Terraform Code
│
▼
Terraform Plan JSON
│
▼
OPA/Rego Evaluation
│
┌────┴────┐
│ │
PASS FAIL
│ │
▼ ▼
Deploy Block PipelineWriting Your First Rego Policy
Goal
Block public S3 buckets.
Rego Policy
package aws.s3
deny[msg] {
input.resource_type == "aws_s3_bucket"
input.config.acl == "public-read"
msg := "Public S3 bucket detected"
}Example Input
{
"resource_type": "aws_s3_bucket",
"config": {
"acl": "public-read"
}
}OPA Output
{
"deny": [
"Public S3 bucket detected"
]
}Pipeline fails immediately.
Advanced OPA Policy Example
Prevent wildcard IAM permissions.
Bad IAM Policy
{
"Action": "*",
"Resource": "*",
"Effect": "Allow"
}Rego Detection
package aws.iam
deny[msg] {
input.Statement[_].Action == "*"
msg := "Wildcard actions are not allowed"
}Real Enterprise Use Cases of OPA

OPA in CI/CD Pipeline
GitHub Actions Example
name: Policy Check
on: [push]
jobs:
opa-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install OPA
run: |
curl -L -o opa \
https://openpolicyagent.org/downloads/latest/opa_linux_amd64
chmod +x opa
sudo mv opa /usr/local/bin/
- name: Run Policy Check
run: |
opa eval \
--input terraform-plan.json \
--data policies/ \
"data.aws.s3.deny"Now Let's Talk About Cedar
This is where things become futuristic.
What is Cedar?
Cedar is an authorization policy language created by AWS.
It powers:
- fine-grained permissions,
- application authorization,
- modern access control systems.
It is heavily used with:
- Amazon Verified Permissions
- Zero Trust systems
- Multi-tenant SaaS applications
Why Cedar Matters
Traditional IAM struggles with:
- dynamic permissions,
- contextual access,
- relationship-based access,
- tenant isolation,
- business logic authorization.
Cedar solves this elegantly.
Real Example
Imagine a SaaS platform.
Rules:
- Managers can approve expenses.
- Employees can only view their own expenses.
- Finance can access all invoices.
- Contractors cannot access payroll data.
Hardcoding this logic becomes messy.
Cedar makes it clean.
Cedar Policy Example
permit(
principal,
action == Action::"view",
resource
)
when {
principal.department == resource.department
};What This Means
A user can access a resource only if:
- The action is
view - AND both belong to the same department.
Simple. Readable. Powerful.
Another Cedar Example
Allow only managers to approve deployments.
permit(
principal,
action == Action::"approveDeployment",
resource
)
when {
principal.role == "manager"
};Cedar vs IAM

Combining SCP + OPA + Cedar
This is where mature cloud governance happens.
Complete Governance Flow
┌────────────────────────────────────┐
│ SCPs │
│ Global AWS Guardrails │
│ (Never allow dangerous actions) │
└────────────────────────────────────┘
↓
┌────────────────────────────────────┐
│ OPA │
│ CI/CD Validation │
│ (Prevent insecure deployments) │
└────────────────────────────────────┘
↓
┌────────────────────────────────────┐
│ Cedar │
│ Application Authorization │
│ (Control user access dynamically) │
└────────────────────────────────────┘Enterprise Architecture Example
Imagine a banking platform.
SCP Layer
Security team enforces:
- approved regions only,
- mandatory CloudTrail,
- deny public S3,
- deny root usage.
OPA Layer
DevSecOps enforces:
- encryption enabled,
- mandatory tags,
- no wildcard IAM,
- approved AMI IDs,
- secure Terraform.
Cedar Layer
Application team enforces:
- customer isolation,
- RBAC,
- tenant permissions,
- API authorization.
Real-World DevSecOps Workflow
Developer Writes Terraform
│
▼
Git Push Event
│
▼
OPA Security Validation
│
▼
Approved Deployment
│
▼
AWS SCP Enforcement
│
▼
Application Uses Cedar
For Runtime AccessChallenges in Policy-as-Code
It's powerful… but not easy.

How Mature Teams Solve This
1. Treat Policies Like Software
Policies should have:
- PR reviews,
- testing,
- CI validation,
- versioning.
2. Create Reusable Policy Libraries
Instead of:
- writing duplicate policies,
- centralize governance modules.
3. Start With Warnings
Don't block everything immediately.
Phase rollout:
- Audit mode
- Warning mode
- Enforcement mode
Testing Policies
This is extremely important.
Example OPA Unit Test
package aws.s3
test_public_bucket_denied {
deny[msg] with input as {
"resource_type": "aws_s3_bucket",
"config": {
"acl": "public-read"
}
}
msg == "Public S3 bucket detected"
}Why Testing Matters
Without testing:
- security policies become dangerous,
- deployments break unexpectedly,
- Teams lose trust in governance.
Good governance should feel:
- predictable,
- transparent,
- stable.
Future of Policy-as-Code
This space is evolving rapidly.
Trends You Should Watch

Where Cedar Fits Into the Future
Cedar is important because cloud authorization is becoming:
- dynamic,
- contextual,
- identity-driven.
Future applications will require:
- relationship-based permissions,
- temporary access,
- risk-aware authorization,
- tenant isolation.
Cedar was designed for this future.
Final Thoughts
Policy-as-Code is no longer optional.
Modern cloud systems are too dynamic for:
- spreadsheets,
- manual reviews,
- tribal knowledge,
- human memory.
The future belongs to organizations where:
- Security is automated,
- governance is codified,
- compliance is continuous,
- and policies are version-controlled.
SCPs protect the cloud foundation.
OPA protects deployments.
Cedar protects applications.
Together, they create a modern cloud governance model.
Practical Learning Roadmap
If you want to master this domain:
Step 1 — Learn AWS IAM Deeply
Understand:
- policies,
- conditions,
- permissions boundaries,
- SCPs.
Step 2 — Learn Terraform Security
Practice:
- secure modules,
- infrastructure validation,
- drift detection.
Step 3 — Learn OPA/Rego
Build:
- CI/CD validation policies,
- Kubernetes policies,
- Terraform governance.
Step 4 — Learn Cedar
Focus on:
- fine-grained authorization,
- SaaS security,
- Zero Trust patterns.
Recommended Lab
Terraform + GitHub Actions + OPA + AWS Organizations + Cedar Demo AppFeatures:
- SCP enforcement
- Terraform validation
- API authorization
- Multi-tenant access control
This single project can massively strengthen your:
- DevSecOps portfolio,
- cloud security skills,
platform engineering expertise.
Conclusion
The biggest shift happening in cloud security is this:
Security is moving from documentation to automation.
And Policy-as-Code is at the center of that transformation.
If you learn:
- SCPs,
- OPA,
- Cedar,
- governance pipelines,
You'll be learning the exact skills modern platform security teams are investing in today.
Bonus: Complete Folder Structure Example
policy-as-code-project/
│
├── terraform/
│ ├── main.tf
│ └── variables.tf
│
├── policies/
│ ├── s3.rego
│ ├── iam.rego
│ └── tests/
│
├── scps/
│ └── deny-unapproved-regions.json
│
├── cedar/
│ └── authorization.cedar
│
├── github-actions/
│ └── policy-check.yml
│
└── README.mdAuthor's Note
Cloud security is evolving from:
- reactive defense to
- proactive enforcement.
The engineers who understand Policy-as-Code today will help define the next generation of secure cloud platforms tomorrow.