guard

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2026 License: MIT Imports: 28 Imported by: 0

README

Guard

Guard

Enterprise-grade authorization and API security platform for Go.

Docs · Install · Quick Start · Components · Roadmap

Go License Status


Guard is a Go-native security toolkit that simplifies authentication, authorization, and API protection for modern applications and microservices. It provides session management, RBAC, ABAC, API key authentication, rate limiting, audit logging, and security middleware with a developer-friendly API.

Features

🔐 Session management 👥 Role-Based Access Control (RBAC)
🏷️ Attribute-Based Access Control (ABAC) 🔑 API key authentication
⚡ Configurable rate limiting 📋 Audit logs
🛡️ Security middleware (CSRF, headers, body limit) 🔄 Automatic permission sync from routes
🖥️ Server-rendered admin panel 👑 Protected super admin role
🚀 net/http, Gin, Echo, Fiber, Chi, Iris, Hertz, Beego, gorilla/mux, httprouter 💾 PostgreSQL, Redis

Planned (not yet available): MySQL, service-to-service authentication, security analytics, plugin architecture. See Roadmap.

Frameworks

The HTTP layer is plain net/http (httpguard): routes, middleware and the admin panel all come as http.Handler, so the net/http router family works with no adapter, and Echo, Fiber, Iris, Hertz and Beego get thin adapters in their own Go modules — installing Guard pulls none of them in.

mux := http.NewServeMux()
httpguard.Mount(mux, g, httpguard.Options{AuthPath: "/api/auth", AdminPath: "/api/guard"})
mux.Handle("/guard-admin/", adminui.Handler(g, adminui.Options{}))
mux.Handle("GET /api/invoices/{id}",
    httpguard.RequirePermission(g, opts, "invoice.read")(invoiceHandler))

Full table, per-framework snippets and the path-parameter wiring for chi, gorilla/mux and httprouter: docs/frameworks.md.

Installation

go get github.com/bakhod1r/guard

Requirements: Go 1.26+, PostgreSQL 13+ (CI tests 13 and 17), Redis 6.2+ (CI tests 7).

Quick Start

Guard does not create a users table. It detects your existing table (users.id — bigint, uuid, text…) and references it.

pool, _ := pgxpool.New(ctx, os.Getenv("DATABASE_URL"))
rdb := redis.NewClient(&redis.Options{Addr: os.Getenv("REDIS_ADDR")})

g, _ := guard.New(guard.Config{DB: pool, Redis: rdb, UserTable: "users", UserIDColumn: "id"})

g.WriteMigrations(ctx, "./migrations/guard") // detects users.id type, renders SQL into your repo (never overwrites)
g.Migrate(ctx, "./migrations/guard")         // goose, version table guard_schema_version

// give an existing user of yours login credentials + admin role
g.EnsureAdmin(ctx, adminUserID, "admin@example.com", os.Getenv("ADMIN_PASSWORD"))

r := gin.Default()
opts := ginguard.Options{
    // optional self-registration: insert a NEW row into your users table, return its id
    CreateUser: func(ctx context.Context, email string) (string, error) { /* INSERT ... RETURNING id::text */ },
}
ginguard.Mount(r.Group("/api"), g, opts)          // /api/auth/*, /api/guard/*
adminui.Mount(r, g, adminui.Options{})            // /guard-admin (HTML panel)

r.GET("/api/invoices/:id", ginguard.RequirePermission(g, opts, "invoice.read"), handler)

Link accounts for users you already have: g.CreateAccount(ctx, userID, email, password, attrs, guard.RequestMeta{}).

Run the example

# whole stack in containers (app + PostgreSQL + Redis)
docker compose -f examples/gin/docker-compose.yml up --build
# API:   http://localhost:18080/api/auth/login
# Panel: http://localhost:18080/guard-admin   (admin@example.com / change-me-now)

