auth

package
v0.0.0-...-3400737 Latest Latest
Warning

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

Go to latest
Published: Dec 8, 2025 License: Apache-2.0 Imports: 41 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// StateCreate allows creating new states
	StateCreate = "state:create"

	// StateRead allows reading state metadata
	StateRead = "state:read"

	// StateList allows listing states
	StateList = "state:list"

	// StateUpdateLabels allows updating state labels
	StateUpdateLabels = "state:update-labels"

	// StateDelete allows deleting states
	StateDelete = "state:delete"
)

Control Plane Actions (state management)

View Source
const (
	// TfstateRead allows reading Terraform state content
	TfstateRead = "tfstate:read"

	// TfstateWrite allows writing Terraform state content
	TfstateWrite = "tfstate:write"

	// TfstateLock allows locking a state
	TfstateLock = "tfstate:lock"

	// TfstateUnlock allows unlocking a state
	TfstateUnlock = "tfstate:unlock"
)

Data Plane Actions (Terraform HTTP backend)

View Source
const (
	// DependencyCreate allows creating dependencies
	DependencyCreate = "dependency:create"

	// DependencyRead allows reading dependency metadata
	DependencyRead = "dependency:read"

	// DependencyList allows listing dependencies for a specific state (state-scoped)
	DependencyList = "dependency:list"

	// DependencyListAll allows listing all edges in the system (globally allowed, filtered by handler)
	DependencyListAll = "dependency:list-all"

	// DependencyDelete allows deleting dependencies
	DependencyDelete = "dependency:delete"
)

Dependency Actions

View Source
const (
	// StateOutputList allows listing available output keys from a state
	StateOutputList = "state-output:list"

	// StateOutputRead allows reading specific output values from a state
	StateOutputRead = "state-output:read"

	// StateOutputSchemaWrite allows setting/updating JSON Schema for a state output
	StateOutputSchemaWrite = "state-output:schema-write"

	// StateOutputSchemaRead allows reading JSON Schema for a state output
	StateOutputSchemaRead = "state-output:schema-read"
)

State Output Actions

View Source
const (
	// PolicyRead allows reading label policy
	PolicyRead = "policy:read"

	// PolicyWrite allows updating label policy
	PolicyWrite = "policy:write"
)

Policy Actions (label validation)

View Source
const (
	// AdminRoleManage allows creating/updating/deleting roles
	AdminRoleManage = "admin:role-manage"

	// AdminUserAssign allows assigning/removing roles to/from users
	AdminUserAssign = "admin:user-assign"

	// AdminGroupAssign allows assigning/removing roles to/from groups
	AdminGroupAssign = "admin:group-assign"

	// AdminServiceAccountManage allows creating/revoking service accounts
	AdminServiceAccountManage = "admin:service-account-manage"

	// AdminSessionRevoke allows revoking sessions
	AdminSessionRevoke = "admin:session-revoke"

	// AdminCacheRefresh allows manually refreshing the group→role cache
	AdminCacheRefresh = "admin:cache-refresh"
)

Admin Actions (RBAC management)

View Source
const (
	// StateWildcard grants all state actions
	StateWildcard = "state:*"

	// TfstateWildcard grants all tfstate actions
	TfstateWildcard = "tfstate:*"

	// DependencyWildcard grants all dependency actions
	DependencyWildcard = "dependency:*"

	// StateOutputWildcard grants all state-output actions
	StateOutputWildcard = "state-output:*"

	// PolicyWildcard grants all policy actions
	PolicyWildcard = "policy:*"

	// AdminWildcard grants all admin actions
	AdminWildcard = "admin:*"

	// AllWildcard grants all actions (platform-engineer)
	AllWildcard = "*"
)

Wildcard Actions (used in policies for broad access)

View Source
const (
	// ObjectTypeState represents state resources
	ObjectTypeState = "state"

	// ObjectTypePolicy represents policy resources
	ObjectTypePolicy = "policy"

	// ObjectTypeAdmin represents administrative resources
	ObjectTypeAdmin = "admin"

	// ObjectTypeAll is a wildcard for all object types
	ObjectTypeAll = "*"
)

