Automation Policies - Kion Policy Engine Guide

Follow

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