api

package
v0.0.0-...-7eb8b13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2021 License: NCSA Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultAutoDelete = time.Duration(0)

DefaultAutoDelete determines the duration for which keys with a TTL of -1 will be purged from backend storaoge. This differs somewhat from PurgeAfter in that the latter can be configured for longer durations and will typically not be checked with greater frequency.

View Source
const DefaultAutoRotate = time.Duration(0)

DefaultAutoRotate dictates how old a key may be until it is automatically rotated. This value is 0, implying the key is never rotated automatically.

View Source
const DefaultLength = 32

DefaultLength is the length keys will automatically be set to if the value is not provided.

View Source
const DefaultMaxVersions = 10

DefaultMaxVersions determines how many versions maximum a key will retain by default.

View Source
const DefaultTTL = 0

DefaultTTL determines the default expiration period for a key. This value is 0, meaning the key never expires.

View Source
const MaxKeySize = 1024 * 1024 * 10

MaxKeySize defines the maximum possible size of a key (10 megabytes). For compatibility with CompositeKeys

Variables

This section is empty.

Functions

func GenerateKey

func GenerateKey(length int) ([]byte, error)

GenerateKeyData generates a cryptographically-secure byte slice for use as a key of size `length`.

func GenerateKeyString

func GenerateKeyString(length int) (string, error)

GenerateKeyString returns a base64 implementation of a random series of bytes as generated by GenerateKey.

Types

type AccountHandler

type AccountHandler interface {
	// Hooks for this account. Webhooks may only be defined for specific accounts.
	// These can be enabled or disabled globally or for specific accounts. The
	// administrative account always has webhooks enabled.
	Hooks() []*Hook
}

AccountHandler handles interfacing with the accounts backend implementation via a storage intermediary. What storage intermediary--and how it works--is determined by the backend.

As an example, for the file system backend, implementations of this proxy will perform certain tasks while calling the file system layer for reading and writing to files and directories containing accounting information. This data is then collected and passed along via this defined interface to higher order interfaces and consumers.

type CompositeKey

type CompositeKey struct {
	Name   string
	Cipher *Key
	HMAC   *Key
}

CompositeKey is a convenience type for generating composite keys intended for encryption and validation. When wrapping a key ring with this type, it will handle key management for the caller.

func CompositeKeyFromKeyRing

func CompositeKeyFromKeyRing(name string, keyring *KeyRing) (*CompositeKey, error)

func EmptyCompositeKey

func EmptyCompositeKey(name string, cipherLength, hmacLength int) *CompositeKey

func NewCompositeKey

func NewCompositeKey(name string, cipherLength, hmacLength int) (*CompositeKey, error)

type CompositeKeyCreatedSignal

type CompositeKeyCreatedSignal func(*CompositeKey, *KeyRing)

CompositeKeyCreatedSignal is fired whenever a composite key is created or added via CreateComposite* or AddComposite*.

type CompositeKeyRemovedSignal

type CompositeKeyRemovedSignal func(*CompositeKey, *KeyRing)

CompositeKeyRemovedSignal is fired whenever a composite key is removed from the key ring.

type Hook

type Hook struct {
	// Name; mostly for symbolic use or in interfaces.
	Name string

	// URI defining the template status as listed in the file doc.
	URI string

	// HookType may be one of UpdateHook, CreateHook, or CombinedHook.
	HookType HookType

	// Headers for the request. May contain optional authorization data. By
	// default, this will always contain "Content-Type: application/json" unless
	// another content type is supplied.
	Headers http.Header
}

Hook for communicating key events with remote services. See file documentation for a detailed discussion of how hooks work.

type HookType

type HookType int
const (
	UpdateHook HookType = iota
	CreateHook
	CombinedHook
)

type Key

type Key struct {
	// Name of the current key.
	Name string

	// Custom indicates whether the key is a user-specified (custom) key or
	// generated by KeyStar.
	Custom bool

	// Length defines how many bytes the key should comprise.
	Length int

	// Encoded contains the base64-encoded key data.
	Encoded string

	// Created stores the creation time of the key in UTC.
	Created time.Time

	// Version specifies the current version of this key.
	Version int

	// IsComposite key.
	IsComposite bool

	// IsParent key in a multi-key relationship.
	IsParent bool
	// contains filtered or unexported fields
}

Key is a type that identifies a singular key or key version. Key may be encapsulated within other types to form composite keys (see CompositeKey) or used individually.

func EmptyKey

func EmptyKey(name string, length int) *Key

func NewKey

func NewKey(name string, length int) (*Key, error)

NewKey generates a key of the specified name and length with all other properties configured to their defaults. If key generation fails, this returns an error of type ErrGeneratingKey.

