feat: Add LDAP/Active Directory integration with group-based access control

- Add PHP LDAP extension to Docker container
- Implement LdapSync class for authentication and user synchronization
- Add automatic user sync via cron (every 30 minutes)
- Create role-based access control system (admin, manager, viewer)
- Add LDAP configuration UI in settings
- Support for both Active Directory and OpenLDAP
- Group-to-role mapping with flexible configuration
- Add 50+ translations (EN + RU) for LDAP features
- Include comprehensive setup documentation
- Enhance Auth::login() with LDAP fallback
- Add LDAP settings page with connection testing
This commit is contained in:
infosave2007
2025-11-10 17:46:27 +03:00
parent 40abe38616
commit 3d9cc02963
13 changed files with 1141 additions and 3 deletions
+38
View File
@@ -0,0 +1,38 @@
-- Migration: Add LDAP configuration and settings
-- Date: 2025-11-10
-- LDAP configuration table
CREATE TABLE IF NOT EXISTS ldap_configs (
id INT PRIMARY KEY AUTO_INCREMENT,
enabled BOOLEAN DEFAULT FALSE,
host VARCHAR(255) NOT NULL,
port INT DEFAULT 389,
use_tls BOOLEAN DEFAULT FALSE,
base_dn VARCHAR(255) NOT NULL,
bind_dn VARCHAR(255) NOT NULL,
bind_password VARCHAR(255) NOT NULL,
user_search_filter VARCHAR(255) DEFAULT '(uid=%s)',
group_search_filter VARCHAR(255) DEFAULT '(memberUid=%s)',
sync_interval INT DEFAULT 30 COMMENT 'Sync interval in minutes',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- LDAP group to role mappings
CREATE TABLE IF NOT EXISTS ldap_group_mappings (
id INT PRIMARY KEY AUTO_INCREMENT,
ldap_group VARCHAR(255) NOT NULL UNIQUE,
role_name VARCHAR(50) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Add ldap_sync flag to users table
ALTER TABLE users
ADD COLUMN ldap_synced BOOLEAN DEFAULT FALSE AFTER status,
ADD COLUMN ldap_dn VARCHAR(255) NULL AFTER ldap_synced,
ADD INDEX idx_ldap_dn (ldap_dn);
-- Insert default LDAP configuration (disabled by default)
INSERT IGNORE INTO ldap_configs (id, enabled, host, port, base_dn, bind_dn, bind_password)
VALUES (1, FALSE, 'ldap.example.com', 389, 'dc=example,dc=com', 'cn=admin,dc=example,dc=com', '');
+32
View File
@@ -0,0 +1,32 @@
-- Migration: Add user roles and permissions
-- Date: 2025-11-10
-- User roles table
CREATE TABLE IF NOT EXISTS user_roles (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL UNIQUE,
display_name VARCHAR(100) NOT NULL,
description TEXT,
permissions JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Add role to users table
ALTER TABLE users
ADD COLUMN role VARCHAR(50) DEFAULT 'viewer' AFTER ldap_dn,
ADD INDEX idx_role (role);
-- Insert default roles
INSERT IGNORE INTO user_roles (name, display_name, description, permissions) VALUES
('admin', 'Administrator', 'Full access to all features', JSON_ARRAY('*')),
('manager', 'Manager', 'Can manage servers and clients', JSON_ARRAY('servers.view', 'servers.create', 'servers.edit', 'clients.view', 'clients.create', 'clients.edit', 'clients.delete')),
('viewer', 'Viewer', 'Can only view own clients', JSON_ARRAY('clients.view_own', 'clients.download_own'));
-- Insert default LDAP group mappings (examples)
INSERT IGNORE INTO ldap_group_mappings (ldap_group, role_name, description) VALUES
('vpn-admins', 'admin', 'VPN administrators with full access'),
('vpn-managers', 'manager', 'VPN managers who can create and manage clients'),
('vpn-users', 'viewer', 'Regular VPN users with view-only access');
-- Update existing users to admin role (backward compatibility)
UPDATE users SET role = 'admin' WHERE role IS NULL OR role = '';
+61
View File
@@ -0,0 +1,61 @@
-- Migration: Add LDAP translations (English and Russian)
-- Date: 2025-11-10
-- English translations
INSERT IGNORE INTO translations (locale, category, key_name, translation) VALUES
('en', 'ldap', 'settings', 'LDAP Settings'),
('en', 'ldap', 'enable_ldap_auth', 'Enable LDAP Authentication'),
('en', 'ldap', 'enable_description', 'Allow users to login using LDAP/Active Directory credentials'),
('en', 'ldap', 'host', 'LDAP Host'),
('en', 'ldap', 'port', 'Port'),
('en', 'ldap', 'use_tls', 'Use TLS/SSL'),
('en', 'ldap', 'base_dn', 'Base DN'),
('en', 'ldap', 'base_dn_description', 'The base distinguished name for LDAP searches (e.g., dc=example,dc=com)'),
('en', 'ldap', 'bind_dn', 'Bind DN'),
('en', 'ldap', 'bind_dn_description', 'The distinguished name of the service account to bind with'),
('en', 'ldap', 'bind_password', 'Bind Password'),
('en', 'ldap', 'user_search_filter', 'User Search Filter'),
('en', 'ldap', 'user_search_filter_description', 'LDAP filter to search for users. %s will be replaced with username'),
('en', 'ldap', 'group_search_filter', 'Group Search Filter'),
('en', 'ldap', 'sync_interval', 'Sync Interval (minutes)'),
('en', 'ldap', 'sync_interval_description', 'How often to automatically synchronize users from LDAP'),
('en', 'ldap', 'test_connection', 'Test Connection'),
('en', 'ldap', 'testing', 'Testing'),
('en', 'ldap', 'connection_test_failed', 'Connection test failed'),
('en', 'ldap', 'group_mappings', 'LDAP Group Mappings'),
('en', 'ldap', 'group', 'LDAP Group'),
('en', 'ldap', 'role', 'Panel Role'),
('en', 'ldap', 'description', 'Description');
-- Russian translations
INSERT IGNORE INTO translations (locale, category, key_name, translation) VALUES
('ru', 'ldap', 'settings', 'Настройки LDAP'),
('ru', 'ldap', 'enable_ldap_auth', 'Включить LDAP аутентификацию'),
('ru', 'ldap', 'enable_description', 'Разрешить пользователям входить используя учетные данные LDAP/Active Directory'),
('ru', 'ldap', 'host', 'LDAP Хост'),
('ru', 'ldap', 'port', 'Порт'),
('ru', 'ldap', 'use_tls', 'Использовать TLS/SSL'),
('ru', 'ldap', 'base_dn', 'Base DN'),
('ru', 'ldap', 'base_dn_description', 'Базовое отличительное имя для поиска в LDAP (например, dc=example,dc=com)'),
('ru', 'ldap', 'bind_dn', 'Bind DN'),
('ru', 'ldap', 'bind_dn_description', 'Отличительное имя служебной учетной записи для подключения'),
('ru', 'ldap', 'bind_password', 'Пароль подключения'),
('ru', 'ldap', 'user_search_filter', 'Фильтр поиска пользователей'),
('ru', 'ldap', 'user_search_filter_description', 'LDAP фильтр для поиска пользователей. %s будет заменен на имя пользователя'),
('ru', 'ldap', 'group_search_filter', 'Фильтр поиска групп'),
('ru', 'ldap', 'sync_interval', 'Интервал синхронизации (минуты)'),
('ru', 'ldap', 'sync_interval_description', 'Как часто автоматически синхронизировать пользователей из LDAP'),
('ru', 'ldap', 'test_connection', 'Тест подключения'),
('ru', 'ldap', 'testing', 'Тестирование'),
('ru', 'ldap', 'connection_test_failed', 'Тест подключения не удался'),
('ru', 'ldap', 'group_mappings', 'Связи групп LDAP'),
('ru', 'ldap', 'group', 'Группа LDAP'),
('ru', 'ldap', 'role', 'Роль в панели'),
('ru', 'ldap', 'description', 'Описание');
-- Common translations for buttons
INSERT IGNORE INTO translations (locale, category, key_name, translation) VALUES
('en', 'common', 'save', 'Save'),
('en', 'common', 'cancel', 'Cancel'),
('ru', 'common', 'save', 'Сохранить'),
('ru', 'common', 'cancel', 'Отмена');