About Biscuit Authorization
Fine-tuned permissions in a decentralized network.
Background
Biscuits are a special bearer token used to authorize access to resources (e.g. tables) and are associated with a public/private key pair. Public keys are provided when the user creates a resource (such as a table) and are used to validate biscuit signatures during authorization for requests against that resource. Users create and attenuate their own biscuits (using the corresponding private key) without the Space and Time platform holding your secrets— full self-custody of your tables! A biscuit must contain, at minimum, a single capability (i.e. security configuration, such as "I am allowed to read from this table") specifying what operation is allowed on which resource
Public Key Cryptography
Biscuit authorization is based on public key cryptography, meaning each biscuit is associated with a public key and private key. The private key is used to sign the biscuit during creation, and the public key is used to validate the biscuit. When creating a table, you must specify a public key. It will be used to validate signatures on all biscuits provided during request authorization thereafter, and the public key cannot be changed. Make sure to keep your private key safe, as anyone with access can generate biscuits with any level of authority.
Biscuit public/private keys are independent of user public/private keys. Do not use the keypair you use for authentication for resource authorization.
Biscuit Standards
This section outlines the biscuit standards supported by Space and Time.
We are working on adding new standards to enable even more authorization support. Check back soon!
Facts
Facts define claims about a request to be considered during authorization.
Operation
Operations are datalog facts that define what action is being performed in a request. They are defined as follows:
sxt:operation($operation);
The $operation
must be a string and match one of the below:
- SQL operations:
- DDL: for operating on database objects & schema (e.g. table, view)
ddl_create
: SQLCREATE
commandddl_alter
: SQLALTER
commandddl_drop
: SQLDROP
command
- DML: for performing data manipulation
dml_insert
: SQLINSERT
commanddml_update
: SQLUPDATE
commanddml_merge
: DQLMERGE
commanddml_delete
: SQLDELETE
command
- DQL: for performing queries
dql_select
: SQLSELECT
command
- DDL: for operating on database objects & schema (e.g. table, view)
- Kafka ICM operations:
kafka_icm_create
: ICM createkafka_icm_read
: ICM readkafka_icm_update
: ICM updatekafka_icm_delete
: ICM delete
Operation facts should not be specified in your biscuit - they are defined for reference purposes only. The authorization engine will reject biscuits with operation facts.
Resource
Resources are datalog facts that define what is being accessed in a request. They are defined as follows:
sxt:resource($resource);
The $resource
must be a lowercase string and match a valid, existing resource.
- SQL resources: It must include the full resource identifier (i.e., it must include both the namespace and resource name). As an example, the Transactions table in the ETH namespace would be
eth.transactions
. - Kafka ICM resources:
kafka_icm_infrastructure_group
: Kafka infrastructure groupskafka_icm_user
: Kafka userskafka_icm_acl
: Kafka ACLskafka_icm_topic
: Kafka topicskafka_icm_topic_mapping_config
: Kafka topic mapping configuration
Resource facts should not be specified in your biscuit - they are defined for reference purposes only. The authorization engine will reject biscuits with resource facts.
Capability
Capabilities are datalog facts that define what operation is allowed on a given resource, enabling easy specification of a operation-resource matrix. They are defined as follows:
sxt:capability($operation, $resource);
The $operation
must conform to Operation requirements, and the $resource
must conform to Resource requirements.
A basic biscuit needs at least one capability. Your biscuit payload should primarily contain capability facts
User
Users are datalog facts that define what user is submitting a request. They are defined as follows:
sxt:user($userId);
The $userId
must be a valid platform user identifier.
User facts should not be specified in your biscuit - they are defined for reference purposes only. The authorization engine will reject biscuits with user facts.
Wildcards
Wildcards are not recommended in production for security reasons.
Wildcards (*
) represent any in the context of biscuit facts. They can be used as a replacement for explicit definitions of both Operation and Resource values in Capability facts. They ultimately serve as a means to bypass strict access control definitions to allow for more flexible use of biscuits.
As an example, you might want to create a biscuit authorizing access to all operations on a given resource (e.g., the TEST.CUSTOMER table). You would define a wildcard operation capability like this:
sxt:capability("*", "test.customer");
In another example, you might not know all tables you'll create with the same public key, but you're developing an application that should be able to query all of them. You would define a wildcard resource capability like this:
sxt:capability("dql_select", "*");
A word on wildcards and security
Note that wildcards can be dangerous from a security perspective. Since biscuits are bearer tokens, anyone who has access to the token (i.e., bears it) can perform anything that the token authorizes. For this reason, we do not recommend using wildcards in a production application. Instead, wildcards are great for fast development of applications when security considerations matter less. After building your functionality, we HIGHLY recommend that you go back and regenerate biscuits with explicit capabilities defined to limit yourself to security risks.
Checks
Checks are a flexible datalog terms that enable simple validation of datalog facts. If a check fails, the request will be rejected by the authorizer. For all of the above facts, you can define a check to limit how a biscuit can be used.
For example, if you want to create a biscuit authorizing read-only access to your table (e.g., the TEST.CUSTOMER table), you can also add a check to ensure that your user (e.g., the john_doe user) is the only one for whom the biscuit authorization can succeed. Simply define the following payload:
sxt:capability("dql_select", "test.customer");
check if sxt:user("john_doe");
Working with Biscuits
Biscuit manipulation (creating, testing, attenuating, etc.) does not involve the platform, meaning you can create biscuits however you want, whenever you want. Please refer to the biscuit cli guide for more details on how to operate on biscuits on your local machine. The only requirement to create a biscuit is to have access to the appropriate private key. If you use the wrong private key, your biscuit signature won't be valid for the desired table.
Let's say you just created a table called TEST.CUSTOMER
and want to give yourself read-write access. You would specify the following payload in your biscuit:
sxt:capability("dql_select", "test.customer");
sxt:capability("dml_insert", "test.customer");
sxt:capability("dml_update", "test.customer");
sxt:capability("dml_delete", "test.customer");
If you later decide you want to give your friend access to query your table, you have two options. You can either generate a new biscuit with only the dql_select
capability, or you can attenuate your existing biscuit (adding a user check as defined above). Note that biscuits can never grow in scope, they can only become more restrictive (i.e., attenuated). So if you share a biscuit with someone else, they can never add new capabilities!
Namespacing
Namespacing is now supported across the platform! Note that the above documentation now includes the sxt:
prefix. If you've already generated biscuits, don't worry. We're keeping backwards compatibility with the old datalog (i.e., you can still write capability("dql_select", "test.customer")
), but note that this old style is now considered deprecated and will be removed in a future release. Please plan on migrating your biscuits to use the new namespace prefix.
Updated about 1 year ago