protected void GenerateRiskModelPanel(List<HealthcheckRiskRule> rules, int numberOfDomain = 1) { Add(@" <div class=""row d-print-none""><div class=""col-lg-12""> <a data-toggle=""collapse"" data-target=""#riskModel""> <h2>Risk model</h2> </a> </div></div> <div class=""row collapse show d-print-none"" id=""riskModel""> <div class=""col-md-12 table-responsive""> <table class=""model_table""> <thead><tr><th>Stale Objects</th><th>Privileged accounts</th><th>Trusts</th><th>Anomalies</th></tr></thead> <tbody> "); var riskmodel = new Dictionary<RiskRuleCategory, List<RiskModelCategory>>(); foreach (RiskRuleCategory category in Enum.GetValues(typeof(RiskRuleCategory))) { riskmodel[category] = new List<RiskModelCategory>(); } for (int j = 0; j < 4; j++) { for (int i = 0; ; i++) { int id = (1000 * j + 1000 + i); if (Enum.IsDefined(typeof(RiskModelCategory), id)) { riskmodel[(RiskRuleCategory)j].Add((RiskModelCategory)id); } else break; } } foreach (RiskRuleCategory category in Enum.GetValues(typeof(RiskRuleCategory))) { riskmodel[category].Sort( (RiskModelCategory a, RiskModelCategory b) => { return string.Compare(ReportHelper.GetEnumDescription(a), ReportHelper.GetEnumDescription(b)); }); } for (int i = 0; ; i++) { string line = "<tr>"; bool HasValue = false; foreach (RiskRuleCategory category in Enum.GetValues(typeof(RiskRuleCategory))) { if (i < riskmodel[category].Count) { HasValue = true; RiskModelCategory model = riskmodel[category][i]; int score = 0; int numrules = 0; List<HealthcheckRiskRule> rulematched = new List<HealthcheckRiskRule>(); foreach (HealthcheckRiskRule rule in rules) { if (rule.Model == model) { numrules++; score += rule.Points; rulematched.Add(rule); } } string tdclass = ""; if (numrules == 0) { tdclass = "model_good"; } else if (score == 0) { tdclass = "model_info"; } else if (score <= 10 * numberOfDomain) { tdclass = "model_toimprove"; } else if (score <= 30 * numberOfDomain) { tdclass = "model_warning"; } else { tdclass = "model_danger"; } string tooltip = "Rules: " + numrules + " Score: " + (numberOfDomain == 0? 100 : score / numberOfDomain); string tooltipdetail = null; string modelstring = ReportHelper.GetEnumDescription(model); rulematched.Sort((HealthcheckRiskRule a, HealthcheckRiskRule b) => { return a.Points.CompareTo(b.Points); }); foreach (var rule in rulematched) { tooltipdetail += ReportHelper.Encode(rule.Rationale) + "<br>"; var hcrule = RuleSet<T>.GetRuleFromID(rule.RiskId); if (hcrule != null && !string.IsNullOrEmpty(hcrule.ReportLocation)) { tooltipdetail += "<small class='text-muted'>" + ReportHelper.Encode(hcrule.ReportLocation) + "</small><br>"; } } line += "<td class=\"model_cell " + tdclass + "\"><div class=\"div_model\" placement=\"auto right\" data-toggle=\"popover\" title=\"" + tooltip + "\" data-html=\"true\" data-content=\"" + (String.IsNullOrEmpty(tooltipdetail) ? "No rule matched" : "<p>" + tooltipdetail + "</p>") + "\"><span class=\"small\">" + modelstring + "</span></div></td>"; } else line += "<td class=\"model_empty_cell\"></td>"; } line += "</tr>"; if (HasValue) Add(line); else break; } Add(@" </tbody> </table> </div> <div class=""col-md-12"" id=""maturityModel""> Legend: <br> <i class=""risk_model_none""> </i> score is 0 - no risk identified but some improvements detected<br> <i class=""risk_model_low""> </i> score between 1 and 10 - a few actions have been identified<br> <i class=""risk_model_medium""> </i> score between 10 and 30 - rules should be looked with attention<br> <i class=""risk_model_high""> </i> score higher than 30 - major risks identified </div> </div>"); }
protected void GenerateRiskModelPanel() { Add(@" <div class=""row""><div class=""col-lg-12""> <a data-toggle=""collapse"" data-target=""#riskModel""> <h2>Risk model</h2> </a> </div></div> <div class=""row""><div class=""col-lg-12""> <p>This model regroup all rules per category. It summarize what checks are performed. Click on a cell to show all rules associated to a category. </p> </div></div> <div class=""row collapse show"" id=""riskModel""> <div class=""col-md-12 table-responsive""> <table class=""model_table""> <thead><tr><th>Stale Objects</th><th>Privileged accounts</th><th>Trusts</th><th>Anomalies</th></tr></thead> <tbody> "); var riskmodel = new Dictionary <RiskRuleCategory, List <RiskModelCategory> >(); foreach (RiskRuleCategory category in Enum.GetValues(typeof(RiskRuleCategory))) { riskmodel[category] = new List <RiskModelCategory>(); } for (int j = 0; j < 4; j++) { for (int i = 0; ; i++) { int id = (1000 * j + 1000 + i); if (Enum.IsDefined(typeof(RiskModelCategory), id)) { riskmodel[(RiskRuleCategory)j].Add((RiskModelCategory)id); } else { break; } } } foreach (RiskRuleCategory category in Enum.GetValues(typeof(RiskRuleCategory))) { riskmodel[category].Sort( (RiskModelCategory a, RiskModelCategory b) => { return(string.Compare(ReportHelper.GetEnumDescription(a), ReportHelper.GetEnumDescription(b))); }); } for (int i = 0; ; i++) { string line = "<tr>"; bool HasValue = false; foreach (RiskRuleCategory category in Enum.GetValues(typeof(RiskRuleCategory))) { if (i < riskmodel[category].Count) { HasValue = true; RiskModelCategory model = riskmodel[category][i]; int score = 0; int numrules = 0; var rulematched = new List <RuleBase <HealthcheckData> >(); foreach (var rule in RuleSet <HealthcheckData> .Rules) { if (rule.Model == model) { numrules++; score += rule.Points; rulematched.Add(rule); } } string tdclass = ""; tdclass = "model_good"; string modelstring = ReportHelper.GetEnumDescription(model); string tooltip = modelstring + " [Rules: " + numrules + "]"; string tooltipdetail = null; rulematched.Sort((RuleBase <HealthcheckData> a, RuleBase <HealthcheckData> b) => { return(a.Points.CompareTo(b.Points)); }); foreach (var rule in rulematched) { tooltipdetail += "<li>" + ReportHelper.Encode(rule.Title) + "</li><br>"; } line += "<td class=\"model_cell " + tdclass + "\"><div class=\"div_model\" placement=\"auto\" data-toggle=\"popover\" title=\"" + tooltip + "\" data-html=\"true\" data-content=\"" + "<p>" + _resourceManager.GetString(model.ToString() + "_Detail") + "</p>" + (String.IsNullOrEmpty(tooltipdetail) ? "No rule matched" : "<p><ul>" + tooltipdetail + "</ul></p>") + "\"><span class=\"small\">" + modelstring + "</span></div></td>"; } else { line += "<td class=\"model_empty_cell\"></td>"; } } line += "</tr>"; if (HasValue) { Add(line); } else { break; } } Add(@" </tbody> </table> </div> </div>" ); }
private void GenerateRuleAccordeon(RiskRuleCategory category) { var rules = RuleSet <HealthcheckData> .Rules; rules.Sort((RuleBase <HealthcheckData> a, RuleBase <HealthcheckData> b) => { int c = ReportHelper.GetEnumDescription(a.Model).CompareTo(ReportHelper.GetEnumDescription(b.Model)); if (c == 0) { c = a.Title.CompareTo(b.Title); } return(c); } ); var m = RiskModelCategory.Unknown; var data = new List <KeyValuePair <RiskModelCategory, List <RuleBase <HealthcheckData> > > >(); foreach (var rule in rules) { if (rule.Category == category) { if (rule.Model != m) { m = rule.Model; data.Add(new KeyValuePair <RiskModelCategory, List <RuleBase <HealthcheckData> > >(rule.Model, new List <RuleBase <HealthcheckData> >())); } data[data.Count - 1].Value.Add(rule); } } Add(@" <div class=""row""><div class=""col-lg-12""> <p>Each line represents a rule. Click on a rule to expand it and show the details of it. </p> "); foreach (var d in data) { Add(@" <div class=""row""><div class=""col-lg-12 mt-3""> <h3>" ); Add(ReportHelper.GetEnumDescription(d.Key)); Add(@" </h3> "); string description = _resourceManager.GetString(d.Key.ToString() + "_Detail"); if (!string.IsNullOrEmpty(description)) { Add(@" <div class=""row""><div class=""col-lg-12""> <p>" ); Add(description); Add(@" </p> "); } GenerateAccordion("rules" + d.Key.ToString(), () => { foreach (var rule in d.Value) { GenerateIndicatorPanelDetail(d.Key, rule); } }); } }
private void GenerateDomainInformation() { Add(@" <div class=""row""> <div class=""col-md-12 table-responsive""> <table class=""table table-striped table-bordered""> <thead><tr> <th>Domain</th> <th>Netbios Name</th> <th>Domain Functional Level</th> <th>Forest Functional Level</th> <th>Creation date</th> <th>Nb DC</th> <th>Engine</th> <th>Level</th> <th>Schema version</th> </tr> </thead> <tbody> "); foreach (HealthcheckData data in Report) { Add(@" <tr> <td class='text'>" ); Add(PrintDomain(data.Domain)); Add(@"</td> <td class='text'>" ); AddEncoded(data.NetBIOSName); Add(@"</td> <td class='text'>" ); Add(ReportHelper.DecodeDomainFunctionalLevel(data.DomainFunctionalLevel)); Add(@"</td> <td class='text'>" ); Add(ReportHelper.DecodeForestFunctionalLevel(data.ForestFunctionalLevel)); Add(@"</td> <td class='text'>" ); Add(data.DomainCreation.ToString("u")); Add(@"</td> <td class='num'>" ); Add(data.NumberOfDC); Add(@"</td> <td class='text'>" ); Add(data.EngineVersion); Add(@"</td> <td class='text'>" ); Add(data.Level.ToString()); Add(@"</td> <td class='text'>" ); Add(ReportHelper.GetSchemaVersion(data.SchemaVersion)); Add(@"</td> </tr>" ); } Add(@" </tbody> <tfoot> <tr> <td class='text'><b>Total</b></td> <td class='num'>" + Report.Count + @"</td> </tr> </tfoot> </table> </div> </div> "); }
public string GenerateJsonFileChordDiagram(MigrationChecker migrationChecker) { StringBuilder sb = new StringBuilder(); sb.Append("["); bool firstnode = true; foreach (GraphNode node in Nodes) { if (!firstnode) { sb.AppendLine(","); } else { firstnode = false; } sb.Append(" {"); sb.Append(" \"name\": \"" + ReportHelper.EscapeJsonString(node.Domain.DomainName) + "\""); if (node.IsPotentiallyRemoved) { sb.Append(" ,\"potentiallyremoved\": 1"); } var entity = node.Entity; if (entity != null) { sb.Append(entity.GetJasonOutput()); } HealthcheckData data = node.HealthCheckData; if (data != null) { sb.Append(" ,\"score\": " + data.GlobalScore); sb.Append(" ,\"staleObjectsScore\": " + data.StaleObjectsScore); sb.Append(" ,\"privilegiedGroupScore\": " + data.PrivilegiedGroupScore); sb.Append(" ,\"trustScore\": " + data.TrustScore); sb.Append(" ,\"anomalyScore\": " + data.AnomalyScore); if (data.UserAccountData != null) { sb.Append(" ,\"activeusers\": " + data.UserAccountData.NumberActive); } if (data.ComputerAccountData != null) { sb.Append(" ,\"activecomputers\": " + data.ComputerAccountData.NumberActive); } } sb.Append(" ,\"trusts\": ["); bool firstTrust = true; foreach (var edge in node.Trusts.Values) { var destination = edge.Destination; if (!firstTrust) { sb.Append(","); } else { firstTrust = false; } sb.Append(" {"); sb.Append("\"name\": \""); sb.Append(ReportHelper.EscapeJsonString(destination.Domain.DomainName)); sb.Append("\""); var entity2 = destination.Entity; if (entity2 != null) { sb.Append(entity2.GetJasonOutput()); } sb.Append("}"); } sb.Append("]"); sb.Append("}"); } sb.AppendLine("]"); return(sb.ToString()); }
public string GenerateJsonFileFull(MigrationChecker migrationChecker) { Dictionary <int, int> idconversiontable = new Dictionary <int, int>(); StringBuilder sb = new StringBuilder(); sb.Append("{"); // START OF NODES sb.Append(" \"nodes\": ["); // it is important to put the root node as the first node for correct display int nodenumber = 0; bool firstnode = true; foreach (GraphNode node in Nodes) { if (!firstnode) { sb.Append(" },"); } else { firstnode = false; } sb.Append(" {"); sb.Append(" \"id\": " + nodenumber + ","); sb.Append(" \"shortname\": \"" + ReportHelper.EscapeJsonString(node.Domain.DomainName.Split('.')[0]) + "\""); if (node.IsPartOfARealForest()) { sb.Append(" ,\"forest\": \"" + ReportHelper.EscapeJsonString(node.Forest.DomainName) + "\""); } if (node.IsPotentiallyRemoved) { sb.Append(" ,\"potentiallyremoved\": 1"); } var entity = node.Entity; if (entity != null) { sb.Append(entity.GetJasonOutput()); } HealthcheckData data = node.HealthCheckData; sb.Append(" ,\"name\": \"" + ReportHelper.EscapeJsonString(node.Domain.DomainName) + "\""); if (data != null) { sb.Append(" ,\"score\": " + data.GlobalScore); sb.Append(" ,\"staleObjectsScore\": " + data.StaleObjectsScore); sb.Append(" ,\"privilegiedGroupScore\": " + data.PrivilegiedGroupScore); sb.Append(" ,\"trustScore\": " + data.TrustScore); sb.Append(" ,\"anomalyScore\": " + data.AnomalyScore); if (data.UserAccountData != null) { sb.Append(" ,\"activeusers\": " + data.UserAccountData.NumberActive); } if (data.ComputerAccountData != null) { sb.Append(" ,\"activecomputers\": " + data.ComputerAccountData.NumberActive); } } sb.Append(" ,\"dist\": null"); idconversiontable[node.Id] = nodenumber++; } if (Nodes.Count > 0) { sb.Append(" }"); } sb.Append(" ],"); // END OF NODES // START LINKS sb.Append(" \"links\": ["); // avoid a final "," bool absenceOfLinks = true; // subtility: try to regroup 2 links at one if all the properties match // SkipLink contains the edge to ignore List <GraphEdge> SkipLink = new List <GraphEdge>(); // foreach edge foreach (GraphNode node in Nodes) { foreach (GraphEdge edge in node.Trusts.Values) { if (SkipLink.Contains(edge)) { continue; } // for unidirectional trusts // keep only the remote part of the trust. SID Filtering is unknown (avoid evaluating SID Filtering when no value is available) if (edge.TrustDirection == 2 && edge.IsAuthoritative == false) { continue; } // keep only the reception of the trust. SID Filtering status is sure if (edge.TrustDirection == 1 && edge.Destination.Trusts[edge.Source.Domain].IsAuthoritative == true) { continue; } // trying to simplify bidirectional trusts bool isBidirectional = false; if (edge.IsEquivalentToReverseEdge(migrationChecker)) { GraphEdge reverseEdge = edge.Destination.Trusts[edge.Source.Domain]; // keep only one of the two part of the bidirectional trust SkipLink.Add(reverseEdge); isBidirectional = true; } if (!absenceOfLinks) { sb.Append(" },"); } else { absenceOfLinks = false; } sb.Append(" {"); if (edge.TrustDirection == 2) { sb.Append(" \"source\": " + idconversiontable[edge.Destination.Id] + ","); sb.Append(" \"target\": " + idconversiontable[edge.Source.Id] + ","); } else { sb.Append(" \"source\": " + idconversiontable[edge.Source.Id] + ","); sb.Append(" \"target\": " + idconversiontable[edge.Destination.Id] + ","); } // blue: 25AEE4 // orange: FA9426 string sidFiltering = edge.GetSIDFilteringStatus(migrationChecker); if (!edge.IsActive) { // purple sb.Append(" \"color\": \"#A856AA\","); } else { switch (sidFiltering) { case "Remote": // yellow sb.Append(" \"color\": \"#FDC334\","); break; case "Migration": // blue sb.Append(" \"color\": \"#25AEE4\","); break; case "No": // red sb.Append(" \"color\": \"#E75351\","); break; case "Yes": // green sb.Append(" \"color\": \"#74C25C\","); break; } } if (isBidirectional) { sb.Append(" \"type\": \"double\","); } sb.Append(" \"rels\": [\""); sb.Append("Attributes=" + edge.GetTrustAttributes() + ","); if (edge.CreationDate != DateTime.MinValue) { sb.Append("CreationDate=" + edge.CreationDate.ToString("yyyy-MM-dd") + ","); } sb.Append("SIDFiltering=" + sidFiltering); sb.Append((edge.IsActive ? null : ",Inactive")); sb.Append("\"]"); } } if (!absenceOfLinks) { sb.Append(" }"); } sb.Append(" ]"); // END OF LINKS sb.Append("}"); return(sb.ToString()); }