Access Control
Document Version: 1.0 Last Updated: January 6, 2026 Classification: Internal / Partner
Table of Contents
- Overview
- Authentication Mechanisms
- Scope‑Based RBAC Model
- Tenant Isolation
- Permission Matrix
- API Key Management
- Session Management (Clerk)
- Service‑to‑Service Authorization (mTLS)
- Auditing & Logging
- Best Practices & Recommendations
- References
Overview
Fulcrum enforces defense‑in‑depth access control across all entry points. The model combines authentication (who you are) with authorization (what you can do) using scope‑based RBAC and tenant isolation. All enforcement points are implemented in the shared middleware (/internal/middleware/auth.go) and are verified by unit tests and integration tests.
Authentication Mechanisms
| Mechanism | Use‑case | Implementation |
|---|---|---|
| API Key | Programmatic access (SDKs, services) | SHA‑256 hashed keys stored in fulcrum.api_keys table. Validation performed in auth.go. |
| Clerk SSO | Human users accessing the dashboard | OAuth2/OIDC flow handled by Clerk SDK. Session cookies managed by Clerk. |
| mTLS | Service‑to‑service calls within the cluster | Mutual TLS certificates verified by gRPC server (GRPC_TLS_ENABLED). |
All mechanisms require TLS 1.2+ for transport security.
Scope‑Based RBAC Model
Each API key (or Clerk session) is assigned a set of scopes that map to fine‑grained permissions. Scopes are strings like policy:read, cost:write, admin. The special scope * grants full admin rights (legacy keys only).
Scope Definitions
| Scope | Description | Endpoints |
|---|---|---|
policy:read |
Read policy configurations | ListPolicies, GetPolicy |
policy:write |
Create, update, delete policies | CreatePolicy, UpdatePolicy, DeletePolicy |
policy:approve |
Approve pending policies | UpdatePolicy (status=ACTIVE), UpdateApproval |
cost:read |
View cost and budget data | GetCostSummary, GetBudgetStatus |
cost:write |
Manage budgets | CreateBudget, UpdateBudget |
api_key:read |
List API keys | ListApiKeys |
api_key:write |
Create/revoke API keys | CreateApiKey, RevokeApiKey |
admin |
Administrative operations (key rotation, system settings) | All admin endpoints |
Enforcement
The middleware provides HasScope(ctx, scope string) bool. Example:
func (s *policyService) CreatePolicy(ctx context.Context, req *pb.CreatePolicyRequest) (*pb.CreatePolicyResponse, error) {
if !middleware.HasScope(ctx, "policy:write") {
return nil, status.Error(codes.PermissionDenied, "missing policy:write scope")
}
// proceed with creation
}
Tenant Isolation
Every authenticated request carries a tenant_id injected by the authentication middleware. This ID is stored in the request context and used by:
- PostgreSQL Row‑Level Security policies to filter data.
- Rate‑limit buckets (Redis) scoped per tenant.
- Resource naming (e.g., S3 buckets, NATS subjects) prefixed with the tenant ID.
Permission Matrix
| Resource | Required Scope(s) |
|---|---|
| Policy CRUD | policy:read / policy:write |
| Policy Approval | policy:approve |
| Budget View | cost:read |
| Budget Edit | cost:write |
| API Key Management | api_key:read / api_key:write |
| Admin Dashboard | admin |
API Key Management
- Creation –
CreateApiKeygenerates a 32‑byte random secret, stores only the SHA‑256 hash. - Rotation – New keys can be issued; old keys can be revoked via
RevokeApiKey. - Expiration – Optional
expires_attimestamp; expired keys are rejected. - Hints – Last 4‑8 characters of the key are stored for UI identification.
All operations are audited (see Auditing section).
Session Management (Clerk)
- Clerk handles OAuth2 token validation, session refresh, and logout.
- In production, the middleware blocks unauthenticated access and redirects to
/auth-error(seedashboard/src/middleware.ts). - Session IDs are logged with trace IDs for correlation.
Service‑to‑Service Authorization (mTLS)
- Internal services authenticate each other using mutual TLS certificates.
- The client presents a certificate; the server validates it against a trusted CA.
- Service identities are mapped to scopes via a configuration file (
internal/mtls/scopes.yaml).
Auditing & Logging
All access control decisions are logged with the following fields:
- tenant_id
- principal (API key ID or Clerk user ID)
- scopes
- resource and action
- decision (allow / deny)
- trace_id for end‑to‑end correlation
Log format is JSON (see Structured Logging in SECURITY_OVERVIEW.md).
Best Practices & Recommendations
- Least Privilege: Issue API keys with the minimal set of scopes required.
- Rotate Secrets: Rotate API keys and TLS certificates every 90 days.
- Monitor: Alert on
fulcrum_auth_failures_totalandfulcrum_rate_limit_exceeded_total(see Monitoring guide). - Review Scopes: Periodically audit scope assignments for inactive tenants.
- Use Vault: Store private keys and certificates in a secret manager (e.g., HashiCorp Vault, AWS Secrets Manager).
References
- Fulcrum
SECURITY_OVERVIEW.md - Fulcrum
ACCESS_CONTROL.md(this document) - OWASP Access Control Cheat Sheet
- NIST SP 800‑53 AC‑* controls
- PostgreSQL Row‑Level Security documentation
Document version: 1.0 (January 6 2026)