Skip to main content

CEL Expressions Reference

Angos uses CEL (Common Expression Language) for access control policies and retention policies. This reference documents all available variables and functions.


Access Control Variables

Identity (identity)

Information about the authenticated client.

VariableTypeDescription
identity.idstring?Identity ID from configuration
identity.usernamestring?Authenticated username
identity.client_ipstring?Client IP address

Certificate (identity.certificate)

Available when client presents an mTLS certificate.

VariableTypeDescription
identity.certificate.common_names[string]Certificate Common Names
identity.certificate.organizations[string]Certificate Organizations

OIDC (identity.oidc)

Available when client authenticates with OIDC token. Always check for null before accessing.

VariableTypeDescription
identity.oidcobject?OIDC context (null if not OIDC)
identity.oidc.provider_namestringConfigured provider name
identity.oidc.provider_typestringProvider type ("GitHub Actions" or "Generic OIDC")
identity.oidc.claimsmapJWT claims (access with bracket notation)

GitHub Actions Claims:

ClaimDescription
repositoryFull repository name (e.g., "myorg/myrepo")
refGit reference (e.g., "refs/heads/main")
shaCommit SHA
workflowWorkflow file name
workflow_refFull workflow reference path
actorUser who triggered the workflow
event_nameTrigger event (push, pull_request, etc.)
environmentDeployment environment
repository_ownerRepository owner
repository_visibilityRepository visibility (public/private)

Generic OIDC Claims:

ClaimDescription
subSubject identifier
issIssuer
audAudience
emailUser email
nameUser name
groupsUser groups (provider-specific)

Request (request)

Information about the current request. Fields are present based on the action type.

VariableTypeDescription
request.actionstringAction being requested (see Actions table)
request.namespacestring?Repository namespace
request.digeststring?Blob/manifest digest
request.referencestring?Tag or digest reference
request.uuidstring?Upload session UUID
request.nint?Pagination limit
request.laststring?Pagination marker
request.artifact_typestring?Referrer artifact type filter

Actions

ActionDescription
healthzHealth check endpoint
metricsPrometheus metrics endpoint
get-api-versionAPI version check
start-uploadStart blob upload
update-uploadContinue chunked upload
complete-uploadComplete upload
get-uploadGet upload status
cancel-uploadCancel upload
get-blobDownload blob
delete-blobDelete blob
put-manifestPush manifest
get-manifestPull manifest
delete-manifestDelete manifest
get-referrersGet referrers
list-catalogList repositories
list-tagsList tags
ui-assetUI static assets
ui-configUI configuration
list-repositoriesExtension: list repositories
list-namespacesExtension: list namespaces
list-revisionsExtension: list revisions
list-uploadsExtension: list uploads

Retention Policy Variables

Image (image)

Information about the manifest being evaluated.

VariableTypeDescription
image.tagstring/nullTag name, or null if untagged
image.pushed_atintPush time (seconds since epoch)
image.last_pulled_atintLast pull time (0 if never pulled)

Functions

Time Functions

FunctionDescription
now()Current time in seconds since epoch
days(n)Convert days to seconds
hours(n)Convert hours to seconds
minutes(n)Convert minutes to seconds

Retention Functions

FunctionDescription
top_pushed(k)True if among k most recently pushed tags
top_pulled(k)True if among k most recently pulled tags

String Functions (CEL built-in)

FunctionDescription
.matches(regex)Match against regex pattern
.startsWith(prefix)Check prefix
.endsWith(suffix)Check suffix
.contains(substring)Check substring
in [list]Check membership in list

Example Expressions

Access Control

// Require authentication
identity.username != null

// Allow specific user
identity.username == 'admin'

// Allow certificate with organization
identity.certificate.organizations.contains('DevOps')

// OIDC: GitHub Actions from specific org
identity.oidc != null && identity.oidc.claims['repository'].startsWith('myorg/')

// OIDC: Allow main branch pushes
identity.oidc != null &&
identity.oidc.claims['ref'] == 'refs/heads/main' &&
request.action.startsWith('put-')

// OIDC: Allow specific actors
identity.oidc != null &&
identity.oidc.claims['actor'] in ['alice', 'bob', 'dependabot[bot]']

// Allow read operations for everyone
request.action.startsWith('get-')

// Restrict delete to admins
identity.username == 'admin' && request.action == 'delete-manifest'

Retention

// Keep tagged images
image.tag != null

// Keep images pushed within 30 days
image.pushed_at > now() - days(30)

// Keep images pulled within 7 days
image.last_pulled_at > now() - days(7)

// Keep latest tag
image.tag == 'latest'

// Keep semantic version tags
image.tag != null && image.tag.matches('^v?[0-9]+\\.[0-9]+\\.[0-9]+$')

// Keep 10 most recently pushed
top_pushed(10)

// Keep 5 most recently pulled
top_pulled(5)

Common Patterns

Default-Deny with Exceptions

[global.access_policy]
default_allow = false
rules = [
"identity.username == 'admin'",
"identity.certificate.organizations.contains('Platform')",
"identity.oidc != null && identity.oidc.claims['repository'].startsWith('myorg/')"
]

Read-Only for Guests

[repository."public".access_policy]
default_allow = false
rules = [
"request.action.startsWith('get-') || request.action == 'list-tags'",
"identity.username == 'admin'"
]

Combined Retention Rules

[repository."production".retention_policy]
rules = [
"image.tag == 'latest'",
"image.pushed_at > now() - days(90)",
"top_pushed(20)"
]

Error Handling

  • Rules that fail to evaluate (e.g., null access) are skipped with a warning
  • For default-deny: at least one rule must return true to allow
  • For default-allow: at least one rule must return false to deny
  • Always check identity.oidc != null before accessing OIDC fields
  • Use bracket notation for claims: identity.oidc.claims['claim_name']