auth

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package auth implements VORTEX's authentication and authorization (build plan M3.5): a role-based access-control model (org → team → user), API-key issuance and verification, OIDC/SSO login, and the HTTP middleware that ties them together to protect the management API.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotFound is returned when no stored key matches a presented secret.
	ErrNotFound = errors.New("auth: api key not found")
	// ErrExpired is returned when a matching key has passed its ExpiresAt.
	ErrExpired = errors.New("auth: api key expired")
)

API-key store errors.

Functions

func NewAuthMiddleware

func NewAuthMiddleware(keys *APIKeyStore, oidc *OIDCProvider, rbac *RBAC) func(http.Handler) http.Handler

NewAuthMiddleware builds the management-API authentication+authorization middleware. Authentication is attempted in this order:

  1. Authorization: Bearer <token> — verified as an OIDC token (if oidc is configured), otherwise as an API-key secret.
  2. X-API-Key: <secret> — verified as an API-key secret.

A request with no usable credential gets 401. Once authenticated, if the route declares a required role (SetRequiredRole) the user must hold it via rbac.Can(..manage..); otherwise any authenticated user passes. An authz failure gets 403.

func SetRequiredRole

func SetRequiredRole(ctx context.Context, role Role) context.Context

SetRequiredRole returns a copy of ctx carrying the role required to access the current route. When unset, any authenticated user is allowed.

func WithUser

func WithUser(ctx context.Context, u User) context.Context

WithUser returns a copy of ctx carrying the authenticated user.

Types

type APIKey

type APIKey struct {
	ID          string    `json:"id"`   // public identifier (16 hex chars)
	Hash        string    `json:"hash"` // bcrypt hash of the secret
	UserID      string    `json:"user_id"`
	OrgID       string    `json:"org_id"`
	Roles       []Role    `json:"roles"`
	CreatedAt   time.Time `json:"created_at"`
	ExpiresAt   time.Time `json:"expires_at"` // zero = never expires
	Description string    `json:"description"`
}

APIKey is an issued credential. The plaintext secret is never stored; only its bcrypt hash is kept, so a leaked store cannot be used to authenticate.

type APIKeyStore

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

APIKeyStore holds issued API keys in memory, with optional JSON persistence. It is safe for concurrent use. When a persistence path has been set (SetPath), Issue and Revoke flush to disk immediately so an unclean exit does not lose keys issued since boot (production audit M3).

func NewAPIKeyStore

func NewAPIKeyStore() *APIKeyStore

NewAPIKeyStore returns an empty store.

func (*APIKeyStore) Issue

func (s *APIKeyStore) Issue(userID, orgID string, roles []Role, desc string, ttl time.Duration) (APIKey, string, error)

Issue creates a new API key for userID/orgID with the given roles. It returns the stored APIKey (hash only) and the plaintext secret, which is shown to the caller exactly once and never persisted. ttl=0 means the key never expires.

func (*APIKeyStore) List

func (s *APIKeyStore) List(orgID string) []APIKey

List returns all keys for orgID with their hashes redacted (the public view).

func (*APIKeyStore) Load

func (s *APIKeyStore) Load(path string) error

Load replaces the store's contents with the keys in the JSON file at path. A missing file is treated as an empty store (not an error).

func (*APIKeyStore) Revoke

func (s *APIKeyStore) Revoke(id string) error

Revoke removes the key with the given ID. It is idempotent. When a persistence path is set the change is flushed to disk immediately.

func (*APIKeyStore) Save

func (s *APIKeyStore) Save(path string) error

Save persists the store to path as JSON (hashes only, never secrets).

func (*APIKeyStore) SetPath added in v0.3.0

func (s *APIKeyStore) SetPath(path string)

SetPath enables immediate persistence to path: subsequent Issue/Revoke calls flush the whole store atomically. It does not itself write the file.

func (*APIKeyStore) Verify

func (s *APIKeyStore) Verify(secret string) (APIKey, error)