func (*Key) Bytes

func (k *Key) Bytes() ([]byte, error)

Bytes returns the decoded key as a byte slice.

func (*Key) Expires

func (k *Key) Expires() time.Time

Expires returns the timestamp of the key's expiry, defined as its creation time + the TTL. A TTL of 0 means "never expire," while a TTL of -1 means "expire immediately."

func (*Key) Generate

func (k *Key) Generate() error

Generate the key data for this key. This will overwrite whatever key data may be contained by this key.

func (*Key) IsEphemeral

func (k *Key) IsEphemeral() bool

IsEphemeral returns true if the key is considered an ephemeral key. Ephemeral keys are those that have no creation time set and were initialized directly.

func (*Key) IsExpired

func (k *Key) IsExpired() bool

IsExpired returns true if the key has expired, false otherwise.

func (*Key) KeyRing

func (k *Key) KeyRing() *KeyRing

KeyRing returns the key ring instance bound to this key.

func (*Key) MustGetBytes

func (k *Key) MustGetBytes() []byte

MustGetBytes returns the decoded byte array from the specified key. If the decoding process fails, it panics.

type KeyCreatedSignal

type KeyCreatedSignal func(*Key, *KeyRing)

KeyCreateSignal is fired whenever a key is created or added via Create* or Add*.

type KeyRemovedSignal

type KeyRemovedSignal func(*Key, *KeyRing)

KeyRemovedSignal is fired whenever a key is removed from the key ring.

type KeyRing

type KeyRing struct {
	// Name is the symbolic name used for this key ring.
	Name string

	// Created indicates when this key ring was created.
	Created time.Time

	// Rotated indicates when the contents of this key ring were last rotated. May
	// not be supported by all backend and could return the zero time.
	Rotated time.Time

	// TTL defines the maximum duration during which the keys contained within
	// this key ring are considered valid.
	TTL time.Duration

	// MaxVersions determines how many prior versions of each key should be stored
	// by this key ring.
	MaxVersions int

	// DeleteAfter is a hint for the system to determine when a key should be
	// deleted after it has been expired. By default, expired keys are never
	// deleted.
	DeleteAfter time.Duration

	// RotateAfter is another hint for the system determining how long a key
	// should persist before automatically being rotated. RotateAfter should not
	// be used with TTL.
	RotateAfter time.Duration

	// Keys is a map containing all keys associated with this key ring.
	Keys map[string]*Key

	sync.RWMutex
	// contains filtered or unexported fields
}