# or run the app from source against the compose databases
docker compose -f examples/gin/docker-compose.yml up -d --wait postgres redis
DATABASE_URL=postgres://postgres:postgres@localhost:18432/guard?sslmode=disable REDIS_ADDR=localhost:18379 \
GUARD_ADMIN_EMAIL=admin@example.com GUARD_ADMIN_PASSWORD=change-me-now GUARD_INSECURE_COOKIE=1 \
go run ./examples/gin   # http://localhost:8080

Configuration file and autoseed

Load Guard from YAML (${ENV} expansion, unknown keys rejected, secrets from env) and protect host routes by derived permissions:

cfg, _ := config.Load("guard.yaml")
g, _ := cfg.Open(ctx)                                  // PostgreSQL + Redis, migrations if auto_apply
api.Use(ginguard.Protect(g, cfg.HTTPOptions(), "/api")) // GET /api/reports/:id -> reports.read
ao, _ := cfg.AutoseedOptions()
_, _ = ginguard.Autoseed(ctx, g, r.Routes(), ao)       // create permissions; super role gets all, others denied

Key reference and caveats: docs/configuration.md.

HTTP API (ginguard.Mount)

Route Guard
POST /auth/register, POST /auth/login public
POST /auth/logout, POST /auth/logout-all, GET /auth/me, PUT /auth/password session
GET /auth/sessions, DELETE /auth/sessions/:id session
GET /auth/me, POST /auth/authorize session or API key
GET|POST /auth/api-keys, DELETE /auth/api-keys/:id session (keys cannot mint keys)
GET|DELETE /guard/users/:id/api-keys apikey.read / apikey.revoke
GET /guard/users/:id user.read or self
PUT /guard/users/:id/status, PUT /guard/users/:id/attributes user.write
GET /guard/users/:id/roles role.read or self
POST /guard/users/:id/roles, DELETE /guard/users/:id/roles/:role role.assign
GET|DELETE /guard/users/:id/sessions session.read / session.revoke
GET|POST /guard/roles, GET|DELETE /guard/roles/:name role.read / role.write
POST /guard/roles/:name/permissions, DELETE /guard/roles/:name/permissions/:code role.write
GET|POST /guard/permissions permission.read / permission.write
GET|POST /guard/policies, GET|PUT|DELETE /guard/policies/:id policy.read / policy.write
GET /guard/audit audit.read

Credential: X-API-Key: gk_..., Authorization: Bearer <token|gk_...>, or the guard_session cookie (HttpOnly, Secure, SameSite=Strict).

API keys act as their owner narrowed by scopes (invoice.read, invoice.*, *); only the SHA-256 is stored and the token is shown once.

Rate limiting: /auth/login and /auth/register are limited per IP (default 10/min, Options.AuthRateLimit). Any route: ginguard.RateLimit(g, "reports", ratelimit.Rule{Limit: 100, Window: time.Minute}, ginguard.ByPrincipal) — Redis sliding window, X-RateLimit-* and Retry-After headers, fails open if Redis errors.

Authorization model

  • RBAC — role → permission (resource.action); wildcard roles pass everything; user roles may expire.
  • ABAC — policies target (resource, action) (or *) with a condition tree (and/or, negate). Fields: user.*, resource.*, env.*; values starting with $ reference attributes ($user.id).
  • Decision — matching policies sorted by priority ASC; the strongest tier decides, DENY wins inside a tier; no policy matched → RBAC; otherwise deny (fail-closed).
  • Seeded: roles super_admin / admin (wildcard) / user, self-service read policies, blocked user denied (priority 10).

Super admin

super_admin is a system wildcard role (migration 00005). Only a super admin may grant, revoke or delete a privileged role (admin, super_admin, any wildcard role, any role holding role.write, role.assign or policy.write), grant or revoke those management permissions, write policies on resource *, role or policy, or change a privileged user's account; the last super admin cannot lose the role, be banned or suspended (409 last_super_admin). ABAC deny policies still apply to super admins.

_, _ = g.EnsureSuperAdmin(ctx, hostUserID, email, password) // idempotent bootstrap
err := g.AssignRole(ctx, actorID, userID, "admin", nil)     // guard.ErrForbidden unless actor is super admin

