public string GenerateRawContent(PingCastleReportCollection <HealthcheckData> report) { data = NetworkMapData.BuildFromConsolidation(report); sb.Length = 0; GenerateContent(); return(sb.ToString()); }
public string GenerateRawContent(PingCastleReportCollection <HealthcheckData> report, string selectedTab = null) { Report = report; sb.Length = 0; GenerateContent(selectedTab); return(sb.ToString()); }
// sometimes we have only the netbios name. Try to find if we know the FQDN private static void EnrichDomainInfo(PingCastleReportCollection <HealthcheckData> consolidation, HealthCheckTrustDomainInfoData di) { bool enriched = false; // search direct report foreach (HealthcheckData data in consolidation) { if (data.NetBIOSName.Equals(di.NetbiosName, StringComparison.InvariantCultureIgnoreCase)) { di.DnsName = data.DomainFQDN; di.ForestName = data.ForestFQDN; di.Forest = data.Forest; di.Domain = data.Domain; break; } foreach (var trust in data.Trusts) { // for old report: no netbios name defined in domain object ! string[] values = trust.TrustPartner.Split('.'); string netbios = values[0]; if (!String.IsNullOrEmpty(trust.NetBiosName)) { netbios = trust.NetBiosName; } if (netbios.Equals(di.NetbiosName, StringComparison.InvariantCultureIgnoreCase)) { di.DnsName = trust.TrustPartner; // unknown forest name enriched = true; break; } foreach (var forestinfo in trust.KnownDomains) { if (!String.IsNullOrEmpty(forestinfo.NetbiosName) && forestinfo.NetbiosName.Equals(di.NetbiosName, StringComparison.InvariantCultureIgnoreCase)) { di.DnsName = forestinfo.DnsName; di.ForestName = trust.TrustPartner; di.Forest = trust.Domain; di.Domain = forestinfo.Domain; enriched = true; break; } } if (enriched) { break; } } if (enriched) { break; } } }
HealthcheckData GetItem(PingCastleReportCollection <HealthcheckData> reports, int rank) { var e = reports.GetEnumerator(); e.MoveNext(); for (int i = 0; i < rank; i++) { e.MoveNext(); } return(e.Current); }
public PingCastleReportCollection <T> ToLatestReportCollection() { var output = new PingCastleReportCollection <T>(); foreach (var sid in data.Keys) { DateTime maxDate = DateTime.MinValue; foreach (var date in data[sid].Keys) { if (maxDate < date) { maxDate = date; } } output.Add(data[sid][maxDate]); } output.EnrichInformation(); return(output); }
public PingCastleReportCollection <T> GetDataReportAtDate(DateTime dateToIssueReport) { var output = new PingCastleReportCollection <T>(); foreach (var sid in data.Keys) { DateTime min = DateTime.MinValue; foreach (var date in data[sid].Keys) { if (date > min && date <= dateToIssueReport) { min = date; } } if (min != DateTime.MinValue) { output.Add(data[sid][min]); } } output.EnrichInformation(); return(output); }
public string GenerateReportFile(PingCastleReportCollection <HealthcheckData> report, ADHealthCheckingLicense license, string filename) { Report = report; Brand(license); return(GenerateReportFile(filename)); }
public bool CartoTask(bool PerformHealthCheckGenerateDemoReports) { List <HealthcheckAnalyzer.ReachableDomainInfo> domains = null; StartTask("Exploration", () => { HealthcheckAnalyzer hcroot = new HealthcheckAnalyzer(); domains = hcroot.GetAllReachableDomains(Port, Credential); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("List of domains that will be queried"); Console.ResetColor(); foreach (var domain in domains) { Console.WriteLine(domain.domain); } }); var consolidation = new PingCastleReportCollection <HealthcheckData>(); StartTask("Examining all domains in parallele (this can take a few minutes)", () => { BlockingQueue <string> queue = new BlockingQueue <string>(30); int numberOfThread = 100; Thread[] threads = new Thread[numberOfThread]; try { ThreadStart threadFunction = () => { for (; ;) { string domain = null; if (!queue.Dequeue(out domain)) { break; } try { Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] " + "Starting the analysis of " + domain); HealthcheckAnalyzer hc = new HealthcheckAnalyzer(); var data = hc.GenerateCartoReport(domain, Port, Credential, AnalyzeReachableDomains); consolidation.Add(data); Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] " + "Analysis of " + domain + " completed with success"); } catch (Exception ex) { Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] " + "Analysis of " + domain + " failed"); Trace.WriteLine("Exception while analysing domain " + domain + " : " + ex.Message); Trace.WriteLine(ex.StackTrace); } } }; // Consumers for (int i = 0; i < numberOfThread; i++) { threads[i] = new Thread(threadFunction); threads[i].Start(); } foreach (var domain in domains) { queue.Enqueue(domain.domain); } queue.Quit(); Trace.WriteLine("examining domains file completed. Waiting for worker thread to complete"); for (int i = 0; i < numberOfThread; i++) { threads[i].Join(); } Trace.WriteLine("Done examining domains"); } catch (Exception ex) { Trace.WriteLine("Exception while analysing domain in carto: " + ex.Message); Trace.WriteLine(ex.StackTrace); } finally { queue.Quit(); for (int i = 0; i < numberOfThread; i++) { if (threads[i] != null) { if (threads[i].ThreadState == System.Threading.ThreadState.Running) { threads[i].Abort(); } } } } }); if (PerformHealthCheckGenerateDemoReports) { Console.WriteLine("Performing demo report transformation"); Trace.WriteLine("Performing demo report transformation"); consolidation = PingCastleReportHelper <HealthcheckData> .TransformReportsToDemo(consolidation); } if (!StartTask("Healthcheck consolidation", () => { consolidation.EnrichInformation(); ReportHealthCheckMapBuilder nodeAnalyzer = new ReportHealthCheckMapBuilder(consolidation, License); nodeAnalyzer.Log = Console.WriteLine; nodeAnalyzer.CenterDomainForSimpliedGraph = CenterDomainForSimpliedGraph; nodeAnalyzer.GenerateReportFile("ad_carto_full_node_map.html"); nodeAnalyzer.FullNodeMap = false; nodeAnalyzer.CenterDomainForSimpliedGraph = CenterDomainForSimpliedGraph; nodeAnalyzer.GenerateReportFile("ad_carto_simple_node_map.html"); } )) { return(false); } return(true); }
public static NetworkMapData BuildFromConsolidation(PingCastleReportCollection <HealthcheckData> reports) { var data = new NetworkMapData() { Views = new List <NetworkMapDataView>() { new NetworkMapDataView() { framenetwork = Subnet.Parse("10.0.0.0/8"), order = 1024, }, new NetworkMapDataView() { framenetwork = Subnet.Parse("192.168.0.0/16"), order = 256, } }, }; data.networkrange = new Dictionary <string, List <NetworkMapDataItem> >(); data.DomainControllers = new List <NetworkMapDCItem>(); var latestForestReports = new Dictionary <string, HealthcheckData>(); foreach (var report in reports) { // select latest forest report to have the latest network information var version = new Version(report.EngineVersion.Split(' ')[0]); if (!(version.Major < 2 || (version.Major == 2 && version.Minor < 6))) { if (!latestForestReports.ContainsKey(report.Forest.DomainSID) || latestForestReports[report.Forest.DomainSID].GenerationDate < report.GenerationDate) { latestForestReports[report.Forest.DomainSID] = report; } } } // store network information foreach (var report in latestForestReports.Values) { var list = new List <NetworkMapDataItem>(); data.networkrange.Add(report.Forest.DomainSID, list); foreach (var site in report.Sites) { foreach (var network in site.Networks) { list.Add(new NetworkMapDataItem() { Network = Subnet.Parse(network), Source = report.Forest.DomainName, Description = site.Description, Location = site.Location, Name = site.SiteName, }); } } } // tag the network foreach (var report in reports) { IEnumerable <NetworkMapDataItem> networks = null; if (data.networkrange.ContainsKey(report.Forest.DomainSID)) { networks = data.networkrange[report.Forest.DomainSID]; } // collect DC info foreach (var dc in report.DomainControllers) { foreach (string ip in dc.IP) { IPAddress i; if (!IPAddress.TryParse(ip, out i)) { continue; } if (i.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) { continue; } data.DomainControllers.Add(new NetworkMapDCItem() { Name = dc.DCName, Source = report.DomainFQDN, Ip = i, }); if (networks != null) { foreach (var network in networks) { if (network.Network.MatchIp(i)) { if (string.IsNullOrEmpty(network.DomainFQDN)) { network.DomainFQDN = report.DomainFQDN; } else if (network.DomainFQDN == report.DomainFQDN) { } else { network.DomainFQDN = "_multiple_"; } } } } } } } return(data); }
public ReportHealthCheckMapBuilder(PingCastleReportCollection <HealthcheckData> consolidation) : this(consolidation, null) { }
public string GenerateReportFile(PingCastleReportCollection <HealthcheckData> report, ADHealthCheckingLicense license, string filename) { data = NetworkMapData.BuildFromConsolidation(report); return(GenerateReportFile(filename)); }
static public GraphNodeCollection BuildModel(PingCastleReportCollection <HealthcheckData> consolidation, OwnerInformationReferences EntityData) { GraphNodeCollection nodes = new GraphNodeCollection(); // build links based on the most to the less reliable information Trace.WriteLine("Building model"); int nodeNumber = 0; Trace.WriteLine("domain reports"); // enumerate official domains foreach (HealthcheckData data in consolidation) { GraphNode node = nodes.CreateNodeIfNeeded(ref nodeNumber, data.Domain, data.NetBIOSName, data.GenerationDate); node.HealthCheckData = data; node.SetForest(data.Forest); } Trace.WriteLine("direct trust"); // get trust map based on direct trusts data foreach (HealthcheckData data in consolidation) { GraphNode source = nodes.Locate(data); foreach (var trust in data.Trusts) { GraphNode destination = nodes.CreateNodeIfNeeded(ref nodeNumber, trust.Domain, trust.NetBiosName, data.GenerationDate); source.Link(destination, trust); } } Trace.WriteLine("forest trust"); foreach (HealthcheckData data in consolidation) { foreach (var trust in data.Trusts) { // do not examine if we have more accurate information (aka the forest report) if (consolidation.GetDomain(trust.Domain) != null) { continue; } if (trust.KnownDomains != null) { GraphNode source = nodes.Locate(trust); foreach (var domainInfo in trust.KnownDomains) { GraphNode destination = nodes.CreateNodeIfNeeded(ref nodeNumber, domainInfo.Domain, domainInfo.NetbiosName, data.GenerationDate); source.LinkInsideAForest(destination, domainInfo.CreationDate); destination.SetForest(domainInfo.Forest); } } } } Trace.WriteLine("Building reachable links"); // make links based on reachable domains. Information is less reliable. foreach (HealthcheckData data in consolidation) { // ignore report without reachable domains if (data.ReachableDomains == null) { continue; } // ignore reachable links if we have the forest domain report if (consolidation.GetDomain(data.Forest) != null) { continue; } foreach (HealthCheckTrustDomainInfoData di in data.ReachableDomains) { // domain info can contain only netbios name (not FQDN) // enrich it if (di.NetbiosName.Equals(di.DnsName, StringComparison.InvariantCultureIgnoreCase)) { EnrichDomainInfo(consolidation, di); } // if no information was given (only Netbios name!) fallback to a forest trust if (String.IsNullOrEmpty(di.ForestName) || di.ForestName == di.DnsName) { GraphNode childDomain = nodes.CreateNodeIfNeeded(ref nodeNumber, di.Domain, di.NetbiosName, data.GenerationDate); GraphNode myForestRoot = nodes.CreateNodeIfNeeded(ref nodeNumber, data.Forest, null, data.GenerationDate); myForestRoot.LinkTwoForests(childDomain); myForestRoot.SetForest(myForestRoot.Domain); } else { // ignore the domain if the forest trust is known (information should be already there) if (consolidation.GetDomain(di.Forest) != null) { continue; } // add the forest trust if needed GraphNode remoteForestRoot = nodes.CreateNodeIfNeeded(ref nodeNumber, di.Forest, di.ForestNetbios, data.GenerationDate); remoteForestRoot.SetForest(remoteForestRoot.Domain); // add the forest root if needed GraphNode myForestRoot = nodes.CreateNodeIfNeeded(ref nodeNumber, data.Forest, null, data.GenerationDate); myForestRoot.LinkTwoForests(remoteForestRoot); myForestRoot.SetForest(myForestRoot.Domain); // add the trust if the domain is a child of the forest) // (ignore the trust if forest root = trust) GraphNode childDomain = nodes.CreateNodeIfNeeded(ref nodeNumber, di.Domain, di.NetbiosName, data.GenerationDate); remoteForestRoot.LinkInsideAForest(childDomain); childDomain.SetForest(remoteForestRoot.Domain); } } } Trace.WriteLine("enrich forest information"); nodes.EnrichForestInformation(); Trace.WriteLine("done"); nodes.EnrichEntity(EntityData); nodes.RemoveDeletedNodes(); return(nodes); }
public PingCastleReportCollection <HealthcheckData> GenerateForest(int maxDomain = 15) { int numberDomains = rnd.Next(5, maxDomain > 15 ? 15 : maxDomain); var children = new PingCastleReportCollection <HealthcheckData>(); // head of forest var root = GenerateSingleReport(new FakeHealthCheckDataGeneratorDomainModel() { Size = DomainSizeModel.VerySmall }); for (int i = 0; i < numberDomains; i++) { var child = GenerateSingleReport(new FakeHealthCheckDataGeneratorDomainModel() { Size = DomainSizeModel.Medium, Forest = root }); children.Add(child); } foreach (var child in children) { // root trust var trust = new HealthCheckTrustData(); trust.CreationDate = child.DomainCreation; trust.IsActive = true; trust.NetBiosName = child.NetBIOSName; trust.SID = child.DomainSid; trust.TrustDirection = 3; trust.TrustAttributes = 32; trust.TrustType = 2; trust.TrustPartner = child.DomainFQDN; trust.SID = child.DomainSid; trust.KnownDomains = new List <HealthCheckTrustDomainInfoData>(); root.Trusts.Add(trust); // child trust trust = new HealthCheckTrustData(); trust.CreationDate = child.DomainCreation; trust.IsActive = true; trust.NetBiosName = root.NetBIOSName; trust.SID = child.DomainSid; trust.TrustDirection = 3; trust.TrustAttributes = 32; trust.TrustType = 2; trust.TrustPartner = root.DomainFQDN; trust.SID = root.DomainSid; trust.KnownDomains = new List <HealthCheckTrustDomainInfoData>(); child.Trusts.Add(trust); foreach (var child2 in children) { if (child2.DomainSid == child.DomainSid) { continue; } var kdomain = new HealthCheckTrustDomainInfoData(); kdomain.CreationDate = child2.DomainCreation; kdomain.DnsName = child2.DomainFQDN; kdomain.ForestName = child2.ForestFQDN; kdomain.ForestNetbios = root.NetBIOSName; kdomain.ForestSid = root.DomainSid; kdomain.NetbiosName = child2.NetBIOSName; kdomain.Sid = child2.DomainSid; trust.KnownDomains.Add(kdomain); } } // output all domains children.Add(root); return(children); }
public PingCastleReportCollection <HealthcheckData> GenerateData(FakeHealthCheckDataGeneratorModel model) { var output = new PingCastleReportCollection <HealthcheckData>(); var num = 0; while (num < model.NumberOfDomains - 1) { int value = rnd.Next(100); if (value < 20 && model.NumberOfDomains - num > 6) { foreach (var d in GenerateForest(model.NumberOfDomains - num)) { output.Add(d); num++; } } if (value < 60) { output.Add(GenerateSingleReport(new FakeHealthCheckDataGeneratorDomainModel() { Size = DomainSizeModel.Small })); num++; } else if (value < 80) { output.Add(GenerateSingleReport(new FakeHealthCheckDataGeneratorDomainModel() { Size = DomainSizeModel.Medium })); num++; } else { output.Add(GenerateSingleReport(new FakeHealthCheckDataGeneratorDomainModel() { Size = DomainSizeModel.Large })); num++; } } int numberOfTrust = model.NumberOfDomains * model.TrustRatioInPercent / 100; for (int i = 0; i < numberOfTrust; i++) { //take 2 random domains int a = rnd.Next(output.Count); int b = rnd.Next(output.Count); while (a == b) { b = rnd.Next(output.Count); } var source = GetItem(output, a); var destination = GetItem(output, b); //bool forestTrust = false; bool uniDirectional = false; bool sidfiltering = false; DateTime trustCreation = DateBetween2Dates(new DateTime(Math.Max(source.DomainCreation.Ticks, destination.DomainCreation.Ticks)), DateTime.Now); var trust = new HealthCheckTrustData(); trust.CreationDate = trustCreation; trust.IsActive = true; trust.NetBiosName = destination.NetBIOSName; trust.SID = destination.DomainSid; trust.TrustDirection = (uniDirectional ? 1 : 3); trust.TrustAttributes = (sidfiltering ? 4 : 0); trust.TrustType = 2; trust.TrustPartner = destination.DomainFQDN; trust.SID = destination.DomainSid; trust.KnownDomains = new List <HealthCheckTrustDomainInfoData>(); source.Trusts.Add(trust); trust = new HealthCheckTrustData(); trust.CreationDate = trustCreation; trust.IsActive = true; trust.NetBiosName = source.NetBIOSName; trust.SID = source.DomainSid; trust.TrustDirection = (uniDirectional ? 2 : 3); trust.TrustAttributes = (sidfiltering ? 4 : 0); trust.TrustType = 2; trust.TrustPartner = source.DomainFQDN; trust.SID = source.DomainSid; trust.KnownDomains = new List <HealthCheckTrustDomainInfoData>(); destination.Trusts.Add(trust); } return(output); }
public ReportHealthCheckMapBuilder(PingCastleReportCollection <HealthcheckData> consolidation, ADHealthCheckingLicense license) : this(consolidation, (OwnerInformationReferences)null) { Brand(license); }
public ReportHealthCheckMapBuilder(PingCastleReportCollection <HealthcheckData> consolidation, OwnerInformationReferences ownerInformationReferences) { this.Report = consolidation; EntityData = ownerInformationReferences; FullNodeMap = true; }
public string GenerateReportFile(PingCastleReportCollection <CompromiseGraphData> report, ADHealthCheckingLicense license, string filename) { Report = report; return(GenerateReportFile(filename)); }