Automation Policies - Kion Policy Engine Guide

Last updated: September 9, 2026

Kion Policy Engine (KPE) lets you define YAML-based rules that discover cloud resources, evaluate them against conditions, and apply actions — all in a single declarative file. KPE is the engine that powers Automation Policies within Kion. This guide provides you with information on how to construct (or modify) policies for KPE so that you can take maximum advantage of the power available in Kion.

What is a Policy?

A policy is a YAML file with the following keys:

name: "My Policy"          # Human-readable label
filters:                    # List of conditions to match resources
  - field: State.Name
    op: eq
    value: running
actions:                    # What to do with matched resources
  - type: tag
    params:
      key: Environment
      value: production
variables:                  # Optional — define inputs referenced in filters/actions
  environment:
    type: string
    required: true
options:                    # Optional — execution behavior
  dry_run: false

variables , filters, and options are optional. All other keys are required.

Resource Types

Resources follow the format <provider>.<resource_type>. Resources are selected in the UI when making a policy definition.

Provider

Example Resource Types

aws

aws.ec2, aws.s3, aws.iam_role, aws.rdsinstance, aws.kms_key, aws.lambda, aws.eks_node_group

azure

azure.storage_account, azure.virtual_machine

gcp

gcp.storage, gcp.gke_node_pool, gcp.vertex_custom_job

Syntax Basics

Filters

Filters are the conditions used to select resources. Each filter is an object with a field, an op (operator), and usually a value.

filters:
  - field: State.Name
    op: eq
    value: running

Multiple filters at the same level are implicitly AND-ed — all conditions must be true for a resource to match.

filters:
  - field: State.Name
    op: eq
    value: running
  - field: Tags.Owner      # AND this must also be true
    op: not_exists

Operators

Operator

Description

Accepts Value?

Valid Types

eq

Equal to

Yes

string, int, float, bool, time

ne

Not equal to

Yes

string, int, float, bool, time

gt

Greater than

Yes

int, float, time

gte

Greater than or equal

Yes

int, float, time

lt

Less than

Yes

int, float, time

lte

Less than or equal

Yes

int, float, time

in

Value is in list

Yes (array)

string, int, float, bool

not_in

Value is not in list

Yes (array)

string, int, float, bool

contains

String or array contains value

Yes

string, array

regex

Matches a regular expression

Yes (string)

string

exists

Field is present

No

any

not_exists

Field is absent

No

any

Time values must be full ISO 8601 / RFC 3339 strings, e.g. "2025-01-01T00:00:00Z".

Field Access

Use dot notation to reach nested fields:

- field: State.Name                          # nested object field
- field: ScalingConfig.DesiredSize           # deeper nesting
- field: PublicAccessBlockConfiguration.BlockPublicAcls

Tags are accessed with the Tags. prefix:

- field: Tags.Environment      # matches tag key "Environment"
- field: Tags.Owner            # use exists / not_exists to check presence

Logical Operators

Use and:, or:, and not: blocks to compose complex conditions.

OR — at least one sub-condition must match:

filters:
  - or:
    - field: Tags.Owner
      op: not_exists
    - field: Tags.Owner
      op: eq
      value: ""

NOT — the sub-condition must not match:

filters:
  - not:
      field: Tags.Managed
      op: eq
      value: "true"

AND — all sub-conditions must match (explicit form):

filters:
  - and:
    - field: VpcId
      op: exists
    - field: Tags.Owner
      op: not_exists

and:, or:, and not: blocks can be nested inside each other.

Function Filters

Filters can call named functions instead of using field/op/value. Use the function key, with an optional args key for functions that accept parameters.

filters:
  - function: hasActiveInstances        # matches resources where the function returns true
  - not:
      function: hasActiveInstances      # matches resources where it returns false

Some functions accept arguments:

filters:
  - function: hasTag
    args:
      key: "Environment"
      value: "production"

Generic functions

These are available on every resource type:

Function

Description

hasTag

Checks whether a resource has a specific tag key, optionally matching a value

hasTags

Checks whether a resource has all of a given set of tag key-value pairs

has

Checks whether a field path exists on the resource

get

Retrieves a value at a dot-separated field path

contains

Checks whether a string contains a substring

matches

Checks whether a string matches a regex pattern