Object Types for Casbin policies

View Source
const (
	PrefixUser           = "user:"
	PrefixGroup          = "group:"
	PrefixServiceAccount = "sa:"
	PrefixRole           = "role:"
)

Prefix constants for Casbin identifiers These ensure consistent naming across user-role groupings, group-role mappings, and policy definitions

Reference: PREFIX-CONVENTIONS.md §2-3, §9 (helper function patterns)

View Source
const (
	// SessionDuration is the default session lifetime (12 hours)
	SessionDuration = 12 * time.Hour

	// TokenLength is the length of generated bearer tokens in bytes
	TokenLength = 32
)
View Source
const (
	// ReadSelf allows a principal to read their own data
	// This is a special action used in the Casbin model's ownership check
	// When r.act == "read-self" && r.sub == r.obj, access is granted
	ReadSelf = "read-self"
)

Ownership Actions (self-service access)

View Source
const SessionCookieName = "grid.session"
View Source
const SystemUserID = "00000000-0000-0000-0000-000000000000"

SystemUserID is the well-known UUID for the system user, used for attributing actions performed by the system itself (e.g., database seeding, automated tasks).

Variables

View Source
var (
	// ErrOIDCDisabled is returned when OIDC configuration is incomplete.
	ErrOIDCDisabled = errors.New("oidc provider disabled")
)

Functions

func BexprMatchFunction

func BexprMatchFunction() func(args ...any) (any, error)

BexprMatchFunction returns the bexprMatch function for Casbin This function evaluates go-bexpr expressions against resource labels

Reference: research.md §1 (lines 443-482)

func CalculateExpiry

func CalculateExpiry(createdAt time.Time) time.Time

CalculateExpiry calculates session expiry time from creation Returns current time + SessionDuration (12 hours)

func ClaimsFromContext

func ClaimsFromContext(ctx context.Context) (map[string]any, bool)

ClaimsFromContext returns the JWT claims stored on the request context.

func EvaluateBexpr

func EvaluateBexpr(scopeExpr string, labels map[string]any) bool

EvaluateBexpr evaluates a go-bexpr expression against resource labels Empty scopeExpr returns true (no constraint) Caches compiled evaluators for performance

Reference: research.md §1 (lines 443-482)

func ExpandWildcard

func ExpandWildcard(action string) []string

ExpandWildcard expands wildcard actions to their concrete actions Example: "state:*" → ["state:create", "state:read", "state:list", "state:update-labels", "state:delete"]

func ExtractClaimString

func ExtractClaimString(claims map[string]interface{}, claimField string) (string, error)

ExtractClaimString extracts a string claim from JWT claims Generic helper for extracting string values from configurable claim fields

func ExtractEmailFromClaims

func ExtractEmailFromClaims(claims map[string]interface{}, claimField string) (string, error)

ExtractEmailFromClaims extracts the email from JWT claims Uses configurable claim field (default: "email")

func ExtractGroupID

func ExtractGroupID(principal string) (string, error)

ExtractGroupID extracts the group name from a Casbin principal identifier Returns the name without prefix, or error if prefix mismatch Example: ExtractGroupID("group:dev-team") → "dev-team", nil

func ExtractGroups

func ExtractGroups(claims map[string]interface{}, claimField string, claimPath string) ([]string, error)

ExtractGroups handles both flat and nested group claims from JWT tokens Supports:

  • Flat arrays: ["dev-team", "contractors"]
  • Nested objects: [{"name": "dev-team", "type": "team"}] with claimPath="name"

Reference: research.md §9 (lines 629-787), CLARIFICATIONS.md §1 (JWT claim config)

func ExtractGroupsFromIDToken

func ExtractGroupsFromIDToken(idToken string) ([]string, error)

