auth

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2023 License: BSD-3-Clause Imports: 14 Imported by: 1

Documentation

Overview

Package auth enables an Ensign client to authenticate with Ensign's Authn and Authz service called Quarterdeck. Every Ensign RPC must include access tokens with the ProjectID and permissions assigned to the API key; the access tokens are signed by Quarterdeck's private keys which can be verified on an Ensign server using Quarterdeck's public keys. If the RPC credentials have incorrect permissions or attempt to access a resource that does not belong to the project then a gRPC Unauthorized error is returned.

Note: API Keys have access to all the topics in the specified project with the permissions assigned to the key; you cannot limit topics other than by creating new projects.

This package provides a Client that wraps APIKeys and makes requests to Quarterdeck in order to authenticate and refresh Ensign credentials. The client is intended to be used by the Ensign client to maintain an authenticated connection to Ensign for long-running processes (e.g. publishers and subscribers) and will make requests to Quarterdeck in an on-demand fashion to maintain authentication without logging out. The Ensign SDK must ensure that it requests credentials for every RPC call that it makes.

Index

Constants

View Source
const (
	AuthenticateEP = "/v1/authenticate"
	RefreshEP      = "/v1/refresh"
	StatusEP       = "/v1/status"
)

Variables

View Source
var (
	ErrIncompleteCreds = errors.New("both client id and secret are required")
	ErrNoAPIKeys       = errors.New("no api keys available: must login the client first")
)

Functions

func ExpiresAt added in v0.6.0

func ExpiresAt(tks string) (_ time.Time, err error)

func NotBefore added in v0.6.0

func NotBefore(tks string) (_ time.Time, err error)

func Parse added in v0.6.0

func Parse(tks string) (claims *jwt.RegisteredClaims, err error)

func PerRPCToken

func PerRPCToken(accessToken string, insecure bool) grpc.CallOption

PerRPCToken returns a CallOption to attach access tokens to a single RPC call. Because access tokens expire and need to be refreshed; this is the preferred way of attaching credentials to an RPC call.

func WithPerRPCToken

func WithPerRPCToken(accessToken string, insecure bool) grpc.DialOption

WithPerRPCToken returns a DialOption to ensure that the credentials are attached to every RPC call but only have to be specified once by the dialer. The issue with using this method is that access tokens expire; so unless you're expecting your Ensign session to be shorter than the access token duration (about an hour), then using the PerRPCToken CallOption is usually a better choice.

Types

type APIKey

type APIKey struct {
	ClientID     string `json:"client_id"`
	ClientSecret string `json:"client_secret"`
}

APIKey wraps per-project Ensign credentials and can be stored as JSON on disk. This struct is also used to POST JSON requests to the Quarterdeck service.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client connects to the Quarterdeck authentication service in order to authenticate API Keys and to refresh access tokens for Ensign access. The Client maintains the API Keys and tokens so that it can hand out credentials in long running processes, ensuring that the Ensign client can stay logged into Ensign for as long as possible.

func New

func New(authURL string, insecure bool) (client *Client, err error)

Create a new authentication client to connect to Quarterdeck. The authURL should be the endpoint of the Quarterdeck service and must be a parseable URL. The insecure flag tells the client to create Ensign credentials that are insecure; e.g. not requiring a TLS connection. The insecure flag should only be true in development. After creating a Quarterdeck client, ensure to call Login() to prepare it to hand out credentials to connect to Ensign.

func (*Client) Authenticate

func (c *Client) Authenticate(ctx context.Context, apikey *APIKey) (tokens *Tokens, err error)

Authenticate makes a request to the Quarterdeck server with the available API keys in order to fetch new access and refresh tokens. The tokens are returned directly.

func (*Client) Credentials added in v0.6.0

func (c *Client) Credentials(ctx context.Context) (_ credentials.PerRPCCredentials, err error)

Credentials returns the PerRPC credentials to make a gRPC request. If the tokens are expired, this method will refresh them by making a request to Quarterdeck. An error is returned if the client is not logged in. This method should be called before every Ensign RPC in order to ensure the RPC has valid credentials.

func (*Client) Login

func (c *Client) Login(ctx context.Context, clientID, clientSecret string) (creds credentials.PerRPCCredentials, err error)

Login to Quarterdeck, storing the API credentials on the client and making a login request to Quarterdeck to fetch access and refresh tokens. Ensure that a context with a deadline is specified in order to reduce how long the client attempts to login for. Once logged in, the authentication client can hand out credentials on demand. Credentials are returned from this method in case users want to add the credentials as a DialOption; however this is only good for short duration process (e.g. processes that will stop before the access token expires). Long running processes should use the UnaryInterceptor and StreamInterceptor methods or call Credentials to get a PerRPCCredentials CallOption to add to every RPC call.