Upgrading: existing admins are not promoted; call EnsureSuperAdmin once. examples/gin reads GUARD_SUPERADMIN_EMAIL / GUARD_SUPERADMIN_PASSWORD.

Route auto-discovery

api.Use(ginguard.ProtectRoutes(g, opts, so))                  // GET /api/reports/:id -> reports.read
res, err := ginguard.SyncRoutes(ctx, g, r.Routes(), ginguard.SyncOptions{
	Prefix: "/api", SkipPrefixes: []string{"/api/auth", "/api/guard"},
	// FullRoles nil = admin + super_admin; UserActions nil = ["read"] for role "user"
	Overrides: map[string]string{"POST /api/reports/:id/approve": "reports.approve"},
})

Routes served by Guard's own handlers (ginguard.Mount, adminui.Mount) are skipped automatically by both SyncRoutes and ProtectRoutes (detected from gin's handler name); they enforce their own checks. SyncOptions.IncludeGuardRoutes: true opts out. SkipPrefixes still excludes any other path prefix. Routes are stored in guard_route (migration 00006); removed routes are marked stale and existing grants are never revoked. res lists created, skipped and stale entries; the admin panel shows them under Routes.

Access cache

Config.AccessCache: &guard.AccessCacheOptions{} (YAML access_cache.enabled: true) caches role grants and policies per instance and invalidates all instances through a Redis version key (default TTL 30s). Redis failures bypass to PostgreSQL. Behind a load balancer add L2: true (YAML access_cache.shared: true) to also keep the loaded grants and policies in Redis: an in-process miss on one instance is then served from the copy another instance loaded instead of from PostgreSQL, which matters most right after a deploy or an invalidation, when every instance would otherwise reload at once. Shared entries are namespaced by the same version key, so one write invalidates both levels; they expire after L2TTL (default twice TTL). Call g.InvalidateAccess(ctx) after changes made outside Guard (e.g. deleting a host user); g.AccessStats() exposes hit/miss counters.

Layout (DDD)

Context domain application infrastructure
identity user, email, status, lockout register, authenticate, password argon2id, PostgreSQL
session token (SHA-256 id), idle/absolute timeout start, resolve (sliding), revoke Redis
access role, permission, policy tree, Decide authorize, role/policy admin PostgreSQL, memory
apikey key, scopes, expiry/revoke issue, resolve, revoke PostgreSQL, memory

kernel/migrations (goose SQL templates rendered against your user table), adminui (html/template admin panel), ratelimit (Redis sliding window), audit, ginguard (interfaces), guardtest (in-memory Guard for tests).

Testing

make test               # unit tests; integration tests skip without services
make test-integration   # starts PostgreSQL + Redis (compose), go test -race with coverage
make cover              # fails if any package is below 100.0% statements
make lint vuln          # golangci-lint v2 (.golangci.yml), govulncheck

Manual integration run against your own services:

GUARD_TEST_DATABASE_URL=postgres://postgres:postgres@localhost:18432/guard?sslmode=disable \
GUARD_TEST_REDIS_ADDR=localhost:18379 \
go test -count=1 -race -covermode=atomic -coverprofile=coverage.out $(go list ./... | grep -v /examples/)
bash scripts/coverage-gate.sh coverage.out

CI (.github/workflows/ci.yml) runs the same gates on PostgreSQL 13 and 17.

Audit buffering (Redis → PostgreSQL)

By default audit events are written to PostgreSQL synchronously (or in-process with AsyncAudit). For high write volume, queue them in Redis and batch-insert:

g, err := guard.New(guard.Config{
    // ...
    AuditBuffer: guard.AuditBuffer{
        Enabled:   true,
        BatchSize: 500,         // default 500
        Interval:  time.Second, // default 1s
    },
})
defer g.Close(ctx) // flushes the queue on shutdown
  • Events are pushed to <prefix>{audit}:queue; one flusher across all instances holds <prefix>{audit}:lock (30s TTL, extended per batch; hash tag keeps keys in one Redis Cluster slot) and writes batches via RecordBatch (ON CONFLICT (id) DO NOTHING, so retries are idempotent).
  • A failed PostgreSQL write leaves the batch queued for the next tick; undecodable entries, and single events PostgreSQL rejects while the rest of the batch succeeds, move to <prefix>{audit}:dead.
  • If Redis is unreachable, Record falls back to a direct synchronous write.
  • When Enabled, AsyncAudit is ignored.

Trade-offs vs AsyncAudit: queued events survive process restarts and are shared across instances; but List (and GET /guard/audit) shows only flushed events, so reads lag by up to Interval, and a PostgreSQL outage grows the Redis list — size Redis memory and alert on queue length.

Production checklist

Full list with rationale: docs/production.md. Minimum before going live:

  • TLS; InsecureCookie false (default) in ginguard and adminui.
  • gin.Engine.SetTrustedProxies set to your load balancers — otherwise X-Forwarded-For bypasses per-IP login limits.
  • adminui.Options.CSRFSecret from a secret store, identical on all instances.
  • Cookie clients send X-Guard-CSRF: 1 (or a trusted Origin) on unsafe requests; set TrustedOrigins for cross-origin SPAs.
  • One super_admin bootstrapped with EnsureSuperAdmin; GUARD_SUPERADMIN_* removed afterwards.
  • Redis HA with auth/TLS; PostgreSQL pool sized per instance count; sslmode=verify-full.
  • Migrations committed and applied by one release job (Guard holds a PostgreSQL advisory lock during Migrate).
  • Audit retention job, backups with rehearsed restore, key/secret rotation.
  • Logs redact Authorization, X-API-Key, cookies and credential request bodies.
  • Admin panel behind VPN / IP allowlist.

Full documentation site: https://bakhod1r.github.io/guard/

Also: configuration · architecture · HTTP API and error codes · admin panel · security policy · changelog.

Core Components

Component Description
Sessions Secure, stateful session management.
Authorization RBAC and ABAC policy enforcement.
API Keys Secure API key generation, rotation, and validation.
Rate Limiting Route, user, session, or API key-based throttling.
Audit Track authentication and authorization events.
Service Identity Secure service-to-service authentication.
Middleware Plug-and-play security for Go web frameworks.

Why Guard?

Most Go applications combine multiple libraries for sessions, authorization, API keys, rate limiting, and auditing. Guard brings these capabilities together in a single, cohesive platform with a consistent developer experience.

Roadmap

  • Session management
  • RBAC & ABAC
  • API keys
  • Rate limiting
  • Audit logging
  • Service-to-service authentication
  • Admin dashboard
  • Security analytics
  • Policy engine
  • Plugin ecosystem
  • Migration advisory lock (multi-replica Migrate)
  • Echo / Fiber / Chi / net/http adapters
  • v1.0 API freeze

License

MIT License. See LICENSE.

Documentation

Overview

Package guard wires identity, sessions, RBAC/ABAC and audit into one entry point.

g, _ := guard.New(guard.Config{DB: pool, Redis: rdb, UserTable: "users", UserIDColumn: "id"})
_, _ = g.WriteMigrations(ctx, "./migrations/guard") // detects users.id type, renders SQL
_ = g.Migrate(ctx, "./migrations/guard")
ginguard.Mount(router.Group("/api"), g, ginguard.Options{})

Index

Constants

View Source
const RoleSuperAdmin = accessdomain.RoleSuperAdmin

RoleSuperAdmin is the system role that alone manages admin and super_admin grants.

Variables

View Source
var (
	ErrForbidden        = accessdomain.ErrForbidden
	ErrLastSuperAdmin   = accessdomain.ErrLastSuperAdmin
	ErrSuperAdminExpiry = accessdomain.ErrSuperAdminExpiry
)

Super admin errors, re-exported for HTTP error mapping.

