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:

None

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-1

AWS 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

None

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 Pipeline

Writing 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

None

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

None

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 Access

Challenges in Policy-as-Code

It's powerful… but not easy.

None

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:

  1. Audit mode
  2. Warning mode
  3. 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

None

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 App

Features:

  • 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.md

Author'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.