Documentation
¶
Overview ¶
Package tka (WIP) implements the Tailnet Key Authority.
Index ¶
- Variables
- type AUM
- type AUMHash
- type AUMKind
- type AUMSigHash
- type Chonk
- type FS
- type Key
- type KeyID
- type KeyKind
- type Mem
- func (c *Mem) AUM(hash AUMHash) (AUM, error)
- func (c *Mem) ChildAUMs(prevAUMHash AUMHash) ([]AUM, error)
- func (c *Mem) CommitVerifiedAUMs(updates []AUM) error
- func (c *Mem) Heads() ([]AUM, error)
- func (c *Mem) LastActiveAncestor() (*AUMHash, error)
- func (c *Mem) Orphans() ([]AUM, error)
- func (c *Mem) SetLastActiveAncestor(hash AUMHash) error
- type Signature
- type State
Constants ¶
This section is empty.
Variables ¶
var ErrNoSuchKey = errors.New("key not found")
ErrNoSuchKey is returned if the key referenced by a KeyID does not exist.
Functions ¶
This section is empty.
Types ¶
type AUM ¶
type AUM struct { MessageKind AUMKind `cbor:"1,keyasint"` PrevAUMHash []byte `cbor:"2,keyasint"` // Key encodes a public key to be added to the key authority. // This field is used for AddKey AUMs. Key *Key `cbor:"3,keyasint,omitempty"` // KeyID references a public key which is part of the key authority. // This field is used for RemoveKey and UpdateKey AUMs. KeyID KeyID `cbor:"4,keyasint,omitempty"` // State describes the full state of the key authority. // This field is used for Checkpoint AUMs. State *State `cbor:"5,keyasint,omitempty"` // DisablementSecret is used to transmit a secret for disabling // the TKA. // This field is used for DisableNL AUMs. DisablementSecret []byte `cbor:"6,keyasint,omitempty"` // Votes and Meta describe properties of a key in the key authority. // These fields are used for UpdateKey AUMs. Votes *uint `cbor:"7,keyasint,omitempty"` Meta map[string]string `cbor:"8,keyasint,omitempty"` // Signatures lists the signatures over this AUM. // CBOR key 23 is the last key which can be encoded as a single byte. Signatures []Signature `cbor:"23,keyasint,omitempty"` }
AUM describes an Authority Update Message.
The rules for adding new types of AUMs (MessageKind):
- CBOR key IDs must never be changed.
- New AUM types must not change semantics that are manipulated by other AUM types.
- The serialization of existing data cannot change (in other words, if an existing serialization test in aum_test.go fails, you need to try a different approach).
The rules for adding new fields are as follows:
- Must all be optional.
- An unset value must not result in serialization overhead. This is necessary so the serialization of older AUMs stays the same.
- New processing semantics of the new fields must be compatible with the behavior of old clients (which will ignore the field).
- No floats!
func (*AUM) Parent ¶
Parent returns the parent's AUM hash and true, or a zero value and false if there was no parent.
func (AUM) SigHash ¶
func (a AUM) SigHash() AUMSigHash
SigHash returns the cryptographic digest which a signature is over.
This is identical to Hash() except the Signatures are not serialized. Without this, the hash used for signatures would be circularly dependent on the signatures.
func (*AUM) StaticValidate ¶
StaticValidate returns a nil error if the AUM is well-formed.
type AUMKind ¶
type AUMKind uint8
AUMKind describes valid AUM types.
const ( AUMInvalid AUMKind = iota // An AddKey AUM describes a new key trusted by the TKA. // // Only the Key optional field may be set. AUMAddKey // A RemoveKey AUM describes hte removal of a key trusted by TKA. // // Only the KeyID optional field may be set. AUMRemoveKey // A DisableNL AUM describes the disablement of TKA. // // Only the DisablementSecret optional field may be set. AUMDisableNL // A NoOp AUM carries no information and is used in tests. AUMNoOp // A UpdateKey AUM updates the metadata or votes of an existing key. // // Only KeyID, along with either/or Meta or Votes optional fields // may be set. AUMUpdateKey // A Checkpoint AUM specifies the full state of the TKA. // // Only the State optional field may be set. AUMCheckpoint )
Valid AUM types. Do NOT reorder.
type AUMSigHash ¶
AUMSigHash represents the BLAKE2s digest of an Authority Update Message (AUM), sans any signatures.
type Chonk ¶
type Chonk interface { // AUM returns the AUM with the specified digest. // // If the AUM does not exist, then os.ErrNotExist is returned. AUM(hash AUMHash) (AUM, error) // ChildAUMs returns all AUMs with a specified previous // AUM hash. ChildAUMs(prevAUMHash AUMHash) ([]AUM, error) // CommitVerifiedAUMs durably stores the provided AUMs. // Callers MUST ONLY provide AUMs which are verified (specifically, // a call to aumVerify() must return a nil error). // as the implementation assumes that only verified AUMs are stored. CommitVerifiedAUMs(updates []AUM) error // Heads returns AUMs for which there are no children. In other // words, the latest AUM in all possible chains (the 'leaves'). Heads() ([]AUM, error) // SetLastActiveAncestor is called to record the oldest-known AUM // that contributed to the current state. This value is used as // a hint on next startup to determine which chain to pick when computing // the current state, if there are multiple distinct chains. SetLastActiveAncestor(hash AUMHash) error // LastActiveAncestor returns the oldest-known AUM that was (in a // previous run) an ancestor of the current state. This is used // as a hint to pick the correct chain in the event that the Chonk stores // multiple distinct chains. LastActiveAncestor() (*AUMHash, error) }
Chonk implementations provide durable storage for AUMs and other TKA state.
All methods must be thread-safe.
The name 'tailchonk' was coined by @catzkorn.
type FS ¶
type FS struct {
// contains filtered or unexported fields
}
FS implements filesystem storage of TKA state.
FS implements the Chonk interface.
func (*FS) AUM ¶
AUM returns the AUM with the specified digest.
If the AUM does not exist, then os.ErrNotExist is returned.
func (*FS) CommitVerifiedAUMs ¶
CommitVerifiedAUMs durably stores the provided AUMs. Callers MUST ONLY provide AUMs which are verified (specifically, a call to aumVerify must return a nil error), as the implementation assumes that only verified AUMs are stored.
func (*FS) Heads ¶
Heads returns AUMs for which there are no children. In other words, the latest AUM in all possible chains (the 'leaves').
Heads is expected to be called infrequently compared to AUM() or ChildAUMs(), so we haven't put any work into maintaining an index. Instead, the full set of AUMs is scanned.
func (*FS) LastActiveAncestor ¶
LastActiveAncestor returns the oldest-known AUM that was (in a previous run) an ancestor of the current state. This is used as a hint to pick the correct chain in the event that the Chonk stores multiple distinct chains.
Nil is returned if no last-active ancestor is set.
func (*FS) SetLastActiveAncestor ¶
SetLastActiveAncestor is called to record the oldest-known AUM that contributed to the current state. This value is used as a hint on next startup to determine which chain to pick when computing the current state, if there are multiple distinct chains.
type Key ¶
type Key struct { Kind KeyKind `cbor:"1,keyasint"` // Votes describes the weight applied to signatures using this key. // Weighting is used to deterministically resolve branches in the AUM // chain (i.e. forks, where two AUMs exist with the same parent). Votes uint `cbor:"2,keyasint"` // Public encodes the public key of the key. For 25519 keys, // this is simply the point on the curve representing the public // key. Public []byte `cbor:"3,keyasint"` // Meta describes arbitrary metadata about the key. This could be // used to store the name of the key, for instance. Meta map[string]string `cbor:"12,keyasint,omitempty"` }
Key describes the public components of a key known to network-lock.
func (Key) Clone ¶
Clone makes an independent copy of Key.
NOTE: There is a difference between a nil slice and an empty
slice for encoding purposes, so an implementation of Clone() must take care to preserve this.
func (Key) StaticValidate ¶
type KeyID ¶
type KeyID []byte
KeyID references a verification key stored in the key authority.
For 25519 keys: The 32-byte public key.
type Mem ¶
type Mem struct {
// contains filtered or unexported fields
}
Mem implements in-memory storage of TKA state, suitable for tests.
Mem implements the Chonk interface.
func (*Mem) CommitVerifiedAUMs ¶
CommitVerifiedAUMs durably stores the provided AUMs. Callers MUST ONLY provide well-formed and verified AUMs, as the rest of the TKA implementation assumes that only verified AUMs are stored.
func (*Mem) Heads ¶
Heads returns AUMs for which there are no children. In other words, the latest AUM in all chains (the 'leaf').
func (*Mem) LastActiveAncestor ¶
func (*Mem) SetLastActiveAncestor ¶
type Signature ¶
Signature describes a signature over an AUM, which can be verified using the key referenced by KeyID.
type State ¶
type State struct { // LastAUMHash is the blake2s digest of the last-applied AUM. // Because AUMs are strictly ordered and form a hash chain, we // check the previous AUM hash in an update we are applying // is the same as the LastAUMHash. LastAUMHash *AUMHash `cbor:"1,keyasint"` // DisablementSecrets are KDF-derived values which can be used // to turn off the TKA in the event of a consensus-breaking bug. // An AUM of type DisableNL should contain a secret when results // in one of these values when run through the disablement KDF. // // TODO(tom): This is an alpha feature, remove this mechanism once // we have confidence in our implementation. DisablementSecrets [][]byte `cbor:"2,keyasint"` // Keys are the public keys currently trusted by the TKA. Keys []Key `cbor:"3,keyasint"` }
State describes Tailnet Key Authority state at an instant in time.
State is mutated by applying Authority Update Messages (AUMs), resulting in a new State.