Private entries that manage authorization to execute zome calls by sources external to the cell
Two types of private entries:
Capability Grants
Stored by the grantor of the zome call request
Allow an external source to execute a zome call request
When they are deleted, that grant is not longer taken into account in the security checks
This means that the cell is always in control of the grants that it makes to external sources
Capability Claim
Stored by the grantee of the capability
These don’t provide access to external zome call requests
Mostly a convenience entry type just to store information about the Capability Grant
Both can be created as any other entry, at any point in time
Types of capability grant
Unrestricted: disable security checks
Any call to the function coming from any source will be executed
This can be a huge security risk, so we generally don’t grant unrestricted capability grants unless there is a really good reason
Transferable: any source that knows a specific secret
The zome call must carry a secret
Only the calls that carry the secret specified in the capability token will be executed
The secret can be stored in the source chain of the caller with a “Capability Claim” entry
Assigned to specific agents
The zome call must carry the agent public key of the caller and its signature and also a capability secret
Only the calls that a) carry the secret specified and b) are made by one of the agents specified in the capability token are allowed to make the call
Code example
Create unrestricted grant
use hdk::prelude::*;#[hdk_extern]fn zome_function_a(input: String) -> ExternResult<ActionHash> { /** Create, create links, get, query... */ } // Which functions do we grant access to? fn functions_to_grant_capability_for() -> GrantedFunctions { // Type required by the HDK API let zome_name = zome_info()?.name; // Getting the zome name let function_name = FunctionName(String::from("zome_function_a")); // Wrapper around a "String" let mut functions: BTreeSet<(ZomeName, FunctionName)> = BTreeSet::new(); functions.insert((zome_name, function_name)); // Granting access to the function in this zome GrantedFunctions::Listed(functions) // Can be "Listed" functions or "All" functions}#[hdk_extern]fn grant_unrestricted_capability(_: ()) -> ExternResult<()> { let functions = functions_to_grant_capability_for(); let access = CapAccess::Unrestricted; // Can be called from any source let capability_grant = CapGrantEntry { // Built-in private entry functions, access, tag: String::from("unrestricted"), // Convenience tag }; create_cap_grant(capability_grant)?; // Actually commit the capability Ok(())}
Create a transferable grant
// Which secret do they need to know to call those functions? fn cap_secret() -> ExternResult<CapSecret> { // Wrapper around a byte array let bytes = random_bytes(64)?; let secret = CapSecret::try_from(bytes.into_vec()) .map_err(|_| wasm_error!(WasmErrorInner::Guest("Could not build secret".into())))?; Ok(secret)}#[hdk_extern]fn grant_transferable_capability(authorized_agent: AgentPubkey) -> ExternResult<()> { let secret = cap_secret()?; let access = CapAccess::Transferable { // Requests are required to carry this secret secret, }; let capability_grant = CapGrantEntry { functions: functions_to_grant_capability_for(), access, tag: String::from("transferable capability"), // Convenience tag }; create_cap_grant(capability_grant)?; Ok(())}
Create assigned grant
use hdk::prelude::*;#[hdk_extern]fn grant_assigned_capability(authorized_agent: AgentPubkey) -> ExternResult<()> { /** To whom do we grant access to those functions? */ let mut assignees: BTreeSet<AgentPubkey> = BTreeSet::new(); assignees.insert(authorized_agent); // Assign capabilty to the given "authorized_agent" let access = CapAccess::Assigned { // Requests are required to carry this secret and be signed by one of the assignees secret: cap_secret(), assignees }; let capability_grant = CapGrantEntry { functions: functions_to_grant_capability_for(), access, tag: String::from("assigned capability"), // Convenience tag }; create_cap_grant(capability_grant)?; Ok(())}
Create capability claims
use hdk::prelude::*;#[hdk_extern]fn create_claim_for_zome_function_a(grant_data: (AgentPubkey, Secret)) -> ExternResult<()> { let cap_claim = CapClaimEntry { // Built-in private entry grantor: grant_data.0, // Just to remember which agent to call secret: grant_data.1, // Store the secret tag: String::from("claim for zome_function_a"), // Can be different from the tag in the grant }; create_cap_claim(cap_claim)?; // Commit the claim privately Ok(())}