> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ubiquex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Policy as Code

> Enforce security and compliance rules at validate time — before anything is provisioned.

Security and compliance rules are most valuable when they run before anything reaches the cloud. An S3 bucket with a public ACL discovered by a cloud security scanner is a bucket that was already misconfigured, already potentially exposed. A policy that catches that misconfiguration at `ubx validate` — before the bucket exists, before any credentials are needed, before CI even gets to the apply stage — is worth orders of magnitude more. The `policy` block brings compliance rules into your `.iac` source as first-class declarations: a condition over resource attributes, a severity, and an error message. `error` severity violations block `ubx validate` and `ubx apply`. `warn` severity violations are shown but don't block. Every resource of the matching type in every `.iac` file in your project is evaluated against every applicable policy automatically — no separate tool to run, no post-apply scanner to wait for.

## What you'll learn

* How `policy` blocks enforce rules at `ubx validate` time
* The difference between `severity = "error"` and `severity = "warn"`
* How to test a policy by writing a deliberately violating resource

***

## Why this matters

<Info>
  Policy violations with `severity = "error"` block both `ubx validate` and `ubx apply`. This means policy enforcement is part of the same pipeline as type-checking — a project with policy violations is a project that doesn't compile, by design.
</Info>

***

## The source code

<CodeGroup>
  ```hcl main.iac theme={"theme":"css-variables"}
  # This bucket passes the policy — acl = "private".
  unit "aws_s3_bucket_v2" "private_assets" {
    bucket = "myapp-private-assets"
    acl    = "private"
  }

  # Uncommenting this block would violate the policy and produce:
  #   ✗  Policy violation: "no_public_buckets"
  #   unit "aws_s3_bucket_v2" "public_files" violates:
  #   condition "acl != 'public-read' && acl != 'public-read-write'" evaluated to false
  #
  # unit "aws_s3_bucket_v2" "public_files" {
  #   bucket = "myapp-public-files"
  #   acl    = "public-read"    ← would violate the policy
  # }
  ```

  ```hcl policies.iac theme={"theme":"css-variables"}
  # policy blocks evaluate a condition over matching resource attributes.
  # severity = "error"  → blocks ubx validate and ubx apply
  # severity = "warn"   → shown in output but does not block
  policy "no_public_buckets" {
    description = "S3 buckets must not use a public ACL"
    severity    = "error"
    rule {
      resource  = "aws_s3_bucket_v2"
      condition = "acl != 'public-read' && acl != 'public-read-write'"
    }
  }
  ```

  ```hcl inputs.iac theme={"theme":"css-variables"}
  input "env" {
    type    = "string"
    default = "dev"
  }
  ```

  ```hcl ubx.iac theme={"theme":"css-variables"}
  ubx {
    name    = "policy-as-code"
    runtime = "typescript"
    stacks  = ["dev", "staging", "prod"]
  }

  backend "local" {
    path = ".ubx/state"
  }
  ```
</CodeGroup>

***

## How it works

<Steps>
  <Step title="Policies are evaluated during the type-check pass">
    After the schema type check, ubx evaluates every `policy` block against every `unit` block whose resource type matches the `rule.resource` field. This happens at `ubx validate` time — no cloud credentials, no network access required.
  </Step>

  <Step title="The condition is evaluated against resolved attribute values">
    The condition string `"acl != 'public-read' && acl != 'public-read-write'"` is evaluated as an expression against the unit block's attribute map. Attributes with literal values (like `acl = "private"`) are fully evaluated. Attributes with pending values are checked for the presence of a literal that could violate the condition.
  </Step>

  <Step title="Violations are reported with source location">
    A failing condition produces an error referencing the violating `unit` block by file, line, type, and label. The `description` and the condition that failed are both included in the error message, making the violation self-explanatory without needing to look up the policy.
  </Step>
</Steps>

***

## What ubx generates

<Note>
  `policy` blocks produce no generated code — they are compile-time validators only. The generated TypeScript/Python/Go contains only the `unit` resources. Policy enforcement happens in the ubx compiler, not in the Pulumi runtime.
</Note>

```typescript index.ts theme={"theme":"css-variables"}
// Generated by ubx — do not edit
// (policy blocks produce no generated code)
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const privateAssets = new aws.s3.BucketV2("private_assets", {
    bucket: "myapp-private-assets",
    acl: "private",
});
```

***

## Common mistakes

<Warning>
  Policy conditions are evaluated against the raw attribute map — not the generated Pulumi code. The condition `"acl != 'public-read'"` checks the `.iac` attribute `acl`, not the Pulumi SDK's `Acl` property. Use the `.iac` attribute names (snake\_case), not the SDK property names (camelCase).
</Warning>

<Tip>
  Put your policy blocks in a dedicated `policies.iac` file at the project root — or in a shared policies directory if multiple stacks share the same rules. Keeping policies separate from resources makes them easier to audit and update independently.
</Tip>

***

## Run it

```bash theme={"theme":"css-variables"}
ubx validate               # evaluates policies — no cloud credentials needed
ubx validate --strict      # same, but warn-severity violations also become errors
```

***

## What you learned

<Check>`policy` blocks enforce rules at `ubx validate` time — before any cloud credentials are needed</Check>
<Check>`severity = "error"` blocks validate and apply; `severity = "warn"` shows a warning but doesn't block</Check>
<Check>Policy blocks produce no generated code — enforcement is entirely in the ubx compiler</Check>

***

## Next steps

<CardGroup cols={2}>
  <Card title="import existing resource" href="/v1/tutorials/31-import-existing-resource">
    Bring existing cloud resources under ubx management
  </Card>

  <Card title="policy block reference" href="/v1/language/policy">
    Full policy block syntax and condition language
  </Card>
</CardGroup>

***

<Info>
  Full runnable example: [github.com/ubiquex/ubx-examples/30-policy-as-code](https://github.com/ubiquex/ubx-examples/tree/main/30-policy-as-code)
</Info>
