DevSecOps November 28, 2025 7 min read

Compliance as Code: Automating PCI-DSS in GitLab CI/CD

Audits used to take our client 3 weeks of manual evidence gathering. By shifting compliance left, we reduced it to a 2-hour automated report generated directly from the pipeline.


The "audit fatigue" problem

In regulated industries, developers often view security as a blocker. Security teams view developers as reckless. This friction slows down velocity. Our goal was to make "secure" the path of least resistance.

Implementation Strategy

We utilized Open Policy Agent (OPA) and Trivy to enforce rules before code ever reached staging.

1. Container Scanning (Trivy)

Every commit triggers a container scan. If a CVE with severity `CRITICAL` or `HIGH` is found, the pipeline fails immediately. Developers get direct feedback in their MR (Merge Request).

2. Infrastructure Policy (OPA/Rego)

We defined PCI-DSS requirements as code. For example, ensuring no S3 buckets are public and that all EBS volumes are encrypted.

# policy/pci.rego
package kubernetes.admission

deny[msg] {
    input.request.kind.kind == "Pod"
    not input.request.object.spec.securityContext.runAsNonRoot
    msg := "PCI-DSS Requirement: Containers must not run as root"
}

3. Automated Evidence Collection

The final step of a successful production deployment tags the release with a cryptographic signature. A separate tool collects these signatures, the test reports, and the scan results into a read-only S3 bucket accessible by auditors.

Why this matters

Compliance is no longer a yearly panic. It is a continuous state. This approach allowed the client to move from quarterly releases to daily deployments while maintaining full regulatory compliance.

Need help with SOC2 or PCI-DSS?

We build compliant infrastructure. Let's talk.

Contact Solutions Architect