Documentation
¶
Overview ¶
Package provider defines what a provider adapter implements: a declarative Manifest, validation with account discovery, and authentication of outgoing requests. It also holds the Registry a host fills at startup.
Index ¶
- Constants
- Variables
- func Classify(providerKey string, resp *http.Response) error
- func EncodeMaterial(m Material) ([]byte, error)
- func NewTokenClient(ts TokenSource, m Material, hc *http.Client, clock cf.Clock) *http.Client
- func NewTokenTransport(ts TokenSource, m Material, hc *http.Client, next http.RoundTripper, ...) http.RoundTripper
- type AccessToken
- type AuthMethod
- type Field
- type Manifest
- type Material
- type Provider
- type Registry
- type Result
- type RotationMode
- type Scope
- type SetupStep
- type StatusError
- type TokenSource
Constants ¶
const ( // RotationManual means a person replaces the credential, for example // before it expires. RotationManual = "manual" // RotationAutomatic means the host replaces the credential on a // schedule, which usually needs more permission at the service. RotationAutomatic = "automatic" )
Rotation mode keys a host may act on. A provider may describe others; a host that does not know a mode does not offer it.
const TokenExpiryMargin = time.Minute
TokenExpiryMargin is how long before a token expires it is replaced, so a request that starts with a kept token does not finish with an expired one.
Variables ¶
var ErrBadMaterial = errors.New("provider: not credential material")
ErrBadMaterial is returned for plaintext that is not encoded material.
var ErrTokenSourceOnly = errors.New("provider: credential is used through a token source")
ErrTokenSourceOnly is returned by a provider's Authenticate when its credential is used through a TokenSource.
var ErrUnknownProvider = errors.New("provider: unknown provider")
ErrUnknownProvider is returned for a provider key that is not registered.
Functions ¶
func Classify ¶
Classify returns nil for a 2xx response and a *StatusError otherwise: 401 is an invalid credential, 403 an insufficient scope, 429 rate limiting, 5xx transient, and any other status an invalid credential.
func EncodeMaterial ¶
EncodeMaterial returns the plaintext to seal. The caller seals it and clears it.
func NewTokenClient ¶ added in v0.5.0
NewTokenClient returns a copy of hc whose requests carry a token from ts. A provider uses it in Validate to call its service with the credential.
func NewTokenTransport ¶ added in v0.5.0
func NewTokenTransport(ts TokenSource, m Material, hc *http.Client, next http.RoundTripper, clock cf.Clock) http.RoundTripper
NewTokenTransport returns a RoundTripper that authenticates each request, on a copy of it, with a token from ts, and keeps the token until TokenExpiryMargin before it expires. Concurrent requests share one exchange. hc makes the exchange and next carries the requests; both must be restricted to the provider's hosts. A failed exchange is returned and not kept, so the next request tries again. clock may be nil.
Types ¶
type AccessToken ¶ added in v0.5.0
type AccessToken struct {
// Type is the authorization scheme; "Bearer" when empty.
Type string
Value cf.Secret
// ExpiresAt is when the token stops working. A zero value means the
// source does not say, and the token is used once and not kept.
ExpiresAt time.Time
}
AccessToken is a short-lived credential minted from a stored one.
type AuthMethod ¶
type AuthMethod struct {
// Key identifies the method, for example "api_token".
Key string `json:"key"`
Fields []Field `json:"fields"`
Scopes []Scope `json:"scopes,omitempty"`
// AccountSelection says how the account is chosen: "discovered" from the
// credential, or "chosen" by the person from a list.
AccountSelection string `json:"accountSelection,omitempty"`
HelpURL string `json:"helpUrl,omitempty"`
// Setup is what a person does, in order, to create the credential at
// the service before entering it.
Setup []SetupStep `json:"setup,omitempty"`
// Rotation lists the ways the credential can be replaced over its life,
// with what each needs. Empty means the method does not describe
// rotation; a person replaces the credential by reconnecting.
Rotation []RotationMode `json:"rotation,omitempty"`
}
AuthMethod is one way to connect to a provider.
func (AuthMethod) RotationMode ¶ added in v0.4.0
func (a AuthMethod) RotationMode(key string) (RotationMode, bool)
RotationMode returns the method's rotation mode with key.
type Field ¶
type Field struct {
Name string `json:"name"`
Label string `json:"label"`
Secret bool `json:"secret"`
Required bool `json:"required"`
Help string `json:"help,omitempty"`
}
Field is an input a method needs.
type Manifest ¶
type Manifest struct {
// Key identifies the provider, for example "cloudflare".
Key string `json:"key"`
DisplayName string `json:"displayName"`
// BaseURLs are the only origins a request for this provider may reach.
BaseURLs []string `json:"baseUrls"`
AuthMethods []AuthMethod `json:"authMethods"`
HelpURL string `json:"helpUrl,omitempty"`
}
Manifest describes a provider so a user interface can render a connection form and an agent can read what a connection needs. It contains no code.
type Material ¶
type Material struct {
// Kind names the structure, for example "api_token".
Kind string
// Fields holds the credential's values by field name.
Fields map[string]cf.Secret
// ExpiresAt is when an access token expires, if it does.
ExpiresAt *time.Time
}
Material is a credential's plaintext, as a provider adapter sees it. It exists only between unsealing and use; every value is a cf.Secret.
func DecodeMaterial ¶
DecodeMaterial parses unsealed plaintext and clears it.
type Provider ¶
type Provider interface {
// Manifest describes the provider. It is data and never changes.
Manifest() Manifest
// Validate checks the credential with the provider, using hc, which the
// caller has restricted to the manifest's hosts, and returns the account
// it belongs to. A rejection wraps a connectforge provider error.
Validate(ctx context.Context, hc *http.Client, m Material) (Result, error)
// Authenticate adds the credential to an outgoing request. The request
// is the caller's copy.
Authenticate(r *http.Request, m Material) error
}
Provider is an adapter for one external service.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds the providers a host supports. It is safe for concurrent use.
type Result ¶
type Result struct {
AccountID string
AccountLabel string
// Scopes are the permissions the provider reports for the credential,
// if it reports them.
Scopes []string
// ExpiresAt is when the credential stops working, if the provider
// reports it; nil when it does not expire or the provider does not say.
ExpiresAt *time.Time
}
Result is what validation discovered.
type RotationMode ¶ added in v0.4.0
type RotationMode struct {
Key string `json:"key"`
Label string `json:"label"`
Description string `json:"description,omitempty"`
// Scopes are the permissions the credential needs in this mode in
// addition to the method's.
Scopes []Scope `json:"scopes,omitempty"`
// Risks say what those extra permissions also allow, so a person can
// weigh the mode before choosing it.
Risks []string `json:"risks,omitempty"`
// ExpiryDays is the lifetime to give the credential when creating it,
// for services that support one; 0 means no expiry.
ExpiryDays int `json:"expiryDays,omitempty"`
// Recommended marks the mode to offer first. At most one mode is.
Recommended bool `json:"recommended,omitempty"`
}
RotationMode is one way a credential is replaced over its life.
type Scope ¶
type Scope struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Required bool `json:"required,omitempty"`
}
Scope is a permission a method asks for or expects.
type SetupStep ¶ added in v0.4.0
type SetupStep struct {
Title string `json:"title"`
// Detail explains the step in plain text.
Detail string `json:"detail,omitempty"`
// URL opens the page at the service where the step is done.
URL string `json:"url,omitempty"`
// Rotation limits the step to these rotation mode keys; empty means
// every mode.
Rotation []string `json:"rotation,omitempty"`
}
SetupStep is one step of creating a credential at the service.
type StatusError ¶
StatusError is a provider's refusal, classified. It carries the status and the provider's request ID, never a body.
func (*StatusError) Error ¶
func (e *StatusError) Error() string
func (*StatusError) Unwrap ¶
func (e *StatusError) Unwrap() error
Unwrap returns the class, so errors.Is works with connectforge's errors.
type TokenSource ¶ added in v0.5.0
type TokenSource interface {
// Token exchanges the credential for an access token. hc is restricted to
// the manifest's hosts, so the manifest must list the token endpoint's
// origin as well as the service's. A rejection wraps a connectforge
// provider error; an error never contains the credential.
Token(ctx context.Context, hc *http.Client, m Material) (AccessToken, error)
}
TokenSource is an optional capability for a provider whose stored credential is not sent on requests but exchanged for a short-lived access token, such as a service account key signed into a token request.
The broker detects it by type assertion. It mints a token with Token, keeps it until shortly before it expires, and sends it on each request instead of calling Authenticate, which such a provider may leave unsupported. A token is derived from the stored credential and never stored, so a refresh needs no lease and nothing is persisted, unlike a refresh token that the service rotates and the host must store.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package apikey is a provider for services that issue a static API key or token, driven by configuration: where the token goes in a request, which endpoint verifies it, and where the account is in the response.
|
Package apikey is a provider for services that issue a static API key or token, driven by configuration: where the token goes in a request, which endpoint verifies it, and where the account is in the response. |