Documentation
¶
Overview ¶
Package middleware provides HTTP middleware for the API server. This file implements audit logging middleware for admin API endpoints.
Package middleware provides HTTP middleware for the API server. This file implements admin API key authentication middleware.
Index ¶
- Constants
- Variables
- func BodyLimit(maxBytes int64) func(http.Handler) http.Handler
- func CORS(cfg *config.CORSConfig) func(http.Handler) http.Handler
- func CORSWithEnvironment(cfg *config.CORSConfig, appEnv string) func(http.Handler) http.Handler
- func CSRF(cfg CSRFConfig) func(http.Handler) http.Handler
- func CSRFOptional(cfg CSRFConfig) func(http.Handler) http.Handler
- func CampaignRoleResolver(roleQuerier CampaignRoleQuerier) func(http.Handler) http.Handler
- func ClearCSRFTokenCookie(w http.ResponseWriter, cfg CSRFConfig)
- func ConcurrencyLimit(maxConcurrent int) func(http.Handler) http.Handler
- func ContextLogger(log *logger.Logger) func(http.Handler) http.Handler
- func Decompress(config *DecompressConfig) func(http.Handler) http.Handler
- func DecompressForIngest() func(http.Handler) http.Handler
- func DistributedRateLimit(cfg DistributedRateLimitConfig) func(http.Handler) http.Handler
- func EndpointKeyFunc(r *http.Request) string
- func ExtractResourceIDFromPath(path, prefix string) string
- func GenerateCSRFToken() (string, error)
- func GetAccessibleTenants(ctx context.Context) []string
- func GetAdminID(ctx context.Context) string
- func GetAdminRole(ctx context.Context) string
- func GetAdminUser(ctx context.Context) *admin.AdminUser
- func GetAuthProvider(ctx context.Context) string
- func GetCampaignID(ctx context.Context) string
- func GetCampaignRole(ctx context.Context) pentest.CampaignRole
- func GetCampaignStatus(ctx context.Context) pentest.CampaignStatus
- func GetClaims(ctx context.Context) *keycloak.Claims
- func GetCurrentPermVersion(ctx context.Context) int
- func GetEmail(ctx context.Context) string
- func GetFetchedPermissions(ctx context.Context) []string
- func GetLocalClaims(ctx context.Context) *jwt.Claims
- func GetLocalUser(ctx context.Context) *user.User
- func GetLocalUserID(ctx context.Context) shared.ID
- func GetPermissions(ctx context.Context) []string
- func GetRLSTx(ctx context.Context) *sql.Tx
- func GetRequestID(ctx context.Context) string
- func GetRole(ctx context.Context) string
- func GetRoles(ctx context.Context) []string
- func GetSessionID(ctx context.Context) string
- func GetTeamID(ctx context.Context) shared.ID
- func GetTeamMembership(ctx context.Context) *tenant.Membership
- func GetTeamRole(ctx context.Context) tenant.Role
- func GetTeamSlug(ctx context.Context) string
- func GetTenantID(ctx context.Context) string
- func GetTenantIDFromContext(ctx context.Context) (shared.ID, bool)
- func GetTenantMemberships(ctx context.Context) []jwt.TenantMembership
- func GetTenantRole(ctx context.Context) string
- func GetTenantRoles(ctx context.Context) []string
- func GetUserID(ctx context.Context) string
- func GetUserTenantRole(ctx context.Context, tenantID string) string
- func GetUsername(ctx context.Context) string
- func HandleBodyLimitError(w http.ResponseWriter, _ *http.Request)
- func HasAnyPermission(ctx context.Context, permissions ...string) bool
- func HasPermission(ctx context.Context, permission string) bool
- func HasPermissionFromCache(ctx context.Context, permission string) bool
- func HasTenantAccess(ctx context.Context, tenantID string) bool
- func HasTenantRole(ctx context.Context, tenantID string, requiredRole string) bool
- func IsAdmin(ctx context.Context) bool
- func IsOwner(ctx context.Context) bool
- func IsPermissionStale(ctx context.Context) bool
- func IsPlatformAdmin(ctx context.Context) bool
- func Logger(log *logger.Logger) func(http.Handler) http.Handler
- func LoggerWithConfig(log *logger.Logger, cfg LoggerConfig) func(http.Handler) http.Handler
- func Metrics() func(http.Handler) http.Handler
- func MustGetAdminUser(ctx context.Context) *admin.AdminUser
- func MustGetTenantID(ctx context.Context) string
- func OptionalUnifiedAuth(cfg UnifiedAuthConfig) func(http.Handler) http.Handler
- func PlatformAdminRLSMiddleware(db *sql.DB, log *logger.Logger) func(http.Handler) http.Handler
- func RLSContextMiddleware(db *sql.DB, log *logger.Logger) func(http.Handler) http.Handler
- func RateLimit(cfg *config.RateLimitConfig, log *logger.Logger) func(http.Handler) http.Handler
- func RateLimitWithStop(cfg *config.RateLimitConfig, log *logger.Logger) (func(http.Handler) http.Handler, func())
- func RecordAuthFailure(reason string)
- func RecordJobSubmitted(jobType, status string)
- func RecordJobValidationFailure(reason string)
- func RecordSecurityEvent(eventType string)
- func Recovery(log *logger.Logger) func(http.Handler) http.Handler
- func RecoveryWithConfig(log *logger.Logger, isProduction bool) func(http.Handler) http.Handler
- func RequestID() func(http.Handler) http.Handler
- func Require(perm permission.Permission) func(http.Handler) http.Handler
- func RequireAdmin() func(http.Handler) http.Handler
- func RequireAll(perms ...permission.Permission) func(http.Handler) http.Handler
- func RequireAny(perms ...permission.Permission) func(http.Handler) http.Handler
- func RequireCampaignRole(allowed ...pentest.CampaignRole) func(http.Handler) http.Handler
- func RequireCampaignWritable(allowExistingUpdates bool) func(http.Handler) http.Handler
- func RequireDeletePermission() func(http.Handler) http.Handler
- func RequireLocalUser() func(http.Handler) http.Handler
- func RequireMembership(tenantRepo tenant.Repository) func(http.Handler) http.Handler
- func RequireMinTeamRole(minRole tenant.Role) func(http.Handler) http.Handler
- func RequireMinTenantRole(minRole tenant.Role) func(http.Handler) http.Handler
- func RequireOwner() func(http.Handler) http.Handler
- func RequirePlatformAdmin() func(http.Handler) http.Handler
- func RequireRole(roles ...string) func(http.Handler) http.Handler
- func RequireTeamAdmin() func(http.Handler) http.Handler
- func RequireTeamOwner() func(http.Handler) http.Handler
- func RequireTeamRole(roles ...tenant.Role) func(http.Handler) http.Handler
- func RequireTeamWrite() func(http.Handler) http.Handler
- func RequireTenant() func(http.Handler) http.Handler
- func RequireTenantRole(roles ...tenant.Role) func(http.Handler) http.Handler
- func RequireWritePermission() func(http.Handler) http.Handler
- func SecurityHeaders() func(http.Handler) http.Handler
- func SecurityHeadersWithConfig(cfg SecurityHeadersConfig) func(http.Handler) http.Handler
- func SetAuditResourceName(ctx context.Context, name string)
- func SetCSRFTokenCookie(w http.ResponseWriter, token string, cfg CSRFConfig)
- func SetCampaignContext(ctx context.Context, role pentest.CampaignRole, status pentest.CampaignStatus, ...) context.Context
- func SetTeamDBContext(db *sql.DB) func(http.Handler) http.Handler
- func TenantContext(tenantRepo tenant.Repository) func(http.Handler) http.Handler
- func Timeout(timeout time.Duration) func(http.Handler) http.Handler
- func Tracing(serviceName string) func(http.Handler) http.Handler
- func UnifiedAuth(cfg UnifiedAuthConfig) func(http.Handler) http.Handler
- func UserKeyFunc(r *http.Request) string
- func UserSync(userService *app.UserService, log *logger.Logger) func(http.Handler) http.Handler
- type AITriageRateLimitConfig
- type AITriageRateLimiter
- type AdminAuthMiddleware
- type AdminMappingRateLimitConfig
- type AdminMappingRateLimiter
- type AnalyticsRateLimitConfig
- type AnalyticsRateLimiter
- type AuditMiddleware
- func (m *AuditMiddleware) AuditAction(action string) func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditAdminCreate() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditAdminDelete() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditAdminUpdate() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditAgentCreate() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditAgentDelete() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditAgentDisable() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditAgentEnable() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditAgentUpdate() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditJobCancel() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditLog(action, resourceType, resourceIDParam string) func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditResourceAction(action, resourceType string) func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditTargetMappingCreate() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditTargetMappingDelete() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditTargetMappingUpdate() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditTokenCreate() func(http.Handler) http.Handler
- func (m *AuditMiddleware) AuditTokenRevoke() func(http.Handler) http.Handler
- func (m *AuditMiddleware) LogAuthFailure(r *http.Request, reason string)
- func (m *AuditMiddleware) LogAuthSuccess(r *http.Request, adminUser *admin.AdminUser)
- type AuthFailureLimiter
- type AuthFailureLimiterConfig
- type AuthRateLimitConfig
- type AuthRateLimiter
- func (a *AuthRateLimiter) LoginMiddleware() func(http.Handler) http.Handler
- func (a *AuthRateLimiter) PasswordMiddleware() func(http.Handler) http.Handler
- func (a *AuthRateLimiter) RegisterMiddleware() func(http.Handler) http.Handler
- func (a *AuthRateLimiter) Stop()
- func (a *AuthRateLimiter) TokenExchangeMiddleware() func(http.Handler) http.Handler
- type CSRFConfig
- type CampaignRoleQuerier
- type CampaignStatusQuerier
- type DecompressConfig
- type DistributedRateLimitConfig
- type FindingActivityRateLimitConfig
- type FindingActivityRateLimiter
- type LoggerConfig
- type PermissionSyncMiddleware
- type PlatformRegistrationRateLimitConfig
- type PlatformRegistrationRateLimiter
- type RateLimiter
- type ReadEndpointRateLimitConfig
- type ReadEndpointRateLimiter
- type SecurityHeadersConfig
- type TriggerRateLimitConfig
- type TriggerRateLimiter
- type UnifiedAuthConfig
Constants ¶
const ( AdminUserKey logger.ContextKey = "admin_user" AdminIDKey logger.ContextKey = "admin_id" AdminRoleKey logger.ContextKey = "admin_role" )
Admin auth context keys.
const ( UserIDKey = logger.ContextKeyUserID RoleKey logger.ContextKey = "role" RolesKey logger.ContextKey = "roles" // All realm roles EmailKey logger.ContextKey = "email" // User email UsernameKey logger.ContextKey = "username" // Preferred username TenantIDKey logger.ContextKey = "tenant_id" // Multi-tenant: tenant identifier TenantRoleKey logger.ContextKey = "tenant_role" // Multi-tenant: primary role within tenant TenantRolesKey logger.ContextKey = "tenant_roles" // Multi-tenant: all roles within tenant ClaimsKey logger.ContextKey = "keycloak_claims" // Full Keycloak claims for UserSync )
Auth-related context keys - use logger.ContextKey for consistency.
const ( CampaignRoleKey logger.ContextKey = "campaign_role" CampaignStatusKey logger.ContextKey = "campaign_status" CampaignIDKey logger.ContextKey = "campaign_id" )
Campaign RBAC context keys.
const ( // CSRFTokenCookieName is the name of the cookie storing the CSRF token. // This cookie is NOT httpOnly so JavaScript can read it. CSRFTokenCookieName = "csrf_token" // CSRFHeaderName is the header name where the CSRF token should be sent. CSRFHeaderName = "X-CSRF-Token" // CSRFTokenLength is the length of the CSRF token in bytes. CSRFTokenLength = 32 )
const ( // FetchedPermissionsKey stores permissions fetched from Redis/DB (not from JWT). FetchedPermissionsKey logger.ContextKey = "fetched_permissions" // PermVersionKey stores the current permission version from Redis. PermVersionKey logger.ContextKey = "perm_version" // PermStaleKey indicates if the JWT permission version is stale. PermStaleKey logger.ContextKey = "perm_stale" )
PermSyncContextKey is a context key for permission sync data.
const ( // HeaderPermissionStale is set to "true" when JWT permission version doesn't match Redis. HeaderPermissionStale = "X-Permission-Stale" // HeaderPermissionVersion contains the current permission version from Redis. HeaderPermissionVersion = "X-Permission-Version" )
Response headers for permission sync.
const ( SecurityEventAuthFailure = "security.auth.failure" SecurityEventAgentNotFound = "security.agent.not_found" SecurityEventAPIKeyInvalid = "security.apikey.invalid" SecurityEventAgentInactive = "security.agent.inactive" SecurityEventAgentTypeMismatch = "security.agent.type_mismatch" SecurityEventJobAccessDenied = "security.job.access_denied" SecurityEventTokenInvalid = "security.token.invalid" )
Security event constants for logging and metrics.
const ( TeamIDKey logger.ContextKey = "team_id" // shared.ID from URL/database TeamSlugKey logger.ContextKey = "team_slug" // slug string TeamRoleKey logger.ContextKey = "team_role" // tenant.Role from membership MembershipKey logger.ContextKey = "membership" // *tenant.Membership )
Tenant-related context keys for database-based multi-tenancy. These are separate from auth.go's JWT-based tenant keys.
const ( SessionIDKey logger.ContextKey = "session_id" PermissionsKey logger.ContextKey = "permissions" IsAdminKey logger.ContextKey = "is_admin" AuthProviderKey logger.ContextKey = "auth_provider" LocalClaimsKey logger.ContextKey = "local_claims" TenantMembershipsKey logger.ContextKey = "tenant_memberships" AccessibleTenantsKey logger.ContextKey = "accessible_tenants" )
Additional context keys for local auth.
const ( AuthProviderLocal = "local" AuthProviderOIDC = "oidc" )
AuthProvider values for context.
const AdminAPIKeyHeader = "X-Admin-API-Key"
AdminAPIKeyHeader is the header name for admin API key authentication.
const DefaultAccessTokenCookieName = "auth_token"
DefaultAccessTokenCookieName is the default cookie name for access tokens. This should match the frontend's auth.cookieName configuration.
const DefaultMaxBodySize = 10 << 20 // 10 MB
DefaultMaxBodySize is the default maximum request body size (10MB).
const DefaultMaxConcurrentRequests = 1000
DefaultMaxConcurrentRequests is the default maximum number of concurrent requests.
const IngestMaxBodySize = 50 << 20 // 50 MB
IngestMaxBodySize is the maximum request body size for ingest endpoints (50MB).
const LocalUserKey logger.ContextKey = "local_user"
LocalUserKey is the context key for the local user entity.
const (
RequestIDKey = logger.ContextKeyRequestID
)
Use context keys from logger package for consistency.
Variables ¶
var ( // SecurityEventsTotal counts security events by type SecurityEventsTotal = promauto.NewCounterVec( prometheus.CounterOpts{ Name: "security_events_total", Help: "Total number of security events", }, []string{"event_type"}, ) // AuthFailuresTotal counts authentication failures by type AuthFailuresTotal = promauto.NewCounterVec( prometheus.CounterOpts{ Name: "auth_failures_total", Help: "Total number of authentication failures", }, []string{"reason"}, ) // BannedIPsGauge tracks currently banned IPs BannedIPsGauge = promauto.NewGauge( prometheus.GaugeOpts{ Name: "banned_ips_current", Help: "Current number of banned IPs due to auth failures", }, ) // PlatformJobsSubmitted counts platform jobs submitted PlatformJobsSubmitted = promauto.NewCounterVec( prometheus.CounterOpts{ Name: "platform_jobs_submitted_total", Help: "Total number of platform jobs submitted", }, []string{"type", "status"}, ) // PlatformAgentsActive tracks active platform agents PlatformAgentsActive = promauto.NewGauge( prometheus.GaugeOpts{ Name: "platform_agents_active", Help: "Current number of active platform agents", }, ) // JobValidationFailures counts job validation failures by reason JobValidationFailures = promauto.NewCounterVec( prometheus.CounterOpts{ Name: "job_validation_failures_total", Help: "Total number of job validation failures", }, []string{"reason"}, ) )
Functions ¶
func BodyLimit ¶
BodyLimit limits the maximum size of request bodies. If maxBytes is 0, DefaultMaxBodySize is used.
func CORS ¶
CORS adds CORS headers based on configuration. Deprecated: Use CORSWithEnvironment for production-safe CORS handling.
func CORSWithEnvironment ¶ added in v0.1.2
CORSWithEnvironment creates a CORS middleware that enforces environment-specific rules. In production (APP_ENV=production), wildcard "*" origins are rejected at config validation. This function adds runtime enforcement as a defense-in-depth measure.
func CSRF ¶
func CSRF(cfg CSRFConfig) func(http.Handler) http.Handler
CSRF returns a middleware that validates CSRF tokens using Double Submit Cookie pattern. It compares the token in the cookie with the token sent in the X-CSRF-Token header. Safe methods (GET, HEAD, OPTIONS) are exempt from CSRF validation.
func CSRFOptional ¶
func CSRFOptional(cfg CSRFConfig) func(http.Handler) http.Handler
CSRFOptional is like CSRF but only validates if a CSRF cookie is present. Useful for endpoints that can be called both with and without cookies.
func CampaignRoleResolver ¶ added in v0.1.3
func CampaignRoleResolver(roleQuerier CampaignRoleQuerier) func(http.Handler) http.Handler
CampaignRoleResolver creates a middleware that resolves the user's campaign role from the database and stores it in the request context. It uses the {id} URL parameter for the campaign ID. Admin users bypass the DB query entirely.
func ClearCSRFTokenCookie ¶
func ClearCSRFTokenCookie(w http.ResponseWriter, cfg CSRFConfig)
ClearCSRFTokenCookie removes the CSRF token cookie.
func ConcurrencyLimit ¶ added in v0.1.2
ConcurrencyLimit creates a middleware that limits the number of concurrent requests using a semaphore pattern. When the limit is reached, new requests receive a 503 Service Unavailable response.
A maxConcurrent value of 0 or less disables the limit.
func ContextLogger ¶ added in v0.1.2
ContextLogger injects a request-scoped logger into the request context. The logger is enriched with request_id and user_id (when available). Services can retrieve it via logger.FromContext(ctx) for automatic request correlation in logs.
func Decompress ¶
func Decompress(config *DecompressConfig) func(http.Handler) http.Handler
Decompress middleware decompresses request bodies based on Content-Encoding header. Supports gzip and zstd compression.
This middleware should be placed BEFORE body limit middleware to properly limit the decompressed size, not the compressed size.
Example:
router.Use(middleware.Decompress(nil)) router.Use(middleware.BodyLimit(50 * 1024 * 1024)) // 50MB decompressed limit
func DecompressForIngest ¶
DecompressForIngest is a variant specifically for ingest endpoints. It has a higher size limit (100MB) to accommodate large scan reports. SECURITY: Maintains zipbomb protection with higher limits.
func DistributedRateLimit ¶
func DistributedRateLimit(cfg DistributedRateLimitConfig) func(http.Handler) http.Handler
DistributedRateLimit creates middleware using Redis-backed rate limiting. Essential for production multi-instance deployments where in-memory rate limiting is insufficient.
Example usage:
rateLimiter, _ := redis.NewRateLimiter(client, "api", 100, time.Minute, log)
adapter := redis.NewMiddlewareAdapter(rateLimiter)
router.Use(middleware.DistributedRateLimit(middleware.DistributedRateLimitConfig{
Limiter: adapter,
Logger: log,
}))
func EndpointKeyFunc ¶
EndpointKeyFunc returns a key function that includes the endpoint. Useful for per-endpoint rate limiting.
func ExtractResourceIDFromPath ¶
ExtractResourceIDFromPath extracts a resource ID from the URL path. Useful for DELETE operations where the ID might not be in chi params yet.
func GenerateCSRFToken ¶
GenerateCSRFToken generates a cryptographically secure CSRF token.
func GetAccessibleTenants ¶
GetAccessibleTenants extracts the list of tenant IDs the user has access to.
func GetAdminID ¶
GetAdminID extracts the admin ID from context.
func GetAdminRole ¶
GetAdminRole extracts the admin role from context.
func GetAdminUser ¶
GetAdminUser extracts the admin user from context.
func GetAuthProvider ¶
GetAuthProvider extracts the auth provider from context.
func GetCampaignID ¶ added in v0.1.3
GetCampaignID returns the campaign ID from context.
func GetCampaignRole ¶ added in v0.1.3
func GetCampaignRole(ctx context.Context) pentest.CampaignRole
GetCampaignRole returns the user's campaign role from context.
func GetCampaignStatus ¶ added in v0.1.3
func GetCampaignStatus(ctx context.Context) pentest.CampaignStatus
GetCampaignStatus returns the campaign status from context.
func GetCurrentPermVersion ¶
GetCurrentPermVersion returns the current permission version from Redis.
func GetFetchedPermissions ¶
GetFetchedPermissions returns permissions fetched from Redis/DB.
func GetLocalClaims ¶
GetLocalClaims extracts local JWT claims from context.
func GetLocalUser ¶
GetLocalUser extracts the local user entity from context.
func GetLocalUserID ¶
GetLocalUserID extracts the local user ID from context. Returns zero ID if no local user is in context.
func GetPermissions ¶
GetPermissions extracts the permissions from context.
func GetRLSTx ¶
GetRLSTx retrieves the RLS transaction from context. Returns nil if no transaction is set.
func GetRequestID ¶
GetRequestID extracts the request ID from context.
func GetSessionID ¶
GetSessionID extracts the session ID from context.
func GetTeamMembership ¶
func GetTeamMembership(ctx context.Context) *tenant.Membership
GetTeamMembership extracts the membership from context.
func GetTeamRole ¶
GetTeamRole extracts the user's role in the team from context.
func GetTeamSlug ¶
GetTeamSlug extracts the team slug from context.
func GetTenantID ¶
GetTenantID extracts the tenant ID from context.
func GetTenantIDFromContext ¶
GetTenantIDFromContext extracts tenant ID from context. This is a helper that wraps the existing middleware function.
func GetTenantMemberships ¶
func GetTenantMemberships(ctx context.Context) []jwt.TenantMembership
GetTenantMemberships extracts tenant memberships from context.
func GetTenantRole ¶
GetTenantRole extracts the primary tenant role from context.
func GetTenantRoles ¶
GetTenantRoles extracts all tenant roles from context.
func GetUserTenantRole ¶
GetUserTenantRole returns the user's role in a specific tenant.
func GetUsername ¶
GetUsername extracts the preferred username from context.
func HandleBodyLimitError ¶
func HandleBodyLimitError(w http.ResponseWriter, _ *http.Request)
BodyLimitHandler is an error handler for body limit exceeded. Use this in your error handling middleware to catch http.MaxBytesError.
func HasAnyPermission ¶
HasAnyPermission checks if the user has any of the specified permissions.
func HasPermission ¶
HasPermission checks if the user has a specific permission. Owner/Admin (IsAdmin flag in JWT) bypass permission checks - they have almost all permissions. Member/Viewer/Custom roles: permissions fetched from DB (not in JWT). For owner-only operations, use IsOwner() or RequireOwner() middleware.
func HasPermissionFromCache ¶
HasPermissionFromCache checks if user has a permission using fetched permissions. Unlike HasPermission which uses JWT permissions + IsAdmin bypass, this always uses the latest permissions from cache.
NOTE: For backward compatibility, use HasPermission which still works. This function is for explicit cache-based permission checks.
func HasTenantAccess ¶
HasTenantAccess checks if the user has access to a specific tenant.
func HasTenantRole ¶
HasTenantRole checks if user has a specific role (or higher) in a tenant.
func IsAdmin ¶
IsAdmin checks if the user has admin flag set (owner or admin role). When true, the user bypasses general permission checks. For owner-only operations (team delete, billing), use IsOwner() instead.
func IsOwner ¶
IsOwner checks if the user has the owner role. Use this for owner-only operations like team deletion, billing management.
func IsPermissionStale ¶
IsPermissionStale returns true if the JWT permission version doesn't match Redis.
func IsPlatformAdmin ¶
IsPlatformAdmin checks if the user has platform admin privileges. Platform admins can manage platform-wide resources like platform agents. This is typically granted to OpenCTEM staff or system administrators.
Platform admin is determined by: 1. Having "platform_admin" role in RealmAccess (for OIDC/Keycloak) 2. Being the system admin (for local auth - checks specific user IDs or emails)
func LoggerWithConfig ¶
LoggerWithConfig logs HTTP requests with configurable behavior. Use this for production to skip health checks and reduce log volume.
func MustGetAdminUser ¶
MustGetAdminUser extracts admin user from context or panics if not found. Use this in handlers protected by Authenticate() middleware.
func MustGetTenantID ¶
MustGetTenantID extracts tenant ID from context or panics if not found. Use this in handlers protected by RequireTenant() middleware. Panics indicate a programming error (missing middleware), not a user error.
func OptionalUnifiedAuth ¶
func OptionalUnifiedAuth(cfg UnifiedAuthConfig) func(http.Handler) http.Handler
OptionalUnifiedAuth creates an optional authentication middleware. It extracts claims if present but doesn't require authentication.
func PlatformAdminRLSMiddleware ¶
PlatformAdminRLSMiddleware sets the platform admin bypass for RLS. This middleware should be used for platform admin routes that need cross-tenant access.
Usage:
adminRouter.Use(PlatformAdminAuthMiddleware)
adminRouter.Use(PlatformAdminRLSMiddleware(db, log))
adminRouter.Get("/all-findings", handler.ListAllFindings)
func RLSContextMiddleware ¶
RLSContextMiddleware sets the PostgreSQL session variable for Row Level Security. This middleware should be applied AFTER authentication middleware.
How it works:
- Extracts tenant_id from the authenticated context
- Begins a database transaction
- Sets `app.current_tenant_id` session variable for RLS policies
- Stores the transaction in context for handlers to use
- Commits/rollbacks based on response status
Usage in routes:
router.Use(authMiddleware)
router.Use(RLSContextMiddleware(db, log))
router.Get("/findings", handler.ListFindings) // RLS automatically filters
func RateLimit ¶
RateLimit creates a rate limiting middleware from config. Note: For proper cleanup, use RateLimitWithStop instead.
func RateLimitWithStop ¶
func RateLimitWithStop(cfg *config.RateLimitConfig, log *logger.Logger) (func(http.Handler) http.Handler, func())
RateLimitWithStop creates a rate limiting middleware and returns a stop function. The stop function should be called during graceful shutdown.
func RecordAuthFailure ¶
func RecordAuthFailure(reason string)
RecordAuthFailure increments the auth failure counter.
func RecordJobSubmitted ¶
func RecordJobSubmitted(jobType, status string)
RecordJobSubmitted increments the job submitted counter.
func RecordJobValidationFailure ¶
func RecordJobValidationFailure(reason string)
RecordJobValidationFailure increments the validation failure counter.
func RecordSecurityEvent ¶
func RecordSecurityEvent(eventType string)
RecordSecurityEvent increments the security event counter.
func Recovery ¶
Recovery recovers from panics and returns a 500 error. In production, stack traces are omitted from logs to prevent information leakage.
func RecoveryWithConfig ¶
RecoveryWithConfig is like Recovery but accepts a production mode flag. SECURITY: In production, stack traces are omitted to prevent sensitive path/code information from being exposed in logs.
func Require ¶
func Require(perm permission.Permission) func(http.Handler) http.Handler
Require creates a middleware that requires a specific permission. Uses permission.Permission constants for type safety.
Example:
r.POST("/", middleware.Require(permission.AssetsWrite)(handler))
r.DELETE("/{id}", middleware.Require(permission.AssetsDelete)(handler))
func RequireAdmin ¶
RequireAdmin creates a middleware that requires admin access (owner or admin role).
func RequireAll ¶
func RequireAll(perms ...permission.Permission) func(http.Handler) http.Handler
RequireAll creates a middleware that requires all of the specified permissions. Uses permission.Permission constants for type safety.
Example:
r.POST("/", middleware.RequireAll(permission.AssetsWrite, permission.RepositoriesWrite)(handler))
func RequireAny ¶
func RequireAny(perms ...permission.Permission) func(http.Handler) http.Handler
RequireAny creates a middleware that requires any of the specified permissions. Uses permission.Permission constants for type safety.
Example:
r.GET("/", middleware.RequireAny(permission.AssetsRead, permission.RepositoriesRead)(handler))
func RequireCampaignRole ¶ added in v0.1.3
RequireCampaignRole creates a middleware that checks the user's campaign role. Admin/owner bypasses the check. If no campaign role is set (not a member), returns 404 to avoid revealing campaign existence.
func RequireCampaignWritable ¶ added in v0.1.3
RequireCampaignWritable creates a middleware that blocks writes on locked campaigns. allowExistingUpdates: if true, on_hold campaigns allow updating existing items.
func RequireDeletePermission ¶
RequireDeletePermission allows owner and admin roles only.
func RequireLocalUser ¶
RequireLocalUser ensures a local user exists in context. Use this for endpoints that require user data from the local database.
func RequireMembership ¶
RequireMembership verifies the authenticated user is a member of the tenant AND that the membership is currently active (not suspended). This is the canonical enforcement point for member suspension — it runs on every tenant-scoped request, so suspension takes effect immediately even if the user is holding a still-valid JWT.
Must be used after KeycloakAuth, UserSync, and TenantContext middleware.
func RequireMinTeamRole ¶
RequireMinTeamRole checks if the user has at least the minimum role level. Uses role hierarchy: owner > admin > member > viewer.
func RequireMinTenantRole ¶
RequireMinTenantRole checks if the user has at least the minimum role level. Uses role hierarchy: owner > admin > member > viewer.
func RequireOwner ¶
RequireOwner creates a middleware that requires owner role. Use this for sensitive operations that only the owner should perform: - TeamDelete: Deleting the tenant - BillingManage: Managing billing settings - GroupsDelete, PermissionSetsDelete, AssignmentRulesDelete: Deleting access control resources
func RequirePlatformAdmin ¶
RequirePlatformAdmin creates a middleware that requires platform admin access. Platform admins can manage OpenCTEM's shared infrastructure like platform agents. This is for OpenCTEM operators, not regular tenant admins.
func RequireRole ¶
RequireRole checks if the user has one of the required roles.
func RequireTeamAdmin ¶
RequireTeamAdmin checks if the user has admin permissions in the team.
func RequireTeamOwner ¶
RequireTeamOwner checks if the user is the owner of the team.
func RequireTeamRole ¶
RequireTeamRole checks if the user has one of the required roles in the team. Must be used after RequireMembership middleware.
func RequireTeamWrite ¶
RequireTeamWrite checks if the user has write permissions in the team.
func RequireTenant ¶
RequireTenant ensures the request has a valid tenant ID.
func RequireTenantRole ¶
RequireTenantRole checks if the user has one of the required roles within the tenant. Uses role from JWT token claims.
func RequireWritePermission ¶
RequireWritePermission allows owner, admin, and member roles.
func SecurityHeaders ¶
SecurityHeaders adds security-related HTTP headers.
func SecurityHeadersWithConfig ¶
func SecurityHeadersWithConfig(cfg SecurityHeadersConfig) func(http.Handler) http.Handler
SecurityHeadersWithConfig adds security headers with custom configuration.
func SetAuditResourceName ¶
SetAuditResourceName sets the resource name in the current request's audit log. Call this from handlers to provide more context for audit logs.
func SetCSRFTokenCookie ¶
func SetCSRFTokenCookie(w http.ResponseWriter, token string, cfg CSRFConfig)
SetCSRFTokenCookie sets the CSRF token in a JavaScript-readable cookie. This is NOT httpOnly so that frontend JavaScript can read and send it in headers.
func SetCampaignContext ¶ added in v0.1.3
func SetCampaignContext(ctx context.Context, role pentest.CampaignRole, status pentest.CampaignStatus, campaignID string) context.Context
SetCampaignContext returns a context with campaign role, status, and ID set.
func SetTeamDBContext ¶
SetTeamDBContext sets the team context for database RLS.
func TenantContext ¶
TenantContext extracts tenant ID from URL path parameter and adds to context. It expects the path parameter to be named "tenant" (e.g., /tenants/{tenant}/assets). The {tenant} can be either a tenant ID (UUID) or tenant slug.
func Timeout ¶
Timeout adds a timeout to each request context. If the handler takes longer than the timeout, the request is canceled.
func Tracing ¶ added in v0.1.2
Tracing returns an OpenTelemetry tracing middleware that creates spans for each HTTP request and propagates trace context.
func UnifiedAuth ¶
func UnifiedAuth(cfg UnifiedAuthConfig) func(http.Handler) http.Handler
UnifiedAuth creates an authentication middleware that supports both local and OIDC authentication. The middleware tries to validate tokens based on the configured auth provider: - "local": Only validates local JWT tokens - "oidc": Only validates Keycloak/OIDC tokens - "hybrid": Tries local first, then falls back to OIDC
Token extraction order: 1. Authorization header (Bearer <token>) 2. Query parameter "token" (for SSE/EventSource which can't send headers)
func UserKeyFunc ¶
UserKeyFunc returns a key function that uses authenticated user ID. Falls back to IP address for unauthenticated requests.
func UserSync ¶
UserSync middleware syncs authenticated users to the local database. It runs AFTER auth middleware (UnifiedAuth or KeycloakAuth) and creates/updates user records. Performance optimization: - First request: creates user if not exists - Subsequent requests: only updates last_login_at every 24 hours This enables: - Local user management independent of Keycloak - User-specific data (preferences, profile) stored locally - Future migration away from Keycloak Supports both local auth (LocalClaimsKey) and OIDC auth (ClaimsKey).
Types ¶
type AITriageRateLimitConfig ¶
type AITriageRateLimitConfig struct {
// TriageRequestsPerMin is the max triage requests per minute per tenant.
// Default: 10 (AI calls are expensive)
TriageRequestsPerMin int
// CleanupInterval for visitor entries.
// Default: 1 minute
CleanupInterval time.Duration
}
AITriageRateLimitConfig configures AI triage rate limits.
func DefaultAITriageRateLimitConfig ¶
func DefaultAITriageRateLimitConfig() AITriageRateLimitConfig
DefaultAITriageRateLimitConfig returns secure defaults for AI triage rate limiting.
type AITriageRateLimiter ¶
type AITriageRateLimiter struct {
// contains filtered or unexported fields
}
AITriageRateLimiter provides rate limiting for AI triage endpoints. This prevents abuse of expensive LLM API calls.
func NewAITriageRateLimiter ¶
func NewAITriageRateLimiter(cfg AITriageRateLimitConfig, log *logger.Logger) *AITriageRateLimiter
NewAITriageRateLimiter creates a rate limiter for AI triage endpoints.
func (*AITriageRateLimiter) RequestMiddleware ¶
func (a *AITriageRateLimiter) RequestMiddleware() func(http.Handler) http.Handler
RequestMiddleware returns middleware for AI triage request endpoints (POST). Uses tenant ID as the rate limit key for per-tenant limiting.
func (*AITriageRateLimiter) Stop ¶
func (a *AITriageRateLimiter) Stop()
Stop gracefully shuts down the rate limiter.
type AdminAuthMiddleware ¶
type AdminAuthMiddleware struct {
// contains filtered or unexported fields
}
AdminAuthMiddleware provides authentication for admin API endpoints.
func NewAdminAuthMiddleware ¶
func NewAdminAuthMiddleware(adminRepo admin.Repository, log *logger.Logger) *AdminAuthMiddleware
NewAdminAuthMiddleware creates a new AdminAuthMiddleware.
func (*AdminAuthMiddleware) Authenticate ¶
func (m *AdminAuthMiddleware) Authenticate(next http.Handler) http.Handler
Authenticate validates the admin API key and adds admin info to context. Use this middleware for all admin endpoints.
func (*AdminAuthMiddleware) RequirePermission ¶
RequirePermission creates middleware that requires a specific permission. Use after Authenticate middleware.
func (*AdminAuthMiddleware) RequireRole ¶
RequireRole creates middleware that requires a specific admin role. Use after Authenticate middleware.
type AdminMappingRateLimitConfig ¶
type AdminMappingRateLimitConfig struct {
// WriteRequestsPerMin is the max write requests per minute per admin.
// Default: 10 (as per RFC 2026-02-02-asset-types-cleanup.md)
WriteRequestsPerMin int
// CleanupInterval for visitor entries.
// Default: 1 minute
CleanupInterval time.Duration
}
AdminMappingRateLimitConfig configures admin mapping rate limits.
func DefaultAdminMappingRateLimitConfig ¶
func DefaultAdminMappingRateLimitConfig() AdminMappingRateLimitConfig
DefaultAdminMappingRateLimitConfig returns secure defaults for admin mapping rate limiting.
type AdminMappingRateLimiter ¶
type AdminMappingRateLimiter struct {
// contains filtered or unexported fields
}
AdminMappingRateLimiter provides rate limiting for admin target mapping endpoints. This prevents abuse of admin configuration APIs.
func NewAdminMappingRateLimiter ¶
func NewAdminMappingRateLimiter(cfg AdminMappingRateLimitConfig, log *logger.Logger) *AdminMappingRateLimiter
NewAdminMappingRateLimiter creates a rate limiter for admin target mapping endpoints.
func (*AdminMappingRateLimiter) Stop ¶
func (a *AdminMappingRateLimiter) Stop()
Stop gracefully shuts down the rate limiter.
func (*AdminMappingRateLimiter) WriteMiddleware ¶
func (a *AdminMappingRateLimiter) WriteMiddleware() func(http.Handler) http.Handler
WriteMiddleware returns middleware for admin mapping write endpoints (POST/PATCH/DELETE). Uses admin ID (from context) or IP as the rate limit key.
type AnalyticsRateLimitConfig ¶
type AnalyticsRateLimitConfig struct {
// ListRequestsPerMin is the max list requests per minute per tenant.
// Default: 60 (1 per second)
ListRequestsPerMin int
// AggregatedRequestsPerMin is the max aggregated stats requests per minute per tenant.
// Default: 30 (more expensive queries)
AggregatedRequestsPerMin int
// CleanupInterval for visitor entries.
// Default: 1 minute
CleanupInterval time.Duration
}
AnalyticsRateLimitConfig configures analytics-specific rate limits.
func DefaultAnalyticsRateLimitConfig ¶
func DefaultAnalyticsRateLimitConfig() AnalyticsRateLimitConfig
DefaultAnalyticsRateLimitConfig returns secure defaults for analytics rate limiting.
type AnalyticsRateLimiter ¶
type AnalyticsRateLimiter struct {
// contains filtered or unexported fields
}
AnalyticsRateLimiter provides rate limiting for agent analytics endpoints. This prevents abuse and ensures fair resource usage for analytics queries.
func NewAnalyticsRateLimiter ¶
func NewAnalyticsRateLimiter(cfg AnalyticsRateLimitConfig, log *logger.Logger) *AnalyticsRateLimiter
NewAnalyticsRateLimiter creates a rate limiter for analytics endpoints.
func (*AnalyticsRateLimiter) AggregatedMiddleware ¶
func (a *AnalyticsRateLimiter) AggregatedMiddleware() func(http.Handler) http.Handler
AggregatedMiddleware returns middleware for aggregated stats endpoints. Uses tenant ID (or user ID for admin) as the rate limit key. More restrictive as aggregated queries are more expensive.
func (*AnalyticsRateLimiter) ListMiddleware ¶
func (a *AnalyticsRateLimiter) ListMiddleware() func(http.Handler) http.Handler
ListMiddleware returns middleware for analytics list endpoints. Uses tenant ID (or user ID for admin) as the rate limit key.
func (*AnalyticsRateLimiter) Stop ¶
func (a *AnalyticsRateLimiter) Stop()
Stop gracefully shuts down all rate limiters.
type AuditMiddleware ¶
type AuditMiddleware struct {
// contains filtered or unexported fields
}
AuditMiddleware provides audit logging for admin API endpoints.
func NewAuditMiddleware ¶
func NewAuditMiddleware(auditRepo admin.AuditLogRepository, log *logger.Logger) *AuditMiddleware
NewAuditMiddleware creates a new AuditMiddleware.
func (*AuditMiddleware) AuditAction ¶
AuditAction creates a simpler audit middleware for actions without URL params.
func (*AuditMiddleware) AuditAdminCreate ¶
func (m *AuditMiddleware) AuditAdminCreate() func(http.Handler) http.Handler
AuditAdminCreate returns middleware for admin user creation.
func (*AuditMiddleware) AuditAdminDelete ¶
func (m *AuditMiddleware) AuditAdminDelete() func(http.Handler) http.Handler
AuditAdminDelete returns middleware for admin user deletion.
func (*AuditMiddleware) AuditAdminUpdate ¶
func (m *AuditMiddleware) AuditAdminUpdate() func(http.Handler) http.Handler
AuditAdminUpdate returns middleware for admin user updates.
func (*AuditMiddleware) AuditAgentCreate ¶
func (m *AuditMiddleware) AuditAgentCreate() func(http.Handler) http.Handler
AuditAgentCreate returns middleware for platform agent creation.
func (*AuditMiddleware) AuditAgentDelete ¶
func (m *AuditMiddleware) AuditAgentDelete() func(http.Handler) http.Handler
AuditAgentDelete returns middleware for platform agent deletion.
func (*AuditMiddleware) AuditAgentDisable ¶
func (m *AuditMiddleware) AuditAgentDisable() func(http.Handler) http.Handler
AuditAgentDisable returns middleware for disabling platform agents.
func (*AuditMiddleware) AuditAgentEnable ¶
func (m *AuditMiddleware) AuditAgentEnable() func(http.Handler) http.Handler
AuditAgentEnable returns middleware for enabling platform agents.
func (*AuditMiddleware) AuditAgentUpdate ¶
func (m *AuditMiddleware) AuditAgentUpdate() func(http.Handler) http.Handler
AuditAgentUpdate returns middleware for platform agent updates.
func (*AuditMiddleware) AuditJobCancel ¶
func (m *AuditMiddleware) AuditJobCancel() func(http.Handler) http.Handler
AuditJobCancel returns middleware for platform job cancellation.
func (*AuditMiddleware) AuditLog ¶
func (m *AuditMiddleware) AuditLog(action, resourceType, resourceIDParam string) func(http.Handler) http.Handler
AuditLog creates middleware that logs admin actions to the audit log. Should be used after AdminAuthMiddleware.Authenticate().
Parameters:
- action: The action being performed (e.g., "agent.create", "token.revoke")
- resourceType: The type of resource (e.g., "agent", "token")
- resourceIDParam: The chi URL param name for resource ID (e.g., "id", "agentID")
func (*AuditMiddleware) AuditResourceAction ¶
func (m *AuditMiddleware) AuditResourceAction(action, resourceType string) func(http.Handler) http.Handler
AuditResourceAction creates audit middleware for resource-specific actions.
func (*AuditMiddleware) AuditTargetMappingCreate ¶
func (m *AuditMiddleware) AuditTargetMappingCreate() func(http.Handler) http.Handler
AuditTargetMappingCreate returns middleware for target mapping creation.
func (*AuditMiddleware) AuditTargetMappingDelete ¶
func (m *AuditMiddleware) AuditTargetMappingDelete() func(http.Handler) http.Handler
AuditTargetMappingDelete returns middleware for target mapping deletion.
func (*AuditMiddleware) AuditTargetMappingUpdate ¶
func (m *AuditMiddleware) AuditTargetMappingUpdate() func(http.Handler) http.Handler
AuditTargetMappingUpdate returns middleware for target mapping updates.
func (*AuditMiddleware) AuditTokenCreate ¶
func (m *AuditMiddleware) AuditTokenCreate() func(http.Handler) http.Handler
AuditTokenCreate returns middleware for bootstrap token creation.
func (*AuditMiddleware) AuditTokenRevoke ¶
func (m *AuditMiddleware) AuditTokenRevoke() func(http.Handler) http.Handler
AuditTokenRevoke returns middleware for bootstrap token revocation.
func (*AuditMiddleware) LogAuthFailure ¶
func (m *AuditMiddleware) LogAuthFailure(r *http.Request, reason string)
LogAuthFailure logs a failed authentication attempt.
func (*AuditMiddleware) LogAuthSuccess ¶
func (m *AuditMiddleware) LogAuthSuccess(r *http.Request, adminUser *admin.AdminUser)
LogAuthSuccess logs a successful authentication.
type AuthFailureLimiter ¶
type AuthFailureLimiter struct {
// contains filtered or unexported fields
}
AuthFailureLimiter tracks auth failures and blocks IPs after too many failures. This provides protection against brute-force attacks on platform agent credentials.
func NewAuthFailureLimiter ¶
func NewAuthFailureLimiter(cfg AuthFailureLimiterConfig, log *logger.Logger) *AuthFailureLimiter
NewAuthFailureLimiter creates a new auth failure limiter.
func (*AuthFailureLimiter) GetStats ¶
func (afl *AuthFailureLimiter) GetStats() (trackedIPs int, bannedIPs int)
GetStats returns current limiter stats.
func (*AuthFailureLimiter) IsBanned ¶
func (afl *AuthFailureLimiter) IsBanned(ip string) bool
IsBanned checks if an IP is currently banned.
func (*AuthFailureLimiter) RecordFailure ¶
func (afl *AuthFailureLimiter) RecordFailure(ip string) bool
RecordFailure records an auth failure for an IP. Returns true if the IP is now banned.
func (*AuthFailureLimiter) RecordSuccess ¶
func (afl *AuthFailureLimiter) RecordSuccess(ip string)
RecordSuccess clears failure count for an IP (on successful auth).
func (*AuthFailureLimiter) Stop ¶
func (afl *AuthFailureLimiter) Stop()
Stop stops the cleanup goroutine.
type AuthFailureLimiterConfig ¶
type AuthFailureLimiterConfig struct {
// MaxFailures is the max auth failures before IP is banned.
// Default: 5
MaxFailures int
// BanDuration is how long an IP is banned after max failures.
// Default: 15 minutes
BanDuration time.Duration
// WindowDuration is the time window for counting failures.
// Default: 5 minutes
WindowDuration time.Duration
// CleanupInterval for removing old entries.
// Default: 1 minute
CleanupInterval time.Duration
}
AuthFailureLimiterConfig configures the auth failure limiter.
func DefaultAuthFailureLimiterConfig ¶
func DefaultAuthFailureLimiterConfig() AuthFailureLimiterConfig
DefaultAuthFailureLimiterConfig returns secure defaults.
type AuthRateLimitConfig ¶
type AuthRateLimitConfig struct {
// LoginRatePerMin is the max login attempts per minute per IP.
// Default: 5
LoginRatePerMin int
// RegisterRatePerMin is the max registration attempts per minute per IP.
// Default: 3
RegisterRatePerMin int
// PasswordResetRatePerMin is the max password reset/forgot attempts per minute per IP.
// Default: 3
PasswordResetRatePerMin int
// TokenExchangeRatePerMin is the max token exchange/refresh attempts per minute per IP.
// Higher than login because token exchange requires a valid refresh token (not brute-forceable)
// and is used for tenant switching which may happen frequently.
// Default: 20
TokenExchangeRatePerMin int
// CleanupInterval for visitor entries.
// Default: 1 minute
CleanupInterval time.Duration
}
AuthRateLimitConfig configures auth-specific rate limits.
func DefaultAuthRateLimitConfig ¶
func DefaultAuthRateLimitConfig() AuthRateLimitConfig
DefaultAuthRateLimitConfig returns secure defaults for auth rate limiting.
type AuthRateLimiter ¶
type AuthRateLimiter struct {
// contains filtered or unexported fields
}
AuthRateLimiter provides stricter rate limiting for authentication endpoints. This is critical for preventing brute-force attacks.
func NewAuthRateLimiter ¶
func NewAuthRateLimiter(cfg AuthRateLimitConfig, log *logger.Logger) *AuthRateLimiter
NewAuthRateLimiter creates a rate limiter specialized for authentication endpoints.
func (*AuthRateLimiter) LoginMiddleware ¶
func (a *AuthRateLimiter) LoginMiddleware() func(http.Handler) http.Handler
LoginMiddleware returns middleware for login endpoints. Applies strict rate limiting to prevent brute-force attacks.
func (*AuthRateLimiter) PasswordMiddleware ¶
func (a *AuthRateLimiter) PasswordMiddleware() func(http.Handler) http.Handler
PasswordMiddleware returns middleware for password reset/forgot endpoints.
func (*AuthRateLimiter) RegisterMiddleware ¶
func (a *AuthRateLimiter) RegisterMiddleware() func(http.Handler) http.Handler
RegisterMiddleware returns middleware for registration endpoints.
func (*AuthRateLimiter) Stop ¶
func (a *AuthRateLimiter) Stop()
Stop gracefully shuts down all rate limiters.
func (*AuthRateLimiter) TokenExchangeMiddleware ¶ added in v0.1.2
func (a *AuthRateLimiter) TokenExchangeMiddleware() func(http.Handler) http.Handler
TokenExchangeMiddleware returns middleware for token exchange/refresh endpoints. Uses a higher rate limit than login because token exchange requires a valid refresh token (not brute-forceable) and is used for tenant switching.
type CSRFConfig ¶
type CSRFConfig struct {
// Secure sets the Secure flag on the CSRF cookie.
Secure bool
// Domain sets the Domain for the CSRF cookie.
Domain string
// SameSite sets the SameSite policy.
SameSite http.SameSite
// Path sets the cookie path.
Path string
// TTL is the token validity period.
TTL time.Duration
// Logger for CSRF operations.
Logger *logger.Logger
}
CSRFConfig holds CSRF middleware configuration.
func NewCSRFConfig ¶
func NewCSRFConfig(cfg config.AuthConfig, log *logger.Logger) CSRFConfig
NewCSRFConfig creates a CSRFConfig from AuthConfig.
type CampaignRoleQuerier ¶ added in v0.1.3
type CampaignRoleQuerier interface {
GetUserRole(ctx context.Context, tenantID, campaignID, userID string) (pentest.CampaignRole, error)
}
CampaignRoleQuerier resolves a user's campaign role from the database.
type CampaignStatusQuerier ¶ added in v0.1.3
type CampaignStatusQuerier interface {
GetCampaignStatus(ctx context.Context, tenantID, campaignID string) (pentest.CampaignStatus, error)
}
CampaignStatusQuerier resolves a campaign's status. Optional — if nil, status not set in context.
type DecompressConfig ¶
type DecompressConfig struct {
// MaxDecompressedSize is the maximum size of decompressed body.
// Default: 50MB
MaxDecompressedSize int64
// MaxCompressedSize is the maximum size of compressed input.
// Default: 10MB (prevents reading huge compressed payloads)
MaxCompressedSize int64
// MaxCompressionRatio is the maximum allowed compression ratio.
// If decompressed/compressed > this ratio, reject as potential zipbomb.
// Default: 100 (100:1 ratio)
MaxCompressionRatio float64
// AllowedEncodings specifies which encodings are allowed.
// Default: ["gzip", "zstd"]
AllowedEncodings []string
}
DecompressConfig configures the decompression middleware.
func DefaultDecompressConfig ¶
func DefaultDecompressConfig() *DecompressConfig
DefaultDecompressConfig returns the default configuration.
type DistributedRateLimitConfig ¶
type DistributedRateLimitConfig struct {
// Limiter is the Redis-backed rate limiter adapter.
Limiter *redisinfra.MiddlewareAdapter
// KeyFunc extracts the rate limit key from the request.
// Defaults to using client IP.
KeyFunc func(r *http.Request) string
// Logger for rate limit events.
Logger *logger.Logger
// SkipFunc optionally skips rate limiting for certain requests.
SkipFunc func(r *http.Request) bool
}
DistributedRateLimitConfig configures the distributed rate limit middleware.
type FindingActivityRateLimitConfig ¶
type FindingActivityRateLimitConfig struct {
// ListRequestsPerMin is the max list activity requests per minute per user.
// Default: 60
ListRequestsPerMin int
// CleanupInterval for visitor entries.
// Default: 1 minute
CleanupInterval time.Duration
}
FindingActivityRateLimitConfig configures finding activity rate limits.
func DefaultFindingActivityRateLimitConfig ¶
func DefaultFindingActivityRateLimitConfig() FindingActivityRateLimitConfig
DefaultFindingActivityRateLimitConfig returns secure defaults.
type FindingActivityRateLimiter ¶
type FindingActivityRateLimiter struct {
// contains filtered or unexported fields
}
FindingActivityRateLimiter provides rate limiting for finding activity endpoints. This prevents enumeration attacks and DoS on activity APIs.
func NewFindingActivityRateLimiter ¶
func NewFindingActivityRateLimiter(cfg FindingActivityRateLimitConfig, log *logger.Logger) *FindingActivityRateLimiter
NewFindingActivityRateLimiter creates a rate limiter for finding activity endpoints.
func (*FindingActivityRateLimiter) ListMiddleware ¶
func (f *FindingActivityRateLimiter) ListMiddleware() func(http.Handler) http.Handler
ListMiddleware returns middleware for activity list endpoints. Uses user ID (or IP) as the rate limit key for per-user limiting.
func (*FindingActivityRateLimiter) Stop ¶
func (f *FindingActivityRateLimiter) Stop()
Stop gracefully shuts down the rate limiter.
type LoggerConfig ¶
type LoggerConfig struct {
// SkipPaths are paths that should not be logged (e.g., health checks)
SkipPaths []string
// SkipSuccessful skips logging for successful requests (2xx status codes)
// Useful for high-traffic endpoints where you only care about errors
SkipSuccessful bool
// SlowRequestThreshold logs requests slower than this as warnings
// Set to 0 to disable slow request logging
SlowRequestThreshold time.Duration
}
LoggerConfig configures HTTP request logging behavior.
func DefaultLoggerConfig ¶
func DefaultLoggerConfig() LoggerConfig
DefaultLoggerConfig returns default logging configuration.
type PermissionSyncMiddleware ¶
type PermissionSyncMiddleware struct {
// contains filtered or unexported fields
}
PermissionSyncMiddleware handles permission synchronization and stale detection. It enriches the request context with permissions from Redis cache and sets the X-Permission-Stale header when JWT version doesn't match Redis version.
func NewPermissionSyncMiddleware ¶
func NewPermissionSyncMiddleware( permCache *app.PermissionCacheService, permVersion *app.PermissionVersionService, log *logger.Logger, ) *PermissionSyncMiddleware
NewPermissionSyncMiddleware creates a new permission sync middleware.
func (*PermissionSyncMiddleware) EnrichPermissions ¶
func (m *PermissionSyncMiddleware) EnrichPermissions(next http.Handler) http.Handler
EnrichPermissions fetches permissions from Redis cache and adds them to context. Also checks for stale permissions and sets the X-Permission-Stale header.
This middleware should be placed AFTER UnifiedAuth in the middleware chain. It uses the user ID and tenant ID from the context set by UnifiedAuth.
Flow: 1. Get tenant ID and user ID from context 2. Get current permission version from Redis 3. Compare with JWT's perm_version (if present) 4. If mismatch: set X-Permission-Stale header 5. Fetch permissions from Redis cache (or DB fallback) 6. Store permissions in context for handlers
type PlatformRegistrationRateLimitConfig ¶
type PlatformRegistrationRateLimitConfig struct {
// RegistrationRatePerMin is the max registration attempts per minute per IP.
// Default: 5 (very strict for bootstrap token protection)
RegistrationRatePerMin int
// CleanupInterval for visitor entries.
// Default: 1 minute
CleanupInterval time.Duration
}
PlatformRegistrationRateLimitConfig configures platform registration rate limits.
func DefaultPlatformRegistrationRateLimitConfig ¶
func DefaultPlatformRegistrationRateLimitConfig() PlatformRegistrationRateLimitConfig
DefaultPlatformRegistrationRateLimitConfig returns secure defaults.
type PlatformRegistrationRateLimiter ¶
type PlatformRegistrationRateLimiter struct {
// contains filtered or unexported fields
}
PlatformRegistrationRateLimiter provides strict rate limiting for platform agent registration. This prevents brute-force attacks on bootstrap tokens.
func NewPlatformRegistrationRateLimiter ¶
func NewPlatformRegistrationRateLimiter(cfg PlatformRegistrationRateLimitConfig, log *logger.Logger) *PlatformRegistrationRateLimiter
NewPlatformRegistrationRateLimiter creates a rate limiter for platform agent registration.
func (*PlatformRegistrationRateLimiter) Middleware ¶
func (p *PlatformRegistrationRateLimiter) Middleware() func(http.Handler) http.Handler
Middleware returns the platform registration rate limiting middleware.
func (*PlatformRegistrationRateLimiter) Stop ¶
func (p *PlatformRegistrationRateLimiter) Stop()
Stop gracefully shuts down the rate limiter.
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter implements a per-IP rate limiter.
func NewRateLimiter ¶
func NewRateLimiter(cfg *config.RateLimitConfig, log *logger.Logger) *RateLimiter
NewRateLimiter creates a new rate limiter.
func (*RateLimiter) Middleware ¶
func (rl *RateLimiter) Middleware() func(http.Handler) http.Handler
Middleware returns the rate limiting middleware.
func (*RateLimiter) Stop ¶
func (rl *RateLimiter) Stop()
Stop stops the cleanup goroutine and waits for it to exit. Safe to call multiple times.
type ReadEndpointRateLimitConfig ¶ added in v0.1.3
type ReadEndpointRateLimitConfig struct {
// ReadRequestsPerMin is the max GET requests per minute per user.
// Default: 120 (2 per second — generous for normal usage, blocks scraping)
ReadRequestsPerMin int
// CleanupInterval for visitor entries.
// Default: 1 minute
CleanupInterval time.Duration
}
ReadEndpointRateLimitConfig configures read endpoint rate limits.
func DefaultReadEndpointRateLimitConfig ¶ added in v0.1.3
func DefaultReadEndpointRateLimitConfig() ReadEndpointRateLimitConfig
DefaultReadEndpointRateLimitConfig returns secure defaults for read endpoint rate limiting.
type ReadEndpointRateLimiter ¶ added in v0.1.3
type ReadEndpointRateLimiter struct {
// contains filtered or unexported fields
}
ReadEndpointRateLimiter provides per-user rate limiting for read/list endpoints. This prevents enumeration attacks and excessive polling on GET endpoints across all authenticated API routes.
func NewReadEndpointRateLimiter ¶ added in v0.1.3
func NewReadEndpointRateLimiter(cfg ReadEndpointRateLimitConfig, log *logger.Logger) *ReadEndpointRateLimiter
NewReadEndpointRateLimiter creates a rate limiter for read/list endpoints.
func (*ReadEndpointRateLimiter) Middleware ¶ added in v0.1.3
func (rel *ReadEndpointRateLimiter) Middleware() func(http.Handler) http.Handler
Middleware returns middleware that rate-limits GET requests per user. Non-GET requests pass through without rate limiting.
func (*ReadEndpointRateLimiter) Stop ¶ added in v0.1.3
func (rel *ReadEndpointRateLimiter) Stop()
Stop gracefully shuts down the rate limiter.
type SecurityHeadersConfig ¶
type SecurityHeadersConfig struct {
// HSTSEnabled enables HTTP Strict Transport Security.
// Should be true in production with HTTPS.
HSTSEnabled bool
// HSTSMaxAge is the max-age for HSTS in seconds (default: 1 year).
HSTSMaxAge int
// HSTSIncludeSubdomains includes subdomains in HSTS.
HSTSIncludeSubdomains bool
}
SecurityHeadersConfig configures security headers.
type TriggerRateLimitConfig ¶
type TriggerRateLimitConfig struct {
// PipelineTriggersPerMin is the max pipeline triggers per minute per tenant.
// Default: 30
PipelineTriggersPerMin int
// ScanTriggersPerMin is the max scan triggers per minute per tenant.
// Default: 20
ScanTriggersPerMin int
// QuickScanTriggersPerMin is the max quick scan triggers per minute per tenant.
// Default: 10 (stricter as quick scans can be resource-intensive)
QuickScanTriggersPerMin int
// CleanupInterval for visitor entries.
// Default: 1 minute
CleanupInterval time.Duration
}
TriggerRateLimitConfig configures trigger-specific rate limits.
func DefaultTriggerRateLimitConfig ¶
func DefaultTriggerRateLimitConfig() TriggerRateLimitConfig
DefaultTriggerRateLimitConfig returns secure defaults for trigger rate limiting.
type TriggerRateLimiter ¶
type TriggerRateLimiter struct {
// contains filtered or unexported fields
}
TriggerRateLimiter provides rate limiting for pipeline and scan trigger endpoints. This prevents abuse and ensures fair resource usage.
func NewTriggerRateLimiter ¶
func NewTriggerRateLimiter(cfg TriggerRateLimitConfig, log *logger.Logger) *TriggerRateLimiter
NewTriggerRateLimiter creates a rate limiter specialized for trigger endpoints.
func (*TriggerRateLimiter) PipelineMiddleware ¶
func (t *TriggerRateLimiter) PipelineMiddleware() func(http.Handler) http.Handler
PipelineMiddleware returns middleware for pipeline trigger endpoints. Uses tenant ID as the rate limit key for per-tenant limiting.
func (*TriggerRateLimiter) QuickScanMiddleware ¶
func (t *TriggerRateLimiter) QuickScanMiddleware() func(http.Handler) http.Handler
QuickScanMiddleware returns middleware for quick scan trigger endpoints. Uses tenant ID as the rate limit key for per-tenant limiting.
func (*TriggerRateLimiter) ScanMiddleware ¶
func (t *TriggerRateLimiter) ScanMiddleware() func(http.Handler) http.Handler
ScanMiddleware returns middleware for scan trigger endpoints. Uses tenant ID as the rate limit key for per-tenant limiting.
func (*TriggerRateLimiter) Stop ¶
func (t *TriggerRateLimiter) Stop()
Stop gracefully shuts down all rate limiters.
type UnifiedAuthConfig ¶
type UnifiedAuthConfig struct {
Provider config.AuthProvider
LocalValidator *jwt.Generator
OIDCValidator *keycloak.Validator
Logger *logger.Logger
SessionTimeoutMinutes int // Session timeout in minutes (0 = disabled)
}
UnifiedAuthConfig holds configuration for unified auth middleware.