Grant Privileged Actions at Runtime
You can use the PrivilegedAction Type to grant an @action(authz='always') action permission to invoke other actions that its caller would not otherwise be authorized to invoke, without rebuilding the platform.
See Define Permissions to learn more about access controls in the C3 Agentic AI Platform.
Baseline grants compared to runtime grants
The platform ships an immutable, code-reviewed baseline of privileged-action grants that is compiled into the platform and cannot be changed at runtime.
Use runtime grants to extend that baseline from a running cluster. Runtime grants are stored in the cluster-managed PrivilegedAction.Config and suit changes a cluster administrator needs to make without a platform rebuild. Runtime grants are subject to the exact same checks as the baseline: the granting action must be @action(authz='always'), and the recorded source-code fingerprint must match the action's implementation at authorization time.
This topic shows you how to use the PrivilegedAction Type to grant privileged actions at runtime.
Grant privileged actions using PrivilegedAction
The following functions allow you to grant and manage privileged actions at runtime:
- PrivilegedAction#fingerprint: Use to compute the source-code fingerprint of the action you are granting.
- PrivilegedAction#enableDynamicGrants: Use to enable runtime grants so they take effect at authorization time.
- PrivilegedAction#add: Use to grant a privileged action permission to invoke one or more child actions.
- PrivilegedAction#remove: Use to revoke a runtime grant.
- PrivilegedAction#disableDynamicGrants: Use to turn off all runtime grants at once without removing them.
To grant a privileged action at runtime, complete the following steps:
- Compute the source-code fingerprint of the granting action.
- Enable runtime grants.
- Add the grant.
All of the mutating functions are protected by the cluster-admin action group, so only a cluster administrator (or root) can call them. This ensures an application cannot use them to escalate its own privileges.
Compute the source-code fingerprint
Runtime grants are keyed by a source-code fingerprint that pins the grant to a specific version of the granting action's source. The fingerprint is required and is verified at authorization time to detect tampering.
Run the following code in C3 AI Console to compute the fingerprint of the granting action:
PrivilegedAction.fingerprint("MyApp.PrivilegedAction", "doThing")This returns the fingerprint string you pass to PrivilegedAction#add and PrivilegedAction#remove.
Enable and add a runtime grant
Run the following code in C3 AI Console as a cluster administrator to enable runtime grants and add a grant at the desired configuration override:
var fingerprint = PrivilegedAction.fingerprint("MyApp.PrivilegedAction", "doThing");
PrivilegedAction.enableDynamicGrants("CLUSTER");
PrivilegedAction.add(
PrivilegedAction.Grant.make({
privilegedAction: "MyApp.PrivilegedAction#doThing",
actionFingerprint: fingerprint,
grantedChildren: ["MyApp.Config#getSecret"]
}),
"CLUSTER"
)The PrivilegedAction#add function takes a PrivilegedAction.Grant and the configuration override:
grant.privilegedAction: The granting action, written as"<Type>#<action>".grant.actionFingerprint: The source-code fingerprint of the granting action, computed with PrivilegedAction#fingerprint. This is required.grant.grantedChildren: The child actions to grant, each written as"<Type>#<childAction>"or a bare"<Type>"to allow any action on that Type.override: The configuration override level to persist the grant at, such asCLUSTER.
You can grant multiple child actions in a single call:
PrivilegedAction.add(
PrivilegedAction.Grant.make({
privilegedAction: "MyApp.PrivilegedAction#doThing",
actionFingerprint: fingerprint,
grantedChildren: ["MyApp.Config#getSecret", "MyApp.Config#setConfigValue"]
}),
"CLUSTER"
)Demonstrate a runtime grant
The following example demonstrates granting MyApp.PrivilegedAction#doThing permission to invoke MyApp.Config#getSecret.
- Run the following code in C3 AI Console as a cluster administrator to enable runtime grants and add the grant:
var fingerprint = PrivilegedAction.fingerprint("MyApp.PrivilegedAction", "doThing");
PrivilegedAction.enableDynamicGrants("CLUSTER");
PrivilegedAction.add(
PrivilegedAction.Grant.make({
privilegedAction: "MyApp.PrivilegedAction#doThing",
actionFingerprint: fingerprint,
grantedChildren: ["MyApp.Config#getSecret"]
}),
"CLUSTER"
)After you add the grant, MyApp.PrivilegedAction#doThing can invoke MyApp.Config#getSecret, even for callers who are not otherwise authorized to call MyApp.Config#getSecret directly.
- Run the following code in C3 AI Console as a cluster administrator to revoke the grant:
PrivilegedAction.remove(
PrivilegedAction.Grant.make({
privilegedAction: "MyApp.PrivilegedAction#doThing",
actionFingerprint: PrivilegedAction.fingerprint("MyApp.PrivilegedAction", "doThing")
}),
"CLUSTER"
)After you remove the grant, MyApp.PrivilegedAction#doThing can no longer invoke MyApp.Config#getSecret. Only grants added with PrivilegedAction#add can be removed; the seeded baseline is immutable. When removing a grant you only need to identify it by privilegedAction and actionFingerprint; grantedChildren is ignored.
Disable runtime grants
After you add runtime grants, you can turn them all off at once (for example, during an incident) without removing them.
Run the following code in C3 AI Console as a cluster administrator to disable runtime grants:
PrivilegedAction.disableDynamicGrants("CLUSTER")While disabled, the system ignores all runtime grants and only the immutable baseline applies. Because the grants are preserved, re-enabling restores the previously added grants:
PrivilegedAction.enableDynamicGrants("CLUSTER")Configuration overrides
Runtime grants are stored in PrivilegedAction.Config, so they follow the standard Config framework override precedence: a value set at a more-specific override, such as ENV, wins over one set at a less-specific override, such as CLUSTER or ROOT. This applies to both the grants and the enable switch. For example, setting the enable switch to disabled at ENV masks an enabled state set at CLUSTER or ROOT, turning off runtime grants for that environment until you clear the more-specific override.
Alternative to using PrivilegedAction
Privileged actions apply only to @action(authz='always') actions that must invoke actions on their caller's behalf. To control which users can access a Type's actions or objects instead, see Add Access Controls to a Role using Data Permissions and Add Access Controls to a Type Using AclEnabled.