ExtractGroupsFromIDToken parses a JWT ID token and extracts the "groups" claim. The token is parsed without verification since it's already validated and stored in the database. Returns an empty slice if no groups claim is present.

This function is used by: - Session interceptor (to extract groups from stored ID token for external IdP users) - SSO callback handler (to extract groups during initial authentication)

Related: grid-80ad (External IdP group-to-role mapping fix)

func ExtractNameFromClaims

func ExtractNameFromClaims(claims map[string]interface{}) string

ExtractNameFromClaims extracts the name from JWT claims (optional) Uses standard "name" claim field

func ExtractRoleID

func ExtractRoleID(principal string) (string, error)

ExtractRoleID extracts the role name from a Casbin principal identifier Returns the name without prefix, or error if prefix mismatch Example: ExtractRoleID("role:product-engineer") → "product-engineer", nil

func ExtractServiceAccountID

func ExtractServiceAccountID(principal string) (string, error)

ExtractServiceAccountID extracts the service account ID from a Casbin principal identifier Returns the ID without prefix, or error if prefix mismatch Example: ExtractServiceAccountID("sa:550e8400-e29b-41d4-a716-446655440000") → "550e8400-e29b-41d4-a716-446655440000", nil

func ExtractSubjectFromClaims

func ExtractSubjectFromClaims(claims map[string]interface{}, claimField string) (string, error)

ExtractSubjectFromClaims extracts the user subject ID from JWT claims Uses configurable claim field (default: "sub")

func ExtractUserID

func ExtractUserID(principal string) (string, error)

ExtractUserID extracts the user ID from a Casbin principal identifier Returns the ID without prefix, or error if prefix mismatch Example: ExtractUserID("user:alice@example.com") → "alice@example.com", nil

func GenerateBearerToken

func GenerateBearerToken() (string, string, error)

GenerateBearerToken generates a cryptographically secure random bearer token Returns: token (hex string), token hash (SHA256 hex), error

Reference: FR-007 (session management), data-model.md §294-335 (Session entity)

func GenerateNonce

func GenerateNonce() (string, error)

GenerateNonce generates a random nonce string.

func GetGroupsFromContext

func GetGroupsFromContext(ctx context.Context) []string

GetGroupsFromContext retrieves the resolved group list from the context.

func GetPrincipalType

func GetPrincipalType(principal string) string

GetPrincipalType returns the type of a Casbin principal (user, group, sa, role) Returns empty string if prefix not recognized

func GetRedirectURICookie

func GetRedirectURICookie(w http.ResponseWriter, r *http.Request) string

GetRedirectURICookie retrieves and clears the redirect URI cookie. Returns empty string if cookie not found or expired. Related: Beads issue grid-202d (SSO callback redirect fix)

func GroupID

func GroupID(name string) string

GroupID creates a Casbin group identifier with the standard prefix Example: GroupID("dev-team") → "group:dev-team"

func HashBearerToken

func HashBearerToken(token string) string

HashBearerToken hashes a bearer token for storage/lookup Returns SHA256 hex hash

func HashToken

func HashToken(token string) string

HashToken creates a SHA256 hash of a token string.

func InitEnforcer

func InitEnforcer(db *bun.DB) (casbin.IEnforcer, error)

InitEnforcer creates and initializes a Casbin enforcer with embedded model and database adapter Uses msales/casbin-bun-adapter to share the existing *bun.DB connection pool

Reference: research.md §1 (lines 429-490), §7 (adapter usage)

func IsSessionExpired

func IsSessionExpired(expiresAt time.Time) bool

IsSessionExpired checks if a session has expired

func IsSessionRevoked

func IsSessionRevoked(revoked bool) bool

IsSessionRevoked checks session revocation flag

func JTIFromClaims

func JTIFromClaims(claims map[string]any) (string, bool)

JTIFromClaims extracts the JWT ID claim from the claims map. This is used for revocation checking in the authentication middleware.

func NewVerifier

