* add a new message format for authorizer snapshots
the fact scopes have to be transmitted if we want to replay an
authorizers behaviour. AuthorizerPolicies can be kept as a way to share
plicies to bootstrap the authorizer
* update the format
- externalSignature allows to attach an optional signature (from a non-ephemeral private key)
to biscuit blocks
- scope lets blocks and rules specify which facts can be loaded (either through keywords
for selecting groups of blocks, or through public keys for blocks signed by a specific
key)
- publicKeys provides a way to intern public keys in a way similar to symbols. Only public
keys referenced in datalog elements can be interned
- ThirdPartyBlockRequest / ThirdPartyBlockContents provide a way to add a signed 3rd party block
to a given biscuit token without disclosing the token itself. For that, the request needs to
provide:
- the public key of the last block (needed to pin the signature to a specific biscuit token)
- the list of already interned public keys (needed to properly generate the datalog ast).
Contrary to public keys, interned symbols are not shared to 3rd party blocks to prevent
information leaks.
The response provides the serialized block, as well as the associated signature.
symbols were a kind of strings with less available operations and some
specific optimizations: they store in index into a symbol table carried
by the token, to reduce size by avoiding repetitions.
They were too confusing for users, and now that #authority and #ambient
are gone, we can remove them completely.
The symbol table was useful though, so now the symbol table is used for
all predicate names and strings
there are two use cases for this:
- quickly loading verifier policies from a serialized state instead of
manually adding datalog elements one by one through the verifier API.
The policies could even be written in a different system then published
to running instances dynamically
- save the state of a verifier, including ambient data, facts, rules and
checks coming from a token, to later load it into another verifier and inspect
it
this commit introduces a method-like syntax for these operations:
- .starts_with()
- .ends_with()
- .matches()
- .contains() (replacing the In operation)
There is no satisfying name to replace the "not in" operation, so it is
replaced by a "contains" and negation, like this: "!set.contains($var)".
The NotIn operation is removed from the V1 schema
the meaning of "caveat" was not clear enough for users (outside of those
already familiar with macaroons), while "check" is more obvious: in a
"checklist", all items must be validated.
Allow and deny policies can be added only in the verifier (not in
tokens so there's no format change here). They use rules under the hood
like checks, and are tested one by one until one of them matches.
A default policy should be added to the verifier, otherwise it will
return the NoMatchingPolicy error. To keep the current behaviour of
accepting the request once all checks have been validated, we use the
default policy "allow if true", that only contains the expression
"true".
At last, we introduce a new syntax for checks and policies:
caveat1($0) <- resource(#ambient, $0), operation(#ambient, #read), right(#authority, $0, #read)
is rewritten as:
check if resource(#ambient, $0), operation(#ambient, #read), right(#authority, $0, #read)
Similarly, allow and deny policies use "allow if" and "deny if"
prefixes. If a check contains multiple rules, they are separated with
"or". All of those keywords are case insensitive.
this changes the Protobuf format to add a version field to blocks, set
to 0 for now. This change will ship in the 0.9 version of the Rust
version.
When deserializing a token, we wil check the version field. if not
present, we assume the block is at version 0. A token can contain blocks
with different versions, so a token generated by an old library can be
attenuated by a newer one.
If the version is higher than the maximum one for the library, the token
will be rejected
before:
- rules in an authority block are authority facts generation rules
- rules in other blocks are caveats
now:
- rules in an authority block are authority facts generation rules
- rules in other block are facts generation rules for this block's validation
- caveats in the authority block are tested once at the beginning of
the validation
- caveats in an other block are specific to that block's validation