View Source
var ErrNoRouteRegistry = errors.New("guard: route registry needs a PostgreSQL-backed Guard")

ErrNoRouteRegistry is returned by ListRoutes on a Guard without PostgreSQL.

View Source
var ErrSessionRequired = errors.New("guard: this operation requires a session, not an API key")

Functions

This section is empty.

Types

type APIKey

type APIKey = apikeydomain.Key

Re-exported domain types so host apps need a single import.

type APIKeyToken

type APIKeyToken = apikeydomain.Token

Re-exported domain types so host apps need a single import.

type AccessCacheOptions

type AccessCacheOptions = accessinfra.CacheOptions

AccessCacheOptions configures Config.AccessCache.

type AccessCacheStats

type AccessCacheStats = accessinfra.CacheStats

Re-exported domain types so host apps need a single import.

type AuditBuffer

type AuditBuffer struct {
	Enabled   bool
	BatchSize int
	Interval  time.Duration
}

AuditBuffer configures the Redis-backed audit queue. Events are pushed to the Redis list <RedisPrefix>audit:queue and flushed every Interval (default 1s) in batches of BatchSize (default 500). The queue survives process restarts and is shared by every instance. When Redis is unavailable events fall back to direct PostgreSQL writes. Call Guard.Close on shutdown to drain it.

type AuditEvent

type AuditEvent = audit.Event

Re-exported domain types so host apps need a single import.

type Config

type Config struct {
	DB    *pgxpool.Pool
	Redis redis.UniversalClient
	// RedisPrefix namespaces session keys. Default "guard:".
	RedisPrefix string
	// Session lifetime. Each zero field uses its default (30m idle / 7d absolute).
	Session SessionPolicy
	// Lockout for password guessing. Each zero field uses its default (5 attempts / 15m).
	Lockout Lockout
	// DefaultRole is assigned on CreateAccount. Default "user"; "-" disables.
	DefaultRole string
	// UserTable is the host application's existing user table ("users" or
	// "schema.users"). Guard never creates it; its tables reference it. Default "users".
	UserTable string
	// UserIDColumn is the primary key (or unique) column of UserTable. Default "id".
	UserIDColumn string
	// Logger receives operational events (audit write failures at Warn, failed
	// logins at Info). Raw emails, passwords and tokens are never logged.
	// Default slog.Default().
	Logger *slog.Logger
	// AsyncAudit > 0 writes audit events through a non-blocking buffer of this
	// size; overflow is dropped and counted. 0 (default) writes synchronously.
	// Call Guard.Close on shutdown to flush.
	AsyncAudit int
	// AuditBuffer queues audit events in Redis and batch-writes them to
	// PostgreSQL. When Enabled, AsyncAudit is ignored.
	AuditBuffer AuditBuffer
	// AccessCache enables the in-process role/policy cache for authorization
	// (invalidated cluster-wide through Redis). nil (default) disables it.
	// Empty Prefix uses RedisPrefix; nil OnError logs at Warn.
	AccessCache *accessinfra.CacheOptions
	// PasswordHashParams overrides argon2id parameters; values below the OWASP
	// floor make New fail. nil uses secure defaults. Legacy bcrypt hashes are
	// always verified and upgraded on login.
	PasswordHashParams *PasswordHashParams
	// AuditEmailKey (>= 32 random bytes, keep secret) makes login audit events
	// store "email_hmac" (hex HMAC-SHA256, first 16 bytes) instead of the
	// unkeyed "email_sha256" fingerprint, which is brute-forceable from a list
	// of known addresses. Raw emails are never stored in audit metadata.
	AuditEmailKey []byte
}

type Decision

type Decision = accessdomain.Decision

Re-exported domain types so host apps need a single import.

type Guard

type Guard struct {
	Identity *identityapp.Service
	Sessions *sessionapp.Service
	Access   *accessapp.Service
	APIKeys  *apikeyapp.Service
	Audit    audit.Log
	// Limiter is nil when no Redis-backed limiter was configured.
	Limiter ratelimit.Limiter
	// contains filtered or unexported fields
}