func (*Client) Refresh

func (c *Client) Refresh(ctx context.Context, refresh *Tokens) (tokens *Tokens, err error)

Refresh makes a request to the Quarterdeck server with the refresh token in order to fetch a new access token. If the refresh token is expired an error is returned. The new tokens are returned directly.

func (*Client) Reset added in v0.6.0

func (c *Client) Reset()

Reset removes the apikeys and tokens from the client (used for testing).

func (*Client) SetAPIKey added in v0.6.0

func (c *Client) SetAPIKey(key *APIKey)

SetAPIKey allows the test suite to set the apikey on the client.

func (*Client) SetTokens added in v0.6.0

func (c *Client) SetTokens(tokens *Tokens)

SetTokens allows the test suite to set the tokens on the client.

func (*Client) Status added in v0.6.0

func (c *Client) Status(ctx context.Context) (status *Status, err error)

Status makes a request to the Quarterdeck server to check if the service is online and ready to make requests. The status check is returned directly.

func (*Client) StreamAuthenticate added in v0.6.0

func (c *Client) StreamAuthenticate(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (_ grpc.ClientStream, err error)

An interceptor that adds credentials to every streaming request made by the gRPC client.

func (*Client) UnaryAuthenticate added in v0.6.0

func (c *Client) UnaryAuthenticate(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) (err error)

An interceptor that adds credentials on every unary request made by the gRPC client.

func (*Client) WaitForReady added in v0.6.0

func (c *Client) WaitForReady(ctx context.Context) (err error)

Wait for ready polls the Quarterdeck status endpoint until it responds with a 200, retrying with exponential backoff or until the context deadline is expired. If the input context does not have a deadline, then a default deadline of 5 minutes is used so this method does not block indefinitely. When the Quarterdeck service is ready then no error is returned; if the Quartdeck does not respond within the retry window an error is returned.

type Credentials

type Credentials struct {
	// contains filtered or unexported fields
}

Credentials implement the credentials.PerRPCCredentials interface so that the access token can be embedded in the metadata of each RPC call for authentication and authorization. The credentials wrap an access token and whether or not the credentials can be used in insecure mode. Insecure should almost always be false; the only exception is when doing local development with an Ensign service running in docker compose or in CI tests. For staging and production, insecure should be false.

func (*Credentials) Equals added in v0.6.0

func (t *Credentials) Equals(o *Credentials) bool

Equals compares credentials (primarily used for testing).

func (*Credentials) GetRequestMetadata

func (t *Credentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)

GetRequestMetadata attaches the bearer access token to the authorization header.

func (*Credentials) RequireTransportSecurity

func (t *Credentials) RequireTransportSecurity() bool

RequireTransportSecurity should almost always return true unless accessing a local Ensign server in development or CI environments.

type Reply

type Reply struct {
	Success bool   `json:"success"`
	Error   string `json:"error,omitempty"`
}

Reply contains standard fields that are used for generic API responses and errors.

type Status added in v0.6.0

type Status struct {
	Status  string `json:"status"`
	Uptime  string `json:"uptime,omitempty"`
	Version string `json:"version,omitempty"`
}

Status describes the current state of the Quarterdeck service. This struct is used to GET JSON requests from the Quarterdeck service.

type StatusError

type StatusError struct {
	StatusCode int
	Reply      Reply
}

StatusError decodes an error response from Quarterdeck.

func (*StatusError) Error

func (e *StatusError) Error() string

type Tokens

type Tokens struct {
	AccessToken  string `json:"access_token,omitempty"`
	RefreshToken string `json:"refresh_token,omitempty"`
	LastLogin    string `json:"last_login,omitempty"`
	// contains filtered or unexported fields
}

Tokens are handed out by Quarterdeck to login to the Ensign service. The AccessToken is used to create gRPC per-RPC credentials and the refresh token is used to fetch a new access token when it expires. Tokens can be cached as JSON on disk. This struct is also used to GET/POST JSON requests from/to the Quarterdeck service.

func (*Tokens) AccessValid added in v0.6.0

func (t *Tokens) AccessValid() (valid bool, err error)

AccessValid returns true if the access token has not expired

func (*Tokens) RefreshValid added in v0.6.0

func (t *Tokens) RefreshValid() (valid bool, err error)

RefreshValid returns true if the refresh token has not expired and it is after the not before time when the token cannot yet be used.

Directories

Path Synopsis
Package authtest provides some simple JWT token testing functionality for use in Ensign SDK tests.
Package authtest provides some simple JWT token testing functionality for use in Ensign SDK tests.

Jump to

Keyboard shortcuts

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