Documentation
¶
Index ¶
- Constants
- Variables
- func WithRNG(r io.Reader) compositionOption
- func WithRootKeyID(id uint32) compositionOption
- func WithSymbols(symbols *datalog.SymbolTable) builderOption
- type Authorizer
- type AuthorizerOption
- type BinaryOp
- type Biscuit
- func (b *Biscuit) Append(rng io.Reader, block *Block) (*Biscuit, error)
- func (b *Biscuit) Authorizer(root ed25519.PublicKey, opts ...AuthorizerOption) (Authorizer, error)
- func (b *Biscuit) AuthorizerFor(keySource PublickKeyByIDProjection, opts ...AuthorizerOption) (Authorizer, error)
- func (b *Biscuit) BlockCount() int
- func (b *Biscuit) Checks() [][]datalog.Check
- func (b *Biscuit) Code() []string
- func (b *Biscuit) CreateBlock() BlockBuilder
- func (b *Biscuit) GetBlockID(fact Fact) (int, error)
- func (b *Biscuit) GetContext() string
- func (b *Biscuit) RevocationIds() [][]byte
- func (b *Biscuit) RootKeyID() *uint32
- func (b *Biscuit) Seal(rng io.Reader) (*Biscuit, error)
- func (b *Biscuit) Serialize() ([]byte, error)
- func (b *Biscuit) String() string
- type Block
- type BlockBuilder
- type Bool
- type Builder
- type Bytes
- type Check
- type Date
- type Expression
- type Fact
- type FactSet
- type Integer
- type Op
- type OpType
- type ParsedAuthorizer
- type ParsedBlock
- type Policy
- type PolicyKind
- type Predicate
- type PublickKeyByIDProjection
- type Rule
- type Set
- type String
- type Term
- type TermType
- type UnaryOp
- type Unmarshaler
- type Value
- type Variable
Examples ¶
Constants ¶
const ( PolicyKindAllow = iota PolicyKindDeny )
const MaxSchemaVersion uint32 = 3
const MinSchemaVersion uint32 = 3
Variables ¶
var ( ErrMissingSymbols = errors.New("biscuit: missing symbols") ErrPolicyDenied = errors.New("biscuit: denied by policy") ErrNoMatchingPolicy = errors.New("biscuit: denied by no matching policies") )
var ( // ErrSymbolTableOverlap is returned when multiple blocks declare the same symbols ErrSymbolTableOverlap = errors.New("biscuit: symbol table overlap") // ErrInvalidAuthorityIndex occurs when an authority block index is not 0 ErrInvalidAuthorityIndex = errors.New("biscuit: invalid authority index") // ErrInvalidAuthorityFact occurs when an authority fact is an ambient fact ErrInvalidAuthorityFact = errors.New("biscuit: invalid authority fact") // ErrInvalidBlockFact occurs when a block fact provides an authority or ambient fact ErrInvalidBlockFact = errors.New("biscuit: invalid block fact") // ErrInvalidBlockRule occurs when a block rule generate an authority or ambient fact ErrInvalidBlockRule = errors.New("biscuit: invalid block rule") // ErrEmptyKeys is returned when verifying a biscuit having no keys ErrEmptyKeys = errors.New("biscuit: empty keys") // ErrNoPublicKeyAvailable is returned when no public root key is available to verify the // signatures on a biscuit's blocks. ErrNoPublicKeyAvailable = errors.New("biscuit: no public key available") // ErrUnknownPublicKey is returned when verifying a biscuit with the wrong public key ErrUnknownPublicKey = errors.New("biscuit: unknown public key") ErrInvalidSignature = errors.New("biscuit: invalid signature") ErrInvalidSignatureSize = errors.New("biscuit: invalid signature size") ErrInvalidKeySize = errors.New("biscuit: invalid key size") ErrUnsupportedAlgorithm = errors.New("biscuit: unsupported signature algorithm") // Deprecated: use ErrUnsupportedAlgorithm. UnsupportedAlgorithm = ErrUnsupportedAlgorithm )
var ( ErrDuplicateFact = errors.New("biscuit: fact already exists") ErrInvalidBlockIndex = errors.New("biscuit: invalid block index") )
var ( // DefaultAllowPolicy allows the biscuit to verify sucessfully as long as all its checks generate some facts. DefaultAllowPolicy = Policy{Kind: PolicyKindAllow, Queries: []Rule{{Head: Predicate{Name: "allow"}}}} // DefaultDenyPolicy makes the biscuit verification fail in all cases. DefaultDenyPolicy = Policy{Kind: PolicyKindDeny, Queries: []Rule{{Head: Predicate{Name: "deny"}}}} )
var ErrFactNotFound = errors.New("biscuit: fact not found")
Functions ¶
func WithRNG ¶
WithRNG supplies a random number generator as a byte stream from which to read when generating key pairs with which to sign blocks within biscuits.
func WithRootKeyID ¶
func WithRootKeyID(id uint32) compositionOption
WithRootKeyID specifies the identifier for the root key pair used to sign a biscuit's authority block, allowing a consuming party to later select the corresponding public key to validate that signature.
func WithSymbols ¶
func WithSymbols(symbols *datalog.SymbolTable) builderOption
WithSymbols supplies a symbol table to use when composing biscuits.
Types ¶
type Authorizer ¶
type Authorizer interface {
AddAuthorizer(a ParsedAuthorizer)
AddBlock(b ParsedBlock)
AddFact(fact Fact)
AddRule(rule Rule)
AddCheck(check Check)
AddPolicy(policy Policy)
Authorize() error
Query(rule Rule) (FactSet, error)
Biscuit() *Biscuit
Reset()
PrintWorld() string
LoadPolicies([]byte) error
SerializePolicies() ([]byte, error)
}
func NewVerifier ¶
func NewVerifier(b *Biscuit, opts ...AuthorizerOption) (Authorizer, error)
type AuthorizerOption ¶
type AuthorizerOption func(w *authorizer)
func WithWorldOptions ¶
func WithWorldOptions(opts ...datalog.WorldOption) AuthorizerOption
type Biscuit ¶
type Biscuit struct {
// contains filtered or unexported fields
}
Biscuit represents a valid Biscuit token It contains multiple `Block` elements, the associated symbol table, and a serialized version of this data
Example ¶
package main
import (
"crypto/ed25519"
"crypto/rand"
"fmt"
"github.com/eclipse-biscuit/biscuit-go/v2"
"github.com/eclipse-biscuit/biscuit-go/v2/parser"
)
func main() {
rng := rand.Reader
publicRoot, privateRoot, _ := ed25519.GenerateKey(rng)
authority, err := parser.FromStringBlockWithParams(`
right("/a/file1.txt", {read});
right("/a/file1.txt", {write});
right("/a/file2.txt", {read});
right("/a/file3.txt", {write});
`, map[string]biscuit.Term{"read": biscuit.String("read"), "write": biscuit.String("write")})
if err != nil {
panic(fmt.Errorf("failed to parse authority block: %v", err))
}
builder := biscuit.NewBuilder(privateRoot)
builder.AddBlock(authority)
b, err := builder.Build()
if err != nil {
panic(fmt.Errorf("failed to build biscuit: %v", err))
}
token, err := b.Serialize()
if err != nil {
panic(fmt.Errorf("failed to serialize biscuit: %v", err))
}
fmt.Printf("Token1 length: %d\n", len(token))
deser, err := biscuit.Unmarshal(token)
if err != nil {
panic(fmt.Errorf("failed to deserialize biscuit: %v", err))
}
blockBuilder := deser.CreateBlock()
block, err := parser.FromStringBlockWithParams(`
check if resource($file), operation($permission), [{read}].contains($permission);`,
map[string]biscuit.Term{"read": biscuit.String("read")})
if err != nil {
panic(fmt.Errorf("failed to parse block: %v", err))
}
blockBuilder.AddBlock(block)
b2, err := deser.Append(rng, blockBuilder.Build())
if err != nil {
panic(fmt.Errorf("failed to append: %v", err))
}
token2, err := b2.Serialize()
if err != nil {
panic(fmt.Errorf("failed to serialize biscuit: %v", err))
}
fmt.Printf("Token2 length: %d\n", len(token2))
// Verify
b2, err = biscuit.Unmarshal(token2)
if err != nil {
panic(fmt.Errorf("failed to deserialize token: %v", err))
}
v1, err := b2.Authorizer(publicRoot)
if err != nil {
panic(fmt.Errorf("failed to create verifier: %v", err))
}
authorizer, err := parser.FromStringAuthorizerWithParams(`
resource({res});
operation({op});
allow if right({res}, {op});
`, map[string]biscuit.Term{"res": biscuit.String("/a/file1.txt"), "op": biscuit.String("read")})
if err != nil {
panic(fmt.Errorf("failed to parse authorizer: %v", err))
}
v1.AddAuthorizer(authorizer)
if err := v1.Authorize(); err != nil {
// fmt.Println(v1.PrintWorld())
fmt.Println("forbidden to read /a/file1.txt")
} else {
//fmt.Println(v1.PrintWorld())
fmt.Println("allowed to read /a/file1.txt")
}
v1, _ = b2.Authorizer(publicRoot)
authorizer, err = parser.FromStringAuthorizerWithParams(`
resource({res});
operation({op});
allow if right({res}, {op});
`, map[string]biscuit.Term{"res": biscuit.String("/a/file1.txt"), "op": biscuit.String("write")})
if err != nil {
panic(fmt.Errorf("failed to parse authorizer: %v", err))
}
v1.AddAuthorizer(authorizer)
if err := v1.Authorize(); err != nil {
fmt.Println("forbidden to write /a/file1.txt")
} else {
fmt.Println("allowed to write /a/file1.txt")
}
}
Output: Token1 length: 251 Token2 length: 433 allowed to read /a/file1.txt forbidden to write /a/file1.txt
func New ¶
func New(rng io.Reader, root ed25519.PrivateKey, baseSymbols *datalog.SymbolTable, authority *Block) (*Biscuit, error)
func (*Biscuit) Authorizer ¶
func (b *Biscuit) Authorizer(root ed25519.PublicKey, opts ...AuthorizerOption) (Authorizer, error)
Authorizer checks the signature and creates an Authorizer. The Authorizer can then test the authorizaion policies and accept or refuse the request.
func (*Biscuit) AuthorizerFor ¶
func (b *Biscuit) AuthorizerFor(keySource PublickKeyByIDProjection, opts ...AuthorizerOption) (Authorizer, error)
AuthorizerFor selects from the supplied source a root public key to use to verify the signatures on the biscuit's blocks, returning an error satisfying errors.Is(err, ErrNoPublicKeyAvailable) if no such public key is available. If the signatures are valid, it creates an Authorizer, which can then test the authorization policies and accept or refuse the request.
func (*Biscuit) BlockCount ¶
func (*Biscuit) CreateBlock ¶
func (b *Biscuit) CreateBlock() BlockBuilder
func (*Biscuit) GetBlockID ¶
GetBlockID returns the first block index containing a fact starting from the authority block and then each block in the order they were added. ErrFactNotFound is returned when no block contains the fact.
func (*Biscuit) GetContext ¶
func (*Biscuit) RevocationIds ¶
type BlockBuilder ¶
type BlockBuilder interface {
AddBlock(block ParsedBlock) error
AddFact(fact Fact) error
AddRule(rule Rule) error
AddCheck(check Check) error
SetContext(string)
Build() *Block
}
func NewBlockBuilder ¶
func NewBlockBuilder(baseSymbols *datalog.SymbolTable) BlockBuilder
type Builder ¶
type Builder interface {
AddBlock(block ParsedBlock) error
AddAuthorityFact(fact Fact) error
AddAuthorityRule(rule Rule) error
AddAuthorityCheck(check Check) error
SetContext(string)
Build() (*Biscuit, error)
}
func NewBuilder ¶
func NewBuilder(root ed25519.PrivateKey, opts ...builderOption) Builder
type Expression ¶
type Expression []Op
type ParsedAuthorizer ¶
type ParsedAuthorizer struct {
Policies []Policy
Block ParsedBlock
}
type ParsedBlock ¶
type Policy ¶
type Policy struct {
Queries []Rule
Kind PolicyKind
}
type PolicyKind ¶
type PolicyKind byte
type PublickKeyByIDProjection ¶
A PublickKeyByIDProjection inspects an optional ID for a public key and returns the corresponding public key, if any. If it doesn't recognize the ID or can't find the public key, or no ID is supplied and there is no default public key available, it should return an error satisfying errors.Is(err, ErrNoPublicKeyAvailable).
func WithRootPublicKeys ¶
func WithRootPublicKeys(keysByID map[uint32]ed25519.PublicKey, defaultKey *ed25519.PublicKey) PublickKeyByIDProjection
WithRootPublicKeys supplies a mapping to public keys from their corresponding IDs, used to select which public key to use to verify the signatures on a biscuit's blocks based on the key ID embedded within the biscuit when it was created. If the biscuit has no key ID available, this function selects the optional default key instead. If no public key is available—whether for the biscuit's embedded key ID or a default key when no such ID is present—it returns ErrNoPublicKeyAvailable.
func WithSingularRootPublicKey ¶
func WithSingularRootPublicKey(key ed25519.PublicKey) PublickKeyByIDProjection
WithSingularRootPublicKey supplies one public key to use as the root key with which to verify the signatures on a biscuit's blocks.
type Rule ¶
type Rule struct {
Head Predicate
Body []Predicate
Expressions []Expression
}
type Unmarshaler ¶
type Unmarshaler struct {
Symbols *datalog.SymbolTable
}