Verify checks a presented secret and returns the matching key. The secret carries its key ID as a prefix ("<id>.<random>"), so verification is a single bcrypt comparison against that key. It returns ErrNotFound when no key matches and ErrExpired when the matching key has expired.

type Action

type Action string

Action is an operation a role may be permitted to perform on a resource.

const (
	ActionRead   Action = "read"
	ActionWrite  Action = "write"
	ActionDeploy Action = "deploy"
	ActionManage Action = "manage"
)

Actions.

type OIDCConfig

type OIDCConfig struct {
	ProviderURL  string   // issuer URL, e.g. https://accounts.google.com
	ClientID     string   // OAuth2 client ID
	ClientSecret string   // OAuth2 client secret
	RedirectURL  string   // callback URL registered with the provider
	Scopes       []string // requested scopes; defaults to openid, email, profile
}

OIDCConfig configures the OIDC/SSO login flow.

type OIDCProvider

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

OIDCProvider wraps an OIDC issuer: the discovered provider, an ID-token verifier, and the OAuth2 config used to build auth URLs and exchange codes.

func NewOIDCProvider

func NewOIDCProvider(ctx context.Context, cfg OIDCConfig) (*OIDCProvider, error)

NewOIDCProvider discovers the issuer's endpoints from cfg.ProviderURL and builds a provider ready to issue auth URLs, exchange codes, and verify tokens. It returns an error if discovery fails.

func (*OIDCProvider) AuthCodeURL

func (p *OIDCProvider) AuthCodeURL(state string) string

AuthCodeURL returns the provider's authorization URL for the given state, which the client redirects the user to in order to log in.

func (*OIDCProvider) Exchange

func (p *OIDCProvider) Exchange(ctx context.Context, code string) (User, error)

Exchange exchanges an authorization code for tokens, verifies the ID token, and maps its claims onto a User. New SSO users get the viewer role by default.

func (*OIDCProvider) Middleware

func (p *OIDCProvider) Middleware() func(http.Handler) http.Handler

Middleware authenticates requests by verifying a bearer ID token against the OIDC provider and storing the resulting User in the request context. Requests without a valid token receive 401.

type Permission

type Permission struct {
	Role      Role
	Actions   []Action
	Resources []Resource
}

Permission defines what a role may do: the set of actions it can perform on the set of resources.

type RBAC

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

RBAC holds role definitions and answers authorization questions. It is safe for concurrent use.

func NewRBAC

func NewRBAC() *RBAC

NewRBAC returns an RBAC seeded with the built-in role definitions:

admin    — every action on every resource
operator — read+write+deploy on routes, config, nodes
viewer   — read on every resource
readonly — read on routes and config only

func (*RBAC) AddRole

func (r *RBAC) AddRole(name Role, perms Permission) error

AddRole adds or replaces a role definition.

func (*RBAC) Can

func (r *RBAC) Can(user User, action Action, resource Resource) bool

Can reports whether any of the user's roles grants action on resource.

func (*RBAC) Roles

func (r *RBAC) Roles() []Role

Roles returns the names of all defined roles.

type Resource

type Resource string

Resource is a category of object that actions apply to.

const (
	ResourceRoutes  Resource = "routes"
	ResourceSecrets Resource = "secrets"
	ResourceConfig  Resource = "config"
	ResourceNodes   Resource = "nodes"
)

Resources.

type Role

type Role string

Role is a named bundle of permissions assigned to users and API keys.

const (
	RoleAdmin    Role = "admin"
	RoleOperator Role = "operator"
	RoleViewer   Role = "viewer"
	RoleReadonly Role = "readonly"
)

Built-in roles.

func RequiredRoleFromContext

func RequiredRoleFromContext(ctx context.Context) (Role, bool)

RequiredRoleFromContext returns the required role set by SetRequiredRole.

type User

type User struct {
	ID     string
	Email  string
	OrgID  string
	TeamID string
	Roles  []Role
}

User is an authenticated principal in the org → team → user hierarchy.

func UserFromContext

func UserFromContext(ctx context.Context) (User, bool)

UserFromContext returns the authenticated user stored in ctx, if any.

Jump to

Keyboard shortcuts

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