pub fn create_cap_grant(
cap_grant_entry: CapGrantEntry,
) -> ExternResult<ActionHash>
Expand description
Create a capability grant.
Wraps the create
HDK function with system type parameters set.
This guards against sending application entry data or setting the wrong entry type.
Capability grants are explicit entries in the local source chain that grant access to functions running in the current conductor.
The grant must be sent (e.g. with a crate::p2p::call_remote
) to the grantees so they can commit a claim and then call back with it in the future.
When an agent wants to expose zome functions to be called remotely by other agents they need to select a security model and probably generate a secret.
The input needs to evalute to a ZomeCallCapGrant
struct which defines the tag, access and
granted zome/function pairs. The access is a CapAccess
enum with variants CapAccess::Unrestricted
,
CapAccess::Transferable
, and CapAccess::Assigned
.
The tag is an arbitrary String
that developers or users can use to categorise and administer
grants committed to the chain. The tag should also match the CapClaim
tags committed on the
recipient chain when a CapGrant
is committed and shared. The tags are not checked or compared
in any security sensitive contexts.
Provided the grant author agent is reachable on the network:
CapAccess::Unrestricted
access means any external agent can call the externCapAccess::Transferable
access means any external agent with a valid secret can call the externCapAccess::Assigned
access means only explicitly approved agents with a valid secret can call the extern
The authoring agent itself always has an implicit capability which grants access to its own externs, and needs no special capability grant.
All logic runs on the author agent’s machine against their own source chain:
- New entries are committed to the author’s chain with the author’s signature
- Signals are emmitted to the author’s system and GUI
- The author must be online from the perspective of the caller
- The author can chain
call_remote
back to the caller or any other agent
The happ developer needs to plan carefully to ensure auditability and accountability is maintained for all writes and network calls if this is important to the integrity of the happ.
Multiple CapGrant
entries can be relevant to a single attempted zome call invocation.
The most specific and strict CapGrant
that validates will be used. For example, if a user
provided a valid transferable secret to a function that is currently unrestricted, the zome
call will be executed with the stricter transferable access.
(also potentially not needed when we enforce uniqueness - see below)
CapGrant
entries can be updated and deleted in the same way as standard app entries.
The CRUD model for CapGrant
is much simpler than app entries:
- versions are always local to a single source chain so partitions can never happen
- updates function like delete+create so that old grants are immediately revoked by a new grant
- deletes immediately revoke the referenced grant
- version histories are linear so there can never be a branching history of updates and deletes
Secrets must be unique across all grants and claims in a source chain and should be generated
using the generate_cap_secret
function that sources the correct number of cryptographically
strong random bytes from the host.
If any CapGrant
is valid for a zome call invocation it will execute. Given that secrets must
be unique across all grants and claims this is easy to ensure for assigned and transferable
access. Special care is required for Unrestricted grants as several may apply to a single
extern at one time, or may apply in addition to a stricter grant. In this case, revoking a
stricter grant, or failing to revoke all Unrestricted grants will leave the function open.
There is an apparent “chicken or the egg” situation where CapGrant
are required for remote
agents to call externs, so how does an agent request a grant in the first place?
The simplest pattern is for agents to create an extern dedicated to assess incoming grant
requests and to apply CapAccess::Unrestricted
access to it during the zome’s init
callback.
If Alice wants access to Bob’s foo
function she first grants Bob Assigned
access to her own
accept_foo_grant
extern and sends her grant’s secret to Bob’s issue_foo_grant
function. Bob
receives Alice’s request and, if he is willing to grant Alice access, he commits Alice’s secret
as a CapClaim
to his chain. Bob then generates a new secret and commits it in a CapGrant
for foo
, most likely explicitly Assigned
to Alice, and sends his secret and Alice’s secret
to Alice’s accept_foo_grant
extern. Alice checks her grant, which matches Bob’s public key
and the secret Bob received from her, then she commits a new CapClaim including the secret that
Bob generated. Now Alice can call foo
on Bob’s machine any time he is online, and because all
the secrets are CapAccess::Assigned
Bob can track and update exactly who has access to his externs.