func NewVerifier(cfg *config.Config, opts ...VerifierOption) (func(http.Handler) http.Handler, error)

NewVerifier constructs a Chi-compatible middleware that validates JWTs using go-oidc-middleware.

func RoleID

func RoleID(name string) string

RoleID creates a Casbin role identifier with the standard prefix Example: RoleID("product-engineer") → "role:product-engineer"

func ServiceAccountID

func ServiceAccountID(id string) string

ServiceAccountID creates a Casbin service account identifier with the standard prefix Example: ServiceAccountID("550e8400-e29b-41d4-a716-446655440000") → "sa:550e8400-e29b-41d4-a716-446655440000"

func SetClaimsContext

func SetClaimsContext(ctx context.Context, claims map[string]any) context.Context

SetClaimsContext allows middleware to inject synthetic claims (e.g., from session cookies). This enables session authentication to reuse the existing JWT authentication flow.

func SetGroupsContext

func SetGroupsContext(ctx context.Context, groups []string) context.Context

SetGroupsContext stores the resolved group list on the context.

func SetRedirectURICookie

func SetRedirectURICookie(w http.ResponseWriter, r *http.Request, redirectURI string)

SetRedirectURICookie stores the redirect URI in a temporary cookie for the SSO flow. This cookie is short-lived (10 minutes) and used to remember where to redirect after OAuth callback. Related: Beads issue grid-202d (SSO callback redirect fix)

func SetTokenHashContext

func SetTokenHashContext(ctx context.Context, hash string) context.Context

SetTokenHashContext allows middleware to set token hash for session lookup.

func SetUserContext

func SetUserContext(ctx context.Context, principal AuthenticatedPrincipal) context.Context

SetUserContext stores the authenticated principal on the context for downstream consumers.

func TerraformBasicAuthShim

func TerraformBasicAuthShim(next http.Handler) http.Handler

TerraformBasicAuthShim rewrites Terraform's Basic Auth credential promotion into a standard Bearer token header. The password component of the decoded credential is treated as the bearer token and injected into the Authorization header so downstream middleware can operate on a canonical representation. Requests that already present a Bearer token are left untouched.

func TokenHashFromContext

func TokenHashFromContext(ctx context.Context) (string, bool)

TokenHashFromContext returns the SHA256 hash of the bearer token extracted during verification.

func TokenStringFromContext

func TokenStringFromContext(ctx context.Context) (string, bool)

TokenStringFromContext returns the raw bearer token extracted during verification.

func UserID

func UserID(id string) string

UserID creates a Casbin user identifier with the standard prefix Example: UserID("alice@example.com") → "user:alice@example.com"

func ValidateAction

func ValidateAction(action string) bool

ValidateAction checks if an action string is valid This prevents typos when creating/updating policies

func ValidateClaims

func ValidateClaims(claims map[string]interface{}, requiredClaims []string) error

ValidateClaims performs comprehensive validation of JWT claims Checks required fields, expiration, and claim formats

Reference: FR-006, FR-006a (token validation requirements)

func ValidateEmail

func ValidateEmail(email string) error

ValidateEmail validates email format (basic RFC 5322 check)

func ValidateSessionInfo

func ValidateSessionInfo(info *SessionInfo) error

ValidateSessionInfo validates session info before creation Ensures exactly one identity type is set

func ValidateSessionToken

func ValidateSessionToken(expiresAt time.Time, revoked bool, identityDisabled bool) error

ValidateSessionToken performs comprehensive session validation Checks expiration, revocation, and identity status

Reference: FR-007 (session revocation), FR-070b (cascade revocation)

func ValidateSubject

func ValidateSubject(subject string) error

ValidateSubject validates the subject claim format Subject must be in format: provider|provider_user_id (e.g., "keycloak|123")

Reference: data-model.md §56 (User.Subject validation)

Types

type AuthenticatedPrincipal

