azureai-optimizer
Version:
AI-Powered Azure Infrastructure Optimization via Model Context Protocol
316 lines • 14 kB
JavaScript
/**
* Security Assessment Tool
* AI-powered Azure security compliance analysis
*/
// import { SecurityCenter } from '@azure/arm-security';
// import { PolicyClient } from '@azure/arm-policy';
import { Logger } from '../utils/logger.js';
import { AIAnalyzer } from '../ai/analyzer.js';
import { MCPError, ErrorCode } from '../utils/errors.js';
export class SecurityAssessmentTool {
name = 'security_compliance_check';
description = 'AI-powered Azure security and compliance assessment';
inputSchema = {
type: 'object',
properties: {
subscription_id: {
type: 'string',
description: 'Azure subscription ID to assess'
},
resource_group: {
type: 'string',
description: 'Optional: Specific resource group to assess'
},
compliance_framework: {
type: 'string',
enum: ['SOC2', 'ISO27001', 'NIST', 'CIS', 'custom'],
description: 'Compliance framework to assess against',
default: 'SOC2'
},
include_remediation: {
type: 'boolean',
description: 'Include detailed remediation steps (default: true)',
default: true
},
severity_filter: {
type: 'string',
enum: ['low', 'medium', 'high', 'critical'],
description: 'Filter findings by minimum severity level'
}
},
required: ['subscription_id', 'compliance_framework']
};
aiAnalyzer;
logger;
constructor(config) {
this.logger = new Logger('SecurityAssessmentTool');
this.aiAnalyzer = new AIAnalyzer(config.aiProviders);
}
async execute(args, _context) {
const startTime = Date.now();
let apiCalls = 0;
try {
this.logger.info(`🔒 Starting security assessment for subscription: ${args.subscription_id}`);
this.logger.info(`📋 Compliance framework: ${args.compliance_framework}`);
// Initialize Azure clients
// this.securityClient = new SecurityCenter(context.credential, args.subscription_id);
// this._policyClient = new PolicyClient(context.credential, args.subscription_id);
// Fetch security assessments
this.logger.info('🔍 Fetching security assessments...');
const securityAssessments = await this.fetchSecurityAssessments(args);
apiCalls++;
// Fetch policy compliance
this.logger.info('📜 Fetching policy compliance...');
const policyCompliance = await this.fetchPolicyCompliance(args);
apiCalls++;
// Process security findings
const processedFindings = this.processSecurityFindings(securityAssessments, args.compliance_framework, args.severity_filter);
// Calculate compliance score
const complianceScore = this.calculateComplianceScore(processedFindings, args.compliance_framework);
// AI-powered analysis
this.logger.info('🤖 Performing AI security analysis...');
const aiInsights = await this.aiAnalyzer.analyzeSecurityCompliance({
findings: processedFindings,
policyCompliance,
framework: args.compliance_framework,
subscriptionId: args.subscription_id,
assessmentContext: {
resourceGroup: args.resource_group,
includeRemediation: args.include_remediation
}
});
// Build result
const result = {
success: true,
data: {
compliance_summary: complianceScore,
security_findings: processedFindings,
policy_compliance: policyCompliance,
ai_insights: aiInsights
},
metadata: {
execution_time: Date.now() - startTime,
api_calls: apiCalls,
assessment_date: new Date().toISOString(),
framework_version: this.getFrameworkVersion(args.compliance_framework)
}
};
this.logger.info(`✅ Security assessment completed`);
this.logger.info(`📊 Compliance score: ${complianceScore.overall_score}%`);
this.logger.info(`🚨 Found ${processedFindings.length} security findings`);
return result;
}
catch (error) {
this.logger.error('❌ Security assessment failed:', error);
if (error instanceof MCPError) {
throw error;
}
throw new MCPError(ErrorCode.INTERNAL_ERROR, `Security assessment failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
async fetchSecurityAssessments(args) {
try {
const scope = args.resource_group
? `/subscriptions/${args.subscription_id}/resourceGroups/${args.resource_group}`
: `/subscriptions/${args.subscription_id}`;
// Stub implementation - actual implementation would use Security Center API
// const assessments = await this.securityClient.assessments.list(scope);
console.debug('Security assessments scope:', scope);
return [];
}
catch (error) {
this.logger.warn('⚠️ Failed to fetch security assessments:', error);
return [];
}
}
async fetchPolicyCompliance(args) {
try {
const scope = args.resource_group
? `/subscriptions/${args.subscription_id}/resourceGroups/${args.resource_group}`
: `/subscriptions/${args.subscription_id}`;
// Stub implementation - actual implementation would use proper Azure Policy API
const policyStates = [];
// Using scope to suppress unused variable warning
console.debug('Policy compliance scope:', scope);
return this.processPolicyCompliance(policyStates);
}
catch (error) {
this.logger.warn('⚠️ Failed to fetch policy compliance:', error);
return {
total_policies: 0,
compliant_policies: 0,
non_compliant_policies: 0,
policy_violations: []
};
}
}
processSecurityFindings(assessments, framework, severityFilter) {
const findings = assessments.map(assessment => {
const severity = this.mapSeverity(assessment.properties?.status?.severity);
return {
id: assessment.name || 'unknown',
title: assessment.properties?.displayName || 'Security Finding',
description: assessment.properties?.description || 'No description available',
severity,
category: assessment.properties?.assessmentType || 'General',
affected_resources: assessment.properties?.resourceDetails?.id ? [assessment.properties.resourceDetails.id] : [],
compliance_impact: this.getComplianceImpact(assessment, framework),
remediation_steps: assessment.properties?.remediation?.description ?
[assessment.properties.remediation.description] : []
};
});
// Apply severity filter
if (severityFilter) {
const severityOrder = { low: 1, medium: 2, high: 3, critical: 4 };
const minSeverity = severityOrder[severityFilter.toLowerCase()];
return findings.filter(finding => {
const findingSeverity = severityOrder[finding.severity.toLowerCase()];
return findingSeverity >= minSeverity;
});
}
return findings;
}
processPolicyCompliance(policyStates) {
const violations = {};
let totalPolicies = 0;
let compliantPolicies = 0;
if (policyStates.value) {
policyStates.value.forEach((state) => {
totalPolicies++;
if (state.complianceState === 'Compliant') {
compliantPolicies++;
}
else {
const policyName = state.policyDefinitionName || 'Unknown Policy';
if (!violations[policyName]) {
violations[policyName] = { count: 0, resources: [] };
}
violations[policyName].count++;
if (state.resourceId) {
violations[policyName].resources.push(state.resourceId);
}
}
});
}
return {
total_policies: totalPolicies,
compliant_policies: compliantPolicies,
non_compliant_policies: totalPolicies - compliantPolicies,
policy_violations: Object.entries(violations).map(([policy, data]) => ({
policy_name: policy,
violation_count: data.count,
affected_resources: data.resources
}))
};
}
calculateComplianceScore(findings, framework) {
const frameworkControls = this.getFrameworkControls(framework);
const totalControls = frameworkControls.length;
// Map findings to controls
const failedControls = new Set();
findings.forEach(finding => {
const mappedControls = this.mapFindingToControls(finding, framework);
mappedControls.forEach(control => failedControls.add(control));
});
const passedControls = totalControls - failedControls.size;
const overallScore = totalControls > 0 ? Math.round((passedControls / totalControls) * 100) : 0;
return {
framework,
overall_score: overallScore,
total_controls: totalControls,
passed_controls: passedControls,
failed_controls: failedControls.size,
not_applicable: 0 // This would be calculated based on resource types
};
}
mapSeverity(azureSeverity) {
switch (azureSeverity?.toLowerCase()) {
case 'low': return 'Low';
case 'medium': return 'Medium';
case 'high': return 'High';
case 'critical': return 'Critical';
default: return 'Medium';
}
}
getComplianceImpact(assessment, framework) {
// Map assessment to compliance framework impact
const category = assessment.properties?.assessmentType || '';
switch (framework) {
case 'SOC2':
if (category.includes('Access'))
return 'CC6.1 - Logical Access Controls';
if (category.includes('Encryption'))
return 'CC6.7 - Data Transmission and Disposal';
if (category.includes('Network'))
return 'CC6.1 - Network Security';
return 'General SOC2 Control';
case 'ISO27001':
if (category.includes('Access'))
return 'A.9 - Access Control';
if (category.includes('Encryption'))
return 'A.10 - Cryptography';
if (category.includes('Network'))
return 'A.13 - Communications Security';
return 'General ISO27001 Control';
default:
return 'Compliance Impact Assessment Required';
}
}
getFrameworkControls(framework) {
// Simplified control sets - in production, these would be comprehensive
switch (framework) {
case 'SOC2':
return [
'CC1.1', 'CC1.2', 'CC1.3', 'CC1.4', 'CC1.5',
'CC2.1', 'CC2.2', 'CC2.3',
'CC3.1', 'CC3.2', 'CC3.3', 'CC3.4',
'CC4.1', 'CC4.2',
'CC5.1', 'CC5.2', 'CC5.3',
'CC6.1', 'CC6.2', 'CC6.3', 'CC6.4', 'CC6.5', 'CC6.6', 'CC6.7', 'CC6.8',
'CC7.1', 'CC7.2', 'CC7.3', 'CC7.4', 'CC7.5',
'CC8.1'
];
case 'ISO27001':
return [
'A.5', 'A.6', 'A.7', 'A.8', 'A.9', 'A.10',
'A.11', 'A.12', 'A.13', 'A.14', 'A.15', 'A.16', 'A.17', 'A.18'
];
case 'NIST':
return [
'ID.AM', 'ID.BE', 'ID.GV', 'ID.RA', 'ID.RM', 'ID.SC',
'PR.AC', 'PR.AT', 'PR.DS', 'PR.IP', 'PR.MA', 'PR.PT',
'DE.AE', 'DE.CM', 'DE.DP',
'RS.RP', 'RS.CO', 'RS.AN', 'RS.MI', 'RS.IM',
'RC.RP', 'RC.IM', 'RC.CO'
];
default:
return ['CTRL-001', 'CTRL-002', 'CTRL-003']; // Generic controls
}
}
mapFindingToControls(finding, framework) {
// Simplified mapping - in production, this would be more sophisticated
const controls = [];
const category = finding.category.toLowerCase();
if (framework === 'SOC2') {
if (category.includes('access'))
controls.push('CC6.1');
if (category.includes('encryption'))
controls.push('CC6.7');
if (category.includes('network'))
controls.push('CC6.1');
if (category.includes('monitoring'))
controls.push('CC7.1');
}
return controls.length > 0 ? controls : ['CTRL-001']; // Default control
}
getFrameworkVersion(framework) {
switch (framework) {
case 'SOC2': return '2017';
case 'ISO27001': return '2013';
case 'NIST': return '1.1';
case 'CIS': return '8.0';
default: return '1.0';
}
}
}
//# sourceMappingURL=security-assessment.js.map