Permission Tokens
The ArangoPermissionToken custom resource creates JWT tokens for accessing ArangoDB deployments with specific roles and policies.
Creating a Token
apiVersion: permission.arangodb.com/v1alpha1
kind: ArangoPermissionToken
metadata:
name: my-service-token
spec:
deployment:
name: my-deployment
ttl: 2h
roles:
- viewer
- editor
policyName: my-policy
scope:
statements:
- effect: Allow
actions:
- "collection:read"
- "collection:write"
resources:
- "my-collection"
Spec Fields
| Field | Required | Default | Description |
|---|---|---|---|
deployment.name | Yes | - | Name of the ArangoDeployment |
ttl | No | 1h | Token lifetime (minimum 15m) |
roles | No | [] | List of role names to include in the JWT |
policyName | No | - | Name of the ArangoPermissionPolicy CRD to reference |
scope | No | - | Boundary policy that constrains what the referenced policy can grant on this token’s managed role |
Scope
The scope field defines the permission boundary for the token’s managed role. Even if the referenced policy grants broad access, the scope restricts what the managed role can actually provide.
For example, if policyName references a policy that allows *:* on *, but the scope only allows collection:read on my-collection, then the token’s managed role will only grant read access to my-collection.
When scope is omitted, the managed role has no additional constraints beyond the referenced policy.
What the Operator Creates
When spec.policyName is set, the operator automatically:
- Creates an ArangoDB user with a random password
- Resolves the ArangoPermissionPolicy CRD referenced by
spec.policyName - Creates a role in the sidecar (
managed:operator:<uid>) that references the external policy and usesspec.scopeas its boundary - Generates a JWT signed with the deployment’s JWT secret, containing:
- The created username
- Roles from
spec.rolesplus the managed role name - Expiration based on
spec.ttl
- Stores the JWT in a Kubernetes Secret (owned by the token resource)
Retrieving the Token
The JWT is stored in a Secret created by the operator:
kubectl get secret -l "app.kubernetes.io/managed-by=arangodb-operator" \
-o jsonpath='{.items[0].data.token}' | base64 -d
Or check the token status for the secret name:
kubectl get arangopermissiontoken my-service-token -o jsonpath='{.status.secret.name}'
Then:
kubectl get secret <secret-name> -o jsonpath='{.data.token}' | base64 -d
Token Lifecycle
- Tokens are automatically refreshed at half their TTL
- The JWT is regenerated when:
- The signing secret changes
- The roles list changes (e.g., managed role is created)
- The TTL changes
- On deletion, the operator cleans up:
- The ArangoDB user
- The sidecar role
The referenced ArangoPermissionPolicy is not deleted when the token is removed — it is managed independently.
Example: Read-Only Service Token
First create a policy:
apiVersion: permission.arangodb.com/v1alpha1
kind: ArangoPermissionPolicy
metadata:
name: monitoring-policy
spec:
deployment:
name: production
policy:
statements:
- effect: Allow
actions:
- "database:read"
- "collection:read"
resources:
- "*"
- effect: Deny
actions:
- "database:write"
- "collection:write"
resources:
- "*"
Then create a token referencing it:
apiVersion: permission.arangodb.com/v1alpha1
kind: ArangoPermissionToken
metadata:
name: monitoring-token
spec:
deployment:
name: production
ttl: 4h
policyName: monitoring-policy
scope:
statements:
- effect: Allow
actions:
- "database:read"
- "collection:read"
resources:
- "*"
This creates a token scoped to read-only access. The scope acts as a boundary — even if the referenced policy were to be updated with broader permissions, this token’s role would remain limited to read operations.