<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>108.bz &#187; Graphs</title>
	<atom:link href="http://www.108.bz/posts/tag/graphs/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.108.bz</link>
	<description>Wandering futilities...</description>
	<lastBuildDate>Fri, 27 May 2011 09:08:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Active Directory Graphs</title>
		<link>http://www.108.bz/posts/it/active-directory-graphs/</link>
		<comments>http://www.108.bz/posts/it/active-directory-graphs/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 15:26:32 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[Graphs]]></category>
		<category><![CDATA[VBS]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=443</guid>
		<description><![CDATA[Domain Controllers replicate Active Directory data with each other. They do so through Connections that are partly generated by the KCC (Knowledge Consistency Checker), partly configured by you: the Sysadmin . Each connection is one-way. If you open Active Directory Sites and Services, expand a Site and then a Server node, you&#8217;ll notice that Connections [...]]]></description>
			<content:encoded><![CDATA[<p>Domain Controllers replicate Active Directory data with each other. They do so through <i>Connections</i> that are partly generated by the <i>KCC</i> (Knowledge Consistency Checker), partly configured by you: the Sysadmin . Each connection is one-way. If you open <i>Active Directory Sites and Services</i>, expand a Site and then a Server node, you&#8217;ll notice that Connections listed under <i>NTDS Settings</i> are labeled &#8220;From Server&#8221; and &#8220;From Site&#8221;. In the image below (stolen from <a href="http://technet.microsoft.com/en-us/library/dd277430.aspx">here</a>), the DC named HEIDITEST will replicate AD changes by sending them <i>to</i> MHILLMAN2. The Connection Object is thus defined <i>from</i> HEIDITEST, <i>to</i> MHILLMAN2. You can expect a specular Connection to exist, defined under the <i>NTDS Settings</i> node of HEIDITEST.<br />
<a href="http://www.108.bz/wp-content/uploads/2010/04/adss.gif"><img src="http://www.108.bz/wp-content/uploads/2010/04/adss-300x135.gif" alt="" title="Active Directory Sites and Services" width="300" height="135" class="alignnone size-medium wp-image-452" /></a><br />
See <a href="http://technet.microsoft.com/en-us/library/dd277429.aspx">Active Directory Replication</a> for a more in-depth explanation.<br />
Besides Connection objects automatically created by the <i>KCC</i>, which does its best to build a proper replication topology, you sometimes add your own for fault/link tolerance or other reasons. If the domain is sufficiently big, things may become messy. Instead of fumbling my way through <i>Active Directory Sites and Services</i> I wanted to automatically generate a visual representation of such topology, with DCs and Connections: time to write yet another script. </p>
<p>This time I chose VBS over Perl, hoping that this post would be more &#8220;instructional&#8221;. Perl on Windows is not so common, while VBScript is the standard way to automate stuff on that O.S. (despite the language being incredibly clumsy and annoying<sup class='footnote'><a href='#fn-443-1' id='fnref-443-1'>1</a></sup>).</p>
<p>As for the graph format, I chose to output <a href="http://www.graphviz.org/">Graphviz</a> <a href="http://www.graphviz.org/doc/info/lang.html">DOT</a> format/language.</p>
<p>The script works this way:</p>
<ul>
<li>Find the current domain.</li>
<li>Find all the Domain Controllers (AD objects of class <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">nTDSDSA</span>, see <a href="http://blogs.technet.com/heyscriptingguy/archive/2004/12/16/how-can-i-get-a-list-of-all-the-domain-controllers-in-my-domain.aspx">this</a>) and the <i>Site</i> they&#8217;re in.</li>
<li>For each DC/Site, select <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">nTDSConnection</span> objects in <i>NTDS Settings</i>. Of course this is done by means of LDAP queries over <a href="http://en.wikipedia.org/wiki/ActiveX_Data_Objects">ADO</a>, but the view we get is equivalent to what we&#8217;re seeing in <i>Active Directory Sites and Services</i>.</li>
<li>Print the DOT graph on standard output: DCs, connections and sites. DCs in the same site will be clustered together.</li>
</ul>
<p>To use it, first generate the graph&#8217;s definition:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cscript /nologo ntdsconnections_graph.vbs &gt; AD-pre.dot</div></div>
<p>Then use Graphviz&#8217;s tools to lay out the graph and turn it into an actual image. For optimal results, I suggest something like:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ccomps -x AD-pre.dot | dot | gvpack -u | neato -Tpng -n2 &gt; AD-pre.png</div></div>
<p>Here&#8217;s what showed up, in my test case:<br />
<a href="http://www.108.bz/wp-content/uploads/2010/04/AD-pre.png"><img src="http://www.108.bz/wp-content/uploads/2010/04/AD-pre-300x160.png" alt="" title="AD-pre" width="300" height="160" class="alignnone size-medium wp-image-454" /></a></p>
<p>And here&#8217;s the same Domain, after some treatment:<br />
<a href="http://www.108.bz/wp-content/uploads/2010/04/AD-post.png"><img src="http://www.108.bz/wp-content/uploads/2010/04/AD-post-300x104.png" alt="" title="AD-post" width="300" height="104" class="alignnone size-medium wp-image-455" /></a><br />
Such graphs may be useful from a Sysadmin point of view, but they&#8217;re quite ugly, honestly. I originally thought to use Graphviz to output &#8220;some&#8221; format, read it in <a href="http://projects.gnome.org/dia/">Dia</a> or similar diagram drawing software, and then fix the aesthetics. But Dia support (if it ever worked) has been dropped from Grapviz (<a href="http://www.graphviz.org/cvs/ChangeLog">December 10, 2009</a>). Dia&#8217;s 0.97.1 tarball bears a &#8220;dot2dia.py&#8221; plugin, but I haven&#8217;t hacked it into working. Any other editable format known to Graphviz (e.g.: SVG) doesn&#8217;t support &#8220;connector&#8221; primitives meaning that arrows won&#8217;t stick to objects while you drag them around&#8230; I&#8217;ll follow up if I make some progress.</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">' A/D replication topology graph (Graphviz .DOT format)<br />
</span><span style="color: #008000;">' in the current Domain.<br />
</span><span style="color: #008000;">' ----------------------------<br />
</span><span style="color: #008000;">' Giuliano - http://www.108.bz<br />
</span><br />
<span style="color: #000080;">Set</span> objRootDSE = GetObject(<span style="color: #800000;">&quot;LDAP://RootDSE&quot;</span>)<br />
strConfigurationNC = objRootDSE.<span style="color: #000080;">Get</span>(<span style="color: #800000;">&quot;configurationNamingContext&quot;</span>)<br />
<br />
<span style="color: #000080;">Set</span> adoCommand = CreateObject(<span style="color: #800000;">&quot;ADODB.Command&quot;</span>)<br />
<span style="color: #000080;">Set</span> adoConnection = CreateObject(<span style="color: #800000;">&quot;ADODB.Connection&quot;</span>)<br />
adoConnection.Provider = <span style="color: #800000;">&quot;ADsDSOObject&quot;</span><br />
adoConnection.<span style="color: #000080;">Open</span> <span style="color: #800000;">&quot;Active Directory Provider&quot;</span><br />
adoCommand.ActiveConnection = adoConnection<br />
<br />
strBase = <span style="color: #800000;">&quot;&lt;LDAP://&quot;</span> &amp; strConfigurationNC &amp; <span style="color: #800000;">&quot;&gt;&quot;</span><br />
strFilter = <span style="color: #800000;">&quot;(objectClass=nTDSDSA)&quot;</span><br />
strAttributes = <span style="color: #800000;">&quot;AdsPath&quot;</span><br />
strQuery = strBase &amp; <span style="color: #800000;">&quot;;&quot;</span> &amp; strFilter &amp; <span style="color: #800000;">&quot;;&quot;</span> &amp; strAttributes &amp; <span style="color: #800000;">&quot;;subtree&quot;</span><br />
<br />
adoCommand.CommandText = strQuery<br />
adoCommand.Properties(<span style="color: #800000;">&quot;Page Size&quot;</span>) = 100<br />
adoCommand.Properties(<span style="color: #800000;">&quot;Timeout&quot;</span>) = 60<br />
adoCommand.Properties(<span style="color: #800000;">&quot;Cache Results&quot;</span>) = <span style="color: #000080;">False</span><br />
<br />
<span style="color: #000080;">Set</span> adoRecordset = adoCommand.Execute<br />
<br />
<span style="color: #000080;">Dim</span> dictDCtoSite<br />
<span style="color: #000080;">Set</span> dictDCtoSite = CreateObject(<span style="color: #800000;">&quot;Scripting.Dictionary&quot;</span>)<br />
<span style="color: #000080;">Dim</span> dictSites<br />
<span style="color: #000080;">Set</span> dictSites = CreateObject(<span style="color: #800000;">&quot;Scripting.Dictionary&quot;</span>)<br />
<span style="color: #000080;">Dim</span> arrLink()<br />
<br />
<span style="color: #000080;">Function</span> pp(s)<br />
&nbsp; &nbsp; pp = Replace(right(s,len(s)-3), <span style="color: #800000;">&quot;-&quot;</span>, <span style="color: #800000;">&quot;_&quot;</span>) <span style="color: #008000;">' trash the leading &quot;CN=&quot;<br />
</span><span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Do</span> <span style="color: #000080;">Until</span> adoRecordset.EOF<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> objDC = _<br />
&nbsp; &nbsp; &nbsp; &nbsp; GetObject(GetObject(adoRecordset.Fields(<span style="color: #800000;">&quot;AdsPath&quot;</span>).Value).Parent)<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> objSite = _<br />
&nbsp; &nbsp; &nbsp; &nbsp; GetObject(GetObject(objDC.Parent).Parent)<br />
&nbsp; &nbsp; dictDCtoSite.Add objDC.name, objSite.name<br />
&nbsp; &nbsp; <span style="color: #000080;">if</span> <span style="color: #000080;">not</span> dictSites.Exists(objSite.name) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; dictSites.Add objSite.name, 1<br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; adoRecordset.MoveNext<br />
<span style="color: #000080;">Loop</span><br />
adoRecordset.<span style="color: #000080;">Close</span><br />
<br />
<span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> strDcRDN <span style="color: #000080;">in</span> dictDCtoSite.Keys <br />
&nbsp; &nbsp; strSiteRDN = dictDCtoSite.Item(strDcRDN)<br />
<br />
&nbsp; &nbsp; strNtdsSettingsPath = <span style="color: #800000;">&quot;LDAP://cn=NTDS Settings,&quot;</span> &amp; strDcRDN &amp; _<br />
&nbsp; &nbsp; <span style="color: #800000;">&quot;,cn=Servers,&quot;</span> &amp; strSiteRDN &amp; <span style="color: #800000;">&quot;,cn=Sites,&quot;</span> &amp; strConfigurationNC<br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> objNtdsSettings = GetObject(strNtdsSettingsPath)<br />
<br />
&nbsp; &nbsp; objNtdsSettings.Filter = Array(<span style="color: #800000;">&quot;nTDSConnection&quot;</span>)<br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> objConnection <span style="color: #000080;">In</span> objNtdsSettings<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">'WScript.Echo strSiteRDN &amp; &quot; : &quot; &amp; Split(objConnection.fromServer, &quot;,&quot;)(1) &amp; &quot; -&gt; &quot; &amp; strDcRDN <br />
</span>&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">ReDim</span> <span style="color: #000080;">Preserve</span> arrLink(2,k)<br />
&nbsp; &nbsp; &nbsp; &nbsp; arrLink(0,k) = strSiteRDN<br />
&nbsp; &nbsp; &nbsp; &nbsp; arrLink(1,k) = Split(objConnection.fromServer, <span style="color: #800000;">&quot;,&quot;</span>)(1)<br />
&nbsp; &nbsp; &nbsp; &nbsp; arrLink(2,k) = strDcRDN<br />
&nbsp; &nbsp; &nbsp; &nbsp; k = k + 1<br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> strNtdsSettingsPath = <span style="color: #000080;">Nothing</span><br />
<span style="color: #000080;">Next</span><br />
<br />
<span style="color: #000080;">Dim</span> arrSubgraphs()<br />
<span style="color: #000080;">Redim</span> arrSubgraphs(dictSites.Count-1)<br />
<br />
WScript.Echo <span style="color: #800000;">&quot;Digraph AD {&quot;</span><br />
WScript.Echo <span style="color: #800000;">&quot; &nbsp;fontname=helvetica;&quot;</span><br />
WScript.Echo <span style="color: #800000;">&quot; &nbsp;node [fontname=helvetica];&quot;</span><br />
<span style="color: #008000;">' Same site links<br />
</span><span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> strSiteRDN <span style="color: #000080;">in</span> dictSites<br />
&nbsp; &nbsp; nosamesitelinks = <span style="color: #000080;">True</span><br />
&nbsp; &nbsp; headerwritten = <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; <span style="color: #000080;">For</span> k = 0 <span style="color: #000080;">To</span> <span style="color: #000080;">Ubound</span>(arrLink, 2)<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">If</span> strSiteRDN = arrLink(0,k) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">if</span> dictDCtoSite.Item(arrLink(1,k)) = dictDCtoSite.Item(arrLink(2,k)) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">if</span> nosamesitelinks <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nosamesitelinks = <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WScript.Echo <span style="color: #800000;">&quot; &nbsp; &nbsp;subgraph cluster_&quot;</span> &amp; pp(strSiteRDN) &amp; <span style="color: #800000;">&quot; {&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; headerwritten = <span style="color: #000080;">True</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WScript.Echo <span style="color: #800000;">&quot; &nbsp; &nbsp; &nbsp; &nbsp;&quot;</span> &amp; pp(arrLink(1,k)) &amp; <span style="color: #800000;">&quot; -&gt; &quot;</span> &amp; pp(arrLink(2,k)) &amp; <span style="color: #800000;">&quot;;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span><br />
&nbsp; &nbsp; <span style="color: #000080;">If</span> headerwritten <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; WScript.Echo <span style="color: #800000;">&quot; &nbsp; &nbsp; &nbsp; &nbsp;label= &quot;</span><span style="color: #800000;">&quot;&quot;</span> &amp; pp(strSiteRDN) &amp; <span style="color: #800000;">&quot;&quot;</span><span style="color: #800000;">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; WScript.Echo <span style="color: #800000;">&quot; &nbsp; &nbsp;}&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<span style="color: #000080;">Next</span><br />
Wscript.Echo<br />
<span style="color: #008000;">' Inter-site links<br />
</span><span style="color: #000080;">For</span> k = 0 <span style="color: #000080;">To</span> <span style="color: #000080;">Ubound</span>(arrLink, 2)<br />
&nbsp; &nbsp; <span style="color: #000080;">if</span> dictDCtoSite.Item(arrLink(1,k)) &lt;&gt; dictDCtoSite.Item(arrLink(2,k)) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; WScript.Echo <span style="color: #800000;">&quot; &nbsp; &nbsp;&quot;</span> &amp; pp(arrLink(1,k)) &amp; <span style="color: #800000;">&quot; -&gt; &quot;</span> &amp; pp(arrLink(2,k)) &amp; <span style="color: #800000;">&quot;;&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<span style="color: #000080;">Next</span><br />
WScript.Echo <span style="color: #800000;">&quot;}&quot;</span></div></div>
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-443-1'>No powerful and convenient data types, no free and ready to use debugger, no public CPAN-like module repository, unnecessarily verbose syntax; I may go on for an hour&#8230; <span class='footnotereverse'><a href='#fnref-443-1'>&#8617;</a></span></li>
</ol>
</div>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=443" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/it/active-directory-graphs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

