Pulumi Policy as Code (CrossGuard)

Hard 28 min read

What is CrossGuard?

Why Policy as Code?

The Problem: Security and compliance reviews are manual, slow, and inconsistent. Teams discover policy violations after deployment when the damage is already done.

The Solution: Pulumi CrossGuard lets you define policies in code that automatically validate every resource before it is created, updated, or deleted.

Real Impact: Organizations using CrossGuard catch 99% of policy violations before deployment, reducing security incidents by 85%.

Real-World Analogy

Think of CrossGuard as a building code inspector:

  • Policy Packs = The building code book with all regulations
  • Resource Validation = Inspecting each room individually
  • Stack Validation = Inspecting the entire building as a whole
  • Advisory = A warning note that does not block construction
  • Mandatory = A stop-work order that blocks construction until fixed

CrossGuard Key Features

Resource Policies

Validate individual resources against rules. Check tags, encryption, network exposure, and instance sizes.

Stack Policies

Validate the entire stack holistically. Ensure cost budgets, resource counts, and cross-resource relationships.

Configurable Rules

Make policies configurable so different teams can adjust thresholds while maintaining the same base rules.

Publish & Share

Publish policy packs to the Pulumi Cloud and enforce them across all stacks in your organization.

Policy Enforcement Flow
Code pulumi up Policy Check CrossGuard validates each resource & the full stack PASS Deploy FAIL Reject Advisory: warn only Mandatory: block deploy

Writing Policy Packs

policy-pack/index.ts
import * as policy from "@pulumi/policy";

new policy.PolicyPack("aws-security", {
    policies: [
        {
            name: "s3-no-public-access",
            description: "S3 buckets must not be publicly accessible",
            enforcementLevel: "mandatory",
            validateResource: policy.validateResourceOfType(
                "aws:s3/bucketV2:BucketV2",
                (bucket, args, reportViolation) => {
                    // Policy logic here
                }
            ),
        },
        {
            name: "require-encryption",
            description: "All storage resources must use encryption",
            enforcementLevel: "mandatory",
            validateResource: (args, reportViolation) => {
                if (args.type === "aws:ebs/volume:Volume") {
                    if (!args.props.encrypted) {
                        reportViolation("EBS volumes must be encrypted");
                    }
                }
            },
        },
        {
            name: "cost-control",
            description: "EC2 instances must use approved sizes",
            enforcementLevel: "advisory",
            validateResource: (args, reportViolation) => {
                const allowed = ["t3.micro", "t3.small", "t3.medium"];
                if (args.type === "aws:ec2/instance:Instance") {
                    if (!allowed.includes(args.props.instanceType)) {
                        reportViolation(
                            `Instance type ${args.props.instanceType} not in approved list`
                        );
                    }
                }
            },
        },
    ],
});

Resource Validation

resource-policies.ts
// Validate tags on all taggable resources
{
    name: "require-tags",
    description: "All resources must have required tags",
    enforcementLevel: "mandatory",
    validateResource: (args, reportViolation) => {
        const requiredTags = ["Environment", "Team", "CostCenter"];
        if (args.props.tags) {
            for (const tag of requiredTags) {
                if (!args.props.tags[tag]) {
                    reportViolation(`Missing required tag: ${tag}`);
                }
            }
        }
    },
},

// Prevent overly permissive security groups
{
    name: "no-open-ssh",
    description: "Security groups must not allow SSH from 0.0.0.0/0",
    enforcementLevel: "mandatory",
    validateResource: (args, reportViolation) => {
        if (args.type === "aws:ec2/securityGroup:SecurityGroup") {
            const ingress = args.props.ingress || [];
            for (const rule of ingress) {
                if (rule.fromPort <= 22 && rule.toPort >= 22) {
                    if ((rule.cidrBlocks || []).includes("0.0.0.0/0")) {
                        reportViolation("SSH must not be open to the world");
                    }
                }
            }
        }
    },
}

Stack Validation

stack-policies.ts
// Validate the entire stack
{
    name: "max-resource-count",
    description: "Stack must not exceed 100 resources",
    enforcementLevel: "advisory",
    validateStack: (args, reportViolation) => {
        if (args.resources.length > 100) {
            reportViolation(
                `Stack has ${args.resources.length} resources (max 100). Consider splitting.`
            );
        }
    },
},

// Ensure every public-facing resource has a WAF
{
    name: "require-waf-for-public",
    description: "Public ALBs must have WAF protection",
    enforcementLevel: "mandatory",
    validateStack: (args, reportViolation) => {
        const publicAlbs = args.resources.filter(
            r => r.type === "aws:lb/loadBalancer:LoadBalancer" && !r.props.internal
        );
        const wafAssociations = args.resources.filter(
            r => r.type === "aws:wafv2/webAclAssociation:WebAclAssociation"
        );
        if (publicAlbs.length > wafAssociations.length) {
            reportViolation("All public ALBs must have WAF associations");
        }
    },
}

Enforcement Levels

LevelBehaviorUse Case
advisoryWarns but allows deploymentNew policies, cost optimization hints
mandatoryBlocks deployment on violationSecurity, compliance, critical rules
disabledPolicy is skipped entirelyTemporarily disabling a policy

Running Policies

commands.sh
# Run preview with a local policy pack
pulumi preview --policy-pack ./policy-pack

# Deploy with policy enforcement
pulumi up --policy-pack ./policy-pack

# Publish a policy pack to Pulumi Cloud
cd policy-pack
pulumi policy publish my-org

# Enable a published policy on a stack
pulumi policy enable my-org/aws-security latest

Quick Reference

CrossGuard Best Practices

  • Start with advisory policies and promote to mandatory after validation
  • Use resource validation for individual compliance checks
  • Use stack validation for cross-resource relationship checks
  • Publish policy packs to enforce organization-wide standards
  • Version policy packs and test them against sample stacks before publishing
  • Make policies configurable to allow team-specific thresholds