key

package
v0.10.2 Latest Latest
Warning

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

Go to latest
Published: Jul 28, 2021 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package key provides a simple API for loading public and private keys from resources.

Index

Constants

View Source
const (
	// KeyIdParameterName is the template parameter that must be present in URI templates
	// if there are any parameters.  URI templates accepted by this package have either no parameters
	// or exactly one (1) parameter with this name.
	KeyIdParameterName = "keyId"

	DefaultKeysUpdateInterval = 24 * time.Hour
)

Variables

View Source
var (
	ErrorPEMRequired                 = errors.New("Keys must be PEM-encoded")
	ErrorUnsupportedPrivateKeyFormat = errors.New("Private keys must be in PKCS1 or PKCS8 format")
	ErrorNotRSAPrivateKey            = errors.New("Only RSA private keys are supported")
	ErrorNotRSAPublicKey             = errors.New("Only RSA public keys or certificates are suppored")
)
View Source
var (
	// ErrorInvalidTemplate is the error returned when a URI template is invalid for a key resource
	ErrorInvalidTemplate = fmt.Errorf(
		"Key resource template must support either no parameters are the %s parameter",
		KeyIdParameterName,
	)

	ErrNoResolverFactory = errors.New("no resolver factory configuration found")
)

Functions

func ExampleSingleKeyConfiguration added in v0.10.0

func ExampleSingleKeyConfiguration()

func ExampleURITemplateConfiguration added in v0.10.0

func ExampleURITemplateConfiguration()

func ProvideResolver added in v0.10.0

func ProvideResolver(key string, optional bool) fx.Option

func WithUpdate

func WithUpdate(o UpdateOptions) (context.Context, func())

WithUpdate (conditionally) spawns a goroutine and returns the child context and cancelation the updater runs within. This also follows the pattern of context.WithCancel, context.WithTimeout, etc.

Types

type Cache

type Cache interface {
	Resolver

	// UpdateKeys updates all keys known to this cache.  This method makes
	// a best-effort to avoid blocking other goroutines which use ResolveKey,
	// which may mean copy-on-write semantics.
	//
	// The first return value is the count of keys for which attempts were
	// made to update.
	//
	// UpdateKeys may run multiple I/O operations.  The second return value is a slice of
	// errors that occurred while it attempted to update each key.  Exactly one (1)
	// attempt will be made to update each key present in the cache, regardless
	// of any update errors for each individual key.  This slice may be nil if no
	// errors occurred.
	UpdateKeys(ctx context.Context) (int, []error)
}

Cache is a Resolver type which provides caching for keys based on keyID.

All implementations will block the first time a particular key is accessed and will initialize the value for that key. Thereafter, all updates happen in a separate goroutine. This allows HTTP transactions to avoid paying the cost of loading a key after the initial fetch.

type MockCache

type MockCache struct {
	mock.Mock
}

MockCache is a stretchr mock for Cache. It's exposed for other package tests.

func (*MockCache) ResolveKey

func (cache *MockCache) ResolveKey(ctx context.Context, keyId string) (Pair, error)

func (*MockCache) UpdateKeys

func (cache *MockCache) UpdateKeys(ctx context.Context) (int, []error)

type MockPair

type MockPair struct {
	mock.Mock
}

MockPair is a stretchr mock for Pair. It's exposed for other package tests.

func (*MockPair) HasPrivate

func (pair *MockPair) HasPrivate() bool

func (*MockPair) Private

func (pair *MockPair) Private() interface{}

func (*MockPair) Public

func (pair *MockPair) Public() interface{}

func (*MockPair) Purpose

func (pair *MockPair) Purpose() Purpose

type MockParser

type MockParser struct {
	mock.Mock
}

func (*MockParser) ParseKey

func (parser *MockParser) ParseKey(ctx context.Context, purpose Purpose, data []byte) (Pair, error)

type MockResolver

type MockResolver struct {
	mock.Mock
}

MockResolver is a stretchr mock for Resolver. It's exposed for other package tests.

func (*MockResolver) ResolveKey

func (resolver *MockResolver) ResolveKey(ctx context.Context, keyId string) (Pair, error)

type Pair

type Pair interface {
	// Purpose returns the configured intended usage of this key pair
	Purpose() Purpose

	// Public returns the public key associated with this pair.  It will never be nil
	Public() interface{}

	// HasPrivate tests whether this key Pair has a private key
	HasPrivate() bool

	// Private returns the optional private key associated with this Pair.  If there
	// is no private key, this method returns nil.
	Private() interface{}
}

Pair represents a resolved key pair. For all Pair instances, the private key is optional, while the public key will always be present.

type Parser

