ABAC + SSO + LDAP/AD — Enterprise Identity Setup
UVP
HeliosDB Full ships three enterprise-identity layers in one binary: an XACML-style ABAC engine (PDP/PEP/PIP/PAP), SAML 2.0 + OAuth 2.0 + OIDC SSO with built-in connectors for Okta / Auth0 / Azure AD / Google Workspace, and LDAP / Active Directory integration with group-to-role mapping. JIT user provisioning, SCIM 2.0, single logout, session limits, and PKCE are first-class. Plug your IdP in once, get RBAC + ABAC + JIT + SLO across every protocol HeliosDB speaks (PostgreSQL, MySQL, MongoDB, REST, GraphQL).
Prerequisites
- HeliosDB Full v8.0.3
- An IdP you control (Okta, Auth0, Azure AD, Google Workspace, or a custom SAML/OIDC provider)
- LDAP or Active Directory bind credentials, if you want directory integration
- ~45 minutes if you do all three; ~15 if you only do SSO
The three subsystems are independent. You can enable just SSO, just ABAC, or any combination.
1. Architecture in 90 Seconds
┌──────────────────────────────────┐ user request ───▶ │ Protocol layer (PG/MySQL/REST/…) │ └──────────────┬───────────────────┘ │ ┌──────────────▼───────────────────┐ │ Auth pipeline │ │ SSO ─────► JIT provisioning │ │ LDAP ───► group → role mapping │ │ RBAC v2 ► role → privilege set │ │ ABAC ───► PDP evaluates request │ └──────────────┬───────────────────┘ │ allow/deny + obligations ┌──────────────▼───────────────────┐ │ Storage / query engine │ └──────────────────────────────────┘RBAC answers “what role does this user have?”. ABAC answers “given this user, this resource, this action, this environment — should I let it through?”. They compose: RBAC narrows the set, ABAC vetoes within it.
2. SSO — SAML, OAuth, OIDC
2a. Configuration File
Create sso.toml:
# Okta SAML 2.0[[providers]]name = "okta"type = "saml"enabled = trueentity_id = "heliosdb-prod"acs_url = "https://app.example.com/sso/acs"metadata_url = "https://dev-123.okta.com/app/metadata"
# Auth0 OIDC[[providers]]name = "auth0"type = "oauth"enabled = trueclient_id = "your-client-id"client_secret_env = "AUTH0_SECRET"authorization_endpoint = "https://tenant.auth0.com/authorize"token_endpoint = "https://tenant.auth0.com/oauth/token"redirect_uri = "https://app.example.com/oauth/callback"
[session]timeout_seconds = 28800 # 8 hoursmax_concurrent_sessions = 5
[provisioning]enabled = truedefault_roles = ["user"]2b. Wire It In
use heliosdb_sso::{SsoManager, SsoConfig};
let config = SsoConfig::from_file("sso.toml")?;let manager = SsoManager::new(config).await?;
// Initiate SAMLlet auth_url = manager.initiate_saml_login("okta").await?;// redirect the user to auth_url ...
// Receive SAMLResponse on /sso/acslet user = manager.handle_saml_response(saml_response).await?;println!("Authenticated: {} ({})", user.user.email, user.session.id);2c. Provider-Specific Setup
| Provider | Time to set up | Critical claims |
|---|---|---|
| Okta SAML | 10 min | email, name, groups |
| Azure AD SAML | 12 min | email, name, groups (security-group GUIDs) |
| Google Workspace SAML | 8 min | email, name |
| Auth0 OIDC | 5 min | sub, email, https://example.com/groups |
| Custom OIDC | varies | sub, email, custom-namespaced groups |
Tip: for Azure AD, request the groups claim using the security group GUIDs mode, not display names — display names are not unique.
2d. SQL Surface
-- Show all configured providersSHOW SSO PROVIDERS;
-- Active sessionsSHOW SSO SESSIONS;SHOW SSO SESSIONS WHERE user_id = 'jane@example.com';
-- Force-logoutTERMINATE SSO SESSION 'sso_abc123';2e. Admin REST API
GET /api/sso/providersGET /api/sso/providers/oktaPOST /api/sso/providers/okta/testGET /api/sso/sessionsDELETE /api/sso/sessions/sso_123GET /api/sso/stats2f. Performance & Limits
- 1000+ concurrent SSO sessions per node
- Sub-millisecond session validation (in-memory cache)
- JWKS auto-refresh
- PKCE on every OAuth Authorization Code flow
3. LDAP / Active Directory
LDAP authentication is a thin layer: bind, look up the user, fetch group memberships, map groups to HeliosDB roles. The crate is intentionally small (~883 LOC) — one module — and re-uses the upstream ldap3 library.
3a. Configure
[ldap]url = "ldaps://dc01.corp.example.com:636"bind_dn = "CN=heliosdb-svc,OU=Service Accounts,DC=corp,DC=example,DC=com"bind_password_env = "LDAP_SVC_PASSWORD"user_base_dn = "OU=Users,DC=corp,DC=example,DC=com"user_filter = "(&(objectClass=user)(sAMAccountName={username}))"group_base_dn = "OU=Groups,DC=corp,DC=example,DC=com"group_filter = "(&(objectClass=group)(member={user_dn}))"
[[group_mapping]]ldap_group = "DBA-Admins"heliosdb_role = "admin"
[[group_mapping]]ldap_group = "Engineering"heliosdb_role = "developer"
[[group_mapping]]ldap_group = "Compliance-RO"heliosdb_role = "auditor"3b. Wire It In
The Active Directory case is the same — AD is just an LDAP server with extra schema. Set url to your domain controller, user_filter typically uses sAMAccountName, group lookups walk memberOf.
3c. Verifying Group Mapping
-- Show what role HeliosDB resolved for a given LDAP userSELECT * FROM heliosdb_ldap_resolved_roles WHERE username = 'jane.doe';-- → role: 'admin', source_group: 'DBA-Admins'If a user is a member of multiple mapped groups, the highest-privilege role wins (admin > developer > auditor > user).
4. ABAC — Fine-Grained Access Control
ABAC is the layer that makes “this analyst can only see customer rows from the EU between 09:00 and 18:00 CET, except their own team’s rows which they can see anytime” expressible. The engine implements XACML-style PDP/PEP/PIP/PAP separation.
4a. The Four Components
| Acronym | Module | Job |
|---|---|---|
| PEP | evaluator.rs | Policy Enforcement Point — sits in the request path |
| PDP | pdp.rs | Policy Decision Point — evaluates policies and returns Permit/Deny |
| PIP | pip.rs | Policy Information Point — fetches attributes (user, resource, environment) |
| PAP | pap.rs | Policy Administration Point — admin API for CRUD on policies |
4b. Define a Policy
-- Policy: analysts can SELECT from `customers` where the row's region matches the user's region,-- only during business hours in the user's timezone.CREATE ABAC POLICY analyst_customer_access TARGET resource = 'customers' AND action = 'SELECT' CONDITION ( user.role = 'analyst' AND resource.region = user.region AND env.local_hour BETWEEN 9 AND 18 ) EFFECT permit OBLIGATION audit ('analyst-customer-read');The CONDITION clause is evaluated by the PDP for every query. Attributes with the user., resource., and env. prefixes are fetched by the PIP — user.* from the SSO/LDAP claims, resource.* from row metadata or labels, env.* from the runtime (time, IP, MFA status).
4c. Test It
-- Dry-run a request through the PDP without executing the queryEXPLAIN ABAC FOR USER 'jane.doe' ACTION 'SELECT' ON 'customers' WHERE id = 7;Result:
decision : Permitmatched : analyst_customer_accessobligations: audit('analyst-customer-read')attributes: user.region = 'EU' resource.region = 'EU' env.local_hour = 14If the decision is Deny, the response shows which policy denied it and why.
4d. Combining Policies
The PDP evaluates all matching policies and combines them with a configurable algorithm:
| Algorithm | Behaviour |
|---|---|
permit-overrides | Any Permit wins (default for read) |
deny-overrides | Any Deny wins (recommended for writes) |
first-applicable | First matching policy wins |
only-one-applicable | Error if more than one matches |
Set per-action:
ALTER ABAC ENGINE SET combining_algorithm_for SELECT = 'permit-overrides', combining_algorithm_for INSERT = 'deny-overrides', combining_algorithm_for UPDATE = 'deny-overrides', combining_algorithm_for DELETE = 'deny-overrides';5. End-to-End — A Realistic Setup
The goal: an analyst signs in via Okta SAML, lands in the analyst role via group mapping, can read customers only in their region during business hours, with every read audited.
5a. SSO
[[providers]]name = "okta"type = "saml"entity_id = "heliosdb-prod"acs_url = "https://app.example.com/sso/acs"metadata_url = "https://dev-123.okta.com/app/metadata"
[provisioning]enabled = truedefault_roles = ["user"]5b. Group → Role mapping (driven by SAML claim)
CREATE GROUP MAPPING 'okta-analysts' TO ROLE 'analyst';Okta sends groups: ["okta-analysts"] in the SAML assertion; JIT provisioning attaches the role.
5c. ABAC
CREATE ABAC POLICY analyst_region_read TARGET resource = 'customers' AND action = 'SELECT' CONDITION (user.role = 'analyst' AND resource.region = user.region AND env.local_hour BETWEEN 9 AND 18) EFFECT permit OBLIGATION audit ('analyst-region-read');
CREATE ABAC POLICY analyst_no_writes TARGET resource = 'customers' AND action IN ('INSERT', 'UPDATE', 'DELETE') CONDITION (user.role = 'analyst') EFFECT deny;5d. Verify
EXPLAIN ABAC FOR USER 'jane.doe' ACTION 'SELECT' ON 'customers' WHERE id = 7;EXPLAIN ABAC FOR USER 'jane.doe' ACTION 'UPDATE' ON 'customers' WHERE id = 7;The first returns Permit with the audit obligation; the second returns Deny and names analyst_no_writes.
6. Production Checklist
SSO
- HTTPS enforced on the ACS / redirect URL
- XML signature verification is on for SAML
- PKCE is on for every OAuth flow (the default — don’t disable it)
-
max_concurrent_sessionsis set per your security policy - Session timeout is short enough that lost devices don’t stay authenticated for days
LDAP / AD
- Bind via
ldaps://(port 636), not plain LDAP - Service account credentials are in a secret manager, not the config file
- Group-to-role mapping is documented and reviewed quarterly
-
user_filterexcludes service accounts from interactive login
ABAC
- Combining algorithm is
deny-overridesfor writes - Every Permit policy has an
OBLIGATION audit (…)for traceability - Policies are version-controlled (the PAP supports import/export — keep them in git)
- An emergency
superuser-bypasspolicy exists, and access to that role is gated by MFA
7. Verification Status
| Component | Status notes |
|---|---|
| SSO (SAML / OAuth / OIDC) | Production. 70+ tests, supports 1000+ concurrent sessions, sub-ms session validation |
| LDAP / AD | Active. Single-module crate (~883 LOC). Group → role mapping is straightforward; complex AD topologies (multiple forests, trust boundaries) may need custom code |
| ABAC | Production. PDP/PEP/PIP/PAP separation matches XACML 3.0 vocabulary; combining algorithms above implemented |
| SCIM 2.0 user sync | Documented as optional in the SSO crate — verify against your IdP before relying on it |
Where Next
- Multi-Tenancy Setup — combine ABAC with per-tenant isolation
- Cognitive Agents — the SecurityMonitor agent ingests ABAC denials as anomaly signals
- PITR Recovery — audit log retention is required for regulated workloads
References
- Source:
/home/app/Helios/Full/heliosdb-security/crates/{abac,sso,ldap}/ - ABAC modules:
pdp.rs,pep.rs(inevaluator.rs),pip.rs,pap.rs,policy_engine.rs,xacml.rs - SSO providers directory:
heliosdb-security/crates/sso/src/providers/