Skip to content

Add Directory Authentication and Role Mapping#1191

Draft
sempervictus wants to merge 1 commit into
RightNow-AI:mainfrom
sempervictus:feature/directory_backend
Draft

Add Directory Authentication and Role Mapping#1191
sempervictus wants to merge 1 commit into
RightNow-AI:mainfrom
sempervictus:feature/directory_backend

Conversation

@sempervictus
Copy link
Copy Markdown

Implement trait-based external authentication provider architecture supporting LDAP/LDAPS with dynamic user provisioning and group-based RBAC mapping.

The implementation enables deployment owners to leverage existing Active Directory or OpenLDAP directories for user authentication and role assignment. Users are automatically provisioned on first authentication based on directory group membership mapped to OpenFang roles (owner/admin/user/viewer).

Key features:

  • LDAPS support with TLS/SSL and self-signed certificate handling
  • Group-to-role mapping with privilege hierarchy (higher role wins)
  • Automatic user provisioning from directory attributes
  • Credential separation (bind passwords in env until vaults work)
  • Connection timeout enforcement and certificate validation
  • Seamless integration with existing static user configuration

The trait-based design allows future extension to SAML and OIDC providers while maintaining a consistent authentication interface.

Security considerations:

  • TLS enforcement required for all LDAP connections
  • Bind credentials never stored in configuration files
  • Certificate validation enabled by default (bypass disabled)
  • Role mappings use regex patterns for flexible group matching
  • Users created only after successful directory authentication

Configuration:

 [[external_auth_providers]]                                                                                                                                                                                                                    
 type = "ldap"                                                                                                                                                                                                                                  
 name = "active-directory"                                                                                                                                                                                                                      
 uri = "ldaps://dc01.example.com:636"                                                                                                                                                                                                           
 bind_dn = "CN=Service Account,OU=Service Accounts,DC=example,DC=com"                                                                                                                                                                           
 bind_password_env = "LDAP_BIND_PASSWORD"                                                                                                                                                                                                       
 base_dn = "DC=example,DC=com"                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                
 [external_auth_providers.attribute_mapping]                                                                                                                                                                                                    
 user_id_attr = "sAMAccountName"                                                                                                                                                                                                                
 name_attr = "displayName"                                                                                                                                                                                                                      
 email_attr = "mail"                                                                                                                                                                                                                            
 group_attr = "memberOf"                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                
 [[external_auth_providers.role_mappings]]                                                                                                                                                                                                      
 group_pattern = "CN=OpenFang-Admins,OU=Groups,DC=example,DC=com"                                                                                                                                                                               
 role = "admin"                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                
 [[external_auth_providers.role_mappings]]                                                                                                                                                                                                      
 group_pattern = "CN=OpenFang-Users,OU=Groups,DC=example,DC=com"                                                                                                                                                                                
 role = "user"                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                
 [[external_auth_providers.role_mappings]]                                                                                                                                                                                                      
 group_pattern = "CN=OpenFang-Viewers,OU=Groups,DC=example,DC=com"                                                                                                                                                                              
 role = "viewer"                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                
 [external_auth_providers.connection]                                                                                                                                                                                                           
 timeout_secs = 30                                                                                                                                                                                                                              
 tls_enabled = true                                                                                                                                                                                                                             
 ca_cert_path = "/etc/ssl/certs/example-ca.pem"                                                                                                                                                                                                 
 start_tls = false                                                                                                                                                                                                                              
 disable_tls_verify = false

Summary

Implement directory authentication trait and LDAP/S initial directory provider

Changes

Testing

  • cargo clippy --workspace --all-targets -- -D warnings passes
    -- unrelated failure in telegram section:
    Checking openfang-kernel v0.6.8 (/opt/code/Rust/ML/Agents/openfang/crates/openfang-kernel)
error: unnecessary use of `get("target_agent_name").is_none()`
    --> crates/openfang-channels/src/telegram.rs:1751:30
     |
