cs-element
Version:
Advanced reactive data management library with state machines, blueprints, persistence, compression, networking, and multithreading support
543 lines (540 loc) • 20.4 kB
JavaScript
'use strict';
// Уровни безопасности
var SecurityLevel;
(function (SecurityLevel) {
SecurityLevel["PUBLIC"] = "public";
SecurityLevel["PROTECTED"] = "protected";
SecurityLevel["PRIVATE"] = "private";
SecurityLevel["CONFIDENTIAL"] = "confidential";
SecurityLevel["TOP_SECRET"] = "top_secret";
})(SecurityLevel || (SecurityLevel = {}));
// Типы разрешений
var PermissionType;
(function (PermissionType) {
PermissionType["READ"] = "read";
PermissionType["WRITE"] = "write";
PermissionType["DELETE"] = "delete";
PermissionType["EXECUTE"] = "execute";
PermissionType["ADMIN"] = "admin";
})(PermissionType || (PermissionType = {}));
// Методы аутентификации
var AuthenticationMethod;
(function (AuthenticationMethod) {
AuthenticationMethod["PASSWORD"] = "password";
AuthenticationMethod["TOKEN"] = "token";
AuthenticationMethod["CERTIFICATE"] = "certificate";
AuthenticationMethod["BIOMETRIC"] = "biometric";
AuthenticationMethod["MULTI_FACTOR"] = "multi_factor";
})(AuthenticationMethod || (AuthenticationMethod = {}));
// Алгоритмы шифрования
var EncryptionAlgorithm;
(function (EncryptionAlgorithm) {
EncryptionAlgorithm["AES_256"] = "aes-256";
EncryptionAlgorithm["RSA_2048"] = "rsa-2048";
EncryptionAlgorithm["ECDSA"] = "ecdsa";
EncryptionAlgorithm["CHACHA20"] = "chacha20";
})(EncryptionAlgorithm || (EncryptionAlgorithm = {}));
class SecurityPlugin {
/**
* Установка ключа шифрования для элемента
*/
setEncryptionKey(elementId, key) {
this._encryptionKeys.set(elementId, key);
}
/**
* Получение ключа шифрования для элемента
*/
getEncryptionKey(elementId) {
return this._encryptionKeys.get(elementId);
}
constructor(config = {}) {
this.name = 'SecurityPlugin';
this.version = '1.0.0';
this.description = 'Плагин для обеспечения безопасности, аутентификации и авторизации';
this.users = new Map();
this.roles = new Map();
this.rules = new Map();
this.sessions = new Map();
this.auditLogs = [];
this._encryptionKeys = new Map(); // Для хранения ключей шифрования
this.config = {
enabled: true,
defaultSecurityLevel: SecurityLevel.PROTECTED,
encryptionConfig: {
algorithm: EncryptionAlgorithm.AES_256,
keySize: 256,
iterations: 10000
},
sessionTimeout: 3600000, // 1 час
maxFailedAttempts: 5,
lockoutDuration: 900000, // 15 минут
auditingEnabled: true,
encryptionEnabled: true,
requireAuthentication: false,
allowAnonymous: true,
...config
};
this.stats = {
totalUsers: 0,
activeUsers: 0,
lockedUsers: 0,
totalRoles: 0,
totalRules: 0,
activeRules: 0,
auditLogs: 0,
failedAttempts: 0,
successfulLogins: 0,
deniedOperations: 0,
encryptedElements: 0
};
this.initializeDefaultRoles();
}
install() {
console.log(`Установка ${this.name} v${this.version}`);
// Очистка истекших сессий
setInterval(() => this.cleanupExpiredSessions(), 60000); // каждую минуту
// Очистка старых аудит логов
if (this.config.auditingEnabled) {
setInterval(() => this.cleanupAuditLogs(), 3600000); // каждый час
}
}
uninstall() {
this.sessions.clear();
console.log(`${this.name} деинициализирован`);
}
getConfig() {
return { ...this.config };
}
updateConfig(newConfig) {
this.config = { ...this.config, ...newConfig };
}
// Lifecycle hooks
async beforeCreate(element, context) {
if (!this.config.enabled)
return { success: true };
const securityContext = this.getSecurityContext(context);
const hasPermission = await this.checkPermission(securityContext, PermissionType.WRITE);
if (!hasPermission) {
this.logAudit(securityContext, 'create_element', 'denied', { elementId: element.id });
return {
success: false,
error: 'Недостаточно прав для создания элемента',
metadata: { securityLevel: this.config.defaultSecurityLevel }
};
}
// Установка уровня безопасности
if (!element.getData('securityLevel')) {
element.setData('securityLevel', this.config.defaultSecurityLevel);
}
this.logAudit(securityContext, 'create_element', 'success', { elementId: element.id });
return { success: true };
}
async beforeUpdate(element, context) {
if (!this.config.enabled)
return { success: true };
const securityContext = this.getSecurityContext(context);
const elementSecurityLevel = element.getData('securityLevel') || this.config.defaultSecurityLevel;
const hasPermission = await this.checkElementAccess(securityContext, element, PermissionType.WRITE);
if (!hasPermission) {
this.logAudit(securityContext, 'update_element', 'denied', {
elementId: element.id,
securityLevel: elementSecurityLevel
});
return {
success: false,
error: 'Недостаточно прав для изменения элемента'
};
}
this.logAudit(securityContext, 'update_element', 'success', { elementId: element.id });
return { success: true };
}
async beforeDelete(element, context) {
if (!this.config.enabled)
return { success: true };
const securityContext = this.getSecurityContext(context);
const hasPermission = await this.checkElementAccess(securityContext, element, PermissionType.DELETE);
if (!hasPermission) {
this.logAudit(securityContext, 'delete_element', 'denied', { elementId: element.id });
return {
success: false,
error: 'Недостаточно прав для удаления элемента'
};
}
this.logAudit(securityContext, 'delete_element', 'success', { elementId: element.id });
return { success: true };
}
async afterRead(element, context) {
if (!this.config.enabled)
return { success: true };
const securityContext = this.getSecurityContext(context);
const hasPermission = await this.checkElementAccess(securityContext, element, PermissionType.READ);
if (!hasPermission) {
this.logAudit(securityContext, 'read_element', 'denied', { elementId: element.id });
return {
success: false,
error: 'Недостаточно прав для чтения элемента'
};
}
// Расшифровка данных если необходимо
if (this.config.encryptionEnabled) {
await this.decryptElementData(element, securityContext);
}
this.logAudit(securityContext, 'read_element', 'success', { elementId: element.id });
return { success: true };
}
// Управление пользователями
createUser(userData) {
const user = {
id: this.generateId(),
failedAttempts: 0,
isActive: true,
...userData
};
this.users.set(user.id, user);
this.updateStats();
return user;
}
getUser(id) {
return this.users.get(id);
}
getUserByUsername(username) {
for (const user of this.users.values()) {
if (user.username === username) {
return user;
}
}
return undefined;
}
updateUser(id, updates) {
const user = this.users.get(id);
if (!user)
return false;
Object.assign(user, updates);
this.updateStats();
return true;
}
deleteUser(id) {
const deleted = this.users.delete(id);
if (deleted)
this.updateStats();
return deleted;
}
// Управление ролями
createRole(roleData) {
const role = {
id: this.generateId(),
...roleData
};
this.roles.set(role.id, role);
this.updateStats();
return role;
}
getRole(id) {
return this.roles.get(id);
}
updateRole(id, updates) {
const role = this.roles.get(id);
if (!role)
return false;
Object.assign(role, updates);
this.updateStats();
return true;
}
deleteRole(id) {
const deleted = this.roles.delete(id);
if (deleted)
this.updateStats();
return deleted;
}
// Управление правилами безопасности
addSecurityRule(ruleData) {
const rule = {
id: this.generateId(),
createdAt: new Date(),
updatedAt: new Date(),
...ruleData
};
this.rules.set(rule.id, rule);
this.updateStats();
return rule;
}
getSecurityRule(id) {
return this.rules.get(id);
}
updateSecurityRule(id, updates) {
const rule = this.rules.get(id);
if (!rule)
return false;
Object.assign(rule, { ...updates, updatedAt: new Date() });
this.updateStats();
return true;
}
deleteSecurityRule(id) {
const deleted = this.rules.delete(id);
if (deleted)
this.updateStats();
return deleted;
}
// Аутентификация и авторизация
async authenticate(username, password, _method = AuthenticationMethod.PASSWORD) {
const user = this.getUserByUsername(username);
if (!user || !user.isActive) {
this.stats.failedAttempts++;
return null;
}
// Проверка блокировки
if (user.lockedUntil && user.lockedUntil > new Date()) {
return null;
}
// Проверка пароля
const isValidPassword = await this.verifyPassword(password, user);
if (!isValidPassword) {
user.failedAttempts++;
this.stats.failedAttempts++;
// Блокировка при превышении попыток
if (user.failedAttempts >= this.config.maxFailedAttempts) {
user.lockedUntil = new Date(Date.now() + this.config.lockoutDuration);
this.updateStats();
}
return null;
}
// Успешная аутентификация
user.failedAttempts = 0;
user.lastLogin = new Date();
user.lockedUntil = undefined;
const sessionId = this.generateSessionId();
const session = {
user,
sessionId,
timestamp: new Date(),
operation: 'login'
};
this.sessions.set(sessionId, session);
this.stats.successfulLogins++;
this.updateStats();
return sessionId;
}
logout(sessionId) {
return this.sessions.delete(sessionId);
}
getSession(sessionId) {
const session = this.sessions.get(sessionId);
if (!session)
return undefined;
// Проверка истечения сессии
if (Date.now() - session.timestamp.getTime() > this.config.sessionTimeout) {
this.sessions.delete(sessionId);
return undefined;
}
return session;
}
async checkPermission(context, permission) {
if (!this.config.requireAuthentication && this.config.allowAnonymous) {
return true;
}
if (!context.user) {
return false;
}
const user = context.user;
// Проверка прямых разрешений пользователя
if (user.permissions.includes(permission) || user.permissions.includes(PermissionType.ADMIN)) {
return true;
}
// Проверка разрешений через роли
for (const roleId of user.roles) {
const role = this.roles.get(roleId);
if (role && role.isActive && (role.permissions.includes(permission) || role.permissions.includes(PermissionType.ADMIN))) {
return true;
}
}
return false;
}
async checkElementAccess(context, element, permission) {
const hasBasePermission = await this.checkPermission(context, permission);
if (!hasBasePermission) {
return false;
}
const elementSecurityLevel = element.getData('securityLevel') || this.config.defaultSecurityLevel;
const userSecurityLevel = context.user?.securityLevel || SecurityLevel.PUBLIC;
return this.compareSecurityLevels(userSecurityLevel, elementSecurityLevel);
}
async encryptElementData(element, _context) {
try {
const data = element.serialize();
const encryptedData = await this.encrypt(JSON.stringify(data));
element.setData('_encrypted', true);
element.setData('_encryptedData', encryptedData);
this.stats.encryptedElements++;
return true;
}
catch (error) {
console.error('Ошибка шифрования данных элемента:', error);
return false;
}
}
async decryptElementData(element, _context) {
try {
if (!element.getData('_encrypted')) {
return true; // Данные не зашифрованы
}
const encryptedData = element.getData('_encryptedData');
if (!encryptedData) {
return false;
}
const decryptedData = await this.decrypt(encryptedData);
const data = JSON.parse(decryptedData);
// Восстановление данных
Object.keys(data).forEach(key => {
if (key !== '_encrypted' && key !== '_encryptedData') {
element.setData(key, data[key]);
}
});
element.deleteData('_encrypted');
element.deleteData('_encryptedData');
return true;
}
catch (error) {
console.error('Ошибка расшифровки данных элемента:', error);
return false;
}
}
// Аудит
logAudit(context, operation, result, details) {
if (!this.config.auditingEnabled)
return;
const auditLog = {
id: this.generateId(),
timestamp: new Date(),
user: context.user?.username,
operation,
resource: context.resource,
result,
details,
securityLevel: context.user?.securityLevel || SecurityLevel.PUBLIC,
ipAddress: context.ipAddress,
userAgent: context.userAgent
};
this.auditLogs.push(auditLog);
this.stats.auditLogs++;
if (result === 'denied') {
this.stats.deniedOperations++;
}
}
getAuditLogs(filter) {
if (!filter)
return [...this.auditLogs];
return this.auditLogs.filter(log => {
return Object.entries(filter).every(([key, value]) => {
return log[key] === value;
});
});
}
getSecurityContext(context) {
return {
user: context?.user,
sessionId: context?.sessionId,
ipAddress: context?.ipAddress,
userAgent: context?.userAgent,
timestamp: new Date(),
operation: context?.operation || 'unknown',
resource: context?.resource,
metadata: context?.metadata
};
}
compareSecurityLevels(userLevel, requiredLevel) {
const levels = [
SecurityLevel.PUBLIC,
SecurityLevel.PROTECTED,
SecurityLevel.PRIVATE,
SecurityLevel.CONFIDENTIAL,
SecurityLevel.TOP_SECRET
];
const userLevelIndex = levels.indexOf(userLevel);
const requiredLevelIndex = levels.indexOf(requiredLevel);
return userLevelIndex >= requiredLevelIndex;
}
async verifyPassword(password, _user) {
// Простая проверка пароля (в реальном приложении должен быть хеш)
return password.length >= 8; // Минимальная проверка
}
async encrypt(data) {
// Простое шифрование для демонстрации
return Buffer.from(data).toString('base64');
}
async decrypt(encryptedData) {
// Простая расшифровка для демонстрации
return Buffer.from(encryptedData, 'base64').toString();
}
initializeDefaultRoles() {
// Создание базовых ролей
this.createRole({
name: 'admin',
description: 'Администратор системы',
permissions: [PermissionType.ADMIN],
securityLevel: SecurityLevel.TOP_SECRET,
isActive: true
});
this.createRole({
name: 'user',
description: 'Обычный пользователь',
permissions: [PermissionType.READ, PermissionType.WRITE],
securityLevel: SecurityLevel.PROTECTED,
isActive: true
});
this.createRole({
name: 'guest',
description: 'Гостевой доступ',
permissions: [PermissionType.READ],
securityLevel: SecurityLevel.PUBLIC,
isActive: true
});
}
cleanupExpiredSessions() {
const now = Date.now();
for (const [sessionId, session] of this.sessions.entries()) {
if (now - session.timestamp.getTime() > this.config.sessionTimeout) {
this.sessions.delete(sessionId);
}
}
this.updateStats();
}
cleanupAuditLogs() {
// Удаление логов старше 30 дней
const thirtyDaysAgo = Date.now() - (30 * 24 * 60 * 60 * 1000);
this.auditLogs = this.auditLogs.filter(log => log.timestamp.getTime() > thirtyDaysAgo);
this.stats.auditLogs = this.auditLogs.length;
this.stats.lastAuditCleanup = new Date();
}
updateStats() {
this.stats.totalUsers = this.users.size;
this.stats.activeUsers = Array.from(this.users.values()).filter(u => u.isActive).length;
this.stats.lockedUsers = Array.from(this.users.values()).filter(u => u.lockedUntil && u.lockedUntil > new Date()).length;
this.stats.totalRoles = this.roles.size;
this.stats.totalRules = this.rules.size;
this.stats.activeRules = Array.from(this.rules.values()).filter(r => r.enabled).length;
}
generateId() {
return Math.random().toString(36).substr(2, 9);
}
generateSessionId() {
return Math.random().toString(36).substr(2, 16) + Date.now().toString(36);
}
// Публичные методы для получения статистики и данных
getStats() {
return { ...this.stats };
}
getAllUsers() {
return Array.from(this.users.values());
}
getAllRoles() {
return Array.from(this.roles.values());
}
getAllSecurityRules() {
return Array.from(this.rules.values());
}
getActiveSessions() {
return Array.from(this.sessions.values());
}
}
exports.SecurityPlugin = SecurityPlugin;
//# sourceMappingURL=security.js.map