# Designing an ISO-27001-Native CI/CD Pipeline on AWS

> **“We passed an ISO-27001 surveillance audit with zero Jira tickets, zero screenshots, and zero manual evidence.”**

That line usually gets silence. Then disbelief. Then the real question:

> *“Okay… how?”*

This article answers that. Not with theory but with **architecture, you can actually build on AWS**.

---

# Where This Idea Really Came From (No Fiction)

This didn’t start as a “compliance initiative”. It started during a late-night ISO audit prep cycle on a production AWS platform that was already:

* secure by design
    
* fully automated
    
* running mature CI/CD pipelines
    

Yet, every audit cycle looked the same. Two weeks before the audit:

* Jira filled with *“ISO Evidence – URGENT”*
    
* Engineers re-explained changes from months ago
    
* Screenshots of pipelines that already enforced controls
    
* Security teams became evidence collectors instead of engineers
    

Nothing was broken. The **system was already enforcing the controls**. However, ISO didn’t trust the system because it didn’t **speak ISO’s language**.

---

# The Breaking Point

In one call, someone said:

> *“Can you just raise a Jira ticket so we have evidence?”*

That “change” already had:

* protected branches
    
* multiple approvals
    
* immutable artifacts in ECR
    
* full CloudTrail logs
    

Yet none of it counted.

That’s when the thought hit, not as inspiration but frustration:

> **Why are humans translating system behavior into documents  
> instead of systems generating audit-grade evidence themselves?**

---

# The Shift: Reading ISO as Architecture

That night, ISO-27001 stopped looking like a policy.

It started looking like a **system design specification**.

Not:

> *“How do we prove this control?”*

But:

> *“If this control were enforced by software, what would it look like?”*

Suddenly, Annex A became deterministic.

| ISO Control Intent | Pipeline Primitive |
| --- | --- |
| Change control | Branch protection |
| Segregation of duties | Approval graph |
| Integrity | Immutable artifacts |
| Traceability | Hash-linked logs |
| Audit evidence | Auto-generated facts |

ISO wasn’t asking for screenshots. ISO was describing **how a system should behave**.

---

# The First Experiment (Small but Dangerous)

I didn’t redesign everything. I added one thing. After every deployment, the pipeline emitted a JSON file:

```json
{
  "control_id": "A.8.32",
  "commit": "9a1c…",
  "approvals": ["security", "platform"],
  "artifact_digest": "sha256:…",
  "pipeline_run": "run-8732",
  "timestamp": "2026-01-21T10:41:00Z"
}
```

No humans. No tickets. No screenshots.

Just **facts**, produced by the system.

---

# The Audit That Changed Everything

At the next ISO surveillance audit, instead of folders, we gave the auditor:

* read-only access
    
* time-bounded queries
    
* evidence already mapped to controls
    

No walkthrough.  
No explanations.

After exploring quietly, the auditor said:

> *“So this pipeline doesn’t allow violations in the first place?”*

Exactly.

We didn’t prove compliance. We **eliminated the possibility of non-compliance**.

---

# What “ISO-Native” Actually Means

| Traditional ISO | ISO-Native |
| --- | --- |
| ISO as paperwork | ISO as system logic |
| Evidence collected later | Evidence generated by default |
| Humans enforce | Pipelines enforce |
| Audit preparation | Continuous audit readiness |

This is **ISO-driven engineering**, not ISO-aware tooling.

---

# The AWS ISO-Native CI/CD Architecture

### In depth

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1768983328023/c050e6d3-8989-4126-bd39-cc559c8edfb6.jpeg align="center")

### Core Components (AWS)

1. **ISO Control Registry (YAML in Git)**
    
2. **CI/CD Orchestrator (GitHub Actions / CodePipeline)**
    
3. **Policy Engine (OPA / Conftest)**
    
4. **Artefact Store (ECR – immutable digests)**
    
5. **Evidence Ledger (S3 Object Lock + KMS)**
    
6. **Audit Logs (CloudTrail + hash chaining)**
    
7. **Auditor Read-Only Interface (Athena / API Gateway)**
    