1751 |         assert!(msg.metadata.get("target_agent_name").is_none());
     |                 -------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |                 |
     |                 help: replace it with: `!msg.metadata.contains_key("target_agent_name")`
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.94.0/index.html#unnecessary_get_then_check
     = note: `-D clippy::unnecessary-get-then-check` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::unnecessary_get_then_check)]`

error: unnecessary use of `get("target_agent_name").is_none()`
    --> crates/openfang-channels/src/telegram.rs:1785:30
     |
1785 |         assert!(msg.metadata.get("target_agent_name").is_none());
     |                 -------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |                 |
     |                 help: replace it with: `!msg.metadata.contains_key("target_agent_name")`
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.94.0/index.html#unnecessary_get_then_check

error: could not compile `openfang-channels` (lib test) due to 2 previous errors
warning: build failed, waiting for other jobs to finish...
  • cargo test --workspace passes (wasm targets fail in MPROTECT systems by the way)
  • Live integration tested (if applicable)

Security

  • No new unsafe code
  • No secrets or API keys in diff
  • User input validated at boundaries

Implement trait-based external authentication provider architecture
supporting LDAP/LDAPS with dynamic user provisioning and group-based
RBAC mapping.

The implementation enables deployment owners to leverage existing
Active Directory or OpenLDAP directories for user authentication and
role assignment. Users are automatically provisioned on first
authentication based on directory group membership mapped to OpenFang
roles (owner/admin/user/viewer).

Key features:
- LDAPS support with TLS/SSL and self-signed certificate handling
- Group-to-role mapping with privilege hierarchy (higher role wins)
- Automatic user provisioning from directory attributes
- Credential separation (bind passwords in env until vaults work)
- Connection timeout enforcement and certificate validation
- Seamless integration with existing static user configuration

The trait-based design allows future extension to SAML and OIDC
providers while maintaining a consistent authentication interface.

Security considerations:
- TLS enforcement required for all LDAP connections
- Bind credentials never stored in configuration files
- Certificate validation enabled by default (bypass disabled)
- Role mappings use regex patterns for flexible group matching
- Users created only after successful directory authentication

Configuration:

```toml
 [[external_auth_providers]]                                                                                                                                                                                                                    │
 type = "ldap"                                                                                                                                                                                                                                  │
 name = "active-directory"                                                                                                                                                                                                                      │
 uri = "ldaps://dc01.example.com:636"                                                                                                                                                                                                           │
 bind_dn = "CN=Service Account,OU=Service Accounts,DC=example,DC=com"                                                                                                                                                                           │
 bind_password_env = "LDAP_BIND_PASSWORD"                                                                                                                                                                                                       │
 base_dn = "DC=example,DC=com"                                                                                                                                                                                                                  │
                                                                                                                                                                                                                                                │
 [external_auth_providers.attribute_mapping]                                                                                                                                                                                                    │
 user_id_attr = "sAMAccountName"                                                                                                                                                                                                                │
 name_attr = "displayName"                                                                                                                                                                                                                      │
 email_attr = "mail"                                                                                                                                                                                                                            │
 group_attr = "memberOf"                                                                                                                                                                                                                        │
                                                                                                                                                                                                                                                │
 [[external_auth_providers.role_mappings]]                                                                                                                                                                                                      │
 group_pattern = "CN=OpenFang-Admins,OU=Groups,DC=example,DC=com"                                                                                                                                                                               │
 role = "admin"                                                                                                                                                                                                                                 │
                                                                                                                                                                                                                                                │
 [[external_auth_providers.role_mappings]]                                                                                                                                                                                                      │
 group_pattern = "CN=OpenFang-Users,OU=Groups,DC=example,DC=com"                                                                                                                                                                                │
 role = "user"                                                                                                                                                                                                                                  │
                                                                                                                                                                                                                                                │
 [[external_auth_providers.role_mappings]]                                                                                                                                                                                                      │
 group_pattern = "CN=OpenFang-Viewers,OU=Groups,DC=example,DC=com"                                                                                                                                                                              │
 role = "viewer"                                                                                                                                                                                                                                │
                                                                                                                                                                                                                                                │
 [external_auth_providers.connection]                                                                                                                                                                                                           │
 timeout_secs = 30                                                                                                                                                                                                                              │
 tls_enabled = true                                                                                                                                                                                                                             │
 ca_cert_path = "/etc/ssl/certs/example-ca.pem"                                                                                                                                                                                                 │
 start_tls = false                                                                                                                                                                                                                              │
 disable_tls_verify = false
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant