Skip to content

Testing

Evaluate a Policy against real Users, Applications, and Resources before it goes live, and read the denial when a live request fails

The Run test panel evaluates one request against the Policies you are editing, using the real Users, Applications, and Resources in the Zone. Nothing is deployed, no token is issued, and no Activity event is recorded. Keycard evaluates a delegated request as two checks, the User’s own access and the Application’s right to act for them, so a Policy that covers a delegated flow has to pass both.

This page tests the allow-cli-access Policy from Configuration: the User half, the Application half, and the denial you expect. It then covers the request context fields. For reading the denial a live request produces, see Troubleshooting.

  • The Admin organization Role, or the Manager Role on the Zone (see Roles & Permissions)
  • A Policy Set with at least one Policy. The steps use the set built in Configuration, where allow-cli-access permits any User on OpenID Connect UserInfo and permits Keycard CLI on the same Resource when acting for a User. Substitute your own Application and Resource if you built something else.

The panel evaluates whatever you have open. The caption above the fields tells you which.

Where you open itWhat is evaluated
A Policy Set, viewing a published versionEvery Policy in that version. Pick a different version in History to test it instead.
A Policy Set with unsaved changesThe unsaved draft, marked Draft
A new Policy SetThe Policies added so far, before the set is saved
A Policy, viewing a published versionThat Policy alone
A Policy with unsaved rulesThe rules as currently written, marked Draft

A Policy tested on its own can return Allow while the set returns Deny: a forbid in another Policy wins over a permit in this one. Test the set before you activate it.

  1. Open the set and the Run test tab

    In Keycard Console, open Policies, select the Policy Sets tab, and click your set. The right-hand panel opens on Run test with the caption Against every policy in this set.

  2. Test the User

    FieldValue
    ActorYour own account, from the Users section of the picker
    Actionany
    ResourceOpenID Connect UserInfo
    User contextOff

    Click Run.

    The Run test panel with a User as the actor and the UserInfo Resource selected, returning Allow

    The result is Allow with one entry under Determining policies. With User context off this is a single check: context.on_behalf and context.impersonate are both false and there is no context.subject. It mirrors the Subject check in a delegated request, so if it fails here, no Application will get access for that User either.

  3. Test the Application

    FieldValue
    ActorKeycard CLI, from the Applications section of the picker
    Actionany
    ResourceOpenID Connect UserInfo
    User contextOn
    SubjectYour own account

    Click Run.

    The Run test panel with Keycard CLI as the actor, User context enabled with a subject set, returning Allow with two determining policies

    The result is Allow with two determining policies. Setting a Subject turns the run into a delegated request, which Keycard evaluates as two checks: the Subject’s own access (on_behalf == false) and the Actor’s right to act for them (on_behalf == true). Both have to permit, and Determining policies lists the rule that satisfied each.

  4. Test what should be denied

    Change Resource to Events API and click Run.

    The Run test panel with Keycard CLI as the actor and Events API as the Resource, returning Deny with no determining policies

    The result is Deny with nothing under Determining policies: no rule in the set mentions this Resource, so the request falls through to the default deny. This is the denial the CLI hits at sign-in in Verify with the CLI.

    Switch Resource back to OpenID Connect UserInfo, keep Keycard CLI as the Actor, and turn User context off. The result is Deny again. Without a Subject the CLI is evaluated as acting on its own, so a rule that requires context.on_behalf == true does not match.

    When a forbid rule causes a denial, it appears under Determining policies. An empty list on Deny always means no permit matched.

  5. Read the determining policies

    Each entry has the form <policy-version-id>::<rule-id>. Rules built in Visual mode are numbered policy0, policy1, and so on in the order they appear. A rule written in the Cedar tab with an @id("...") annotation shows that name instead, which makes the list easier to read once a set has more than a handful of rules.

  6. Test an earlier version

    Open the History tab and click a version. The editor switches to read-only and the Run test tab now evaluates that version; the badge beside the set name shows which. Run the same requests to see how the decision differed. Testing a version does not activate it; see Versions and Rollback for that.

Turning User context on reveals the request context, which lets you test richer authorization checks than actor, action, and Resource alone. Each field maps to one attribute in the Cedar context record described in the Policy Schema.

FieldCedar attributeWhat it stands in for
Subjectcontext.subject; sets context.on_behalf to true on the Actor’s checkThe User the Application acts for. The Subject’s Role and Group membership is read from the Zone.
Scopescontext.scopesThe OAuth scopes in the request
Session IDNoneRecorded with the request for correlation. No schema version exposes it to rules, so it does not change the decision.
Actor emailcontext.actor_claims.emailThe email claim on the Actor’s token
Actor groupscontext.actor_claims.groupsThe groups claim on the Actor’s token
Subject emailcontext.subject_claims.emailThe email claim on the Subject’s token
Subject groupscontext.subject_claims.groupsThe groups claim the identity provider put on the Subject’s token at sign-in

An empty field leaves its attribute out of the context entirely, which is why rules guard with context has scopes && before reading it. The fields are available without a Subject, so you can test a User actor with scopes by turning User context on and leaving Subject empty.

The rule below, from Restrict a Resource to a Group, only permits a read-write session role:

@id("permit-data-analysts-snowflake")
permit (
principal in Keycard::Group::"data-analysts",
action,
resource
)
when
{
resource.identifier == "<resource-identifier>" &&
context has scopes &&
context.scopes.containsAny(["session:role:READWRITE_ROLE"])
};

Set Actor to the Application, Resource to the Snowflake Resource, turn User context on, set Subject to a member of data-analysts, and add session:role:READWRITE_ROLE under Scopes. Run once for Allow, remove the scope, and run again for Deny.

Membership is read from Zone data when the request is evaluated, so there is nothing to type. Pick a Subject who belongs to the Group for Allow, then a User who does not for Deny. For a rule written as context.subject in Keycard::Group::"on-call", the membership that matters is the Subject’s, not the Actor’s. Adding or removing a member changes the result on the next run without editing the Policy.

Rules that read context.subject_claims.groups match the groups claim from the identity provider, not Keycard Group membership. To test permit-idp-engineering-group, add Engineering under Subject groups. Actor groups does the same for the Actor’s own token.