## Step 1: ISO Control Registry (Source of Truth)

### `controls/iso27001.yaml`

```yaml
A.8.32:
  title: Change Management
  pipeline:
    branch_protection:
      - main
    approvals:
      min: 2
      roles:
        - security
        - platform
    artifacts:
      immutable: true
    evidence:
      retention_years: 7
```

This file **replaces**:

* change tickets
    
* wiki pages
    
* approval SOPs
    

## Step 2: Branching Strategy Enforced by ISO

```text
main        → production (locked)
release/*  → promotion only
develop    → integration
feature/*  → ephemeral
```

### GitHub Branch Protection (Example)

```yaml
required_reviews: 2
required_status_checks:
  - iso-policy-check
  - security-scan
```

You **cannot** bypass ISO controls even accidentally.

## Step 3: Segregation of Duties (OPA)

### `policy/approvals.rego`

```rego
package iso.approvals

deny[msg] {
  input.approvals.count < 2
  msg := "ISO violation: insufficient approvals"
}

deny[msg] {
  input.approvals.roles[_] == "developer"
  msg := "ISO violation: self-approval blocked"
}
```

Pipeline fails instantly. No human escalation required.

## Step 4: Artefact Immutability (AWS ECR)

### Build Once, Promote Everywhere

```bash
docker buildx build \
  --provenance=true \
  --sbom=true \
  -t 764227591594.dkr.ecr.eu-west-2.amazonaws.com/app:${GIT_SHA} \
  --push .
```

Deployments **only reference digests**:

```yaml
image: app@sha256:abc123
```

OPA blocks mutable tags.

## Step 5: Evidence Auto-Generation

### Evidence Schema

```json
{
  "control_id": "A.8.32",
  "commit": "abc123",
  "approvals": ["security", "platform"],
  "artifact_digest": "sha256:…",
  "pipeline_run": "run-9921",
  "timestamp": "2026-01-21T12:01:00Z"
}
```

Generated on **every pipeline run**.

## Step 6: Immutable Evidence Ledger (AWS)

### S3 + Object Lock + KMS

```markdown
resource "aws_s3_bucket" "evidence" {
  bucket = "iso-evidence-ledger"
  object_lock_enabled = true
}

resource "aws_s3_bucket_object_lock_configuration" "lock" {
  bucket = aws_s3_bucket.evidence.id
  rule {
    default_retention {
      mode  = "COMPLIANCE"
      days = 2555
    }
  }
}
```

✔ Cannot be altered  
✔ Cannot be deleted  
✔ Auditor-grade by design

## Step 7: Auditor-Ready Queries (No Screenshots)

### Athena Example

```sql
SELECT *
FROM evidence
WHERE control_id = 'A.8.32'
AND timestamp BETWEEN date '2025-01-01' AND date '2026-01-01';
```

Auditors **self-serve evidence**.

---

# Auditor’s Perspective (Sidebar)

> *“Most teams show me screenshots and tell me what should have happened.”*
> 
> *“This system shows me what* ***could not have happened***\*.”\*

From an auditor’s point of view, this architecture is powerful because:

* controls are preventative, not detective
    
* evidence is generated, not curated
    
* logs are immutable and queryable
    
* explanations are unnecessary
    

**Trust shifts from people to systems,** and that’s exactly what ISO intended.

---

## Testing the System (Break It on Purpose)

| Test | Result |
| --- | --- |
| Push to `main` | ❌ blocked |
| Self-approve PR | ❌ denied |
| Redeploy old image | ❌ digest mismatch |
| Delete evidence | ❌ S3 Object Lock |

If it fails in production, it **fails before the audit**.

---

# Why This Changes Everything

ISO-27001 stops being:

* a quarterly fire drill
    
* a security tax
    
* an engineering slowdown
    

And becomes:

* a **property of the pipeline**
    
* a **by-product of delivery**
    
* a **competitive advantage**
    

---

# Final Thought

ISO 27001 was never meant to be bureaucratic. It was meant to describe **safe system behaviour**.

> **When controls become code, compliance stops being work and becomes inevitable.**