startsWith / endsWith

Prefix and suffix checks

isEmpty

Checks whether a value is empty

length

Returns the length of a string, array, or map

Resource-specific functions

Each resource type may expose additional functions. These are only valid for the resource type they belong to. Resource-specific functions are defined for each resource on the Technical Overview page under the Supported Resources section.

Actions

Actions run against every resource that passes the filters.

Action

Description

tag

Add or update a single tag

bulk_tag

Add or update multiple tags at once

delete

Delete the resource

stop

Stop a running resource (compute/cluster)

start

Start a stopped resource

Single tag

actions:
  - type: tag
    params:
      key: ComplianceStatus
      value: "review-required"
      overwrite: false        # skip if tag already exists

Multiple tags

actions:
  - type: bulk_tag
    params:
      tags:
        ManagedBy: "kion-policy-engine"
        LastTagged: "{{.Timestamp}}"   # template variable
      overwrite: true

Custom Variables

Custom variables must be declared in the policy body (for now). We will explore removing this requirement in the future. Define reusable inputs in a variables block and reference them anywhere in filters or actions using ${var.name}.

variables:
  environment:
    type: string
    description: "Target environment"
    required: true        # must be supplied at execution time
  region:
    type: string
    default: "us-east-1"  # used if not supplied

filters:
  - field: Tags.Environment
    op: eq
    value: "${var.environment}"

actions:
  - type: bulk_tag
    params:
      tags:
        Region: "${var.region}"

Each variable must declare a type and either required: true or a default value — not both.

Type

Accepted values

string

Text

int

Whole number

float

Decimal number

bool

true / false

list

Array of values

map

Key-value object

Policy Examples

Example 1: Multi-Condition Filter with Tagging

This policy finds S3 buckets where versioning is not enabled and tags them for a compliance review.

name: "Flag Unversioned S3 Buckets
filters:
  - field: Versioning.Status
    op: ne
    value: Enabled
  - field: Tags.ComplianceReview
    op: not_exists
actions:
  - type: bulk_tag
    params:
      tags:
        ComplianceReview: "versioning-disabled"
        LastChecked: "{{.Timestamp}}"
      overwrite: false

What this shows:

  • Multiple top-level filters are implicitly AND-ed — both conditions must be true

  • Dot notation reaches nested fields (Versioning.Status)

  • not_exists checks for a missing tag key

  • {{.Timestamp}} is a template variable resolved at execution time

Example 2: Function Filters

This policy deletes Classic ELBs that have no registered instances — using a resource-specific function rather than a field comparison.

name: "Delete Unused Classic ELBs"
filters:
  - not:
      function: hasActiveInstances
actions:
  - type: delete

The same pattern works for functions that accept arguments. This policy uses the generic hasTag function to find EC2 instances missing a required tag:

name: "Flag EC2 Instances Missing Owner Tag"
filters:
  - not:
      function: hasTag
      args:
        key: "Owner"
actions:
  - type: tag
    params:
      key: ReviewStatus
      value: "missing-owner"
      overwrite: false

What this shows:

  • function: replaces field/op/value entirely — the two forms cannot be mixed in a single filter entry

  • not: wraps a function filter the same way it wraps a field filter

  • Generic functions like hasTag work on any resource; resource-specific functions like hasActiveInstances are only valid on the resource type they belong to (aws.elb in this case)

Example 3: Parameterized Policy with Variables

This policy uses variables so the same policy file can be applied to different environments without editing the YAML.

name: "Tag Resources by Environment"
variables:
  environment:
    type: string
    description: "The target environment (e.g. production, staging)"
    required: true
  cost_center:
    type: string
    default: "unassigned"
filters:
  - field: Tags.Environment
    op: eq
    value: "${var.environment}"
  - field: Tags.CostCenter
    op: not_exists
actions:
  - type: bulk_tag
    params:
      tags:
        CostCenter: "${var.cost_center}"
        ManagedBy: "kion-policy-engine"
      overwrite: fal

What this shows:

  • Variables are declared under variables: with a type and either required: true or a default

  • They are referenced in filters and action params using ${var.name}

  • required: true means the value must be supplied at execution time; default is used when it is not

  • The same policy file can run against production, staging, or any other environment by passing a different environment value