<?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>vmweaver.com &#187; Active Directory</title>
	<atom:link href="http://vmweaver.com/index.php/tag/active-directory/feed/" rel="self" type="application/rss+xml" />
	<link>http://vmweaver.com</link>
	<description>Mindless ramblings of a geek...</description>
	<lastBuildDate>Thu, 06 Oct 2011 20:42:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Powershell and AD Object Recovery (Prologue)</title>
		<link>http://vmweaver.com/index.php/2010/02/powershell-ad-recovery-prologue/</link>
		<comments>http://vmweaver.com/index.php/2010/02/powershell-ad-recovery-prologue/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 02:11:46 +0000</pubDate>
		<dc:creator>Mark A. Weaver</dc:creator>
				<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[AD]]></category>
		<category><![CDATA[Recovery]]></category>

		<guid isPermaLink="false">http://vmweaver.com/?p=229</guid>
		<description><![CDATA[I have been toying with an idea for a while since I have been diving deeper into Active Directory stuff with Powershell. The idea is to develop a full Active Directory object backup and recovery tool. There are several excellent tools available commercially that do this, but with IT staffs and budgets shrinking it is [...]]]></description>
			<content:encoded><![CDATA[<p>I have been toying with an idea for a while since I have been diving deeper into Active Directory stuff with Powershell.</p>
<p>The idea is to develop a full Active Directory object backup and recovery tool.  There are several excellent tools available commercially that do this, but with IT staffs and budgets shrinking it is often difficult to justify the cost.  </p>
<p>I am sure others have thought about it, maybe dabbled with it, but it seems to me that all of tools and components are available to do this, just that nobody (that I know of) has kind of glued them all together in an easy-to-use interface.</p>
<p>I know many of you may say &#8220;Hey, doesn&#8217;t Microsoft have an AD Recycle Bin now?&#8221;.  Well yes, they do&#8230;BUT many folks, I believe, are probably still running 2003 AD instances.  Regardless of all of that, though, this sounds like a good exercise to at least explore doing a larger-scale &#8220;application&#8221; using Powershell.</p>
<p>This will also be my first major dive in the Powershell V2.0, so I hope to be discovering new and interesting ways to put these tools together.</p>
<p>From my perspective, I see several main components that will need development:<br />
1. A user Interface.  While I have done some of this with &#8220;visual&#8221; languages and a touch with Powershell, I haven&#8217;t done anything very extensive.<br />
2. Interfacing with some type of database solution (probably SQL Server)<br />
3. Access to AD objects without 3rd party utilities. I think this will be fairly straightforward but  may end up using the Quest tools.<br />
4. Access to the &#8220;delete objects&#8221; container in the directory and a means to reanimate those objects.  (<a href="http://www.sdmsoftware.com/freeware.php">SDM Software Grou</a>p has some great cmdlets for doing this which I will probably look at using).<br />
5. General functions for manipulating AD objects (again&#8230;pretty easy)</p>
<p>One question keeps coming to mind, though is whether something like this would be useful?  I am not entirely sure, but I hope so!  To that end, I think the journey may be more worthwhile than the outcome.</p>
<p>Anyway, I hope to be spending more time with (when I *HAVE* spare time) and I hope to chronicle this &#8220;journey&#8221; here as I go.</p>
<p>If anyone has an opinion on this undertaking or has advice, please let me know.</p>
<p>Stay tuned for updates.  Right now I am standing up a small infrastructure at home to support this development effort.</p>
<p>Thanks and Happy Scripting!</p>
<p> &#8212; Mark</p>
]]></content:encoded>
			<wfw:commentRss>http://vmweaver.com/index.php/2010/02/powershell-ad-recovery-prologue/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powershell and Unknown User SIDs</title>
		<link>http://vmweaver.com/index.php/2009/10/powershell-and-unknown-user-sids/</link>
		<comments>http://vmweaver.com/index.php/2009/10/powershell-and-unknown-user-sids/#comments</comments>
		<pubDate>Fri, 09 Oct 2009 18:01:19 +0000</pubDate>
		<dc:creator>Mark A. Weaver</dc:creator>
				<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[AD]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[User Management]]></category>

		<guid isPermaLink="false">http://vmweaver.com/?p=204</guid>
		<description><![CDATA[Once again, my apologies for my lack of posting.. Anyway&#8230; An interesting thing came up at work the other day when one of my fellow administrators asked me if I could resolve an unknown SID he was seeing in some logs to see what the heck it belonged to. Since I had been telling him [...]]]></description>
			<content:encoded><![CDATA[<p>Once again, my apologies for my lack of posting..</p>
<p>Anyway&#8230;</p>
<p>An interesting thing came up at work the other day when one of my fellow administrators asked me if I could resolve an unknown SID he was seeing in some logs to see what the heck it belonged to.</p>
<p>Since I had been telling him that Powershell could do ANYTHING (slight exaggeration, I know)&#8230; that it should be able to do this.</p>
<p>Well, it certainly is an interesting notion.</p>
<p>I know that I have run into this in the past where you have file system ACLs set and there are a bunch of SIDs sitting in there that nobody seems to know who they belong to.</p>
<p>While it isn&#8217;t THAT important to resolve them since the user account is most likely no longer around, it IS an interesting thought exercise.</p>
<p>After perusing the web looking for others who have done something similar, I feel I had enough to throw something together..</p>
<p>Basically when an Active Directory object (like a user) is &#8220;deleted&#8221;, it is really just Tombstoned for a period of time and is moved to the hidden container &#8220;Deleted Objects&#8221; and then removed after like 90 days or so.</p>
<p>Here is my solution to &#8220;finding&#8221; those objects.</p>
<p>First you will have to know what Domain you want to look at for this object AND you have know the SID you are looking for.</p>

<div class="wp_syntax"><div class="code"><pre class="powershell" style="font-family:monospace;"><span style="color: #0000FF;">function</span> Resolve<span style="color: pink;">-</span>DeletedUserSID<span style="color: #000000;">&#40;</span><span style="color: #800080;">$Domain</span><span style="color: pink;">,</span> <span style="color: #800080;">$UserSID</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #008000;">## This is kind of a mashup of a few different scripts I found online in some forums.</span>
	<span style="color: #008000;">## Unfortunately I don't remember who did them.  If it was you, point me to your post and I will</span>
	<span style="color: #008000;">## give you the credit for your piece.</span>
	<span style="color: #008000;">## </span>
	<span style="color: #008000;">## Returns User information for deleted account with the specified SID and User Domain</span>
&nbsp;
	<span style="color: #800080;">$DomainRoot</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;LDAP://&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$Domain</span>.trim<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
	<span style="color: #800080;">$DomainDN</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#91;</span>adsi<span style="color: #000000;">&#93;</span> <span style="color: #000000;">&#40;</span> <span style="color: #800080;">$DomainRoot</span> <span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>.DistinguishedName
	<span style="color: #800080;">$adspath</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;LDAP://&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$DomainDN</span>
	<span style="color: #800080;">$root</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>system.directoryservices.Directoryentry<span style="color: #000000;">&#93;</span> <span style="color: #800080;">$Adspath</span>
	<span style="color: #800080;">$root</span>.psbase.AuthenticationType <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>system.directoryservices.authenticationtypes<span style="color: #000000;">&#93;</span>::Fastbind
	<span style="color: #008000;">## We will be looking in the &quot;Deleted Objects&quot; container which is normally hidden, etc.</span>
	<span style="color: #008000;">## You will need to execute this with an account that has DomainAdmin rights to the domain you are</span>
	<span style="color: #008000;">## querying.</span>
	<span style="color: #800080;">$root</span>.psbase.path <span style="color: pink;">=</span> <span style="color: #800000;">&quot;LDAP://cn=Deleted Objects,&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$DomainDN</span>
	<span style="color: #800080;">$search</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>system.directoryservices.directorysearcher<span style="color: #000000;">&#93;</span> <span style="color: #800080;">$root</span>
	<span style="color: #800080;">$search</span>.<span style="color: #0000FF;">filter</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;(&amp;(isDeleted=TRUE)(!(objectClass=computer))(objectclass=user))&quot;</span>
	<span style="color: #800080;">$search</span>.Tombstone <span style="color: pink;">=</span> <span style="color: #800080;">$true</span>
&nbsp;
	<span style="color: #008000;"># If you have more than 1000 users, you must NOT define SizeLimit (we haven't)</span>
	<span style="color: #008000;"># and PageSize must be less than the default value (of 1000). </span>
	<span style="color: #008000;"># I found this a bit strange...but as long as we understand it, I guess it is okay</span>
	<span style="color: #800080;">$Search</span>.PageSize <span style="color: pink;">=</span> <span style="color: #804000;">500</span>
&nbsp;
	<span style="color: #008000;"># Only look in the top level of the Deleted Objects container.</span>
	<span style="color: #800080;">$search</span>.SearchScope <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>system.directoryservices.searchscope<span style="color: #000000;">&#93;</span>::OneLevel
	<span style="color: #800080;">$result</span> <span style="color: pink;">=</span> <span style="color: #800080;">$search</span>.FindAll<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
&nbsp;
	<span style="color: #008000;"># If the SID isn't found, you will get nothing returned.</span>
	<span style="color: #800080;">$result</span> <span style="color: pink;">|</span> <span style="color: #008080; font-weight: bold;">Select-Object</span> <span style="color: pink;">@</span><span style="color: #000000;">&#123;</span> Name <span style="color: pink;">=</span> <span style="color: #800000;">&quot;Name&quot;</span> ; Expression <span style="color: pink;">=</span> <span style="color: #000000;">&#123;</span> <span style="color: #000080;">$_</span>.Properties.Item<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;Name&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#91;</span><span style="color: #804000;">0</span><span style="color: #000000;">&#93;</span>.split<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;<span style="color: #008080; font-weight: bold;">`n</span>&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#91;</span><span style="color: #804000;">0</span><span style="color: #000000;">&#93;</span> <span style="color: #000000;">&#125;</span> <span style="color: #000000;">&#125;</span><span style="color: pink;">,</span> `
	<span style="color: pink;">@</span><span style="color: #000000;">&#123;</span> Name <span style="color: pink;">=</span> <span style="color: #800000;">&quot;SAMAccountName&quot;</span> ; Expression <span style="color: pink;">=</span> <span style="color: #000000;">&#123;</span> <span style="color: #000080;">$_</span>.Properties.Item<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;SAMAccountName&quot;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#125;</span> <span style="color: #000000;">&#125;</span><span style="color: pink;">,</span> `
	<span style="color: pink;">@</span><span style="color: #000000;">&#123;</span> Name <span style="color: pink;">=</span> <span style="color: #800000;">&quot;SID&quot;</span> ; Expression <span style="color: pink;">=</span> <span style="color: #000000;">&#123;</span> <span style="color: #008080; font-weight: bold;">New-Object</span> System.Security.Principal.SecurityIdentifier<span style="color: #000000;">&#40;</span><span style="color: #000080;">$_</span>.Properties.Item<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;ObjectSID&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#91;</span><span style="color: #804000;">0</span><span style="color: #000000;">&#93;</span><span style="color: pink;">,</span> <span style="color: #804000;">0</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#125;</span> <span style="color: #000000;">&#125;</span><span style="color: pink;">,</span> `
	<span style="color: pink;">@</span><span style="color: #000000;">&#123;</span> Name <span style="color: pink;">=</span> <span style="color: #800000;">&quot;WhenChanged&quot;</span> ; Expression <span style="color: pink;">=</span> <span style="color: #000000;">&#123;</span> <span style="color: #000080;">$_</span>.Properties.Item<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;WhenChanged&quot;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#125;</span> <span style="color: #000000;">&#125;</span> `
	<span style="color: pink;">|</span> <span style="color: #008080; font-weight: bold;">where-Object</span> <span style="color: #000000;">&#123;</span> <span style="color: #000080;">$_</span>.SID <span style="color: #FF0000;">-ieq</span> <span style="color: #800080;">$UserSid</span>.Trim<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>As always&#8230;</p>
<p>Happy Scripting!!!! and let me know if you have questions or problems.</p>
<p>&#8211; Mark</p>
]]></content:encoded>
			<wfw:commentRss>http://vmweaver.com/index.php/2009/10/powershell-and-unknown-user-sids/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powershell &#8211; Recursive Group Membership</title>
		<link>http://vmweaver.com/index.php/2009/08/powershell-recursive-group-membership/</link>
		<comments>http://vmweaver.com/index.php/2009/08/powershell-recursive-group-membership/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 02:11:57 +0000</pubDate>
		<dc:creator>Mark A. Weaver</dc:creator>
				<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[Group Membership]]></category>

		<guid isPermaLink="false">http://vmweaver.com/?p=146</guid>
		<description><![CDATA[Well, I am back for yet another Powershell script. This is one that I found pretty useful actually. As one of the people really pushing automation in my group at work, I was tasked with getting a list of all users in the &#8220;Domain Admins&#8221; group for all domains in our Active Directory forest. One [...]]]></description>
			<content:encoded><![CDATA[<p>Well, I am back for yet another Powershell script. This is one that I found pretty useful actually.<br />
As one of the people really pushing automation in my group at work, I was tasked with getting a list of all users in the &#8220;Domain Admins&#8221; group for all domains in our Active Directory forest.</p>
<p>One of the challenges in doing this is that you may have a bunch of nested groups and we needed to dump users from all nested groups, etc.  I do realize that there are probably tools and what-not that would this for me, but what fun is that and why spend the bucks if you can script it out.  I like this approach, too, because I can force the output to be whatever I want and in whichever format is best for what I am trying to accomplish.</p>
<p>From my days in college as a computer science kinda guy, I figured we could use recursion to help walk us through all nested groups.</p>
<p>So for those of you unfamilar with this idea of recursion, I will summarize:<br />
It is basically a function that calls itself until a certain condition is met. At this point the function exits. I know all you CS types may take exception to such a simplified definition, so please google for it or hit up Wikipedia for more detailed info on recursion.</p>
<p>How can this possible help us in our quest to enumeration group memberships?  Well let&#8217;s break it down a little.</p>
<ol>
<li>I start with a group I care about. Let&#8217;s say it is &#8220;Domain Admins&#8221; for domain &#8220;office1.contoso.com&#8221;.</li>
<li>I have a function (&#8220;get-groupmembers&#8221;) that I use to enumerate the members of this group and do something with them (output, write to file, etc)</li>
<li>As I am enumerating them, I find a member that is of type &#8220;group&#8221; called something like &#8220;Corp Admins&#8221;</li>
<li>I now call my function (&#8220;get-groupmembers&#8221;) with this nested group (&#8220;Corp Admins&#8221;) to enumerate the members</li>
<li>As I am enumerating them, I find ANOTHER group called &#8220;Help Desk On-Call&#8221; inside of &#8220;Corp Admins&#8221;</li>
<li>I can now call my funciton (&#8220;get-groupmembers&#8221;) ANOTHER time and keep going until I only have users and have walked all of the nested groups</li>
</ol>
<p>I know this may sound a little weird &#8220;that I am calling myself&#8221; over and over again, but it is actually pretty efficient.</p>
<p>Let&#8217;s jump into some code now.</p>
<p>For starters, I need to have some functions that take a Fully Qualified Domain Name (for an Active Directory Domain) and convert it into an LDAP-ish format.  For example, I needed &#8220;office1.contoso.com&#8221; to be transformed into &#8220;DC=office1,DC=contoso,DC=com&#8221;.  I know this isn&#8217;t rocket-surgery, but I just threw some stuff together for it.</p>

<div class="wp_syntax"><div class="code"><pre class="powershell" style="font-family:monospace;"><span style="color: #0000FF;">function</span> Convert<span style="color: pink;">-</span>DNStoDN <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#91;</span><span style="color: #008080;">string</span><span style="color: #000000;">&#93;</span><span style="color: #800080;">$DNSName</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
   <span style="color: #008000;">#  Create an array of each item in the string separated by &quot;.&quot;</span>
   <span style="color: #800080;">$DNSArray</span> <span style="color: pink;">=</span> <span style="color: #800080;">$DNSName</span>.Split<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;.&quot;</span><span style="color: #000000;">&#41;</span>
  <span style="color: #008000;"># Let's go through our new array and do something with each item</span>
   <span style="color: #0000FF;">for</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$x</span> <span style="color: pink;">=</span> <span style="color: #804000;">0</span>; <span style="color: #800080;">$x</span> <span style="color: #FF0000;">-lt</span> <span style="color: #800080;">$DNSArray</span>.Length ; <span style="color: #800080;">$x</span><span style="color: pink;">++</span><span style="color: #000000;">&#41;</span>
      <span style="color: #000000;">&#123;</span>
        <span style="color: #008000;">#I don't want a comma after my last item, so check to see if I am on my last one and set</span>
        <span style="color: #008000;"># $Separator equal to nothing.</span>
        <span style="color: #008000;"># Remember that we need to go to Length-1 because arrays are &quot;0 based indexes&quot;</span>
         <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$x</span> <span style="color: #FF0000;">-eq</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$DNSArray</span>.Length <span style="color: pink;">-</span> <span style="color: #804000;">1</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#123;</span><span style="color: #800080;">$Separator</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;&quot;</span><span style="color: #000000;">&#125;</span><span style="color: #0000FF;">else</span><span style="color: #000000;">&#123;</span><span style="color: #800080;">$Separator</span> <span style="color: pink;">=</span><span style="color: #800000;">&quot;,&quot;</span><span style="color: #000000;">&#125;</span>
         <span style="color: #000000;">&#91;</span><span style="color: #008080;">string</span><span style="color: #000000;">&#93;</span><span style="color: #800080;">$DN</span> <span style="color: pink;">+=</span> <span style="color: #800000;">&quot;DC=&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$DNSArray</span><span style="color: #000000;">&#91;</span><span style="color: #800080;">$x</span><span style="color: #000000;">&#93;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$Separator</span>
      <span style="color: #000000;">&#125;</span>
   <span style="color: #0000FF;">return</span> <span style="color: #800080;">$DN</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>We will also need to be able to split the FQDN of the DOMAIN out from the DN of a group or user. So, I have something like &#8220;CN=Me,OU=User1,DC=office1,DC=contoso,DC=com&#8221; and want to get the FQDN of this domain.  For this example this would output &#8220;office1.contoso.com&#8221;.</p>

<div class="wp_syntax"><div class="code"><pre class="powershell" style="font-family:monospace;"><span style="color: #0000FF;">function</span> Convert<span style="color: pink;">-</span>DNtoDNS <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#91;</span><span style="color: #008080;">string</span><span style="color: #000000;">&#93;</span><span style="color: #800080;">$DN</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #800080;">$DNArray</span> <span style="color: pink;">=</span> <span style="color: #800080;">$DN</span>.Split<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;,&quot;</span><span style="color: #000000;">&#41;</span>
     <span style="color: #008000;"># Let's go through our new array and do something with each item</span>
   <span style="color: #0000FF;">for</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$x</span> <span style="color: pink;">=</span> <span style="color: #804000;">0</span>; <span style="color: #800080;">$x</span> <span style="color: #FF0000;">-lt</span> <span style="color: #800080;">$DNArray</span>.Length ; <span style="color: #800080;">$x</span><span style="color: pink;">++</span><span style="color: #000000;">&#41;</span>
      <span style="color: #000000;">&#123;</span>
        <span style="color: #008000;">#I don't want a period after my last item, so check to see if I am on my last one and set</span>
        <span style="color: #008000;"># $Separator equal to nothing.</span>
        <span style="color: #008000;"># Remember that we need to go to Length-1 because arrays are &quot;0 based indexes&quot;</span>
         <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$x</span> <span style="color: #FF0000;">-eq</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$DNArray</span>.Length <span style="color: pink;">-</span> <span style="color: #804000;">1</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#123;</span><span style="color: #800080;">$Separator</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;&quot;</span><span style="color: #000000;">&#125;</span><span style="color: #0000FF;">else</span><span style="color: #000000;">&#123;</span><span style="color: #800080;">$Separator</span> <span style="color: pink;">=</span><span style="color: #800000;">&quot;.&quot;</span><span style="color: #000000;">&#125;</span>
        <span style="color: #008000;"># Now we have to see if we look like &quot;DC=&quot;. If it does, we will</span>
        <span style="color: #008000;"># start to construct our DNS name.</span>
        <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$DNArray</span><span style="color: #000000;">&#91;</span><span style="color: #800080;">$x</span><span style="color: #000000;">&#93;</span>.Split<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;=&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#91;</span><span style="color: #804000;">0</span><span style="color: #000000;">&#93;</span> <span style="color: #FF0000;">-ilike</span> <span style="color: #800000;">&quot;DC&quot;</span><span style="color: #000000;">&#41;</span>
          <span style="color: #000000;">&#123;</span>
               <span style="color: #008000;"># Let's grab the &quot;contoso&quot; side of the &quot;DC=contoso&quot;</span>
              <span style="color: #000000;">&#91;</span><span style="color: #008080;">string</span><span style="color: #000000;">&#93;</span><span style="color: #800080;">$DNS</span> <span style="color: pink;">+=</span> <span style="color: #800080;">$DNArray</span><span style="color: #000000;">&#91;</span><span style="color: #800080;">$x</span><span style="color: #000000;">&#93;</span>.Split<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;=&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#91;</span><span style="color: #804000;">1</span><span style="color: #000000;">&#93;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$Separator</span>
           <span style="color: #000000;">&#125;</span>
      <span style="color: #000000;">&#125;</span>
   <span style="color: #0000FF;">return</span> <span style="color: #800080;">$DNS</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Now that we have those little &#8220;cameo&#8221; functions, we will move on to the more of the meat-and-potatoes of the script.<br />
The next function will be to actually enumerate a group in Active Directory without using the Quest Tools for Active Directory (if you don&#8217;t have those yet, you need to them).</p>
<p>We are actually going to use some .NET calls to get the directory objects.  My colleague <a title="Mike Hays' Blog" href="http://blog.mike-hays.net/" target="_blank">Mike Hays</a> actually did a lot of this part of the code.</p>

<div class="wp_syntax"><div class="code"><pre class="powershell" style="font-family:monospace;"><span style="color: #0000FF;">function</span> get<span style="color: pink;">-</span>groupmember<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#91;</span><span style="color: #008080;">string</span><span style="color: #000000;">&#93;</span><span style="color: #800080;">$domain</span><span style="color: pink;">,</span> <span style="color: #000000;">&#91;</span><span style="color: #008080;">string</span><span style="color: #000000;">&#93;</span><span style="color: #800080;">$groupName</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
   <span style="color: #008000;"># I have passed in the FQDN and Groupname I am interested in</span>
   <span style="color: #008000;"># I just need to convert my FQDN into an LDAP style name using my previous function</span>
   <span style="color: #800080;">$DN</span> <span style="color: pink;">=</span> convert<span style="color: pink;">-</span>DNStoDN<span style="color: #000000;">&#40;</span><span style="color: #800080;">$Domain</span><span style="color: #000000;">&#41;</span>
   <span style="color: #800080;">$domainLDAPUrl</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;LDAP://&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$DN</span>
   <span style="color: #008000;"># Setup my directory connection using .NET call</span>
   <span style="color: #800080;">$ent</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>System.DirectoryServices.DirectoryEntry<span style="color: #000000;">&#93;</span> <span style="color: #000000;">&#40;</span> <span style="color: #800080;">$domainLDAPUrl</span> <span style="color: #000000;">&#41;</span>
&nbsp;
   <span style="color: #008000;"># Define my &quot;searcher&quot; object to query the directory</span>
   <span style="color: #800080;">$srch</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>System.DirectoryServices.DirectorySearcher<span style="color: #000000;">&#93;</span> <span style="color: #000000;">&#40;</span> <span style="color: #800080;">$ent</span> <span style="color: #000000;">&#41;</span>
&nbsp;
   <span style="color: #008000;"># Setup my search criteria.. looking for all Groups with CN=GroupName</span>
   <span style="color: #800080;">$groupNameFilter</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;(&amp;(objectClass=group)(CN=&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$groupName</span> <span style="color: pink;">+</span> <span style="color: #800000;">&quot;))&quot;</span>
   <span style="color: #800080;">$srch</span>.<span style="color: #0000FF;">Filter</span> <span style="color: pink;">=</span> <span style="color: #800080;">$groupNameFilter</span>
&nbsp;
   <span style="color: #008000;"># Now go execute my query to and put the results in $coll</span>
   <span style="color: #800080;">$coll</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>System.DirectoryServices.SearchResultCollection<span style="color: #000000;">&#93;</span>      <span style="color: #800080;">$srch</span>.FindAll<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
&nbsp;
   <span style="color: #0000FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$rs</span> <span style="color: #0000FF;">in</span> <span style="color: #800080;">$coll</span><span style="color: #000000;">&#41;</span>
     <span style="color: #000000;">&#123;</span>
       <span style="color: #008000;"># Now get a collection of properties for that object</span>
       <span style="color: #800080;">$resultPropColl</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>System.DirectoryServices.ResultPropertyCollection<span style="color: #000000;">&#93;</span> <span style="color: #800080;">$rs</span>.Properties
&nbsp;
       <span style="color: #008000;"># Cycle through all group members</span>
       <span style="color: #0000FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$memberColl</span> <span style="color: #0000FF;">in</span> <span style="color: #800080;">$resultPropColl</span><span style="color: #000000;">&#91;</span><span style="color: #800000;">&quot;member&quot;</span><span style="color: #000000;">&#93;</span><span style="color: #000000;">&#41;</span>
         <span style="color: #000000;">&#123;</span>
           <span style="color: #008000;"># Build my membership array</span>
           <span style="color: #000000;">&#91;</span><span style="color: #008080;">array</span><span style="color: #000000;">&#93;</span><span style="color: #800080;">$gpMemberEntry</span> <span style="color: pink;">+=</span> <span style="color: #000000;">&#91;</span>System.DirectoryServices.DirectoryEntry<span style="color: #000000;">&#93;</span> <span style="color: #000000;">&#40;</span> <span style="color: #800000;">&quot;LDAP://&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$memberColl</span> <span style="color: #000000;">&#41;</span>
          <span style="color: #000000;">&#125;</span>
   <span style="color: #000000;">&#125;</span>
  <span style="color: #008000;"># Send back my group members.</span>
  <span style="color: #0000FF;">return</span> <span style="color: #800080;">$gpMemberEntry</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Okay.. now that we have THAT setup let&#8217;s talk about the next bits of code.<br />
This is where we will have our recursive function &#8220;Get-AllMembers&#8221;.  In it, you will a call to itself.  One of the biggest concerns is that you can end up in an unending or infinite cycle.  I don&#8217;t really do any checking in this little scripty-do-dad, so that may be something for later.</p>

<div class="wp_syntax"><div class="code"><pre class="powershell" style="font-family:monospace;"><span style="color: #0000FF;">function</span> get<span style="color: pink;">-</span>allmembers<span style="color: #000000;">&#40;</span><span style="color: #800080;">$objectName</span><span style="color: pink;">,</span> <span style="color: #800080;">$OF</span><span style="color: pink;">,</span> <span style="color: #800080;">$GN</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #008000;"># Split out my domain name  (should be FQDN) and the group name</span>
    <span style="color: #800080;">$domainName</span> <span style="color: pink;">=</span> <span style="color: #800080;">$objectname</span>.split<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;\&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#91;</span><span style="color: #804000;">0</span><span style="color: #000000;">&#93;</span>
    <span style="color: #800080;">$ObjectName</span> <span style="color: pink;">=</span> <span style="color: #800080;">$objectname</span>.split<span style="color: #000000;">&#40;</span><span style="color: #800000;">&quot;\&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#91;</span><span style="color: #804000;">1</span><span style="color: #000000;">&#93;</span>
&nbsp;
    <span style="color: #800080;">$members</span> <span style="color: pink;">=</span> get<span style="color: pink;">-</span>groupmember <span style="color: #800000;">&quot;$DomainName&quot;</span> <span style="color: #800000;">&quot;$ObjectName&quot;</span>
    <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$members</span> <span style="color: #FF0000;">-ne</span> <span style="color: #800080;">$NULL</span><span style="color: #000000;">&#41;</span>
     <span style="color: #000000;">&#123;</span>
        <span style="color: #0000FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$member</span> <span style="color: #0000FF;">in</span> <span style="color: #800080;">$members</span><span style="color: #000000;">&#41;</span>
         <span style="color: #000000;">&#123;</span>
            <span style="color: #008000;">#  Grab the domain DNS name out of the object DN</span>
            <span style="color: #800080;">$ObjDomain</span> <span style="color: pink;">=</span> convert<span style="color: pink;">-</span>DNtoDNS <span style="color: #800080;">$Member</span>.DistinguishedName
            <span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$member</span>.objectclass <span style="color: #FF0000;">-contains</span> <span style="color: #800000;">&quot;group&quot;</span><span style="color: #000000;">&#41;</span>
              <span style="color: #000000;">&#123;</span>
                 <span style="color: #008000;">#If my group member is, itself, a group We get to do some recursion</span>
                  <span style="color: #800080;">$out</span> <span style="color: pink;">=</span> <span style="color: #800080;">$objDomain</span> <span style="color: pink;">+</span> <span style="color: #800000;">&quot;\&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$member</span>.name
                  <span style="color: #008080; font-weight: bold;">Write-Host</span> <span style="color: #800080;">$out</span>
                  <span style="color: #008000;"># Call myself with the nested group name</span>
                  get<span style="color: pink;">-</span>allmembers <span style="color: pink;">-</span>ObjectName <span style="color: #800080;">$out</span> <span style="color: pink;">-</span>OF <span style="color: #800080;">$of</span> <span style="color: pink;">-</span>GN <span style="color: #800080;">$GN</span>
               <span style="color: #000000;">&#125;</span>
            <span style="color: #0000FF;">else</span>
               <span style="color: #000000;">&#123;</span>
                  <span style="color: #008000;"># If I get back a user, then see if the user is disabled or not</span>
                  <span style="color: #800080;">$userAndDomain</span> <span style="color: pink;">=</span> <span style="color: #800080;">$objDomain</span> <span style="color: pink;">+</span> <span style="color: #800000;">&quot;\&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$member</span>.name
                  <span style="color: #008000;"># The  UserAccountControl property contains several &quot;flags&quot;</span>
                  <span style="color: #008000;"># that we can interrogate.  By doing a Binary AND we are seeing if the 2nd flag is set.</span>
                  <span style="color: #000000;">&#91;</span><span style="color: #008080;">bool</span><span style="color: #000000;">&#93;</span><span style="color: #800080;">$accountIsDisabled</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span><span style="color: #008080;">int</span><span style="color: #000000;">&#93;</span><span style="color: #800080;">$member</span>.userAccountControl.ToSTring<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #FF0000;">-band</span> <span style="color: #804000;">2</span>
&nbsp;
                  <span style="color: #008000;"># Setup our output (I am choosing to construct a comma-delimited type of output</span>
                  <span style="color: #800080;">$OutText</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;'&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$GN</span> <span style="color: pink;">+</span> <span style="color: #800000;">&quot;','&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$objDomain</span> <span style="color: pink;">+</span> <span style="color: #800000;">&quot;','&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$Member</span>.Samaccountname <span style="color: pink;">+</span> <span style="color: #800000;">&quot;','&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$Member</span>.displayName <span style="color: pink;">+</span> <span style="color: #800000;">&quot;','&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$member</span>.distinguishedName <span style="color: pink;">+</span> <span style="color: #800000;">&quot;','&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$objectname</span> <span style="color: pink;">+</span> <span style="color: #800000;">&quot;','&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$accountIsDisabled</span> <span style="color: pink;">+</span> <span style="color: #800000;">&quot;'&quot;</span>
&nbsp;
                  <span style="color: #008080; font-weight: bold;">Out<span style="color: #FF0000;">-File</span></span> <span style="color: #008080; font-style: italic;">-FilePath</span> <span style="color: #800080;">$OF</span> <span style="color: #008080; font-style: italic;">-inputobject</span> <span style="color: #800080;">$Outtext</span> <span style="color: #008080; font-style: italic;">-append</span> <span style="color: #008080; font-style: italic;">-Encoding</span> <span style="color: #800000;">&quot;ASCII&quot;</span>
&nbsp;
                  <span style="color: #008080; font-weight: bold;">Write-Host</span> <span style="color: #800080;">$OutText</span>
                <span style="color: #000000;">&#125;</span>
         <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
    <span style="color: #0000FF;">else</span>
     <span style="color: #000000;">&#123;</span>
        <span style="color: #008080; font-weight: bold;">Write-Host</span> <span style="color: #800000;">&quot;No Members or no Group:&quot;</span> <span style="color: #800080;">$ObjectName</span> <span style="color: #800000;">&quot;in Domain:&quot;</span> <span style="color: #800080;">$DomainName</span> <span style="color: pink;">-</span>Foreground RED
     <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #008000;">###########################</span>
<span style="color: #008000;">## Main</span>
<span style="color: #008000;">###########################</span>
<span style="color: #800080;">$GroupName</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;Domain Admins&quot;</span>
<span style="color: #800080;">$Today</span> <span style="color: pink;">=</span> <span style="color: #008080; font-weight: bold;">Get-Date</span> <span style="color: #008080; font-style: italic;">-format</span> <span style="color: #800000;">&quot;yyyyMMddhh&quot;</span>
<span style="color: #800080;">$OutputFolder</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;C:\Temp\&quot;</span>
&nbsp;
<span style="color: #0000FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #008080; font-weight: bold;">Test-Path</span> <span style="color: #800080;">$outputFolder</span><span style="color: #000000;">&#41;</span> <span style="color: #FF0000;">-eq</span> <span style="color: #800080;">$False</span><span style="color: #000000;">&#41;</span>
 <span style="color: #000000;">&#123;</span>
    <span style="color: #008080; font-weight: bold;">New-Item</span> <span style="color: #008080; font-style: italic;">-Path</span> <span style="color: #800080;">$OutputFolder</span> <span style="color: pink;">-</span><span style="color: #008080; font-weight: bold;">Type</span> Directory <span style="color: pink;">&gt;</span> <span style="color: #800080;">$NULL</span>
  <span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #008000;"># Grab my forest info</span>
<span style="color: #800080;">$forest</span> <span style="color: pink;">=</span> <span style="color: #000000;">&#91;</span>System.DirectoryServices.ActiveDirectory.Forest<span style="color: #000000;">&#93;</span>::GetCurrentForest<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
&nbsp;
<span style="color: #008000;">#Setup my output file</span>
<span style="color: #800080;">$OutHeader</span> <span style="color: pink;">=</span> <span style="color: #800000;">&quot;'Group','UserDomain','SAMAccount','DisplayName','DN','MemberofGroup','IsDisabled'&quot;</span>
&nbsp;
<span style="color: #008000;"># Define output file name</span>
<span style="color: #800080;">$of</span> <span style="color: pink;">=</span> <span style="color: #800080;">$OutputFolder</span> <span style="color: pink;">+</span> <span style="color: #800080;">$Today</span> <span style="color: pink;">+</span><span style="color: #800000;">&quot;_&quot;</span><span style="color: pink;">+</span> <span style="color: #800080;">$GroupName</span> <span style="color: pink;">+</span> <span style="color: #800000;">&quot;-AuditReport.txt&quot;</span>
&nbsp;
<span style="color: #008080; font-weight: bold;">Out<span style="color: #FF0000;">-File</span></span> <span style="color: #008080; font-style: italic;">-FilePath</span> <span style="color: #800080;">$OF</span> <span style="color: #008080; font-style: italic;">-inputobject</span> <span style="color: #800080;">$OutHeader</span> <span style="color: #008080; font-style: italic;">-Encoding</span> <span style="color: #800000;">&quot;ASCII&quot;</span>
&nbsp;
<span style="color: #008000;"># Cycle through all the child domains in the forest root to query for Group.</span>
<span style="color: #0000FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #800080;">$domain</span> <span style="color: #0000FF;">in</span> <span style="color: #800080;">$forest</span>.Domains<span style="color: #000000;">&#41;</span>
 <span style="color: #000000;">&#123;</span>
    <span style="color: #800080;">$FullGroupName</span> <span style="color: pink;">=</span> <span style="color: #800080;">$domain</span>.name <span style="color: pink;">+</span> <span style="color: #800000;">&quot;\&quot;</span> <span style="color: pink;">+</span> <span style="color: #800080;">$GroupName</span>
    get<span style="color: pink;">-</span>allmembers <span style="color: pink;">-</span>ObjectName <span style="color: #800080;">$FullGroupName</span> <span style="color: pink;">-</span>OF <span style="color: #800080;">$of</span> <span style="color: pink;">-</span>GN <span style="color: #800080;">$FullGroupName</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Just take all of the script blocks from above and paste them into your script.  I am trying to keep these posts a bit shorter, so you may see upcoming posts broken out into parts.</p>
<p>Well, I think I am done here with this one.  Please let me know if you have questions, concerns, or comments.</p>
<p>Please keep in mind that this script will attempt to enumerate the Group in  ALL child domains in your current AD Forest.  If you have a large Forest with lots of child domains&#8230;..this could take a while.</p>
<p>I will be happy to help out with requested changes if they seem like they would be beneficial overall, but I am also a STRONG advocate of doing-it-yourself.<br />
Every bit of Powershell and scripting I have learned by grabbing it and going with it.</p>
<p>Anyway, as always&#8230;thanks for stopping by and happy scripting!!!</p>
<p>&#8211; Mark</p>
]]></content:encoded>
			<wfw:commentRss>http://vmweaver.com/index.php/2009/08/powershell-recursive-group-membership/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
	</channel>
</rss>