KeyRing defines any of several key types that may be persisted to backend storage. This may be a key, composite key (realistically, a specific type of key), or user-supplied secrets. KeyRing encapsulates key versions (if available) and other nuances associated with key storage. In particular, a single key may be stored in KeyRing, or KeyRing may contain multiple Purpose. A single key, however, may only define a singular key entity. (Note: This isn't strictly true; See CompositeKey.)

Keyring may be broken down into separate data structures depending on the backend, each of which has their own implementation for persisting data.

func EmptyKeyRing

func EmptyKeyRing() *KeyRing

EmptyKeyRing returns a pre-initialized, empty keyring.

func NewKeyRing

func NewKeyRing(name string, ttl int) *KeyRing

NewKeyRing returns a pre-initialized keyring.

func (*KeyRing) Add

func (s *KeyRing) Add(key *Key) error

Add inserts an existing key into the backend storage. This is useful if you first require modifying some of the key attributes or if you wish to copy a key from another key ring.

func (*KeyRing) AddComposite

func (s *KeyRing) AddComposite(key *CompositeKey) error

AddComposite inserts an existing composite key into the backend storage. This is useful if you first require modifying some of the key attributes or if you wish to copy a composite key from another key ring.

func (*KeyRing) AttachKey

func (s *KeyRing) AttachKey(key *Key)

AttachKey to this key ring.

func (*KeyRing) Create

func (s *KeyRing) Create(name string, length int) (*Key, error)

Create a key with the specified length. Create will not replace an existing key and will return ErrKeyExists if the key has already been created. If key generation fails, this will return ErrGeneratingKey.

func (*KeyRing) CreateComposite

func (s *KeyRing) CreateComposite(name string, cipherLength,
	hmacLength int) (*CompositeKey, error)

CreateComposite generates a composite key with the specified name, cipher length, and HMAC length.

Internally, the actual implementation creates multiple keys within this key ring using `name` as the key prefix. Client code can extract the same key data by calling Get separately for `name + "::cipher"` or `name + "::hmac"`. Multiple composite keys may exist in a key ring at any given time and rotating the key ring will rotate all associated composite keys.

func (*KeyRing) Get

func (s *KeyRing) Get(name string) (*Key, error)

Get retrieves a key from the storage backend or from the internal map. If you absolutely require reading the key from the storage backend, use Read() instead.

Be aware that Get() will always return keys from the local cache, if they exist, before falling back to calling Read(). Get() may return stales results.

func (*KeyRing) GetComposite

func (s *KeyRing) GetComposite(name string) (*CompositeKey, error)

GetComposite returns the composite key requested by `name`. As with CreateComposite, this simply retrieves standard keys that are part of a composite whole by prefixing them with `name`.

func (*KeyRing) GetOrCreate

func (s *KeyRing) GetOrCreate(name string, length int) (*Key, error)

GetOrCreate the specified key. If the key exists, it will be returned from the local cache or backend storage, in that order (this implementation calls Get() on the specified key first). Otherwise, if ErrNoSuchKey is returned, this will create a new key and return it.

Being as this function can also create keys instead of just reading them, you must specify the key length.

func (*KeyRing) GetOrCreateComposite

func (s *KeyRing) GetOrCreateComposite(name string, cipherLength,
	hmacLength int) (*CompositeKey, error)

GetOrCreateComposite will attempt to return or create the requested key. If the key exists, it will be loaded from the local cache or backend storage, in that order. Otherwise, if ErrNoSuchKey is returned, this will create a new key and return it.

func (*KeyRing) List

func (s *KeyRing) List() ([]*Key, error)

func (*KeyRing) Mapped

func (s *KeyRing) Mapped() (map[string]*Key, error)

Mapped keys associated with this key ring.

At present, this neither reads nor updates the internal cache.

TODO: Fix the above (add or read from cache).

func (*KeyRing) Read

func (s *KeyRing) Read(name string) (*Key, error)

Read the specified key from the storage backend. This will always return a key directly from whatever backend has been configured for this keyring and will bypass internal caches. For greater performance, use Get(). For a freshness guarantee, use this.

Read() always updates the internal cache with the latest copy of the key from backend storage.

func (*KeyRing) Remove

func (s *KeyRing) Remove(name string) error

Remove the specified key associated with this key ring.

func (*KeyRing) RemoveComposite

func (s *KeyRing) RemoveComposite(name string) error

RemoveComposite thereby deleting the underlying keys associated with the specified composite key. This is identical to calling Remove() on the strings `name+"::cipher"` and `name+"::hmac"`.

If this method fails, there is a possibility that the key storage will be left in an unknown state with potentially "dangling" composite keys where either the cipher or HMAC key may not be removed. In such a case, it may be necessary to manually remove the offending key using .Remove().

func (*KeyRing) Rotate

func (s *KeyRing) Rotate() error

Rotate all keys associated with this key ring.

TODO: Unit tests.

func (*KeyRing) Save

func (kr *KeyRing) Save() error

Save the new key ring's state. This will update any changed attributes and reconfigure the expiration monitoring for the updated state.

func (*KeyRing) SetBackend

func (s *KeyRing) SetBackend(backend NamespaceHandler) *KeyRing

SetBackend to the specified storage backend.

func (*KeyRing) SetSignal

func (s *KeyRing) SetSignal(signal *signals.Signal) *KeyRing

SetSignal to the specified signal, typically received from the KeySpace.

func (*KeyRing) Versions

func (s *KeyRing) Versions(name string) ([]*Key, error)

Versions returns a slice containing all key versions associated with the named key.

type KeyRingRotatedSignal

type KeyRingRotatedSignal func(*KeyRing)

KeyRingRotatedSignal is fired whenever the specified key ring is rotated. Currently, this affects all keys.

type Namespace

type Namespace struct {
	// Name of this namespace.
	Name string

	// Parent namespace.
	Parent *Namespace

	// Global namespace (applies globally as well as to accounts).
	Global bool

	// Account namespace (only applies to accounts; defines whether this is an
	// account global namespace or an account-only namespace).
	Account bool

	// Additional metadata to indicate whether this namespace is hashable or not.
	Hashable bool

	// TopLevel namespace. Other namespaces or key ring containers may appear under
	// here.
	TopLevel bool

	// Backend for key ring loading.
	Backend NamespaceHandler

	// Signal handler for event management.
	Signal *signals.Signal
	// contains filtered or unexported fields
}

Namespace instance container.

Namespaces provide a means of grouping together related key rings and their keys. For instance, creating a global namespace of "users" and then creating a key ring named for each account or account ID would be one way of isolating user-specific tokens.

Although namespaces can provide isolation from others to prevent name collisions, it is also possible to provide a look up chain of namespaces through which subsequent parent namespaces are checked until a match is either found or not. Look up specificity is from finer granularity to coarser, i.e.: account namespaces -> account global namespace -> global named namespaces -> global namespace.

func (*Namespace) AddKeyRing

func (n *Namespace) AddKeyRing(keyring *KeyRing) error

AddKeyRing adds an already existing key ring to the backend. If the key ring doesn't already exist, it will be created; if it does, it will be updated with new or changed attributes.

func (*Namespace) CreateKeyRing

func (n *Namespace) CreateKeyRing(name string, ttl int) (*KeyRing, error)

CreateKeyRing with the specified name and TTL.

func (*Namespace) Destroy

func (n *Namespace) Destroy() error

Destroy this namespace.

func (*Namespace) DestroyKeyRing

func (n *Namespace) DestroyKeyRing(name string) error

DestroyKeyRing destroys the key ring associated with this namespace.

func (*Namespace) GetKeyRing

func (n *Namespace) GetKeyRing(name string) (*KeyRing, error)

GetKeyRing returns the specified key ring from the current namespace. This is equivalent to .KeyRing(name, false).

func (*Namespace) GetOrCreateKeyRing

func (n *Namespace) GetOrCreateKeyRing(name string, ttl int) (*KeyRing, error)

GetOrCreateKeyRing as requested by name with the specified TTL. If the key ring exists in the current namespace (and only in the current namespace), it will be returned. Otherwise, the key ring will be created with its TTL set to the specified time-to-live.

func (*Namespace) IsDestroyed

func (n *Namespace) IsDestroyed() bool

IsDestroyed indicates whether or not the namespace has been destroyed.

At present, this is checked by the keyspace, and if this returns true, then a new namespace is returned. Unfortunately, this means that destroyed namespaces will remain in the map indefinitely (or until server restart).

The better solutions are to either move Destroy() to the KeySpace, obviating the need for this method, where it can be called and immediately remove the namespace in question. Or, with a bit more interdependencies on multiple objects, Namespace.Destroy() could instead instruct the KeySpace that it has been removed. The former option would probably make the most sense and wouldn't require the namespace to keep a pointer to its parent KeySpace, but both options will require some code rewrites across the board.

In the case of the former, all Namespace.Destroy() references would have to be rewritten to KeySpace.DestroyNamespace(name); in the latter, the KeySpace would need to be moved to types/api to avoid cyclic imports.

func (*Namespace) KeyRing

func (n *Namespace) KeyRing(name string, lookup bool) (*KeyRing, error)

KeyRing retrieves the named key ring from either the current namespace or any of its parents if lookup is true. Otherwise, only key rings associated with the current namespace are checked.

func (*Namespace) UpdateKeyRing

func (n *Namespace) UpdateKeyRing(keyring *KeyRing) error

UpdateKeyRing updates the specified key ring. Key ring must first be loaded using either .KeyRing() or .GetKeyRing().

type NamespaceHandler

type NamespaceHandler interface {
	// Init this NamespaceHandler instance with the provided namespace under path.
	Init(namespace *Namespace) error

	// AddKeyRing adds an already existing keyring to the backend, persisting it
	// to the implemented storage layer. If the key ring already exists on the
	// storage backend, it will be updated instead.
	AddKeyRing(keyring *KeyRing) error

	// CreateKeyRing generates a new, empty key ring that may be populated at a
	// later date with the specified TTL.
	CreateKeyRing(keyring string, ttl int) (*KeyRing, error)

	// AddKey adds a key to the specified key ring/key pair and persists it to
	// storage. If the key already exists on the storage backend, it will be
	// updated instead.
	AddKey(keyring string, name string, key *Key) error

	// GetKeyRing returns the specified key ring, binding it to this
	// NamespaceHandler's parent interface.
	GetKeyRing(keyring string) (*KeyRing, error)

	// GetKey returns the specified key associated with the requested key ring.
	GetKey(keyring string, name string) (*Key, error)

	// DestroyKeyRing destroys the specified key ring and all of its keys.
	DestroyKeyRing(keyring string) error

	// DestroyNamespace destroys the specified namespace and all of its key rings.
	DestroyNamespace(namespace string) error

	// RemoveKey removes the specified key from the requested key ring.
	RemoveKey(keyring string, name string) error

	// RotateKeyRing rotates all keys associated with the specified key ring,
	// replacing them with the contents of the second argument.
	RotateKeyRing(keyring string, keys map[string]*Key) error

	UpdateKeyRing(keyring *KeyRing) error

	// Keys returns all keys associated with the specified KeyRing.
	Keys(keyring string) (map[string]*Key, error)
}

NamespaceHandler handles interfacing with stored keyrings via the backend implementation, typically utilizing a storage intermediary. See AccountHandler for a somewhat more detailed discussion.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL