# Policy Checking

Source: https://docs.ops0.com/docs/iac/deployments/policies

Enforce security, compliance, and cost policies before deployment to prevent policy violations.

## What is Policy Checking?

Policy checking evaluates planned infrastructure changes against organization policies:

**Policy Types:**
- **Security**: Encryption required, public access blocked, IAM best practices
- **Compliance**: SOC 2, HIPAA, PCI-DSS requirements
- **Cost**: Budget limits, expensive resource warnings
- **Tagging**: Required tags for cost allocation

**When Policies Run:**
- After `terraform plan` produces the change preview
- Before `terraform apply` can execute
- Blocks deployment if **blocking** policies fail

## Policy Results

### Deployment Planned
Terraform plan completes successfully.

### Policies Evaluated
ops0 runs all attached policies against planned changes.

### Results Displayed
Policy check results shown with severity levels.

### Apply Blocked (if needed)
Deployment cannot proceed if blocking policies fail.

---

## Policy Severity Levels

| Severity | Color | Effect | Description |
|----------|-------|--------|-------------|
| **Passing** | Green | None | Change complies with policy |
| **Advisory** | Blue | Warning only | Best practice recommendation, doesn't block |
| **Warning** | Yellow | Warning only | Should be addressed but doesn't block apply |
| **Blocking** | Red | Blocks apply | Must be fixed before deployment can proceed |

---

## Policy Check Example

**Planned Changes:**
```diff
+ aws_s3_bucket.data
    bucket: "my-app-data"
    acl: "public-read"
    encryption: null

+ aws_db_instance.main
    engine: "postgres"
    storage_encrypted: false
    publicly_accessible: true
```

**Policy Check Results:**
```
Policy Evaluation Results
─────────────────────────────────────

❌ BLOCKING: S3 Bucket Encryption Required
Resource: aws_s3_bucket.data
Issue: S3 bucket must have encryption enabled
Fix: Add server_side_encryption_configuration block

❌ BLOCKING: Database Public Access
Resource: aws_db_instance.main
Issue: RDS instances cannot be publicly accessible
Fix: Set publicly_accessible = false

⚠️ WARNING: Database Encryption Disabled
Resource: aws_db_instance.main
Issue: RDS instances should be encrypted at rest
Recommendation: Set storage_encrypted = true

ℹ️ ADVISORY: Missing Required Tags
Resources: aws_s3_bucket.data, aws_db_instance.main
Issue: Resources missing tags: Environment, Owner, CostCenter
Recommendation: Add tags for cost tracking and ownership

Summary:
- 2 blocking issues (deployment blocked)
- 1 warning
- 1 advisory

Fix blocking issues to proceed with deployment.
```

---

## Fixing Policy Violations

### Example 1: Fix S3 Encryption

**Before (Violates Policy):**
```hcl
resource "aws_s3_bucket" "data" {
  bucket = "my-app-data"
  acl    = "private"
}
```

**After (Policy Compliant):**
```hcl
resource "aws_s3_bucket" "data" {
  bucket = "my-app-data"
  acl    = "private"
}

resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
  bucket = aws_s3_bucket.data.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}
```

### Example 2: Fix Database Public Access

**Before (Violates Policy):**
```hcl
resource "aws_db_instance" "main" {
  identifier     = "production-db"
  engine         = "postgres"
  instance_class = "db.t3.medium"
  publicly_accessible = true  # Policy violation
}
```

**After (Policy Compliant):**
```hcl
resource "aws_db_instance" "main" {
  identifier          = "production-db"
  engine              = "postgres"
  instance_class      = "db.t3.medium"
  publicly_accessible = false
  storage_encrypted   = true  # Also fix warning

  tags = {  # Also add required tags
    Environment = "production"
    Owner       = "data-team"
    CostCenter  = "engineering"
  }
}
```

---

## Policy Override (Admin Only)

Users with `policy.override` permission can bypass blocking policies:

### Policy Check Fails
Deployment blocked by policy violation.

### Request Override
Click **Request Policy Override** button.

### Provide Justification
Enter reason for override (required, logged in audit trail).

### Approve
Admin reviews and approves override request.

### Deployment Proceeds
Deployment allowed despite policy failure.

**Override Justification Example:**
```
Override Request
─────────────────────────────────────
Policy: Database Public Access
Resource: aws_db_instance.legacy_app
Violation: publicly_accessible = true

Justification:
Legacy application requires direct database access
from on-premise systems. VPN connection not yet
established. Temporary override approved by CTO.
Will migrate to VPN access within 30 days.

Security mitigation:
- IP whitelist restricts access to office IPs only
- Strong password policy enforced
- Database audit logging enabled

Requested by: sarah@company.com
Approved by: cto@company.com
Expires: 2024-02-15
```

**Override Risks**

Policy overrides should be rare and temporary. Every override is logged in audit logs with full justification. Frequent overrides may indicate policies need adjustment.

---

## Re-Validating After Fixes

After fixing validation errors or policy violations:

### Save Changes
Update Terraform files with fixes.

### Run Validation
Click **Validate** to verify syntax errors fixed.

### Re-Run Policy Check
Start new deployment to trigger policy evaluation.

### Verify Results
Check that previous violations now pass.

---

## Next Steps

- [Creating Policies](https://docs.ops0.com/docs/policies/creating-policies): Learn how to create custom policies

- [Validation](https://docs.ops0.com/docs/iac/deployments/validation): Validate Terraform before policy checks

- [Deployments](https://docs.ops0.com/docs/iac/deployments): Deploy infrastructure after policy checks pass
