Using a connection¶
The broker is the only path from a stored credential to an outgoing request. You ask it for an HTTP client for a connection; it checks that you may, unseals the credential, and returns a client that authenticates each request.
Get a client¶
hc, err := b.HTTPClient(ctx, owner, principal, connectionID, cf.Use{
Consumer: cf.Consumer{Kind: "application", ID: "dashboards"},
Purpose: "traffic",
})
The broker, in order:
- Loads the connection for the owner. Another owner's connection is not found.
- Asks the
Authorizerwhether the principal may use it, and records a refusal as an audit event. - Requires the state to be
connected; otherwiseErrNotUsable. - Reads and decrypts the active credential. Any failure is
ErrCredentialUnavailable. - Returns a client restricted to the provider's hosts.
Use says why: a consumer (an application, workflow or agent) and a purpose.
It is passed to your OnUse hook, if you set one, for counters. An agent
acting for someone sets OnBehalfOf, which is recorded with any refusal.
What the client does¶
- Adds the credential to a copy of each request. The request you built is not modified.
- Reaches only the provider's hosts. A request for any other host fails
with
egress.ErrRefused, as does a redirect to another host, plain HTTP, and a name that resolves to a private, loopback or link-local address. - Holds the credential it was made with. A disconnect or a replaced credential applies to the next client, so make a client per unit of work rather than keeping one for the life of the process.
Hand it to an SDK¶
Most provider SDKs accept an *http.Client. Give them the broker's, and they
authenticate and stay inside the allowed hosts without ever seeing the token:
hc, err := b.HTTPClient(ctx, owner, principal, id, use)
if err != nil {
return err
}
client, err := someprovider.NewClient(someprovider.WithHTTPClient(hc))
If an SDK insists on a token argument, pass any non-empty placeholder: the
broker's transport replaces the Authorization header, or sets the header the
provider's manifest names.
Check before you rely on it¶
A connection can stop working between requests. Call Test when a feature
starts and on a schedule, and show the person Health.LastError when a check
fails. For a feature that cannot proceed, return a message that tells the
person to reconnect, not a raw error.
Dependencies are visible¶
Record a binding when a feature starts depending on a connection, so a disconnect can show what would stop working:
err := svc.Bind(ctx, owner, actor, id,
cf.Consumer{Kind: "application", ID: "dashboards"}, "traffic")
Bindings are idempotent, and deleting a connection removes them. Through
the service, Bind and Unbind require use, so whoever may use a
connection may say that a feature depends on it, and Bindings lists them for
anyone who may view it. Show that list before a disconnect:
bs, err := svc.Bindings(ctx, owner, actor, id)
// "Disconnecting stops: portfolio.site impactchiefs.com (traffic)"
A reconnect leaves bindings untouched.