UNPKG

@boundless-oss/atlas

Version:

Atlas - MCP Server for comprehensive startup project management

755 lines 27.9 kB
import { randomUUID } from 'crypto'; import { createTool, createSuccessResult, createErrorResult } from '../../core/tool-framework.js'; import { SecurityScanner } from './scanner.js'; import { SecurityManager } from '../../utils/security-manager.js'; // Security scanner and manager instances let securityScanner; let securityManager; /** * Get security status */ const getSecurityStatusTool = createTool({ name: 'get_security_status', description: 'Get comprehensive security status overview including recent events, policy status, and system health', category: 'security', readOnly: true, inputSchema: { type: 'object', properties: {}, required: [], additionalProperties: false }, async execute(input, context) { try { // Initialize managers if needed if (!securityManager) { securityManager = SecurityManager.getInstance(); } const status = await securityManager.getSecurityStatus(); return createSuccessResult({ status, generatedAt: new Date().toISOString() }); } catch (error) { return createErrorResult({ code: 'EXECUTION_ERROR', message: `Failed to get security status: ${error instanceof Error ? error.message : 'Unknown error'}`, category: 'execution' }); } } }); /** * Get security events */ const getSecurityEventsTool = createTool({ name: 'get_security_events', description: 'Retrieve security events and incidents with filtering options', category: 'security', readOnly: true, inputSchema: { type: 'object', properties: { timeRange: { type: 'string', enum: ['1h', '24h', '7d', '30d'], default: '24h', description: 'Time range for event retrieval' }, eventTypes: { type: 'array', items: { type: 'string', enum: ['access_denied', 'approval_required', 'policy_violation', 'suspicious_activity', 'error'] }, description: 'Filter events by type' }, severity: { type: 'string', enum: ['low', 'medium', 'high', 'critical'], default: 'low', description: 'Minimum severity level to include' } }, required: [], additionalProperties: false }, async execute(input, context) { try { if (!securityManager) { securityManager = SecurityManager.getInstance(); } const events = await securityManager.getSecurityEvents({ timeRange: input.timeRange || '24h', eventTypes: input.eventTypes, severity: input.severity || 'low' }); return createSuccessResult({ timeRange: input.timeRange || '24h', eventCount: events.length, events, generatedAt: new Date().toISOString() }); } catch (error) { return createErrorResult({ code: 'EXECUTION_ERROR', message: `Failed to get security events: ${error instanceof Error ? error.message : 'Unknown error'}`, category: 'execution' }); } } }); /** * Configure security policy */ const configureSecurityPolicyTool = createTool({ name: 'configure_security_policy', description: 'Configure security policies including approval requirements, role definitions, and risk thresholds', category: 'security', requiresApproval: true, inputSchema: { type: 'object', properties: { requireApprovalFor: { type: 'array', items: { type: 'string' }, description: 'List of operations requiring human approval' }, roles: { type: 'object', additionalProperties: { type: 'array', items: { type: 'string' } }, description: 'Role definitions with permissions' }, riskThresholds: { type: 'object', additionalProperties: { type: 'number' }, description: 'Risk threshold values for different operations' }, logLevel: { type: 'string', enum: ['debug', 'info', 'warn', 'error'], default: 'info', description: 'Security logging level' } }, required: [], additionalProperties: false }, async execute(input, context) { try { if (!securityManager) { securityManager = SecurityManager.getInstance(); } await securityManager.configureSecurityPolicy({ requireApprovalFor: input.requireApprovalFor || [], roles: input.roles || {}, riskThresholds: input.riskThresholds || {}, logLevel: input.logLevel || 'info' }); // Log security event await context.db.run(`INSERT INTO security_events (id, event_type, tool_name, user_id, context, risk_level, details, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ randomUUID(), 'policy_change', 'configure_security_policy', context.userId || 'system', JSON.stringify({ projectId: context.projectId }), 'high', JSON.stringify(input), Date.now() ]); return createSuccessResult({ configuration: { requireApprovalFor: input.requireApprovalFor || [], roles: input.roles || {}, riskThresholds: input.riskThresholds || {}, logLevel: input.logLevel || 'info' }, updatedAt: new Date().toISOString() }); } catch (error) { return createErrorResult({ code: 'EXECUTION_ERROR', message: `Failed to configure security policy: ${error instanceof Error ? error.message : 'Unknown error'}`, category: 'execution' }); } } }); /** * Process security approval */ const processSecurityApprovalTool = createTool({ name: 'process_security_approval', description: 'Process pending security approval requests', category: 'security', inputSchema: { type: 'object', properties: { approvalId: { type: 'string', description: 'Unique identifier for the approval request', minLength: 1 }, decision: { type: 'string', enum: ['approve', 'deny'], description: 'Decision for the approval request' }, reason: { type: 'string', description: 'Optional reason for the decision', maxLength: 1000 } }, required: ['approvalId', 'decision'], additionalProperties: false }, async execute(input, context) { try { if (!securityManager) { securityManager = SecurityManager.getInstance(); } const result = await securityManager.processApproval({ approvalId: input.approvalId, decision: input.decision, reason: input.reason }); // Log security event await context.db.run(`INSERT INTO security_events (id, event_type, tool_name, user_id, context, risk_level, details, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ randomUUID(), 'approval_processed', 'process_security_approval', context.userId || 'system', JSON.stringify({ projectId: context.projectId, approvalId: input.approvalId }), 'medium', JSON.stringify({ decision: input.decision, reason: input.reason }), Date.now() ]); return createSuccessResult({ approvalId: input.approvalId, decision: input.decision, reason: input.reason, result, processedAt: new Date().toISOString() }); } catch (error) { return createErrorResult({ code: 'EXECUTION_ERROR', message: `Failed to process approval: ${error instanceof Error ? error.message : 'Unknown error'}`, category: 'execution' }); } } }); /** * Perform security scan */ const securityScanTool = createTool({ name: 'security_scan', description: 'Perform comprehensive security scan of the project', category: 'security', readOnly: true, inputSchema: { type: 'object', properties: { scanType: { type: 'string', enum: ['quick', 'comprehensive', 'deep'], default: 'comprehensive', description: 'Type of security scan to perform' }, includeFiles: { type: 'boolean', default: true, description: 'Scan source files for security issues' }, includeDependencies: { type: 'boolean', default: true, description: 'Check dependencies for vulnerabilities' }, includeSecrets: { type: 'boolean', default: true, description: 'Scan for exposed secrets and credentials' }, includePermissions: { type: 'boolean', default: true, description: 'Check file permissions and access controls' }, outputFormat: { type: 'string', enum: ['summary', 'detailed', 'json'], default: 'detailed', description: 'Format for scan results' } }, required: [], additionalProperties: false }, async execute(input, context) { try { if (!securityScanner) { const { ConfigManager } = await import('../../config/config-manager.js'); securityScanner = new SecurityScanner(new ConfigManager()); } const config = { scanType: input.scanType || 'comprehensive', includeFiles: input.includeFiles !== false, includeDependencies: input.includeDependencies !== false, includeSecrets: input.includeSecrets !== false, includePermissions: input.includePermissions !== false, outputFormat: input.outputFormat || 'detailed' }; const scanResult = await securityScanner.performScan(config); // Log security event await context.db.run(`INSERT INTO security_events (id, event_type, tool_name, user_id, context, risk_level, details, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ randomUUID(), 'security_scan', 'security_scan', context.userId || 'system', JSON.stringify({ projectId: context.projectId }), scanResult.summary.status === 'fail' ? 'high' : 'low', JSON.stringify({ scanType: input.scanType, summary: scanResult.summary }), Date.now() ]); return createSuccessResult({ scanResult, timestamp: new Date().toISOString() }); } catch (error) { return createErrorResult({ code: 'EXECUTION_ERROR', message: `Security scan failed: ${error instanceof Error ? error.message : 'Unknown error'}`, category: 'execution' }); } } }); /** * Check for secrets */ const checkSecretsTool = createTool({ name: 'check_secrets', description: 'Scan for exposed secrets, API keys, and credentials', category: 'security', readOnly: true, inputSchema: { type: 'object', properties: { scanPath: { type: 'string', default: '.', description: 'Path to scan for secrets' }, excludePaths: { type: 'array', items: { type: 'string' }, default: ['.git', 'node_modules', '.atlas'], description: 'Paths to exclude from scanning' }, customPatterns: { type: 'array', items: { type: 'string' }, description: 'Custom regex patterns to detect secrets' } }, required: [], additionalProperties: false }, async execute(input, context) { try { if (!securityScanner) { const { ConfigManager } = await import('../../config/config-manager.js'); securityScanner = new SecurityScanner(new ConfigManager()); } const secretsFound = await securityScanner.scanForSecrets({ scanPath: input.scanPath || '.', excludePaths: input.excludePaths || ['.git', 'node_modules', '.atlas'], customPatterns: input.customPatterns || [] }); // Log security event if secrets found if (secretsFound.length > 0) { await context.db.run(`INSERT INTO security_events (id, event_type, tool_name, user_id, context, risk_level, details, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ randomUUID(), 'secrets_detected', 'check_secrets', context.userId || 'system', JSON.stringify({ projectId: context.projectId }), 'critical', JSON.stringify({ count: secretsFound.length, types: [...new Set(secretsFound.map((s) => s.type))] }), Date.now() ]); } return createSuccessResult({ secretsFound, scanCompleted: true }); } catch (error) { return createErrorResult({ code: 'EXECUTION_ERROR', message: `Secrets scan failed: ${error instanceof Error ? error.message : 'Unknown error'}`, category: 'execution' }); } } }); /** * Check vulnerabilities */ const vulnerabilityCheckTool = createTool({ name: 'vulnerability_check', description: 'Check dependencies for known vulnerabilities', category: 'security', readOnly: true, inputSchema: { type: 'object', properties: { checkNpm: { type: 'boolean', default: true, description: 'Check npm dependencies' }, checkYarn: { type: 'boolean', default: true, description: 'Check yarn dependencies' }, severity: { type: 'string', enum: ['low', 'moderate', 'high', 'critical'], default: 'moderate', description: 'Minimum severity level to report' }, autoFix: { type: 'boolean', default: false, description: 'Automatically fix vulnerabilities when possible' } }, required: [], additionalProperties: false }, async execute(input, context) { try { if (!securityScanner) { const { ConfigManager } = await import('../../config/config-manager.js'); securityScanner = new SecurityScanner(new ConfigManager()); } const vulnerabilities = await securityScanner.checkVulnerabilities({ checkNpm: input.checkNpm !== false, checkYarn: input.checkYarn !== false, severity: input.severity || 'moderate', autoFix: input.autoFix || false }); // Log security event if vulnerabilities found if (vulnerabilities.total > 0) { await context.db.run(`INSERT INTO security_events (id, event_type, tool_name, user_id, context, risk_level, details, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ randomUUID(), 'vulnerabilities_detected', 'vulnerability_check', context.userId || 'system', JSON.stringify({ projectId: context.projectId }), vulnerabilities.critical > 0 ? 'critical' : 'high', JSON.stringify({ total: vulnerabilities.total, critical: vulnerabilities.critical, high: vulnerabilities.high, moderate: vulnerabilities.moderate, low: vulnerabilities.low }), Date.now() ]); } return createSuccessResult({ vulnerabilities, scanCompleted: true }); } catch (error) { return createErrorResult({ code: 'EXECUTION_ERROR', message: `Vulnerability check failed: ${error instanceof Error ? error.message : 'Unknown error'}`, category: 'execution' }); } } }); /** * Setup security configuration */ const setupSecurityConfigTool = createTool({ name: 'setup_security_config', description: 'Configure comprehensive security tools and policies', category: 'security', requiresApproval: true, inputSchema: { type: 'object', properties: { enablePreCommitScans: { type: 'boolean', default: true, description: 'Enable security scans in pre-commit hooks' }, enableSecretDetection: { type: 'boolean', default: true, description: 'Enable secret detection in CI/CD' }, enableVulnerabilityChecks: { type: 'boolean', default: true, description: 'Enable dependency vulnerability checks' }, createSecurityPolicy: { type: 'boolean', default: true, description: 'Create SECURITY.md policy file' }, setupGitHooks: { type: 'boolean', default: true, description: 'Setup Git hooks for security checks' } }, required: [], additionalProperties: false }, async execute(input, context) { try { if (!securityScanner) { const { ConfigManager } = await import('../../config/config-manager.js'); securityScanner = new SecurityScanner(new ConfigManager()); } const setupResult = await securityScanner.setupSecurityConfiguration({ enablePreCommitScans: input.enablePreCommitScans !== false, enableSecretDetection: input.enableSecretDetection !== false, enableVulnerabilityChecks: input.enableVulnerabilityChecks !== false, createSecurityPolicy: input.createSecurityPolicy !== false, setupGitHooks: input.setupGitHooks !== false }); // Log security event await context.db.run(`INSERT INTO security_events (id, event_type, tool_name, user_id, context, risk_level, details, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ randomUUID(), 'security_setup', 'setup_security_config', context.userId || 'system', JSON.stringify({ projectId: context.projectId }), 'medium', JSON.stringify(input), Date.now() ]); return createSuccessResult({ setupResult, configuration: { enablePreCommitScans: input.enablePreCommitScans !== false, enableSecretDetection: input.enableSecretDetection !== false, enableVulnerabilityChecks: input.enableVulnerabilityChecks !== false, createSecurityPolicy: input.createSecurityPolicy !== false, setupGitHooks: input.setupGitHooks !== false } }); } catch (error) { return createErrorResult({ code: 'EXECUTION_ERROR', message: `Security setup failed: ${error instanceof Error ? error.message : 'Unknown error'}`, category: 'execution' }); } } }); /** * Generate security report */ const generateSecurityReportTool = createTool({ name: 'generate_security_report', description: 'Generate comprehensive security report for the project', category: 'security', readOnly: true, inputSchema: { type: 'object', properties: { includeOverview: { type: 'boolean', default: true, description: 'Include security overview section' }, includeDetails: { type: 'boolean', default: true, description: 'Include detailed findings' }, includeRecommendations: { type: 'boolean', default: true, description: 'Include security recommendations' }, outputPath: { type: 'string', default: 'SECURITY.md', description: 'Path to save the security report' } }, required: [], additionalProperties: false }, async execute(input, context) { try { if (!securityScanner) { const { ConfigManager } = await import('../../config/config-manager.js'); securityScanner = new SecurityScanner(new ConfigManager()); } const report = await securityScanner.generateSecurityReport({ includeOverview: input.includeOverview !== false, includeDetails: input.includeDetails !== false, includeRecommendations: input.includeRecommendations !== false }); // Save report to file const fsModule = await import('fs'); const pathModule = await import('path'); await fsModule.promises.writeFile(pathModule.join(process.cwd(), input.outputPath || 'SECURITY.md'), report.markdown); return createSuccessResult({ reportGenerated: true, outputPath: input.outputPath || 'SECURITY.md', summary: report.summary }); } catch (error) { return createErrorResult({ code: 'EXECUTION_ERROR', message: `Report generation failed: ${error instanceof Error ? error.message : 'Unknown error'}`, category: 'execution' }); } } }); /** * Check data access */ const checkDataAccessTool = createTool({ name: 'check_data_access', description: 'Monitor and detect improper access to .atlas/ directory', category: 'security', readOnly: true, inputSchema: { type: 'object', properties: { scanPath: { type: 'string', default: '.', description: 'Path to scan for data access violations' }, excludePaths: { type: 'array', items: { type: 'string' }, default: ['.git', 'node_modules', 'dist', 'build'], description: 'Paths to exclude from scanning' }, includeWarnings: { type: 'boolean', default: true, description: 'Include warnings for potential violations' }, includeSuggestions: { type: 'boolean', default: true, description: 'Include suggestions for proper MCP tool usage' } }, required: [], additionalProperties: false }, async execute(input, context) { try { if (!securityScanner) { const { ConfigManager } = await import('../../config/config-manager.js'); securityScanner = new SecurityScanner(new ConfigManager()); } const accessViolations = await securityScanner.checkDataAccess({ scanPath: input.scanPath || '.', excludePaths: input.excludePaths || ['.git', 'node_modules', 'dist', 'build'], includeWarnings: input.includeWarnings !== false, includeSuggestions: input.includeSuggestions !== false }); // Log security event if violations found if (accessViolations.length > 0) { await context.db.run(`INSERT INTO security_events (id, event_type, tool_name, user_id, context, risk_level, details, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ randomUUID(), 'data_access_violation', 'check_data_access', context.userId || 'system', JSON.stringify({ projectId: context.projectId }), 'high', JSON.stringify({ violationCount: accessViolations.length, types: [...new Set(accessViolations.map((v) => v.type))] }), Date.now() ]); } return createSuccessResult({ violations: accessViolations, scanCompleted: true }); } catch (error) { return createErrorResult({ code: 'EXECUTION_ERROR', message: `Data access check failed: ${error instanceof Error ? error.message : 'Unknown error'}`, category: 'execution' }); } } }); /** * Setup security management tools */ export async function setupSecurityTools() { return { module: 'security', tools: [ getSecurityStatusTool, getSecurityEventsTool, configureSecurityPolicyTool, processSecurityApprovalTool, securityScanTool, checkSecretsTool, vulnerabilityCheckTool, setupSecurityConfigTool, generateSecurityReportTool, checkDataAccessTool ] }; } //# sourceMappingURL=tools.js.map