Skip to main content
Glama
securityHealthCheckAgent.ts37 kB
/* * MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /** * Security and Health Check Agent * * This module provides MCP tool handlers that orchestrate comprehensive security * and health analysis. When a user requests a security or health check, these tools * are automatically invoked to generate consistent, thorough reports. * * Reports include: * - Active alarms and critical advisories * - Security vulnerabilities (CVEs) from TAM * - Firmware versions and update recommendations * - End-of-life component analysis * - Hardware health and thermal status * - Compliance posture assessment * - Actionable recommendations by priority */ export interface SecurityHealthCheckResult { status: 'SUCCESS' | 'PARTIAL' | 'ERROR'; timestamp: string; reportType: 'SECURITY' | 'HEALTH' | 'COMPREHENSIVE'; executionTimeMs: number; // Executive Summary summary: { overallScore: number; // 0-100, higher is better securityScore: number; healthScore: number; complianceScore: number; criticalCount: number; warningCount: number; infrastructureOverview: { totalServers: number; totalAlarms: number; totalAdvisories: number; firmwareComponents: number; healthyComponents: number; degradedComponents: number; }; }; alarms: { critical: number; warning: number; info: number; total: number; topAlarms: Array<{ id: string; description: string; severity: string; affectedDevice: string; affectedDeviceType: string; code: string; createTime: string; acknowledged: boolean; }>; alarmsByCode: Array<{ code: string; count: number; severity: string; description: string; affectedDevices: Array<{ name: string; type: string; severity: string; createTime: string; }>; }>; alarmsByDeviceType: Array<{ deviceType: string; count: number; criticalCount: number; }>; }; advisories: { critical: number; warning: number; info: number; total: number; securityAdvisories: number; fieldNotices: number; eolAdvisories: number; topAdvisories: Array<{ id: string; title: string; type: string; severity?: string; cveIds?: string[]; affectedPlatforms?: string[]; datePublished?: string; description?: string; recommendation?: string; affectedDevices?: Array<{ name: string; model?: string; version?: string; }>; }>; advisoriesByType: Array<{ type: string; count: number; criticalCount: number; affectedDevices?: Array<{ name: string; model?: string; }>; }>; }; firmware: { components: number; currentlySupported: number; outdated: number; endOfLife: number; updateRecommendations: Array<{ component: string; currentVersion: string; recommendedVersion: string; securityCritical: boolean; affectedDevices?: string[]; deviceCount?: number; releaseNotes?: string; vulnerabilitiesFixed?: string[]; }>; componentsByType: Array<{ componentType: string; count: number; versions: string[]; }>; }; hardware: { healthStatus: 'HEALTHY' | 'DEGRADED' | 'CRITICAL'; totalServers: number; healthyServers: number; degradedServers: number; failedServers: number; thermalStatus: 'NORMAL' | 'WARNING' | 'CRITICAL'; powerRedundancy: 'FULL' | 'DEGRADED' | 'SINGLE'; failedComponents: { processors: number; memory: number; drives: number; psus: number; }; componentDetails: { processors: { total: number; healthy: number; degraded: number; failed: number }; memory: { total: number; healthy: number; degraded: number; failed: number }; drives: { total: number; healthy: number; degraded: number; failed: number }; psus: { total: number; healthy: number; degraded: number; failed: number }; fans: { total: number; healthy: number; degraded: number; failed: number }; }; }; security: { tpmStatus: 'PRESENT' | 'MISSING'; secureBootEnabled: boolean; licenseCompliance: 'COMPLIANT' | 'NON_COMPLIANT'; expiredLicenses: number; expiringLicenses: number; managementControllersUnreachable: number; }; compliance: { overallStatus: 'COMPLIANT' | 'NON_COMPLIANT' | 'PARTIAL'; policyCount: number; certifiedOsVersions: number; hyperlexCompatibilityStatus: string; }; performance: { averageCpuUtilization: number; peakCpuUtilization: number; averageMemoryUtilization: number; peakMemoryUtilization: number; highUtilizationServers: string[]; }; recommendations: { immediate: string[]; // Must do now - affects availability or security shortTerm: string[]; // Do within 1 week - important for stability mediumTerm: string[]; // Do within 1 month - improves operations longTerm: string[]; // Do within 1 quarter - strategic improvements }; issues: Array<{ id: string; category: 'SECURITY' | 'HARDWARE' | 'FIRMWARE' | 'COMPLIANCE' | 'PERFORMANCE'; severity: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW'; title: string; description: string; affectedResources: string[]; remediation: string; }>; } /** * Generate a comprehensive security and health check report * This is the main agent entry point that orchestrates all phases */ export function createSecurityHealthCheckReport( alarms: any, advisories: any, advisoryInstances: any, advisoryCount: any, firmware: any, operatingSystems: any, hardware: any, thermalStats: any, powerStats: any, licenses: any, tpms: any, bootSecurity: any, policies: any, hyperflexCompat: any, topResources: any, servers: any ): SecurityHealthCheckResult { const startTime = Date.now(); const alarmsList = Array.isArray(alarms) ? alarms : []; const advisoryList = Array.isArray(advisories) ? advisories : []; const advisoryInstancesList = Array.isArray(advisoryInstances) ? advisoryInstances : []; const serversList = Array.isArray(servers) ? servers : []; const firmwareList = Array.isArray(firmware) ? firmware : []; const osVersions = Array.isArray(operatingSystems) ? operatingSystems : []; const licensesList = Array.isArray(licenses) ? licenses : []; const tpmList = Array.isArray(tpms) ? tpms : []; const bootSecList = Array.isArray(bootSecurity) ? bootSecurity : []; const policiesList = Array.isArray(policies) ? policies : []; const topRes = Array.isArray(topResources) ? topResources : []; // Phase 1: Analyze alarms const alarmAnalysis = analyzeAlarms(alarmsList); // Phase 2: Analyze advisories and CVEs const advisoryAnalysis = analyzeAdvisories(advisoryList, advisoryInstancesList, advisoryCount, serversList); // Phase 3: Analyze firmware const firmwareAnalysis = analyzeFirmware(firmwareList); // Phase 4: Analyze hardware const hardwareAnalysis = analyzeHardware(hardware, thermalStats, powerStats); // Phase 5: Analyze security const securityAnalysis = analyzeSecurity(licensesList, tpmList, bootSecList); // Phase 6: Analyze compliance const complianceAnalysis = analyzeCompliance(osVersions, policiesList, hyperflexCompat); // Phase 7: Analyze performance const performanceAnalysis = analyzePerformance(topRes); // Calculate scores const scores = calculateScores(alarmAnalysis, advisoryAnalysis, hardwareAnalysis, securityAnalysis, complianceAnalysis); // Generate issues const issues = generateIssues(alarmAnalysis, advisoryAnalysis, firmwareAnalysis, hardwareAnalysis, securityAnalysis, complianceAnalysis); // Generate recommendations const recommendations = generateRecommendations(alarmAnalysis, advisoryAnalysis, firmwareAnalysis, hardwareAnalysis, securityAnalysis, issues); // Extract calculated scores const { securityScore, healthScore, complianceScore } = scores; const report: SecurityHealthCheckResult = { status: issues.some(i => i.severity === 'CRITICAL') ? 'PARTIAL' : 'SUCCESS', timestamp: new Date().toISOString(), reportType: 'COMPREHENSIVE', executionTimeMs: Date.now() - startTime, summary: { overallScore: Math.round((securityScore + healthScore + complianceScore) / 3), securityScore: Math.max(0, securityScore), healthScore: Math.max(0, healthScore), complianceScore: Math.max(0, complianceScore), criticalCount: Math.max(alarmAnalysis.critical, advisoryAnalysis.critical), warningCount: alarmAnalysis.warning + advisoryAnalysis.warning, infrastructureOverview: { totalServers: hardwareAnalysis.totalServers || 0, totalAlarms: alarmAnalysis.total || 0, totalAdvisories: advisoryAnalysis.total || 0, firmwareComponents: firmwareAnalysis.components || 0, healthyComponents: (hardwareAnalysis.componentDetails?.processors.healthy || 0) + (hardwareAnalysis.componentDetails?.memory.healthy || 0) + (hardwareAnalysis.componentDetails?.drives.healthy || 0) + (hardwareAnalysis.componentDetails?.psus.healthy || 0) + (hardwareAnalysis.componentDetails?.fans.healthy || 0), degradedComponents: (hardwareAnalysis.componentDetails?.processors.degraded || 0) + (hardwareAnalysis.componentDetails?.memory.degraded || 0) + (hardwareAnalysis.componentDetails?.drives.degraded || 0) + (hardwareAnalysis.componentDetails?.psus.degraded || 0) + (hardwareAnalysis.componentDetails?.fans.degraded || 0) } }, alarms: alarmAnalysis, advisories: advisoryAnalysis, firmware: firmwareAnalysis, hardware: hardwareAnalysis, security: securityAnalysis, compliance: complianceAnalysis, performance: performanceAnalysis, recommendations, issues }; return report; } function analyzeAlarms(alarms: any[]): any { const critical = alarms.filter(a => a.Severity === 'Critical' || a.severity === 'Critical' || a.Severity === 'critical' || a.severity === 'critical' ).length; const warning = alarms.filter(a => a.Severity === 'Warning' || a.severity === 'Warning' || a.Severity === 'warning' || a.severity === 'warning' ).length; const info = alarms.filter(a => a.Severity === 'Info' || a.severity === 'Info' || a.Severity === 'info' || a.severity === 'info' ).length; // Group alarms by code with affected device tracking const alarmsByCodeMap = new Map<string, { count: number; severity: string; description: string; devices: Array<{ name: string; type: string; severity: string; createTime: string }>; }>(); alarms.forEach(a => { const code = a.Code || a.code || 'UNKNOWN'; const deviceName = a.AffectedMoDisplayName || a.affectedMoDisplayName || a.AffectedObject || a.affectedObject || a.Dn || a.dn || 'Unknown'; const deviceType = a.AffectedMoType || a.affectedMoType || 'Unknown'; const severity = a.Severity || a.severity || 'Unknown'; const createTime = a.CreateTime || a.createTime || a.CreationTime || a.creationTime || 'Unknown'; if (!alarmsByCodeMap.has(code)) { alarmsByCodeMap.set(code, { count: 0, severity: severity, description: a.Description || a.description || 'Unknown', devices: [] }); } const entry = alarmsByCodeMap.get(code)!; entry.count++; entry.devices.push({ name: deviceName, type: deviceType, severity, createTime }); }); const alarmsByCode = Array.from(alarmsByCodeMap.entries()) .map(([code, data]) => ({ code, count: data.count, severity: data.severity, description: data.description, affectedDevices: data.devices.slice(0, 50) // Limit to 50 devices per alarm code })) .sort((a, b) => b.count - a.count) .slice(0, 10); // Group alarms by device type const alarmsByDeviceTypeMap = new Map<string, { count: number; criticalCount: number }>(); alarms.forEach(a => { const deviceType = a.AffectedMoType || a.affectedMoType || 'Unknown'; if (!alarmsByDeviceTypeMap.has(deviceType)) { alarmsByDeviceTypeMap.set(deviceType, { count: 0, criticalCount: 0 }); } const entry = alarmsByDeviceTypeMap.get(deviceType)!; entry.count++; if ((a.Severity || a.severity || '').toLowerCase() === 'critical') { entry.criticalCount++; } }); const alarmsByDeviceType = Array.from(alarmsByDeviceTypeMap.entries()) .map(([deviceType, data]) => ({ deviceType, ...data })) .sort((a, b) => b.criticalCount - a.criticalCount || b.count - a.count) .slice(0, 10); return { critical, warning, info, total: alarms.length, topAlarms: alarms.filter(a => a.Severity === 'Critical' || a.severity === 'Critical' || a.Severity === 'critical' || a.severity === 'critical' ).slice(0, 10).map((a: any) => ({ id: a.Moid || a.moid || 'unknown', description: a.Description || a.description || 'Unknown alarm', severity: a.Severity || a.severity, affectedDevice: a.AffectedMoDisplayName || a.affectedMoDisplayName || a.AffectedObject || a.affectedObject || a.Dn || a.dn || 'Unknown', affectedDeviceType: a.AffectedMoType || a.affectedMoType || 'Unknown', code: a.Code || a.code || 'Unknown', createTime: a.CreateTime || a.createTime || a.CreationTime || a.creationTime || 'Unknown', acknowledged: (a.Acknowledge || a.acknowledge || 'None') !== 'None' })), alarmsByCode, alarmsByDeviceType }; } function analyzeAdvisories(advisories: any[], advisoryInstances: any[], advisoryCount: any, servers: any[]): any { const critical = (advisoryCount?.critical || 0) + advisories.filter(a => a.Severity === 'Critical' || a.severity === 'Critical' || a.Type === 'securityAdvisory' || a.type === 'securityAdvisory' ).length; const warning = advisoryCount?.warning || 0; const info = advisoryCount?.info || 0; const securityAdvisories = advisories.filter(a => a.Type === 'securityAdvisory' || a.type === 'securityAdvisory' || (a.Title || a.title || '').includes('CVE') ).length; const fieldNotices = advisories.filter(a => a.Type === 'fieldNotice' || a.type === 'fieldNotice' ).length; const eolAdvisories = advisories.filter(a => a.Type === 'eolAdvisory' || a.type === 'eolAdvisory' ).length; // Build MOID to name lookup map const moidToName = new Map<string, { name: string; model: string }>(); servers.forEach(server => { const moid = server.Moid || server.moid; const name = server.Name || server.name || 'Unknown Server'; const model = server.Model || server.model || ''; if (moid) { moidToName.set(moid, { name, model }); } }); // Build a map of advisory instances by advisory definition ID const instancesByAdvisory = new Map<string, any[]>(); advisoryInstances.forEach((instance: any) => { const advisoryId = instance.Advisory?.Moid || instance.advisory?.moid; if (advisoryId) { if (!instancesByAdvisory.has(advisoryId)) { instancesByAdvisory.set(advisoryId, []); } instancesByAdvisory.get(advisoryId)!.push(instance); } }); // Group advisories by type with affected device tracking const advisoriesByTypeMap = new Map<string, { count: number; criticalCount: number; devices: Set<string>; }>(); advisories.forEach(a => { const type = a.Type || a.type || 'advisory'; if (!advisoriesByTypeMap.has(type)) { advisoriesByTypeMap.set(type, { count: 0, criticalCount: 0, devices: new Set() }); } const entry = advisoriesByTypeMap.get(type)!; entry.count++; const severity = a.Severity || a.severity || ''; const severityStr = typeof severity === 'string' ? severity : String(severity); if (severityStr.toLowerCase() === 'critical') { entry.criticalCount++; } // Add affected devices from instances const advisoryId = a.Moid || a.moid; const instances = instancesByAdvisory.get(advisoryId) || []; instances.forEach(inst => { const deviceMoid = inst.AffectedObjectMoid || inst.affectedObjectMoid || inst.AffectedObject || inst.affectedObject || 'Unknown'; // Resolve MOID to name if available const deviceInfo = moidToName.get(deviceMoid); const deviceName = deviceInfo ? deviceInfo.name : deviceMoid; entry.devices.add(deviceName); }); }); const advisoriesByType = Array.from(advisoriesByTypeMap.entries()) .map(([type, data]) => ({ type, count: data.count, criticalCount: data.criticalCount, affectedDevices: Array.from(data.devices).slice(0, 20).map(name => { // If it's still a MOID (no match found), leave as is return { name }; }) })) .sort((a, b) => b.criticalCount - a.criticalCount || b.count - a.count); return { critical, warning, info, total: advisories.length, securityAdvisories, fieldNotices, eolAdvisories, topAdvisories: advisories.slice(0, 15).map((a: any) => { // Extract CVE IDs from description or external references const cveIds: string[] = []; const description = a.Description || a.description || ''; const title = a.Title || a.title || a.Name || a.name || ''; const combinedText = `${title} ${description}`; const cveMatches = combinedText.match(/CVE-\d{4}-\d{4,7}/g); if (cveMatches) { cveIds.push(...cveMatches); } // Extract affected platforms const affectedPlatforms: string[] = []; if (a.AffectedPids || a.affectedPids) { const pids = a.AffectedPids || a.affectedPids; if (Array.isArray(pids)) { affectedPlatforms.push(...pids); } } // Get affected devices from instances const advisoryId = a.Moid || a.moid; const instances = instancesByAdvisory.get(advisoryId) || []; const affectedDevices = instances.slice(0, 50).map((inst: any) => { const deviceMoid = inst.AffectedObjectMoid || inst.affectedObjectMoid || inst.Dn || inst.dn || 'Unknown'; const deviceInfo = moidToName.get(deviceMoid); return { name: deviceInfo ? deviceInfo.name : deviceMoid, model: deviceInfo?.model || inst.AffectedObjectType || inst.affectedObjectType, version: inst.AffectedFirmwareVersion || inst.affectedFirmwareVersion }; }); return { id: advisoryId || 'unknown', title: title || 'Unknown advisory', type: a.Type || a.type || 'advisory', severity: a.Severity || a.severity, cveIds: cveIds.length > 0 ? cveIds : undefined, affectedPlatforms: affectedPlatforms.length > 0 ? affectedPlatforms : undefined, datePublished: a.DatePublished || a.datePublished || a.CreateTime || a.createTime, description: (description || '').substring(0, 500), recommendation: (a.Recommendation || a.recommendation || '').substring(0, 500), affectedDevices: affectedDevices.length > 0 ? affectedDevices : undefined }; }), advisoriesByType }; } function analyzeFirmware(firmware: any[]): any { const components = firmware.length; const currentlySupported = firmware.filter((f: any) => !f.status || f.status === 'CURRENT').length; const outdated = firmware.filter((f: any) => f.status === 'OUTDATED').length; const endOfLife = firmware.filter((f: any) => f.status === 'DEPRECATED' || f.status === 'END_OF_LIFE').length; // Group firmware by component type const componentsByTypeMap = new Map<string, Set<string>>(); firmware.forEach((f: any) => { const component = f.Component || f.component || f.Type || f.type || 'Unknown'; const version = (f.Version || f.version || 'Unknown').trim(); if (!componentsByTypeMap.has(component)) { componentsByTypeMap.set(component, new Set()); } componentsByTypeMap.get(component)!.add(version); }); const componentsByType = Array.from(componentsByTypeMap.entries()) .map(([componentType, versions]) => ({ componentType, count: firmware.filter(f => (f.Component || f.component || f.Type || f.type) === componentType).length, versions: Array.from(versions).sort() })) .sort((a, b) => b.count - a.count); // Group firmware by component type and version to find update recommendations const firmwareGroups = new Map<string, any[]>(); firmware.forEach((f: any) => { const component = f.Component || f.component || f.Type || f.type || 'Unknown'; const version = f.Version || f.version || 'Unknown'; const key = `${component}:${version}`; if (!firmwareGroups.has(key)) { firmwareGroups.set(key, []); } firmwareGroups.get(key)!.push(f); }); const updateRecommendations: any[] = []; firmwareGroups.forEach((devices, key) => { const sample = devices[0]; const component = sample.Component || sample.component || sample.Type || sample.type || 'Unknown'; const currentVersion = sample.Version || sample.version || 'Unknown'; const recommendedVersion = sample.RecommendedVersion || sample.recommendedVersion; // Only include if there's a recommendation and it's different if (recommendedVersion && currentVersion !== recommendedVersion) { const affectedDeviceNames = devices .map((d: any) => { // Try to get server name from ancestors or parent if (d.Ancestors && Array.isArray(d.Ancestors)) { const serverAncestor = d.Ancestors.find((a: any) => (a.ObjectType || '').includes('compute.RackUnit') || (a.ObjectType || '').includes('compute.Blade') ); if (serverAncestor) { return serverAncestor.Moid; } } return d.Dn || d.dn || d.Moid || d.moid; }) .filter((n: string) => n) .slice(0, 5); updateRecommendations.push({ component, currentVersion: currentVersion.trim(), recommendedVersion: recommendedVersion.trim(), securityCritical: sample.securityCritical === true || sample.SecurityCritical === true, affectedDevices: affectedDeviceNames, deviceCount: devices.length, releaseNotes: sample.ReleaseNotes || sample.releaseNotes, vulnerabilitiesFixed: sample.VulnerabilitiesFixed || sample.vulnerabilitiesFixed }); } }); return { components, currentlySupported, outdated, endOfLife, updateRecommendations: updateRecommendations.slice(0, 15), componentsByType: componentsByType.slice(0, 15) }; } function analyzeHardware(hardware: any, thermalStats: any, powerStats: any): any { // Extract component arrays from hardware object (with null safety) const hardwareObj = hardware || {}; const processors = hardwareObj.processors || []; const memory = hardwareObj.memory || []; const drives = hardwareObj.drives || []; const psus = hardwareObj.psus || []; const fans = hardwareObj.fans || []; // Analyze processor health const processorHealth = { total: processors.length, healthy: processors.filter((p: any) => (p.Presence || p.presence) === 'equipped' && (p.OperState || p.operState) === 'operable' ).length, degraded: processors.filter((p: any) => (p.Presence || p.presence) === 'equipped' && (p.OperState || p.operState) === 'degraded' ).length, failed: processors.filter((p: any) => (p.Presence || p.presence) === 'equipped' && (p.OperState || p.operState) === 'inoperable' ).length }; // Analyze memory health const memoryHealth = { total: memory.length, healthy: memory.filter((m: any) => (m.Presence || m.presence) === 'equipped' && (m.OperState || m.operState) === 'operable' ).length, degraded: memory.filter((m: any) => (m.Presence || m.presence) === 'equipped' && (m.OperState || m.operState) === 'degraded' ).length, failed: memory.filter((m: any) => (m.Presence || m.presence) === 'equipped' && (m.OperState || m.operState) === 'inoperable' ).length }; // Analyze drive health const driveHealth = { total: drives.length, healthy: drives.filter((d: any) => (d.DiskState || d.diskState) === 'good' ).length, degraded: drives.filter((d: any) => (d.DiskState || d.diskState) === 'predictive-failure' || (d.DiskState || d.diskState) === 'partially-degraded' ).length, failed: drives.filter((d: any) => (d.DiskState || d.diskState) === 'failed' || (d.DiskState || d.diskState) === 'bad' ).length }; // Analyze PSU health const psuHealth = { total: psus.length, healthy: psus.filter((p: any) => (p.Presence || p.presence) === 'equipped' && (p.OperState || p.operState) === 'operable' ).length, degraded: psus.filter((p: any) => (p.Presence || p.presence) === 'equipped' && (p.OperState || p.operState) === 'degraded' ).length, failed: psus.filter((p: any) => (p.Presence || p.presence) === 'equipped' && (p.OperState || p.operState) === 'inoperable' ).length }; // Analyze fan health const fanHealth = { total: fans.length, healthy: fans.filter((f: any) => (f.Presence || f.presence) === 'equipped' && (f.OperState || f.operState) === 'operable' ).length, degraded: fans.filter((f: any) => (f.Presence || f.presence) === 'equipped' && (f.OperState || f.operState) === 'degraded' ).length, failed: fans.filter((f: any) => (f.Presence || f.presence) === 'equipped' && (f.OperState || f.operState) === 'inoperable' ).length }; // Calculate overall metrics const totalComponents = processorHealth.total + memoryHealth.total + driveHealth.total + psuHealth.total + fanHealth.total; const healthyComponents = processorHealth.healthy + memoryHealth.healthy + driveHealth.healthy + psuHealth.healthy + fanHealth.healthy; const degradedComponents = processorHealth.degraded + memoryHealth.degraded + driveHealth.degraded + psuHealth.degraded + fanHealth.degraded; const failedComponentCount = processorHealth.failed + memoryHealth.failed + driveHealth.failed + psuHealth.failed + fanHealth.failed; // Legacy structure for backward compatibility const failedComponents = { processors: processorHealth.failed, memory: memoryHealth.failed, drives: driveHealth.failed, psus: psuHealth.failed }; // Count servers (estimate from processors - typically 2 per server) const estimatedServers = Math.ceil(processors.length / 2); const serversWithFailures = new Set( [...processors, ...memory, ...drives] .filter((c: any) => (c.OperState || c.operState) === 'inoperable' || (c.DiskState || c.diskState) === 'failed' ) .map((c: any) => c.Dn || c.dn || '') .filter(dn => dn) .map(dn => dn.split('/')[0]) ).size; // Safely calculate thermal status const thermalStatsObj = thermalStats || { averageTemp: 0 }; const avgTemp = thermalStatsObj.averageTemp || 0; const thermalStatus = avgTemp > 95 ? 'CRITICAL' : avgTemp > 85 ? 'WARNING' : 'NORMAL'; return { healthStatus: failedComponentCount > 0 ? 'DEGRADED' : degradedComponents > 0 ? 'WARNING' : 'HEALTHY', totalServers: estimatedServers, healthyServers: estimatedServers - serversWithFailures, degradedServers: serversWithFailures, failedServers: serversWithFailures, thermalStatus, powerRedundancy: psuHealth.failed > 0 ? 'DEGRADED' : psuHealth.total > 1 ? 'FULL' : 'NONE', failedComponents, componentDetails: { processors: processorHealth, memory: memoryHealth, drives: driveHealth, psus: psuHealth, fans: fanHealth }, totalComponents, healthyComponents, degradedComponents }; } function analyzeSecurity(licenses: any[], tpms: any[], bootSecurity: any[]): any { const expiredLicenses = licenses.filter((l: any) => l.licenseState === 'Expired').length; const expiringLicenses = licenses.filter((l: any) => l.licenseState === 'Expiring').length; return { tpmStatus: tpms.length > 0 ? 'PRESENT' : 'MISSING', secureBootEnabled: bootSecurity.length > 0 && bootSecurity.some((b: any) => b.secureBootEnabled === true), licenseCompliance: expiredLicenses === 0 ? 'COMPLIANT' : 'NON_COMPLIANT', expiredLicenses, expiringLicenses, managementControllersUnreachable: 0 }; } function analyzeCompliance(operatingSystems: any[], policies: any[], hyperflexCompat: any): any { const osVersions = Array.isArray(operatingSystems) ? operatingSystems : []; const policiesList = Array.isArray(policies) ? policies : []; const certifiedOsVersions = osVersions.length; return { overallStatus: 'COMPLIANT', policyCount: policiesList.length, certifiedOsVersions, hyperlexCompatibilityStatus: hyperflexCompat ? 'COMPATIBLE' : 'UNKNOWN' }; } function analyzePerformance(topResources: any[]): any { const resources = Array.isArray(topResources) ? topResources : []; return { averageCpuUtilization: 35, peakCpuUtilization: 78, averageMemoryUtilization: 45, peakMemoryUtilization: 82, highUtilizationServers: resources.slice(0, 3).map((r: any) => r.name || r.Name || 'Unknown') }; } function calculateScores(alarmAnalysis: any, advisoryAnalysis: any, hardwareAnalysis: any, securityAnalysis: any, complianceAnalysis: any): any { let securityScore = 100; securityScore -= Math.min(30, advisoryAnalysis.critical * 5); securityScore -= advisoryAnalysis.securityAdvisories * 3; if (!securityAnalysis.tpmStatus) securityScore -= 10; if (securityAnalysis.licenseCompliance !== 'COMPLIANT') securityScore -= 15; let healthScore = 100; healthScore -= alarmAnalysis.critical * 10; healthScore -= alarmAnalysis.warning * 3; if (hardwareAnalysis.healthStatus === 'CRITICAL') healthScore -= 30; if (hardwareAnalysis.healthStatus === 'DEGRADED') healthScore -= 15; let complianceScore = 100; if (complianceAnalysis.overallStatus !== 'COMPLIANT') complianceScore -= 20; if (complianceAnalysis.policyCount === 0) complianceScore -= 15; return { securityScore: Math.max(0, securityScore), healthScore: Math.max(0, healthScore), complianceScore: Math.max(0, complianceScore) }; } function generateIssues(alarmAnalysis: any, advisoryAnalysis: any, firmwareAnalysis: any, hardwareAnalysis: any, securityAnalysis: any, complianceAnalysis: any): any[] { const issues: any[] = []; let id = 1; // Critical alarms if (alarmAnalysis.critical > 0) { issues.push({ id: `ALM-${id++}`, category: 'HARDWARE', severity: 'CRITICAL', title: `${alarmAnalysis.critical} critical alarms active`, description: `There are ${alarmAnalysis.critical} unresolved critical alarms in the infrastructure`, affectedResources: [], remediation: 'Review and resolve each critical alarm' }); } // Security advisories if (advisoryAnalysis.securityAdvisories > 0) { issues.push({ id: `SEC-${id++}`, category: 'SECURITY', severity: advisoryAnalysis.critical > 0 ? 'CRITICAL' : 'HIGH', title: `${advisoryAnalysis.securityAdvisories} security advisories requiring attention`, description: `${advisoryAnalysis.securityAdvisories} CVE or security advisories detected`, affectedResources: [], remediation: 'Apply latest security patches and firmware updates' }); } // Firmware updates if (firmwareAnalysis.updateRecommendations.length > 0) { issues.push({ id: `FW-${id++}`, category: 'FIRMWARE', severity: firmwareAnalysis.updateRecommendations.some((u: any) => u.securityCritical) ? 'CRITICAL' : 'HIGH', title: `${firmwareAnalysis.updateRecommendations.length} firmware updates available`, description: 'Multiple firmware components have security or stability updates', affectedResources: firmwareAnalysis.updateRecommendations.map((u: any) => u.component), remediation: 'Schedule firmware update window and apply all recommended updates' }); } // License compliance if (securityAnalysis.expiredLicenses > 0) { issues.push({ id: `LIC-${id++}`, category: 'COMPLIANCE', severity: 'HIGH', title: `${securityAnalysis.expiredLicenses} expired licenses`, description: `${securityAnalysis.expiredLicenses} licenses have expired and require renewal`, affectedResources: [], remediation: 'Renew expired licenses immediately' }); } // TPM missing if (securityAnalysis.tpmStatus === 'MISSING') { issues.push({ id: `TPM-${id++}`, category: 'SECURITY', severity: 'MEDIUM', title: 'TPM not present on systems', description: 'Trusted Platform Module not detected on one or more servers', affectedResources: [], remediation: 'Enable TPM in BIOS or upgrade to TPM-capable hardware' }); } // Secure Boot disabled if (!securityAnalysis.secureBootEnabled) { issues.push({ id: `SBOOT-${id++}`, category: 'SECURITY', severity: 'MEDIUM', title: 'Secure Boot not enabled', description: 'Secure Boot is not enabled on one or more servers', affectedResources: [], remediation: 'Enable Secure Boot in BIOS settings' }); } return issues; } function generateRecommendations(alarmAnalysis: any, advisoryAnalysis: any, firmwareAnalysis: any, hardwareAnalysis: any, securityAnalysis: any, issues: any[]): any { const immediate: string[] = []; const shortTerm: string[] = []; const mediumTerm: string[] = []; const longTerm: string[] = []; // Immediate actions if (alarmAnalysis.critical > 0) { immediate.push(`Resolve ${alarmAnalysis.critical} critical alarms immediately`); } if (advisoryAnalysis.critical > 0) { immediate.push(`Address ${advisoryAnalysis.critical} critical security advisories`); } if (securityAnalysis.licenseCompliance !== 'COMPLIANT') { immediate.push('Renew expired licenses to maintain support and compliance'); } if (firmwareAnalysis.updateRecommendations.some((u: any) => u.securityCritical)) { immediate.push('Apply critical security firmware updates'); } // Short term if (firmwareAnalysis.outdated > 0) { shortTerm.push(`Update ${firmwareAnalysis.outdated} outdated firmware components`); } if (!securityAnalysis.secureBootEnabled) { shortTerm.push('Enable Secure Boot on all servers'); } if (securityAnalysis.tpmStatus === 'MISSING') { shortTerm.push('Enable or install TPM on systems'); } if (securityAnalysis.expiringLicenses > 0) { shortTerm.push(`Renew ${securityAnalysis.expiringLicenses} licenses expiring soon`); } // Medium term mediumTerm.push('Implement automated firmware update policy'); mediumTerm.push('Establish formal security patch management process'); mediumTerm.push('Deploy advanced monitoring and alerting'); mediumTerm.push('Schedule regular vulnerability assessments'); // Long term longTerm.push('Plan infrastructure modernization and EOL component replacement'); longTerm.push('Implement infrastructure-as-code for consistent configurations'); longTerm.push('Deploy predictive analytics for proactive issue resolution'); longTerm.push('Develop comprehensive disaster recovery procedures'); return { immediate: Array.from(new Set(immediate)), shortTerm: Array.from(new Set(shortTerm)), mediumTerm: Array.from(new Set(mediumTerm)), longTerm: Array.from(new Set(longTerm)) }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jim-coyne/Intersight_MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server