func Build

func Build(r Repositories, cfg Config) *Guard

func New

func New(cfg Config) (*Guard, error)

func (*Guard) AccessStats

func (g *Guard) AccessStats() (stats accessinfra.CacheStats, ok bool)

AccessStats returns access cache counters; ok is false when Config.AccessCache is nil.

func (*Guard) AssignRole

func (g *Guard) AssignRole(ctx context.Context, actorID, userID, role string, expiresAt *time.Time) error

AssignRole grants role to userID on behalf of actorID and audits it. Granting admin or super_admin requires a super admin actor (ErrForbidden).

func (*Guard) Authenticate

func (g *Guard) Authenticate(ctx context.Context, credential string) (*Principal, error)

Authenticate resolves a session token or an API key ("gk_...") into a principal. The user row is re-read on every call so bans and role changes apply immediately.

func (*Guard) Authorize

func (g *Guard) Authorize(ctx context.Context, p *Principal, action string, res Resource, env map[string]any) (Decision, error)

Authorize decides whether p may perform action on resource.

func (*Guard) Close

func (g *Guard) Close(ctx context.Context) error

Close flushes buffered audit events (Config.AsyncAudit, Config.AuditBuffer) until done or ctx expires. It never closes the caller's database pool or Redis client.

func (*Guard) CreateAccount

func (g *Guard) CreateAccount(ctx context.Context, userID, email, password string, attrs map[string]any, meta RequestMeta) (*User, error)

CreateAccount gives an existing host user (userID from UserTable) login credentials, assigns DefaultRole and records an audit event.

func (*Guard) EnsureAdmin

func (g *Guard) EnsureAdmin(ctx context.Context, userID, email, password string) (*User, error)

EnsureAdmin gives the existing host user userID an account (if missing) and the admin role. Intended for bootstrap at startup.

func (*Guard) EnsureSuperAdmin

func (g *Guard) EnsureSuperAdmin(ctx context.Context, userID, email, password string) (*User, error)

EnsureSuperAdmin gives the existing host user userID an account (if missing) and the super_admin role. Idempotent; intended for bootstrap (e.g. GUARD_SUPERADMIN_EMAIL / GUARD_SUPERADMIN_PASSWORD at startup). An existing account keeps its password.

func (*Guard) Health

func (g *Guard) Health(ctx context.Context) error

Health pings PostgreSQL and Redis, each with a 2s timeout. It returns an error naming every unhealthy backend, or when none is configured.

func (*Guard) InvalidateAccess

func (g *Guard) InvalidateAccess(ctx context.Context) error

InvalidateAccess drops cached role grants and policies on every instance. Call it after changes that bypass Guard, e.g. deleting a host user (ON DELETE CASCADE). No-op without Config.AccessCache.

func (*Guard) IsSuperAdmin

func (g *Guard) IsSuperAdmin(ctx context.Context, userID string) (bool, error)

IsSuperAdmin reports whether userID actively holds super_admin.

func (*Guard) IssueAPIKey

func (g *Guard) IssueAPIKey(ctx context.Context, p *Principal, name string, scopes []string, expiresAt *time.Time, meta RequestMeta) (*APIKey, APIKeyToken, error)

IssueAPIKey creates a key for p's user. Only session principals may issue keys, so a leaked key cannot mint more keys.

func (*Guard) ListRoutes

func (g *Guard) ListRoutes(ctx context.Context) ([]RouteRecord, error)

ListRoutes returns the route registry, stale routes included.

func (*Guard) Login

func (g *Guard) Login(ctx context.Context, email, password string, meta RequestMeta) (*LoginResult, error)

func (*Guard) Logout

func (g *Guard) Logout(ctx context.Context, p *Principal, meta RequestMeta) error

func (*Guard) Migrate

func (g *Guard) Migrate(ctx context.Context, dir string) error

Migrate applies migrations from dir. dir == "" renders the embedded templates against the detected user table instead.

