From 080624cc5b68b36d4123c772988978e2532ff453 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Tue, 10 Feb 2026 11:34:58 +0100 Subject: [PATCH] parsing signalr messages fix --- rules/network/proxy-auth-failure.yaml | 139 ------- .../Functions/IngestEventsFunction.cs | 34 ++ .../Services/BuiltInAnalyzeRules.cs | 389 ------------------ .../app/sessions/[sessionId]/page.tsx | 2 +- 4 files changed, 35 insertions(+), 529 deletions(-) delete mode 100644 rules/network/proxy-auth-failure.yaml diff --git a/rules/network/proxy-auth-failure.yaml b/rules/network/proxy-auth-failure.yaml deleted file mode 100644 index 50326c43..00000000 --- a/rules/network/proxy-auth-failure.yaml +++ /dev/null @@ -1,139 +0,0 @@ -# Network Rule: Proxy Authentication Failure -# This is an example rule for the Phase 2 rule engine - -id: NET-001 -title: "Proxy Authentication Required" -severity: high -category: network -version: 1.0 -author: "Autopilot Monitor Team" -description: | - Detects when a device is behind a proxy that requires authentication, - but the SYSTEM account (used during Autopilot enrollment) cannot authenticate. - This is one of the most common causes of enrollment failures in enterprise networks. - -conditions: - # Primary signal: HTTP 407 errors from WinHTTP - - signal: "event_407_detected" - source: "windows_events" - provider: "Microsoft-Windows-WinHttp" - event_id: 407 - minimum_occurrences: 1 - - # Supporting signal: Proxy is configured - - signal: "winhttp_proxy_configured" - source: "registry" - path: "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" - value: "ProxyEnable" - expected: 1 - - # Supporting signal: Enrollment stalled at MDM phase - - signal: "enrollment_stalled_at_mdm" - source: "phase_tracking" - phase: "MdmEnrollment" - duration_exceeds_seconds: 300 - -evidence_selectors: - # Collect relevant log lines from IME log - - type: "log_lines" - source: "ime_log" - pattern: "proxy|407|authentication|ProxyAuthenticationRequired" - context_lines: 3 - max_lines: 20 - - # Collect proxy configuration from registry - - type: "registry_value" - path: "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" - values: - - "ProxyServer" - - "ProxyEnable" - - "ProxyOverride" - - # Collect WinHTTP events - - type: "windows_event" - provider: "Microsoft-Windows-WinHttp" - event_ids: [407, 12029, 12032] - max_events: 10 - -explanation: | - The device is configured to use a proxy server that requires authentication. - During Autopilot enrollment, many operations run under the SYSTEM account, - which cannot provide user credentials to authenticate with the proxy. - - This causes connections to Microsoft Intune endpoints to fail, resulting in - enrollment timeouts or failures. - - Common indicators: - - HTTP 407 (Proxy Authentication Required) errors in logs - - Enrollment stalls at the MDM Enrollment phase - - WinHTTP errors about proxy authentication - -remediation: - - title: "Configure proxy bypass" - steps: - - "Add *.manage.microsoft.com to proxy bypass list" - - "Add *.microsoftonline.com to proxy bypass list" - - "Add enterpriseregistration.windows.net to bypass list" - - - title: "Use PAC file" - steps: - - "Create/update PAC file to bypass proxy for Microsoft endpoints" - - "Deploy via GPO or Intune" - - - title: "Use authenticated proxy with certificate" - steps: - - "Configure proxy to trust device certificates" - - "Use certificate-based authentication instead of user credentials" - -related_docs: - - url: "https://learn.microsoft.com/en-us/mem/intune/enrollment/windows-enrollment-network-requirements" - title: "Intune network requirements" - - url: "https://learn.microsoft.com/en-us/mem/autopilot/networking-requirements" - title: "Autopilot networking requirements" - -confidence_scoring: - # Base confidence if just HTTP 407 is detected - base: 50 - - # Additional confidence based on other signals - factors: - # Proxy is actually configured (not direct connection) - - signal: "winhttp_proxy_configured" - weight: 20 - - # Enrollment is actually stalled (not just slow) - - signal: "enrollment_stalled_at_mdm" - weight: 30 - - # Multiple 407 errors (not just one transient issue) - - signal: "multiple_407_errors" - condition: "count >= 5" - weight: 10 - -tags: - - network - - proxy - - authentication - - common - - mdm-enrollment - -# Test data (for validation) -test_cases: - - name: "Proxy auth with bypass configured" - expected: false - evidence: - - event_407_detected: false - - winhttp_proxy_configured: true - - - name: "Direct connection with 407" - expected: false - evidence: - - event_407_detected: true - - winhttp_proxy_configured: false - - - name: "Classic proxy auth failure" - expected: true - evidence: - - event_407_detected: true - - winhttp_proxy_configured: true - - enrollment_stalled_at_mdm: true diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/IngestEventsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/IngestEventsFunction.cs index 6bc447d9..4c710666 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/IngestEventsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/IngestEventsFunction.cs @@ -9,6 +9,7 @@ using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Azure.Functions.Worker.Extensions.SignalRService; using Microsoft.Extensions.Logging; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace AutopilotMonitor.Functions.Functions { @@ -76,6 +77,8 @@ namespace AutopilotMonitor.Functions.Functions } var requestBody = await new StreamReader(req.Body).ReadToEndAsync(); request = JsonConvert.DeserializeObject(requestBody); + if (request?.Events != null) + foreach (var evt in request.Events) NormalizeEventData(evt); } if (request?.Events == null || request.Events.Count == 0) @@ -355,6 +358,7 @@ namespace AutopilotMonitor.Functions.Functions var evt = JsonConvert.DeserializeObject(lines[i]); if (evt != null) { + NormalizeEventData(evt); events.Add(evt); } } @@ -367,6 +371,36 @@ namespace AutopilotMonitor.Functions.Functions }; } + /// + /// Normalizes event Data dictionary by converting Newtonsoft JToken objects to native .NET types. + /// Required because Newtonsoft.Json deserializes nested objects as JObject/JArray, which + /// System.Text.Json (used by SignalR) cannot serialize correctly - producing [[[]]] instead of real values. + /// + private static void NormalizeEventData(EnrollmentEvent evt) + { + if (evt.Data == null || evt.Data.Count == 0) return; + var normalized = new Dictionary(); + foreach (var kvp in evt.Data) + normalized[kvp.Key] = ConvertJTokenToNative(kvp.Value); + evt.Data = normalized; + } + + private static object ConvertJTokenToNative(object value) + { + if (value is JArray jArray) + return jArray.Select(item => ConvertJTokenToNative(item)).ToList(); + if (value is JObject jObject) + { + var dict = new Dictionary(); + foreach (var prop in jObject.Properties()) + dict[prop.Name] = ConvertJTokenToNative(prop.Value); + return dict; + } + if (value is JValue jValue) + return jValue.Value ?? string.Empty; + return value; + } + /// /// Aggregates app install events into AppInstallSummary records /// diff --git a/src/Backend/AutopilotMonitor.Functions/Services/BuiltInAnalyzeRules.cs b/src/Backend/AutopilotMonitor.Functions/Services/BuiltInAnalyzeRules.cs index c416a81f..58063b34 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/BuiltInAnalyzeRules.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/BuiltInAnalyzeRules.cs @@ -12,23 +12,6 @@ namespace AutopilotMonitor.Functions.Services { return new List { - // ===== NETWORK RULES ===== - CreateNetworkProxyAuthRule(), - CreateNetworkDnsFailureRule(), - CreateNetworkSslInspectionRule(), - CreateNetworkCaptivePortalRule(), - CreateNetworkMeteredConnectionRule(), - - // ===== IDENTITY RULES ===== - CreateIdentityAadJoinTimeoutRule(), - CreateIdentityDeviceLimitRule(), - CreateIdentityTimeSyncRule(), - CreateIdentityConditionalAccessRule(), - - // ===== ENROLLMENT RULES ===== - CreateEnrollmentRestrictionRule(), - CreateEnrollmentTermsOfUseRule(), - // ===== APP RULES ===== CreateAppDetectionScriptFailureRule(), CreateAppMsiErrorRule(), @@ -47,258 +30,11 @@ namespace AutopilotMonitor.Functions.Services CreateDeviceSecureBootRule(), // ===== CORRELATION RULES (cross-event analysis) ===== - CreateCorrelationProxyAuthRule(), - CreateCorrelationSslCertFailureRule(), CreateCorrelationNetworkCausedInstallFailureRule(), CreateCorrelationDiskSpaceCausedInstallFailureRule(), - CreateCorrelationTpmIdentityFailureRule() }; } - // ===== NETWORK ===== - - private static AnalyzeRule CreateNetworkProxyAuthRule() => new AnalyzeRule - { - RuleId = "ANALYZE-NET-001", - Title = "Proxy Authentication Required", - Description = "Detects when enrollment fails due to proxy requiring authentication that the SYSTEM account cannot provide.", - Severity = "high", - Category = "network", - BaseConfidence = 50, - Conditions = new List - { - new RuleCondition { Signal = "http_407_error", Source = "event_type", EventType = "error_detected", DataField = "errorCode", Operator = "contains", Value = "407", Required = true }, - new RuleCondition { Signal = "proxy_configured", Source = "event_type", EventType = "gather_proxy_settings", DataField = "ProxyEnable", Operator = "equals", Value = "1" } - }, - ConfidenceFactors = new List - { - new ConfidenceFactor { Signal = "proxy_configured", Condition = "exists", Weight = 20 }, - new ConfidenceFactor { Signal = "enrollment_stalled", Condition = "phase_duration > 300", Weight = 30 } - }, - Explanation = "The device is behind a proxy that requires authentication. During Autopilot enrollment, operations run under the SYSTEM account, which cannot provide user credentials to authenticate with the proxy.", - Remediation = new List - { - new RemediationStep { Title = "Configure proxy bypass", Steps = new List { "Add *.manage.microsoft.com to proxy bypass list", "Add *.microsoftonline.com to proxy bypass list", "Add enterpriseregistration.windows.net to bypass list" } }, - new RemediationStep { Title = "Use PAC file", Steps = new List { "Create/update PAC file to bypass proxy for Microsoft endpoints", "Deploy via GPO or Intune" } } - }, - RelatedDocs = new List - { - new RelatedDoc { Title = "Intune network requirements", Url = "https://learn.microsoft.com/en-us/mem/intune/fundamentals/intune-endpoints" }, - new RelatedDoc { Title = "Autopilot networking requirements", Url = "https://learn.microsoft.com/en-us/mem/autopilot/networking-requirements" } - }, - Tags = new[] { "network", "proxy", "authentication", "common" } - }; - - private static AnalyzeRule CreateNetworkDnsFailureRule() => new AnalyzeRule - { - RuleId = "ANALYZE-NET-002", - Title = "DNS Resolution Failure", - Description = "Detects DNS resolution failures for critical Microsoft enrollment endpoints.", - Severity = "high", - Category = "network", - BaseConfidence = 60, - Conditions = new List - { - new RuleCondition { Signal = "dns_failure", Source = "event_type", EventType = "error_detected", DataField = "message", Operator = "regex", Value = "DNS|name resolution|NXDOMAIN|could not resolve", Required = true } - }, - Explanation = "DNS resolution is failing for critical Microsoft endpoints. This prevents the device from reaching Intune and Azure AD services.", - Remediation = new List - { - new RemediationStep { Title = "Verify DNS configuration", Steps = new List { "Check DNS server configuration", "Verify DNS resolution for login.microsoftonline.com", "Verify DNS resolution for enterpriseregistration.windows.net" } } - }, - Tags = new[] { "network", "dns" } - }; - - private static AnalyzeRule CreateNetworkSslInspectionRule() => new AnalyzeRule - { - RuleId = "ANALYZE-NET-003", - Title = "SSL Inspection Breaking Enrollment", - Description = "Detects SSL/TLS inspection that may interfere with certificate-based enrollment communication.", - Severity = "high", - Category = "network", - BaseConfidence = 70, - Conditions = new List - { - new RuleCondition { Signal = "ssl_inspection", Source = "event_type", EventType = "cert_validation", DataField = "ssl_inspection_detected", Operator = "equals", Value = "true", Required = true } - }, - Explanation = "SSL/TLS inspection (man-in-the-middle) is detected on critical enrollment endpoints. This can break certificate pinning and cause enrollment failures.", - Remediation = new List - { - new RemediationStep { Title = "Bypass SSL inspection", Steps = new List { "Add *.manage.microsoft.com to SSL inspection bypass list", "Add *.microsoftonline.com to bypass list", "Add *.windows.net to bypass list" } } - }, - Tags = new[] { "network", "ssl", "certificate" } - }; - - private static AnalyzeRule CreateNetworkCaptivePortalRule() => new AnalyzeRule - { - RuleId = "ANALYZE-NET-004", - Title = "Captive Portal Detected", - Description = "Detects when the device is stuck behind a captive portal during enrollment.", - Severity = "warning", - Category = "network", - BaseConfidence = 60, - Conditions = new List - { - new RuleCondition { Signal = "captive_portal", Source = "event_type", EventType = "error_detected", DataField = "message", Operator = "regex", Value = "captive|portal|redirect|302.*login", Required = true } - }, - Explanation = "A captive portal is redirecting network traffic. During OOBE, the device cannot interact with captive portals, preventing enrollment.", - Remediation = new List - { - new RemediationStep { Title = "Bypass captive portal for enrollment", Steps = new List { "Whitelist device MAC addresses on the network", "Use a pre-authenticated VLAN for Autopilot devices", "Configure the captive portal to bypass Microsoft endpoints" } } - }, - Tags = new[] { "network", "captive-portal" } - }; - - private static AnalyzeRule CreateNetworkMeteredConnectionRule() => new AnalyzeRule - { - RuleId = "ANALYZE-NET-005", - Title = "Metered Connection Blocking Downloads", - Description = "Detects when a metered connection may be blocking app downloads.", - Severity = "warning", - Category = "network", - BaseConfidence = 40, - Conditions = new List - { - new RuleCondition { Signal = "metered_connection", Source = "event_type", EventType = "gather_network_adapters", DataField = "isMetered", Operator = "equals", Value = "true", Required = true } - }, - Explanation = "The network connection is marked as metered. Windows may restrict downloads over metered connections, slowing or blocking app installations.", - Remediation = new List - { - new RemediationStep { Title = "Configure non-metered connection", Steps = new List { "Connect to a non-metered network", "Configure the connection as non-metered via GPO" } } - }, - Tags = new[] { "network", "metered" } - }; - - // ===== IDENTITY ===== - - private static AnalyzeRule CreateIdentityAadJoinTimeoutRule() => new AnalyzeRule - { - RuleId = "ANALYZE-ID-001", - Title = "Azure AD Join Timeout", - Description = "Detects when Azure AD join is taking too long or timing out.", - Severity = "high", - Category = "identity", - BaseConfidence = 60, - Conditions = new List - { - new RuleCondition { Signal = "identity_phase_stalled", Source = "phase_duration", EventType = "phase_changed", DataField = "currentPhase", Operator = "equals", Value = "Identity", Required = true } - }, - ConfidenceFactors = new List - { - new ConfidenceFactor { Signal = "long_duration", Condition = "phase_duration > 180", Weight = 30 } - }, - Explanation = "The Azure AD / Entra ID join process is taking longer than expected. This may indicate network issues, conditional access policies, or AAD service problems.", - Remediation = new List - { - new RemediationStep { Title = "Verify connectivity", Steps = new List { "Check connectivity to login.microsoftonline.com", "Check connectivity to enterpriseregistration.windows.net" } }, - new RemediationStep { Title = "Check Conditional Access", Steps = new List { "Review CA policies that may block device enrollment", "Check for MFA requirements during join" } } - }, - Tags = new[] { "identity", "aad", "timeout" } - }; - - private static AnalyzeRule CreateIdentityDeviceLimitRule() => new AnalyzeRule - { - RuleId = "ANALYZE-ID-002", - Title = "Device Limit Reached", - Description = "Detects when Azure AD device registration limit has been reached.", - Severity = "high", - Category = "identity", - BaseConfidence = 80, - Conditions = new List - { - new RuleCondition { Signal = "device_limit", Source = "event_type", EventType = "error_detected", DataField = "message", Operator = "regex", Value = "device limit|maximum.*device|MaximumDevicesPerUser", Required = true } - }, - Explanation = "The Azure AD device limit for this user has been reached. The user has registered the maximum number of devices allowed by the tenant policy.", - Remediation = new List - { - new RemediationStep { Title = "Increase device limit", Steps = new List { "Azure Portal > Azure AD > Devices > Device settings", "Increase 'Maximum number of devices per user'" } }, - new RemediationStep { Title = "Remove stale devices", Steps = new List { "Remove old/unused device registrations for the user", "Use Azure AD > Devices to find and delete stale entries" } } - }, - Tags = new[] { "identity", "device-limit" } - }; - - private static AnalyzeRule CreateIdentityTimeSyncRule() => new AnalyzeRule - { - RuleId = "ANALYZE-ID-003", - Title = "Time Synchronization Drift", - Description = "Detects when device time is significantly out of sync, causing certificate and token validation failures.", - Severity = "warning", - Category = "identity", - BaseConfidence = 70, - Conditions = new List - { - new RuleCondition { Signal = "time_sync_error", Source = "event_type", EventType = "error_detected", DataField = "message", Operator = "regex", Value = "time|clock|timestamp.*invalid|certificate.*expired|token.*expired|not yet valid", Required = true } - }, - Explanation = "The device clock appears to be significantly out of sync. This causes certificate validation failures and token expiration issues.", - Remediation = new List - { - new RemediationStep { Title = "Sync device time", Steps = new List { "Ensure NTP access (time.windows.com, port 123/UDP)", "Verify BIOS/UEFI clock is correct", "Check for expired CMOS battery" } } - }, - Tags = new[] { "identity", "time-sync" } - }; - - private static AnalyzeRule CreateIdentityConditionalAccessRule() => new AnalyzeRule - { - RuleId = "ANALYZE-ID-004", - Title = "Conditional Access Policy Blocking", - Description = "Detects when Conditional Access policies are preventing enrollment.", - Severity = "high", - Category = "identity", - BaseConfidence = 70, - Conditions = new List - { - new RuleCondition { Signal = "ca_block", Source = "event_type", EventType = "error_detected", DataField = "message", Operator = "regex", Value = "conditional access|AADSTS53003|AADSTS50076|blocked by.*policy|access.*denied.*policy", Required = true } - }, - Explanation = "A Conditional Access policy is blocking the device or user from completing enrollment. Common causes include MFA requirements, compliant device requirements, or location-based policies.", - Remediation = new List - { - new RemediationStep { Title = "Review CA policies", Steps = new List { "Check Azure AD > Security > Conditional Access", "Look for policies targeting 'Microsoft Intune Enrollment'", "Ensure Autopilot devices are excluded from blocking policies" } } - }, - Tags = new[] { "identity", "conditional-access" } - }; - - // ===== ENROLLMENT ===== - - private static AnalyzeRule CreateEnrollmentRestrictionRule() => new AnalyzeRule - { - RuleId = "ANALYZE-ENR-001", - Title = "Enrollment Restriction Blocking", - Description = "Detects when Intune enrollment restrictions prevent device enrollment.", - Severity = "high", - Category = "enrollment", - BaseConfidence = 80, - Conditions = new List - { - new RuleCondition { Signal = "enrollment_restriction", Source = "event_type", EventType = "error_detected", DataField = "message", Operator = "regex", Value = "enrollment restriction|not allowed.*enroll|platform.*restriction|device type.*not allowed", Required = true } - }, - Explanation = "An Intune enrollment restriction is preventing this device from enrolling. This could be a platform restriction, device type restriction, or device limit restriction.", - Remediation = new List - { - new RemediationStep { Title = "Check enrollment restrictions", Steps = new List { "Intune > Devices > Enrollment restrictions", "Verify Windows platform is allowed", "Check device limit restrictions", "Verify the user is in the correct group" } } - }, - Tags = new[] { "enrollment", "restriction" } - }; - - private static AnalyzeRule CreateEnrollmentTermsOfUseRule() => new AnalyzeRule - { - RuleId = "ANALYZE-ENR-002", - Title = "Terms of Use Blocking Enrollment", - Description = "Detects when Terms of Use acceptance is required but cannot be completed during OOBE.", - Severity = "warning", - Category = "enrollment", - BaseConfidence = 60, - Conditions = new List - { - new RuleCondition { Signal = "terms_of_use", Source = "event_type", EventType = "error_detected", DataField = "message", Operator = "regex", Value = "terms of use|ToU|consent required|AADSTS65004", Required = true } - }, - Explanation = "Terms of Use acceptance is required but the OOBE flow cannot display the ToU page. This blocks enrollment completion.", - Remediation = new List - { - new RemediationStep { Title = "Exclude from ToU", Steps = new List { "Create a CA policy exclusion for Autopilot devices", "Or accept ToU during pre-provisioning instead" } } - }, - Tags = new[] { "enrollment", "terms-of-use" } - }; - // ===== APPS ===== private static AnalyzeRule CreateAppDetectionScriptFailureRule() => new AnalyzeRule @@ -536,89 +272,6 @@ namespace AutopilotMonitor.Functions.Services // ===== CORRELATION RULES ===== // These combine signals from multiple event types for root-cause analysis - private static AnalyzeRule CreateCorrelationProxyAuthRule() => new AnalyzeRule - { - RuleId = "ANALYZE-CORR-001", - Title = "Proxy Authentication Blocking Enrollment", - Description = "Correlates proxy configuration, HTTP 407 errors, and enrollment stall to confirm proxy authentication is the root cause.", - Severity = "critical", - Category = "network", - Trigger = "correlation", - BaseConfidence = 60, - Conditions = new List - { - new RuleCondition { Signal = "proxy_configured", Source = "event_type", EventType = "gather_proxy_settings", DataField = "ProxyEnable", Operator = "equals", Value = "1", Required = true }, - new RuleCondition { Signal = "auth_error", Source = "event_type", EventType = "error_detected", DataField = "message", Operator = "regex", Value = "407|proxy.*auth|ProxyAuthenticationRequired", Required = true }, - new RuleCondition { Signal = "enrollment_failed", Source = "event_type", EventType = "enrollment_failed", Operator = "exists", Value = "" } - }, - ConfidenceFactors = new List - { - new ConfidenceFactor { Signal = "enrollment_failed", Condition = "exists", Weight = 20 }, - new ConfidenceFactor { Signal = "long_network_phase", Condition = "phase_duration > 180", Weight = 15 } - }, - ConfidenceThreshold = 50, - Explanation = "**Root cause confirmed:** The device is behind an authenticated proxy (ProxyEnable=1) and received HTTP 407 errors during enrollment. The SYSTEM account cannot authenticate with the proxy, causing enrollment to fail.\n\nThis is a common issue in corporate environments with SSL-inspecting proxies.", - Remediation = new List - { - new RemediationStep { Title = "Configure proxy bypass for Microsoft endpoints", Steps = new List { - "Add *.manage.microsoft.com to proxy bypass list", - "Add *.microsoftonline.com to proxy bypass list", - "Add enterpriseregistration.windows.net to bypass list", - "Add *.delivery.mp.microsoft.com to bypass list (app downloads)" - }}, - new RemediationStep { Title = "Use PAC file with exceptions", Steps = new List { - "Create/update PAC file to bypass proxy for Microsoft endpoints", - "Deploy PAC file via GPO or DHCP Option 252", - "Ensure PAC file is accessible during OOBE (before user login)" - }} - }, - RelatedDocs = new List - { - new RelatedDoc { Title = "Autopilot networking requirements", Url = "https://learn.microsoft.com/en-us/mem/autopilot/networking-requirements" }, - new RelatedDoc { Title = "Intune network endpoints", Url = "https://learn.microsoft.com/en-us/mem/intune/fundamentals/intune-endpoints" } - }, - Tags = new[] { "correlation", "network", "proxy", "authentication", "root-cause" } - }; - - private static AnalyzeRule CreateCorrelationSslCertFailureRule() => new AnalyzeRule - { - RuleId = "ANALYZE-CORR-002", - Title = "SSL Inspection Breaking Certificate Enrollment", - Description = "Correlates SSL inspection detection with certificate validation errors and enrollment failure to confirm SSL inspection as root cause.", - Severity = "critical", - Category = "network", - Trigger = "correlation", - BaseConfidence = 65, - Conditions = new List - { - new RuleCondition { Signal = "ssl_inspection", Source = "event_type", EventType = "cert_validation", DataField = "ssl_inspection_detected", Operator = "equals", Value = "true", Required = true }, - new RuleCondition { Signal = "cert_error", Source = "event_type", EventType = "error_detected", DataField = "message", Operator = "regex", Value = "certificate|SSL|TLS|trust|chain|CERT_E_|0x800b", Required = true }, - new RuleCondition { Signal = "enrollment_failed", Source = "event_type", EventType = "enrollment_failed", Operator = "exists", Value = "" } - }, - ConfidenceFactors = new List - { - new ConfidenceFactor { Signal = "enrollment_failed", Condition = "exists", Weight = 20 }, - new ConfidenceFactor { Signal = "missing_mdm_cert", Condition = "exists", Weight = 15 } - }, - ConfidenceThreshold = 50, - Explanation = "**Root cause confirmed:** SSL/TLS inspection (MITM proxy) is intercepting connections to Microsoft enrollment endpoints. The intercepted certificates fail validation, breaking the MDM enrollment certificate chain.\n\nThe SSL inspection device replaces Microsoft's certificates with its own, which the enrollment client does not trust.", - Remediation = new List - { - new RemediationStep { Title = "Bypass SSL inspection for Microsoft endpoints", Steps = new List { - "Add *.manage.microsoft.com to SSL inspection bypass list", - "Add *.microsoftonline.com to bypass list", - "Add *.windows.net to bypass list", - "Add *.microsoft.com to bypass list for broader coverage" - }}, - new RemediationStep { Title = "Deploy inspection CA certificate", Steps = new List { - "Export the SSL inspection appliance's root CA certificate", - "Deploy it to devices via Autopilot deployment profile or OEM provisioning", - "Note: This is a workaround; bypass is the recommended approach" - }} - }, - Tags = new[] { "correlation", "network", "ssl", "certificate", "root-cause" } - }; - private static AnalyzeRule CreateCorrelationNetworkCausedInstallFailureRule() => new AnalyzeRule { RuleId = "ANALYZE-CORR-003", @@ -694,47 +347,5 @@ namespace AutopilotMonitor.Functions.Services }, Tags = new[] { "correlation", "apps", "disk-space", "performance", "root-cause" } }; - - private static AnalyzeRule CreateCorrelationTpmIdentityFailureRule() => new AnalyzeRule - { - RuleId = "ANALYZE-CORR-005", - Title = "TPM Issue Blocking Identity Enrollment", - Description = "Correlates TPM not-ready status with identity phase failure and missing device certificates to confirm TPM as root cause.", - Severity = "critical", - Category = "device", - Trigger = "correlation", - BaseConfidence = 60, - Conditions = new List - { - new RuleCondition { Signal = "tpm_issue", Source = "event_type", EventType = "error_detected", DataField = "message", Operator = "regex", Value = "TPM|Trusted Platform|0x80284|0x80290|attestation", Required = true }, - new RuleCondition { Signal = "identity_stalled", Source = "phase_duration", EventType = "phase_changed", DataField = "currentPhase", Operator = "equals", Value = "Identity", Required = true } - }, - ConfidenceFactors = new List - { - new ConfidenceFactor { Signal = "long_identity", Condition = "phase_duration > 300", Weight = 20 }, - new ConfidenceFactor { Signal = "enrollment_failed", Condition = "exists", Weight = 15 } - }, - ConfidenceThreshold = 50, - Explanation = "**Root cause confirmed:** TPM-related errors occurred during the identity phase, which also took longer than expected. The TPM is either not ready, not provisioned, or malfunctioning, preventing Azure AD join and device attestation.\n\nTPM issues block the entire enrollment chain since device identity cannot be established.", - Remediation = new List - { - new RemediationStep { Title = "Fix TPM", Steps = new List { - "Enter BIOS/UEFI and verify TPM is enabled", - "Update TPM firmware to latest version", - "Try clearing TPM: tpm.msc > Clear TPM (WARNING: removes keys)", - "Verify TPM version is 2.0 (required for Autopilot)" - }}, - new RemediationStep { Title = "Pre-provision TPM", Steps = new List { - "Run 'Initialize-Tpm' in elevated PowerShell before enrollment", - "For new devices, ensure OEM has provisioned TPM during manufacturing", - "Check for known TPM firmware issues with your hardware vendor" - }} - }, - RelatedDocs = new List - { - new RelatedDoc { Title = "Autopilot hardware requirements", Url = "https://learn.microsoft.com/en-us/mem/autopilot/software-requirements" } - }, - Tags = new[] { "correlation", "device", "tpm", "identity", "root-cause" } - }; } } diff --git a/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/page.tsx b/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/page.tsx index a37a4142..2227c947 100644 --- a/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/page.tsx +++ b/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/page.tsx @@ -1452,7 +1452,7 @@ function DeviceDetailsCard({ events }: { events: EnrollmentEvent[] }) {
{(bitLockerStatus.volumes as any[]).map((vol: any, i: number) => (
- {vol.driveLetter}: {vol.protectionStatus === "1" ? "Protected" : "Not Protected"} + {vol.driveLetter} {vol.protectionStatus === "1" ? "Protected" : "Not Protected"} {vol.encryptionMethod && ` (Method: ${vol.encryptionMethod})`}
))}