UNPKG

@gati-framework/runtime

Version:

Gati runtime execution engine for running handler-based applications

328 lines 11.3 kB
/** * @module runtime/capability-manager * @description Capability-based security enforcement for modules * * This implements capability enforcement from Task 10: * - Capability validation against module manifests * - Runtime capability checking * - Resource access control * * Requirements: 5.3, 12.1, 12.2 */ /** * Capability Manager * * Enforces capability-based security for modules. * Validates that modules only access resources they have declared capabilities for. */ export class CapabilityManager { /** * Map of module ID to granted capabilities */ grantedCapabilities = new Map(); /** * Map of module ID to network access configuration */ networkAccess = new Map(); /** * System-level capability policies * Defines which capabilities can be granted */ systemPolicies = new Map(); constructor() { // Initialize default system policies this.initializeDefaultPolicies(); } /** * Initialize default system capability policies */ initializeDefaultPolicies() { // Database capabilities this.systemPolicies.set('database:read', { name: 'database:read', description: 'Read access to database', grantable: true, }); this.systemPolicies.set('database:write', { name: 'database:write', description: 'Write access to database', grantable: true, }); // Filesystem capabilities this.systemPolicies.set('filesystem:read', { name: 'filesystem:read', description: 'Read access to filesystem', grantable: true, }); this.systemPolicies.set('filesystem:write', { name: 'filesystem:write', description: 'Write access to filesystem', grantable: true, }); // Network capabilities this.systemPolicies.set('network:egress', { name: 'network:egress', description: 'Outbound network access', grantable: true, }); this.systemPolicies.set('network:ingress', { name: 'network:ingress', description: 'Inbound network access', grantable: true, }); // Secrets capabilities this.systemPolicies.set('secrets:read', { name: 'secrets:read', description: 'Read access to secrets', grantable: true, }); // Cache capabilities this.systemPolicies.set('cache:read', { name: 'cache:read', description: 'Read access to cache', grantable: true, }); this.systemPolicies.set('cache:write', { name: 'cache:write', description: 'Write access to cache', grantable: true, }); // Metrics capabilities this.systemPolicies.set('metrics:write', { name: 'metrics:write', description: 'Write access to metrics', grantable: true, }); // Logging capabilities this.systemPolicies.set('logging:write', { name: 'logging:write', description: 'Write access to logs', grantable: true, }); } /** * Validate module capabilities against system policies * * @param manifest - Module manifest to validate * @returns Validation result with granted/denied capabilities */ validateCapabilities(manifest) { const result = { valid: true, granted: [], denied: [], missingRequired: [], errors: [], }; // Validate each declared capability for (const capability of manifest.capabilities) { const policy = this.systemPolicies.get(capability.name); if (!policy) { // Unknown capability result.errors.push(`Unknown capability: ${capability.name}`); result.denied.push(capability.name); if (capability.required) { result.missingRequired.push(capability.name); result.valid = false; } continue; } if (!policy.grantable) { // Capability exists but cannot be granted result.errors.push(`Capability cannot be granted: ${capability.name}`); result.denied.push(capability.name); if (capability.required) { result.missingRequired.push(capability.name); result.valid = false; } continue; } // Grant the capability result.granted.push(capability.name); } // Validate network access if (manifest.networkAccess.egress) { const hasNetworkCapability = manifest.capabilities.some((c) => c.name === 'network:egress'); if (!hasNetworkCapability) { result.errors.push('Network egress enabled but network:egress capability not declared'); result.valid = false; } } if (manifest.networkAccess.ingress) { const hasNetworkCapability = manifest.capabilities.some((c) => c.name === 'network:ingress'); if (!hasNetworkCapability) { result.errors.push('Network ingress enabled but network:ingress capability not declared'); result.valid = false; } } return result; } /** * Register granted capabilities for a module * * @param moduleId - Module identifier * @param capabilities - List of granted capabilities * @param networkAccess - Network access configuration */ registerModule(moduleId, capabilities, networkAccess) { this.grantedCapabilities.set(moduleId, new Set(capabilities)); this.networkAccess.set(moduleId, networkAccess); } /** * Check if a module has a specific capability * * @param moduleId - Module identifier * @param capability - Capability name to check * @returns True if module has the capability */ hasCapability(moduleId, capability) { const capabilities = this.grantedCapabilities.get(moduleId); return capabilities?.has(capability) ?? false; } /** * Enforce capability check - throws if module lacks capability * * @param moduleId - Module identifier * @param capability - Required capability * @param operation - Description of operation being attempted * @throws {CapabilityError} If module lacks the required capability */ enforceCapability(moduleId, capability, operation) { if (!this.hasCapability(moduleId, capability)) { throw new CapabilityError(`Module "${moduleId}" lacks required capability "${capability}" for operation: ${operation}`, moduleId, capability, operation); } } /** * Check if a module can access a specific network host * * @param moduleId - Module identifier * @param host - Hostname to check * @param port - Port number to check * @returns True if access is allowed */ canAccessNetwork(moduleId, host, port) { const access = this.networkAccess.get(moduleId); if (!access || !access.egress) { return false; } // Check if module has network:egress capability if (!this.hasCapability(moduleId, 'network:egress')) { return false; } // Check allowed hosts if (access.allowedHosts && access.allowedHosts.length > 0) { const hostAllowed = access.allowedHosts.some((allowedHost) => { // Support wildcard matching if (allowedHost.startsWith('*.')) { const domain = allowedHost.slice(2); return host.endsWith(domain); } return host === allowedHost; }); if (!hostAllowed) { return false; } } // Check allowed ports if (port !== undefined && access.allowedPorts && access.allowedPorts.length > 0) { if (!access.allowedPorts.includes(port)) { return false; } } return true; } /** * Enforce network access check - throws if access is denied * * @param moduleId - Module identifier * @param host - Hostname being accessed * @param port - Port number being accessed * @throws {NetworkAccessError} If network access is denied */ enforceNetworkAccess(moduleId, host, port) { if (!this.canAccessNetwork(moduleId, host, port)) { throw new NetworkAccessError(`Module "${moduleId}" denied network access to ${host}${port ? `:${port}` : ''}`, moduleId, host, port); } } /** * Get all granted capabilities for a module * * @param moduleId - Module identifier * @returns Array of granted capability names */ getGrantedCapabilities(moduleId) { const capabilities = this.grantedCapabilities.get(moduleId); return capabilities ? Array.from(capabilities) : []; } /** * Get network access configuration for a module * * @param moduleId - Module identifier * @returns Network access configuration or undefined */ getNetworkAccess(moduleId) { return this.networkAccess.get(moduleId); } /** * Unregister a module and revoke all capabilities * * @param moduleId - Module identifier */ unregisterModule(moduleId) { this.grantedCapabilities.delete(moduleId); this.networkAccess.delete(moduleId); } /** * Add a custom system capability policy * * @param policy - Capability policy to add */ addSystemPolicy(policy) { this.systemPolicies.set(policy.name, policy); } /** * Get all system capability policies * * @returns Array of capability policies */ getSystemPolicies() { return Array.from(this.systemPolicies.values()); } } /** * Capability error thrown when a module attempts unauthorized access */ export class CapabilityError extends Error { moduleId; capability; operation; constructor(message, moduleId, capability, operation) { super(message); this.name = 'CapabilityError'; this.moduleId = moduleId; this.capability = capability; this.operation = operation; if (Error.captureStackTrace) { Error.captureStackTrace(this, CapabilityError); } } } /** * Network access error thrown when a module attempts unauthorized network access */ export class NetworkAccessError extends Error { moduleId; host; port; constructor(message, moduleId, host, port) { super(message); this.name = 'NetworkAccessError'; this.moduleId = moduleId; this.host = host; this.port = port; if (Error.captureStackTrace) { Error.captureStackTrace(this, NetworkAccessError); } } } //# sourceMappingURL=capability-manager.js.map