Documentation ¶
Overview ¶
Package key provides a simple API for loading public and private keys from resources.
Index ¶
Constants ¶
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" )
Variables ¶
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") )
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, ) )
Functions ¶
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 ¶
MockCache is a stretchr mock for Cache. It's exposed for other package tests.
func (*MockCache) ResolveKey ¶
type MockPair ¶
MockPair is a stretchr mock for Pair. It's exposed for other package tests.
func (*MockPair) HasPrivate ¶
type MockParser ¶
type MockResolver ¶
MockResolver is a stretchr mock for Resolver. It's exposed for other package tests.
func (*MockResolver) ResolveKey ¶
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 (Purpose) RequiresPrivateKey ¶
RequiresPrivateKey returns true if this purpose requires a private key, false if it requires a public key.
func (Purpose) String ¶
String returns a human-readable, string representation for a Purpose. Unrecognized purpose values are assumed to be PurposeVerify.
func (*Purpose) UnmarshalJSON ¶
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 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.