Manual compliance checking does not scale in cloud environments where thousands of resources are created and modified daily. Policy-as-Code replaces manual review with automated enforcement using AWS Config, HashiCorp Sentinel, OPA, and Terraform guardrails.
Sign in to mark this article as read and track your progress.
A mid-sized company running 500 EC2 instances across 10 AWS accounts, with 50 developers deploying infrastructure daily, creates hundreds of new resources per week. Manual security review of each resource before deployment is not feasible. Two things must be true for cloud compliance to scale:
Policy-as-Code addresses both requirements by expressing security policies as machine-readable, version-controlled rules that run automatically in CI/CD pipelines and in the cloud environment.
Policy-as-Code (PaC) is the practice of defining and enforcing compliance policies using code — typically declarative rule languages — rather than documentation, manual checklists, or human review. PaC has three properties that manual compliance lacks:
| Property | Manual Compliance | Policy-as-Code |
|---|---|---|
| Consistency | Varies by reviewer | Identical rule execution every time |
| Scale | O(n) human effort | O(1) — rules run in parallel on all resources |
| Auditability | Review meeting notes | Git commit history; policy change reviewed like code |
| Speed | Days to weeks | Seconds (CI pipeline) or minutes (cloud detection) |
AWS Config provides two types of rules:
Managed Rules — Pre-built rules maintained by AWS for common compliance checks:
# Example: Enforce encryption on all new EBS volumes
RuleName: encrypted-volumes
Trigger: Configuration change on AWS::EC2::Volume
Remediation: SSM Automation: AWSSupport-EnableVolumeEncryption
Custom Rules — Lambda-based rules for organisation-specific policies:
# Lambda function: check that all EC2 instances have the 'Owner' tag
def lambda_handler(event, context):
invoking_event = json.loads(event['invokingEvent'])
configuration_item = invoking_event['configurationItem']
tags = configuration_item.get('tags', {})
if 'Owner' not in tags:
return {
'complianceType': 'NON_COMPLIANT',
'annotation': 'EC2 instance missing required Owner tag'
}
return {'complianceType': 'COMPLIANT'}
Auto-remediation: Config can trigger SSM Automation documents to fix non-compliant resources automatically. For example, when s3-bucket-server-side-encryption-enabled fails, an SSM runbook enables default encryption on the bucket.
SCPs, discussed in the governance topic, are also a form of Policy-as-Code. They are JSON documents stored in AWS Organizations and enforced by the IAM service before any IAM evaluation. Key examples:
// Deny creation of IAM users (force all access through SSO)
{
"Effect": "Deny",
"Action": ["iam:CreateUser", "iam:CreateLoginProfile"],
"Resource": "*"
}
// Deny disabling of CloudTrail
{
"Effect": "Deny",
"Action": ["cloudtrail:StopLogging", "cloudtrail:DeleteTrail"],
"Resource": "*"
}
// Deny unencrypted EBS volume creation
{
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:volume/*",
"Condition": {
"Bool": {"ec2:Encrypted": "false"}
}
}
These SCPs are written, reviewed via pull request, and applied to OUs — they apply to all accounts in the OU without any per-account configuration.
Sentinel is HashiCorp's Policy-as-Code framework, integrated with Terraform Cloud and Terraform Enterprise. Sentinel policies run between the terraform plan and terraform apply stages — meaning non-compliant infrastructure is blocked before it is created:
# sentinel.hcl policy: no public S3 buckets
import "tfplan/v2" as tfplan
s3_buckets = filter tfplan.resource_changes as _, rc {
rc.type is "aws_s3_bucket" and
rc.change.actions contains "create"
}
violating_buckets = filter s3_buckets as _, bucket {
bucket.change.after.bucket_policy == null or
"s3:GetObject" in bucket.change.after.bucket_policy
}
main = rule {
length(violating_buckets) is 0
}
Policy enforcement levels in Sentinel:
AWS Security Hub provides pre-packaged compliance standards:
Each standard runs as a collection of Security Hub controls, each backed by Config rules or GuardDuty findings. The Security Hub dashboard shows:
This transforms compliance from an annual audit event into a continuously measured, board-reportable metric.
For organisations subject to DPDP Act 2023, CERT-In 2022, and RBI IT Framework, Policy-as-Code is not just a best practice — it is the only realistic way to demonstrate continuous compliance. Key controls to automate:
| Regulation | Required Control | Policy-as-Code Implementation |
|---|---|---|
| CERT-In 2022 | 180-day log retention | Config rule: cloudtrail-s3-dataevents-enabled + lifecycle policy check |
| CERT-In 2022 | Synchronise time to NTP/NIC STQC servers | Config custom rule: check CloudWatch Agent NTP config |
| DPDP Act 2023 | Data localisation | SCP: Deny requests to non-Indian regions |
| RBI IT 2021 | Access control review every 6 months | Config rule triggering IAM Access Analyzer report |