type AuthenticatedPrincipal struct {
	// Subject is the stable OIDC subject or client identifier (unprefixed).
	Subject string
	// PrincipalID is the Casbin-ready identifier (e.g., user:alice@example.com).
	PrincipalID string
	// InternalID references the backing database record (users.id or service_accounts.id).
	InternalID string
	// Email is optional and present for human users when available.
	Email string
	// Name is optional display name for human users.
	Name string
	// SessionID references the active session row when available.
	SessionID string
	// Roles lists effective Casbin role identifiers resolved during authentication.
	Roles []string
	// Type differentiates users and service accounts.
	Type PrincipalType
}

AuthenticatedPrincipal captures identity metadata propagated through the request context.

func GetUserFromContext

func GetUserFromContext(ctx context.Context) (AuthenticatedPrincipal, bool)

GetUserFromContext retrieves the authenticated principal from the context.

type ErrorResponder

type ErrorResponder func(http.ResponseWriter, *http.Request, error)

ErrorResponder writes authentication failures to the response writer.

type PrincipalType

type PrincipalType string

PrincipalType describes the type of authenticated principal.

const (
	// PrincipalTypeUser represents a human user authenticated via OIDC.
	PrincipalTypeUser PrincipalType = "user"
	// PrincipalTypeServiceAccount represents a non-interactive service account.
	PrincipalTypeServiceAccount PrincipalType = "service_account"
)

type Provider

type Provider struct {
	Router  chi.Router
	Storage op.Storage
}

Provider exposes the server-side OIDC endpoints wired through zitadel/oidc.

func NewOIDCProvider

func NewOIDCProvider(ctx context.Context, cfg config.OIDCConfig, deps ProviderDependencies) (*Provider, error)

NewOIDCProvider builds an OpenID provider instance when OIDC is enabled.

func (*Provider) Handler

func (p *Provider) Handler() chi.Router

Handler exposes the chi.Router handling the OIDC endpoints.

type ProviderDependencies

type ProviderDependencies struct {
	Users           repository.UserRepository
	ServiceAccounts repository.ServiceAccountRepository
	Sessions        repository.SessionRepository
}

ProviderDependencies holds the repositories required by the OIDC storage adapter.

type RelyingParty

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

RelyingParty handles OIDC authentication against an external IdP by wrapping the zitadel/oidc RelyingParty implementation.

func NewRelyingParty

func NewRelyingParty(ctx context.Context, cfg *config.ExternalIdPConfig) (*RelyingParty, error)

NewRelyingParty creates a new RelyingParty for external IdP authentication.

func (*RelyingParty) RP

func (r *RelyingParty) RP() rp.RelyingParty

RP returns the underlying zitadel/oidc RelyingParty interface.

type SessionInfo

type SessionInfo struct {
	UserID           *string // Set for human users
	ServiceAccountID *string // Set for service accounts
	IDToken          string  // OIDC ID token (JWT) for human sessions
	RefreshToken     string  // OIDC refresh token (optional)
	UserAgent        string  // Browser/CLI user agent
	IPAddress        string  // Client IP address
}

SessionInfo represents session metadata for creation

type Skipper

type Skipper func(*http.Request) bool

Skipper defines a function to skip authentication for matching requests.

type VerifierOption

type VerifierOption func(*verifierOptions)

VerifierOption customises the behaviour of the OIDC verifier middleware.

func WithErrorResponder

func WithErrorResponder(responder ErrorResponder) VerifierOption

WithErrorResponder overrides the default error responder used by the verifier.

func WithSkipper

func WithSkipper(skipper Skipper) VerifierOption

WithSkipper overrides the default skipper used by the verifier.

func WithTokenString

func WithTokenString(header, prefix string) VerifierOption

WithTokenString configures an alternate header and prefix that should be treated as a bearer token.

func WithTokenStringOptions

func WithTokenStringOptions(setters ...options.TokenStringOption) VerifierOption

WithTokenStringOptions appends a token extraction strategy used by the verifier. The provided setters mirror go-oidc-middleware's token string configuration helpers.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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