Skip to main content

Overview

A policy is a document that defines the for a group of workers. Given a worker’s properties and their , it describes what accounts and access they should have. Klef compares that to the current state of your systems and generates a of changes to make reality match the policy. A policy is written in Klef Policy Language (KPL).

Anatomy of a Policy

Policies describe who they apply to and how their target’s objects should look.

KPL Reference

applies

Either everyone or a . Segments are a group of workers with something in common. They can be re-used across policies.

stage

A block for one . A worker is in exactly one stage at a time, and the block for that stage decides what applies to them.
Klef determines the worker’s stage from its HRIS’ status and assignment dates. Their lifecycle is defined as:

Omitting a Stage

If a policy has no block for a stage, it says nothing about that stage, and the worker’s accounts keep whatever they already have.
As an example, say your policy has an active block and a terminated block - both modifying a Slack account:
  1. The worker goes on parental leave on May 1st, and moves to the leave stage.
  2. Since the policy has no leave block, Klef makes no changes and their Slack account stays active.
  3. The worker returns on August 1st, and moves back to the active stage. The active block applies again.
  4. If the worker is instead terminated, the terminated block applies and their Slack account is deactivated.

stage released

This block, unlike terminated, applies when the policy stops covering an account. This can occur if a worker leaves the segment, a target is removed from the policy, or the policy is deleted. It’s not a worker lifecycle. Without it, Klef will apply a reasonable default, such as deactivating the account.

target

A block naming one object in one , with the fields that object should have.
You do not have to indicate whether it’s a create or update. Klef compares the fields you wrote against the live object and does whichever one is needed. Each connector page lists the objects it accepts and the fields on each.

Mappings

A line inside a target that sets one field.
A value can also come from a script or a lookup table, which is what resources are for.

Field Types

Templates

Text in quotes is a Liquid template, so it can read worker fields with {{ }} and use Liquid’s filters and tags. Text that runs to several lines is written as a heredoc, opened with <<TAG and closed by a line holding only the tag.

each

A mapping value that writes one row for every record in a worker collection, such as worker.assignments. It fills an array field.
where is an optional filter. Join clauses with and to require all of them, or with or to require any of them.

unmanaged

A mapping value that tells Klef to leave a field untouched. This is particularly useful on a grant such as groups, licenses, or channels. It tells Klef to retain what it had given in an earlier lifecycle stage.

notify

A block that sends a message when its stage’s changes apply, by email, Slack, Teams, or an HTTP request. Its name, in quotes after the channel, is unique across your policies. Klef records what it has sent under that name, so renaming a notification makes it a new one.
Every channel takes these settings:

Email

An email can go to at most 50 addresses across to, cc, and bcc.
Each recipient is one of these:

Slack

Teams

HTTP

Passwords

If a target requires a password, Klef will set its first password. A notification can carry the link to that password as {{ <system>.sign_in_url }}. The password is only shown once and must be changed after first sign-in.

Resources

Scripts, lookup tables, and secrets are global and can be shared between policies.

An Example