type Parser interface {
	// Parse examines data to produce a Pair.  If the returned error is not nil,
	// the Pair will always be nil.  This method is responsible for dealing with
	// any required decoding, such as PEM or DER.
	ParseKey(context.Context, Purpose, []byte) (Pair, error)
}

Parser parses a chunk of bytes into a Pair. Parser implementations must always be safe for concurrent access.

var DefaultParser Parser = defaultParser{}

DefaultParser is the global, singleton default parser. All keys submitted to this parser must be PEM-encoded.

type Purpose

type Purpose int

Purpose is an enumerated type describing the reason a given key is being used. This type implements Parser.

All Purpose values assume PEM-encoded keys. For other formats, a custom Parser decorator can be used. Purpose.RequiresPrivateKey() determines whether to parse the key as a private key.

const (
	// PurposeVerify refers to a key used to verify a signature.  This is the zero-value
	// for Purpose.  These keys must be public keys encoded as PEM blocks.
	PurposeVerify Purpose = Purpose(iota)

	// PurposeSign refers to a key used to create a signature.  These keys must be private,
	// PEM-encoded keys.
	PurposeSign

	// PurposeEncrypt refers to a key used to encrypt data.  These keys must be private,
	// PEM-encoded keys.
	PurposeEncrypt

	// PurposeDecrypt refers to a key used to decrypt data.  These keys must be public,
	// PEM-encoded keys.
	PurposeDecrypt
)

func (Purpose) MarshalJSON

func (p Purpose) MarshalJSON() ([]byte, error)

func (Purpose) RequiresPrivateKey

func (p Purpose) RequiresPrivateKey() bool

RequiresPrivateKey returns true if this purpose requires a private key, false if it requires a public key.

func (Purpose) String

func (p Purpose) String() string

String returns a human-readable, string representation for a Purpose. Unrecognized purpose values are assumed to be PurposeVerify.

func (*Purpose) UnmarshalJSON

func (p *Purpose) UnmarshalJSON(data []byte) error

type Resolver

type Resolver interface {
	// ResolveKey returns a key Pair associated with the given identifier.  The exact mechanics of resolving
	// a keyId into a Pair are implementation-specific.  Implementations are free
	// to ignore the keyId parameter altogether.
	ResolveKey(ctx context.Context, keyId string) (Pair, error)
}

Resolver loads and parses keys associated with key identifiers.

type ResolverFactory

type ResolverFactory struct {
	resource.Factory

	// All keys resolved by this factory will have this purpose, which affects
	// how keys are parsed.
	Purpose Purpose `json:"purpose"`

	// UpdateInterval specifies how often keys should be refreshed.
	// If negative or zero, keys are never refreshed and are cached forever.
	UpdateInterval time.Duration `json:"updateInterval"`

	// Parser is a custom key parser.  If omitted, DefaultParser is used.
	Parser Parser `json:"-"`
}

ResolverFactory provides a JSON representation of a collection of keys together with a factory interface for creating distinct Resolver instances.

This factory uses resource.NewExpander() to create a resource template used in resolving keys. This template can have no parameters, in which case the same resource is used regardless of the key id. If the template has any parameters, it must have exactly (1) parameter and that parameter's name must be equal to KeyIdParameterName.

func (*ResolverFactory) NewResolver

func (factory *ResolverFactory) NewResolver() (Resolver, error)

NewResolver() creates a Resolver using this factory's configuration. The returned Resolver always caches keys forever once they have been loaded.

type ResolverFactoryIn added in v0.10.0

type ResolverFactoryIn struct {
	fx.In
	R *ResolverFactory `name:"key_resolver_factory"`
}

type UpdateOptions

type UpdateOptions struct {
	// Ctx is the required context.  If the caller doesn't have a context, she should
	// use context.Background() here explicitly.  Not permitting nil here is a common pattern,
	// and makes client code self-documenting.
	Ctx context.Context

	// Resolver is the required key resolver that optionally implements Cache.  If this member
	// does not implement cache, no updating is done.
	Resolver Resolver

	// OpTimeout is the amount of time to wait before timing out an UpdateKeys() operation.  If
	// this is 0, then there is no timeout.
	OpTimeout time.Duration

	// Interval is the options time interval for updating.  If unset, no update should occur.
	// This allows client code to turn off updates via configuration without having to do a lot
	// of branching.
	Interval time.Duration

	// NewTicker is the factory function for a ticker.  If nil, the default is used.
	// Injecting a closure here makes testing easier, as unit tests can simply supply
	// their own factory function.
	NewTicker func(time.Duration) (<-chan time.Time, func())
}

UpdateOptions cleans up the signature of WithUpdate. When you have a lot of function parameters, it starts getting hard to read.

Jump to

Keyboard shortcuts

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