func (*Guard) ResetPassword

func (g *Guard) ResetPassword(ctx context.Context, actorID, userID, password string) error

ResetPassword sets a new password (admin action), signs the user out everywhere and revokes every API key of the user. Resetting an admin or super admin needs a super admin actor (ErrForbidden).

func (*Guard) RotateSession

func (g *Guard) RotateSession(ctx context.Context, token SessionToken) (*Session, SessionToken, error)

RotateSession replaces a session token (call after login or privilege change) and records session.rotate. The old token stops working.

func (*Guard) SetAttributes

func (g *Guard) SetAttributes(ctx context.Context, actorID, userID string, attrs map[string]any) error

SetAttributes replaces userID's ABAC attributes on behalf of actorID. Attributes feed ABAC decisions, so users may not change their own unless they are a super admin (ErrForbidden).

func (*Guard) SetUserStatus

func (g *Guard) SetUserStatus(ctx context.Context, actorID, userID string, status Status) error

SetUserStatus changes account status; blocking also revokes every session. Changing an admin or super admin needs a super admin actor (ErrForbidden).

func (*Guard) SuperAdmins

func (g *Guard) SuperAdmins(ctx context.Context) ([]string, error)

SuperAdmins returns the user ids holding super_admin.

func (*Guard) SyncRoutes

func (g *Guard) SyncRoutes(ctx context.Context, routes []Route, o RouteSyncOptions) (RouteSyncResult, error)

SyncRoutes discovers route permissions (see accessapp.Service.SyncRoutes): admin and super_admin get every route permission, the user role gets UserActions (default read) for new routes, and removed routes are marked stale. Idempotent; safe to call at every startup. Records a routes.sync audit event.

func (*Guard) UnassignRole

func (g *Guard) UnassignRole(ctx context.Context, actorID, userID, role string) error

UnassignRole revokes role from userID on behalf of actorID and audits it. Revoking admin or super_admin requires a super admin actor (ErrForbidden); the last super admin keeps the role (ErrLastSuperAdmin).

func (*Guard) UserRef

func (g *Guard) UserRef(ctx context.Context) (migrations.UserRef, error)

UserRef inspects the database and resolves the host user table and its id column type.

func (*Guard) WriteMigrations

func (g *Guard) WriteMigrations(ctx context.Context, dir string) ([]string, error)

WriteMigrations detects the host user table, renders Guard's SQL migrations for it and writes them into dir. Existing files are never overwritten.

type Lockout

type Lockout = identitydomain.Lockout

Re-exported domain types so host apps need a single import.

type LoginResult

type LoginResult struct {
	User    *User
	Session *Session
	Token   SessionToken
}

type PasswordHashParams

type PasswordHashParams struct {
	Memory, Time    uint32
	Threads         uint8
	KeyLen, SaltLen uint32
}

PasswordHashParams are argon2id parameters (Memory in KiB).

type Permission

type Permission = accessdomain.Permission

Re-exported domain types so host apps need a single import.

type Policy

type Policy = accessdomain.Policy

Re-exported domain types so host apps need a single import.

type Principal

type Principal struct {
	User    *User
	Session *Session
	APIKey  *APIKey
	Roles   []Role
}

Principal is the authenticated caller of a request. Exactly one of Session and APIKey is set.

type Repositories

Repositories lets callers swap storage (tests, other databases).

type RequestMeta

type RequestMeta struct {
	IP        string
	UserAgent string
}

RequestMeta describes the HTTP caller for sessions and audit.

type Resource

type Resource = accessdomain.Resource

Re-exported domain types so host apps need a single import.

type Role

type Role = accessdomain.Role

Re-exported domain types so host apps need a single import.

type RoleGrant

type RoleGrant = accessdomain.RoleGrant

Re-exported domain types so host apps need a single import.

type Route

type Route = accessapp.Route

type RouteRecord

type RouteRecord = accessdomain.RouteRecord

type RouteSyncOptions

type RouteSyncOptions = accessapp.RouteSyncOptions

type RouteSyncResult

type RouteSyncResult = accessapp.RouteSyncResult

type Session

type Session = sessiondomain.Session

Re-exported domain types so host apps need a single import.

type SessionPolicy

type SessionPolicy = sessiondomain.Policy

Re-exported domain types so host apps need a single import.

type SessionToken

type SessionToken = sessiondomain.Token

Re-exported domain types so host apps need a single import.

type Status

type Status = identitydomain.Status

Re-exported domain types so host apps need a single import.

type User

type User = identitydomain.User

Re-exported domain types so host apps need a single import.

Directories

Path Synopsis
access
application
Package application contains authorization use cases.
Package application contains authorization use cases.
domain
Package domain holds authorization rules: RBAC roles/permissions and ABAC policies.
Package domain holds authorization rules: RBAC roles/permissions and ABAC policies.
infrastructure
Package infrastructure stores roles, permissions and policies in PostgreSQL.
Package infrastructure stores roles, permissions and policies in PostgreSQL.
adapters
beego module
echo module
fiber module
hertz module
iris module
Package adminui is a server-rendered (html/template) admin panel for Guard: users, RBAC, ABAC policies, sessions, API keys and audit.
Package adminui is a server-rendered (html/template) admin panel for Guard: users, RBAC, ABAC policies, sessions, API keys and audit.
apikey
application
Package application contains API key use cases.
Package application contains API key use cases.
domain
Package domain holds API key rules: issuance, scopes, expiry, revocation.
Package domain holds API key rules: issuance, scopes, expiry, revocation.
infrastructure
Package infrastructure stores API keys in PostgreSQL (or memory for tests).
Package infrastructure stores API keys in PostgreSQL (or memory for tests).
Package audit records security events (logins, role changes, policy edits).
Package audit records security events (logins, role changes, policy edits).
Package config loads a guard.yaml file and wires Guard from it.
Package config loads a guard.yaml file and wires Guard from it.
examples
gin command
Command gin runs Guard's HTTP API on Gin, configured from a YAML file.
Command gin runs Guard's HTTP API on Gin, configured from a YAML file.
Package ginguard exposes Guard over Gin: ready-made auth/admin routes and middleware.
Package ginguard exposes Guard over Gin: ready-made auth/admin routes and middleware.
Package guardtest builds a Guard on in-memory storage (plus a Redis client for sessions) seeded like the SQL migrations.
Package guardtest builds a Guard on in-memory storage (plus a Redis client for sessions) seeded like the SQL migrations.
Package httpguard exposes Guard over net/http: ready-made auth/admin routes and middleware built on http.Handler, with no web framework dependency.
Package httpguard exposes Guard over net/http: ready-made auth/admin routes and middleware built on http.Handler, with no web framework dependency.
identity
application
Package application contains identity use cases.
Package application contains identity use cases.
domain
Package domain holds identity business rules: users, credentials, lockout.
Package domain holds identity business rules: users, credentials, lockout.
infrastructure
Package infrastructure provides identity adapters: argon2id hashing and PostgreSQL storage.
Package infrastructure provides identity adapters: argon2id hashing and PostgreSQL storage.
kernel
migrations
Package migrations ships Guard's PostgreSQL schema as goose migrations.
Package migrations ships Guard's PostgreSQL schema as goose migrations.
pgerr
Package pgerr classifies PostgreSQL errors returned through pgx.
Package pgerr classifies PostgreSQL errors returned through pgx.
Package ratelimit throttles requests with a Redis sliding-window log.
Package ratelimit throttles requests with a Redis sliding-window log.
session
application
Package application contains session use cases.
Package application contains session use cases.
domain
Package domain holds session business rules: lifetime, idle timeout, revocation.
Package domain holds session business rules: lifetime, idle timeout, revocation.
infrastructure
Package infrastructure stores sessions in Redis.
Package infrastructure stores sessions in Redis.

Jump to

Keyboard shortcuts

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