<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4018181297398983593</id><updated>2012-01-27T17:54:56.628-05:00</updated><title type='text'>The Free Loder</title><subtitle type='html'>Sometimes you get more than you pay for.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-3425010639379815124</id><published>2012-01-27T17:54:00.001-05:00</published><updated>2012-01-27T17:54:56.783-05:00</updated><title type='text'>PowerShell DirSync Sample</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Continuing with the &lt;a href="http://dloder.blogspot.com/2012/01/fim-sql-server-ma-or-powershell-for-sql.html" target="_blank"&gt;PoC&lt;/a&gt; setup for the SQL Server MA, I want the flexibility to load the SQL data from either the authoritative text-file, or from a separate AD environment.&amp;#160; This will provide me the ability to test the MA in Dev and QA environments that are not as active as Production.&amp;#160; To do that, I want DirSync data from a source domain to use to populate the table.&lt;/p&gt;  &lt;p&gt;Microsoft’s &lt;a href="http://msdn.microsoft.com/en-us/library/ms677626(v=vs.85).aspx" target="_blank"&gt;DirSync documentation&lt;/a&gt; has a &lt;a href="http://msdn.microsoft.com/en-us/library/ms676896(v=vs.85).aspx" target="_blank"&gt;sample in C++&lt;/a&gt;.&amp;#160; 400+ lines of code!&amp;#160; And a very low percentage of the code volume is directly related to the search.&amp;#160; Yuck.&amp;#160; However, with some more Googling one can find that &lt;a href="http://bsonposh.com" target="_blank"&gt;Brandon&lt;/a&gt; has a &lt;a href="http://msdn.microsoft.com/en-us/library/4b2t08s1.aspx" target="_blank"&gt;System.DirectoryServices.Protocols&lt;/a&gt; &lt;a href="http://bsonposh.com/archives/325" target="_blank"&gt;sample for PowerShell&lt;/a&gt; and the &lt;a href="http://blogs.technet.com/b/isrpfeplat/" target="_blank"&gt;Israel Platforms PFE Team&lt;/a&gt; has a &lt;a href="http://blogs.technet.com/b/isrpfeplat/archive/2010/09/20/using-the-dirsync-control.aspx" target="_blank"&gt;DirSync sample for C#&lt;/a&gt;.&amp;#160; Finally SANS had a nice overview on handling the &lt;a href="http://www.sans.org/windows-security/2010/02/11/powershell-byte-array-hex-convert" target="_blank"&gt;Byte&lt;/a&gt; in PowerShell, which the DirSync cookie uses.&lt;/p&gt;  &lt;p&gt;All the ingredients are assembled.&amp;#160; Combine and bake at 400° for 20 minutes and you get:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;[Reflection.Assembly]::LoadWithPartialName(&amp;quot;System.DirectoryServices.Protocols&amp;quot;) | Out-Null&lt;/p&gt;    &lt;p&gt;If (Test-Path .\cookie.bin –PathType leaf) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [byte[]] $Cookie = Get-Content -Encoding byte –Path .\cookie.bin       &lt;br /&gt;} else {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $Cookie = $null       &lt;br /&gt;}&lt;/p&gt;    &lt;p&gt;$RootDSE = [ADSI]&amp;quot;LDAP://RootDSE&amp;quot;      &lt;br /&gt;$LDAPConnection = New-Object System.DirectoryServices.Protocols.LDAPConnection($RootDSE.dnsHostName)       &lt;br /&gt;$Request = New-Object System.DirectoryServices.Protocols.SearchRequest($RootDSE.defaultNamingContext, &amp;quot;(objectclass=*)&amp;quot;, &amp;quot;Subtree&amp;quot;, $null)       &lt;br /&gt;$DirSyncRC = New-Object System.DirectoryServices.Protocols.DirSyncRequestControl($Cookie, [System.DirectoryServices.Protocols.DirectorySynchronizationOptions]::IncrementalValues, [System.Int32]::MaxValue)       &lt;br /&gt;$Request.Controls.Add($DirSyncRC) | Out-Null       &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;$Response = $LDAPConnection.SendRequest($Request)&lt;/p&gt;    &lt;p&gt;$MoreData = $true&lt;/p&gt;    &lt;p&gt;while ($MoreData) {&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; $Response.Entries | ForEach-Object {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; write-host $_.distinguishedName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; ForEach ($Control in $Response.Controls) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If ($Control.GetType().Name -eq &amp;quot;DirSyncResponseControl&amp;quot;) {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $Cookie = $Control.Cookie       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $MoreData = $Control.MoreData       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $DirSyncRC.Cookie = $Cookie       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $Response = $LDAPConnection.SendRequest($Request)       &lt;br /&gt;}&lt;/p&gt;    &lt;p&gt;Set-Content -Value $Cookie -Encoding byte –Path .\cookie.bin&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;There you have it.&amp;#160; PowerShell DirSync in 27 lines of code!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-3425010639379815124?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/3425010639379815124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2012/01/powershell-dirsync-sample.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/3425010639379815124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/3425010639379815124'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2012/01/powershell-dirsync-sample.html' title='PowerShell DirSync Sample'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-8559282405115454697</id><published>2012-01-26T18:15:00.001-05:00</published><updated>2012-01-26T18:15:49.413-05:00</updated><title type='text'>FIM SQL Server MA (or PowerShell for SQL Table-Valued Parameters)</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Working on a Proof of Concept for FIM has been a refreshing visit to some of my old haunting grounds.&amp;#160; Long before AD existed (or even NT) my first real job was for a database consulting company.&amp;#160; It no longer exists, but its legacy can be found at &lt;a href="http://www.noetix.com"&gt;www.noetix.com&lt;/a&gt;; and some of the people I knew back then are still there.&lt;/p&gt;  &lt;p&gt;The FIM PoC begins with a text-based authoritative data source with no natural key.&amp;#160; The FIM text-based MAs require a key, so I could not use those MAs and still support user account renames.&amp;#160; So I decided to import the data into a SQL Server table with an Identity column and use the SQL Server MA.&amp;#160; This decision has brought me a fair amount of SQL work that I have not done for years.&lt;/p&gt;  &lt;p&gt;The first fun task was generating the delta view.&amp;#160; I opted to follow the &lt;a href="http://technet.microsoft.com/en-us/library/cc708665(WS.10).aspx" target="_blank"&gt;trigger approach&lt;/a&gt;, but wanted it to act more like Active Directory &lt;a href="http://technet.microsoft.com/en-us/query/ms677626" target="_blank"&gt;DirSync&lt;/a&gt; where one can retrieve the deltas based on a cookie being held and presented, but the older deltas still exist.&amp;#160; So I created a timestamp-based view of the delta table at MA runtime specific to my particular FIM instance.&amp;#160; The view will present all the deltas from the last provided timestamp plus a 5 minute overlap to handle the Kerberos-allowed time skew.&amp;#160; This approach also allows a parallel FIM instance to receive its own deltas without impact to each other by simply creating a differently-name view specific to that instance.&lt;/p&gt;  &lt;p&gt;Then I started working on multi-valued attributes.&amp;#160; Per standard normalization rules for SQL, one ends up with a second table linking the primary object table Identity column to the multivalued attribute name and a single value.&amp;#160; To add a second value to the attribute the table needs another row with the same Identity foreign key, same attribute name and the second single value.&lt;/p&gt;  &lt;p&gt;FIM’s granularity for SQL deltas is limited to indicating the object as a whole has changed.&amp;#160; It has no granularity for indicating attribute deltas like DirSync can, so any insert or delete into the multi-valued table triggers a delta of the whole object.&amp;#160; This matches up well with the text-based source as all attributes (single and multi) are encoded into one row in the file.&amp;#160; There is no easy way to know what has changed in the source data when it is received, so I simply need to make sure the SQL data exactly matches the newly received row from the authoritative data source.&amp;#160; Put into practice this means all of the single-valued attributes must be rewritten, all the existing multi-valued attributes must be deleted and the new multi-valued attributes must be inserted.&lt;/p&gt;  &lt;p&gt;I was brought up with the stored-procedure methodology for interacting with any database, so my goal was to develop a stored procedure that I could call from PowerShell to take care of the attribute updates.&amp;#160; I split this into two stored procedures: one for the single-valued attributes, and one for the multi-valued attributes that I could iterate over for each multi-valued attribute in the source feed.&amp;#160; The multi-valued stored procedure causes difficulty in the handling of the one delete and “n” number of inserts.&amp;#160; You can’t put that into one stored procedure and support an unknown number of multi-value attribute inserts.&amp;#160; So either it has to be broken into two stored procedures (execute the delete stored procedure followed by n executions of the insert stored procedure), or find a way to get the single stored procedure to recognize an array for the inserts.&lt;/p&gt;  &lt;p&gt;The multiple stored procedures didn’t sound elegant, and I haven’t worked on SQL Server for a while, so I spent a little time searching and fairly quickly found &lt;a href="http://msdn.microsoft.com/en-us/library/bb510489.aspx" target="_blank"&gt;Table-Valued Parameters&lt;/a&gt; and a great &lt;a href="http://www.sommarskog.se/arrays-in-sql-2008.html" target="_blank"&gt;blog entry from Erland Sommarskog&lt;/a&gt;, SQL Server MVP.&amp;#160; One of the nice benefits of FIM not being cross-platform is its requirement of SQL 2008 and the ability for me to now use other new SQL 2008 features.&lt;/p&gt;  &lt;p&gt;Begin by creating a User Defined Table Type:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;CREATE TYPE [dbo].[multivalue_list] AS TABLE(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [attributevalue] [nvarchar](1024) NOT NULL       &lt;br /&gt;)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Create a stored procedure that uses that type[1]:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;CREATE PROCEDURE      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [dbo].[import_people_multivaluesdata]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; @p_cn varchar(64)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; , @p_attributename varchar(64)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; , @p_multivalue_list multivalue_list READONLY       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;AS       &lt;br /&gt;BEGIN       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -- SET NOCOUNT ON added to prevent extra result sets from       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -- interfering with SELECT statements.       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; SET NOCOUNT ON;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; -- Insert statements for procedure here      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DELETE FROM       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; people_multivalues       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; WHERE       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AttributeName = @p_attributename       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; and ObjectID IN (       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SELECT       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ObjectID       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FROM       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objects       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; WHERE       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; cn = @p_cn       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; INSERT INTO       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; people_multivalues       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; SELECT       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; o.ObjectID       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; , @p_attributename       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; , mvl.attributevalue       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; FROM       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objects o       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; , @p_multivalue_list mvl       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; WHERE       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; o.cn = @p_cn       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; SELECT       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; COUNT(m.objectid) as row_count       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; FROM       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objects o       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; JOIN       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; people_multivalues m       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; o.ObjectID = m.ObjectID       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; WHERE       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; o.cn = @p_cn       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; and m.AttributeName = @p_attributename       &lt;br /&gt;END&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;There are two important things to note in this procedure.&amp;#160; The first is the use of the READONLY directive on the input table parameter.&amp;#160; The second is the FROM clause for the INSERT statement having no JOIN clause.&amp;#160; The incoming table only has the values for multi-valued attribute, so there is nothing on which to join.&amp;#160; This results in the Cartesian product between the two, resulting in one row being inserted for each row in the input table parameter – exactly the goal!&lt;/p&gt;  &lt;p&gt;Calling this procedure from T-SQL is fairly straight forward:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;declare @mylist multivalue_list      &lt;br /&gt;insert @mylist(attributevalue) values ('val1'), ('val2')       &lt;br /&gt;exec import_people_multivaluesdata @p_cn = 'cn1', @p_attributename='multiattr', @p_multivalue_list = @mylist&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Calling this from PowerShell requires a bit more setup.&amp;#160; Mr. Sommarskog’s sample for ADO.Net (really C# SQLClient) can be translated into PowerShell as follows (switching from int to VarChar, and using our above stored procedure):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;$products = &amp;quot;A&amp;quot;, &amp;quot;B&amp;quot;, &amp;quot;C&amp;quot;&lt;/p&gt;    &lt;p&gt;$product_list = New-Object 'System.Collections.Generic.List[Microsoft.SqlServer.Server.SqlDataRecord]'&lt;/p&gt;    &lt;p&gt;$tvp_definition = New-Object Microsoft.SqlServer.Server.SqlMetaData (&amp;quot;attributevalue&amp;quot;, &amp;quot;VarChar&amp;quot;, 1024)&lt;/p&gt;    &lt;p&gt;ForEach ($product in $products) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $rec = new-object Microsoft.SqlServer.Server.SqlDataRecord($tvp_definition)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $rec.SetSQLString(0, $product)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $product_list.Add($rec)       &lt;br /&gt;}&lt;/p&gt;    &lt;p&gt;$cmd.CommandType = CommandType.StoredProcedure      &lt;br /&gt;$cmd.CommandText = &amp;quot;dbo.import_people_multivaluesdata&amp;quot;&lt;/p&gt;    &lt;p&gt;$cmd.Parameters.AddWithValue(&amp;quot;@p_cn&amp;quot;, &amp;quot;cn1&amp;quot;)&amp;#160; | Out-Null      &lt;br /&gt;$cmd.Parameters.AddWithValue(&amp;quot;@p_attributename&amp;quot;, &amp;quot;multiattr&amp;quot;)&amp;#160; | Out-Null       &lt;br /&gt;$cmd.Parameters.Add(&amp;quot;@p_multivalue_list&amp;quot;, [System.Data.SqlDbType]::structured) | Out-Null       &lt;br /&gt;$cmd.Parameters[&amp;quot;@p_multivalue_list&amp;quot;].TypeName = &amp;quot;multivalue_list&amp;quot;       &lt;br /&gt;$cmd.Parameters[&amp;quot;@p_multivalue_list&amp;quot;].Value = $product_list&lt;/p&gt;    &lt;p&gt;$ReturnRowCount = $cmd.ExecuteScalar()&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;And there you have it.&amp;#160; With one call to a stored procedure, all current multi-value attribute entries for a specific attribute will be deleted and completely replaced with the new list of values and is scalable to any number of entries in the list.&lt;/p&gt;  &lt;p&gt;[1] You can tell the difference between my own SQL code for the procedure and the GUI-generated code for the UDT.&amp;#160; This is how I was taught to write SQL code.&amp;#160; I see very few other samples that follow the same layout.&amp;#160; However, this is the only layout that gives you complete control of the ordering of table names or column names where you don’t have to worry about forgetting to have correct punctuation.&amp;#160; All the column names in the select statement are nicely lined up, and you can easily verify all subsequent columns begin with a comma.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-8559282405115454697?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/8559282405115454697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2012/01/fim-sql-server-ma-or-powershell-for-sql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/8559282405115454697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/8559282405115454697'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2012/01/fim-sql-server-ma-or-powershell-for-sql.html' title='FIM SQL Server MA (or PowerShell for SQL Table-Valued Parameters)'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-7009330344184811540</id><published>2011-12-16T20:27:00.001-05:00</published><updated>2011-12-16T20:27:23.123-05:00</updated><title type='text'>Administrator Locked Out of FIM Portal</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I’ve been coming up to speed on MIIS/ILM/FIM lately reading the documentation and walking through the evaluation guides in a small lab forest.&amp;#160; I was walking through the FIM 2010 procedure &lt;a href="http://technet.microsoft.com/en-us/library/ee534908(WS.10).aspx" target="_blank"&gt;Introduction to Publishing To Active Directory from Two Authoritative Data Sources&lt;/a&gt; using FIM 2010 R2.&amp;#160; I had completed the main sync of HR into FIM and back to the Metaverse.&amp;#160; When I switched back to the portal to check on the results I was greeted with an error screen.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-bLyZSbuWfCU/Tuvv51GweOI/AAAAAAAAADE/r9bwUKTlzho/s1600-h/FIMPortalFailure5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Unable to process your request. The requester of this operation is invalid. The requestor&amp;#39;s identity was not found." border="0" alt="Unable to process your request. The requester of this operation is invalid. The requestor&amp;#39;s identity was not found." src="http://lh6.ggpht.com/-7d8Q0sf5yPw/Tuvv7WhlMBI/AAAAAAAAADM/8kmNi5qTdv8/FIMPortalFailure_thumb3.png?imgmax=800" width="591" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I’m not sure what caused the problem.&amp;#160; I didn’t have a backup to roll back to, and I didn’t want to give up and just reinstall.&amp;#160; From experience I know that you seldom learn more about a program than when it’s broken.&amp;#160; So I dove in to the problem.&lt;/p&gt;  &lt;p&gt;I know FIM is mostly a large SQL application.&amp;#160; I understand the sync database pretty well.&amp;#160; It has two main tables.&amp;#160; The mms_metaverse table stores each object in a row and each attribute in a column.&amp;#160; This allows for indexing the attributes for fast joins and searching the metaverse.&amp;#160; The mms_connectorspace is more opaque.&amp;#160; The data from the connector space is stored as XML blobs in the hologram.&lt;/p&gt;  &lt;p&gt;My first glance at the FIMService database showed me it didn’t look anything like the sync database.&lt;/p&gt;  &lt;p&gt;To get started I profiled my attempt to open the portal.&amp;#160; You see a call retrieve the default page from SharePoint, then you see the call to figure out who I am.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-EDvcbwc3IbI/Tuvv7lkciyI/AAAAAAAAADU/vz1OJQZWH9s/s1600-h/FIMSQLProfiler5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="FIMSQLProfiler" border="0" alt="FIMSQLProfiler" src="http://lh3.ggpht.com/-suxwk92Q1KI/Tuvv8a_W92I/AAAAAAAAADc/8eTlhlwqoBk/FIMSQLProfiler_thumb3.png?imgmax=800" width="644" height="305" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This is a stored procedure call to GetUserFromSecurityIdentifier where the parameter appears to be my SID in binary form.&lt;/p&gt;  &lt;p&gt;Since SQL Server Profiler doesn’t show the return value of the query, I ran that query myself.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-fkc3OG1gUnQ/Tuvv8mj82eI/AAAAAAAAADk/A8gF9VMGbbU/s1600-h/FIMQueryFailure5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="exec [FIMService].[fim].GetUserFromSecurityIdentifier @SecurityID=0x0010500000000000515000000467CC6805E2AB86508CBF18EF4010000,@UserID=@p2 output" border="0" alt="exec [FIMService].[fim].GetUserFromSecurityIdentifier @SecurityID=0x0010500000000000515000000467CC6805E2AB86508CBF18EF4010000,@UserID=@p2 output" src="http://lh5.ggpht.com/-z_fgeqHzMgc/Tuvv9GZpMVI/AAAAAAAAADs/88sedNVfMKM/FIMQueryFailure_thumb3.png?imgmax=800" width="644" height="321" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Sure enough, no rows returned.&amp;#160; Looking at the stored procedure, it references the tables UserSecurityIdentifiers and Objects.&amp;#160; UserSecurityIdentifiers was completely empty.&amp;#160; UserSecurityIdentifiers is a simple table with only two columns: UserObjectKey and SecurityIdentifier.&lt;/p&gt;  &lt;p&gt;There’s also a stored procedure called GetUserFromName.&amp;#160; When I ran that, it returned my name, so I was pretty sure I was just missing the row that tied my AD SID to the admin user in FIM.&lt;/p&gt;  &lt;p&gt;To find my admin user in FIM I ran a query against the Objects table to find the FIM builtin administrator account '7FB2B853-24F0-4498-9534-4E10589723C4'&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-WaS_MHDW96k/Tuvv9oi1mKI/AAAAAAAAAD0/Ye7pNKBhQFo/s1600-h/FIMFindAdminObjectKey5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="select * from [FIMService].[fim].[Objects] where objectid=&amp;#39;7FB2B853-24F0-4498-9534-4E10589723C4&amp;#39;" border="0" alt="select * from [FIMService].[fim].[Objects] where objectid=&amp;#39;7FB2B853-24F0-4498-9534-4E10589723C4&amp;#39;" src="http://lh6.ggpht.com/-bkvTX9wWyD4/Tuvv91ujRKI/AAAAAAAAAD4/8Ad_i03Cb98/FIMFindAdminObjectKey_thumb3.png?imgmax=800" width="644" height="321" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;For my instance it returned a value of 2340.&lt;/p&gt;  &lt;p&gt;I issued one more query to insert my SID into the UserSecurityIdentifiers table.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-sqReD9FBHiM/Tuvv-HgFfbI/AAAAAAAAAEA/T6sXouTNjmo/s1600-h/FIMAddSID5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="insert into [FIMService].[fim].UserSecurityIdentifiers values (2340, 0x010500000000000515000000467CC6805E2AB86508CBF18EF4010000)" border="0" alt="insert into [FIMService].[fim].UserSecurityIdentifiers values (2340, 0x010500000000000515000000467CC6805E2AB86508CBF18EF4010000)" src="http://lh6.ggpht.com/-rsnTQdJZ7L4/Tuvv-iUwODI/AAAAAAAAAEI/4_Qce_sM12I/FIMAddSID_thumb3.png?imgmax=800" width="644" height="321" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The value successfully added.&amp;#160; I opened the portal and was treated to the normal administrative view!&lt;/p&gt;  &lt;p&gt;I still don’t know what I changed to cause the SID to be deleted, but now at least I know how to get back in without a backup.&amp;#160; Perhaps some more testing in the future will reveal a repeatable pattern that causes the lockout.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-7009330344184811540?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/7009330344184811540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2011/12/administrator-locked-out-of-fim-portal.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/7009330344184811540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/7009330344184811540'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2011/12/administrator-locked-out-of-fim-portal.html' title='Administrator Locked Out of FIM Portal'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/-7d8Q0sf5yPw/Tuvv7WhlMBI/AAAAAAAAADM/8kmNi5qTdv8/s72-c/FIMPortalFailure_thumb3.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-8373660286784019898</id><published>2011-07-18T18:06:00.000-04:00</published><updated>2011-07-18T18:06:13.676-04:00</updated><title type='text'>Access Denied when backing up WINS on Windows Server 2008</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;As part of switching our services over to Windows Server 2008, we began migrating WINS and our management scripts for WINS.&amp;#160; Our existing Windows Server 2003 based backup script did not work.&amp;#160; It was returning an access denied error.&lt;/p&gt;  &lt;p&gt;Firing up &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx" target="_blank"&gt;Process Monitor&lt;/a&gt; produced this report.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-KyZ22COweso/TiCMPyiRXuI/AAAAAAAAAC0/nF6Hw1f9JFE/s1600-h/WINS_ProcMon5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="WINS_ProcMon" border="0" alt="WINS_ProcMon" src="http://lh3.ggpht.com/-fEsyB-WDq1I/TiCMQF5ernI/AAAAAAAAAC4/vMV4Azdown8/WINS_ProcMon_thumb3.png?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I couldn’t image how a windows service didn’t have permission to write to the filesystem.&lt;/p&gt;  &lt;p&gt;Looking at the properties of the Process Monitor event shows this detail.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-yzelhzJtUTE/TiCMQmEEoWI/AAAAAAAAAC8/KEq-QCSGOCk/s1600-h/WINS_ProcMonDetails4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="WINS_ProcMonDetails" border="0" alt="WINS_ProcMonDetails" src="http://lh5.ggpht.com/-LigsDFDYgHk/TiCMXb4nY4I/AAAAAAAAADA/xLgDC67Mams/WINS_ProcMonDetails_thumb2.png?imgmax=800" width="214" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The user wasn’t NT Authority\System like I had expected.&amp;#160; Instead it was NT Authority\Local Service.&amp;#160; A search for NT Authority\Local Service and WINS produced &lt;a href="http://support.microsoft.com/KB/943514" target="_blank"&gt;KB Article 943514&lt;/a&gt;.&amp;#160; The article only references moving the database from its default location, but it also applies to backing up the database to another folder.&amp;#160; The access denied error is resolved by issuing a command like&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;icacls d:\backupWINS /grant &amp;quot;NT SERVICE\WINS:(OI)(CI)F&amp;quot;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Obviously this grants the WINS service full control of the d:\backupWINS folder so that it now has permissions to create its backup files.&amp;#160; With that in place, no more errors were encountered.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-8373660286784019898?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/8373660286784019898/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2011/07/access-denied-when-backing-up-wins-on.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/8373660286784019898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/8373660286784019898'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2011/07/access-denied-when-backing-up-wins-on.html' title='Access Denied when backing up WINS on Windows Server 2008'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-fEsyB-WDq1I/TiCMQF5ernI/AAAAAAAAAC4/vMV4Azdown8/s72-c/WINS_ProcMon_thumb3.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-5723429682730786570</id><published>2011-03-21T21:39:00.001-04:00</published><updated>2011-07-15T14:53:28.370-04:00</updated><title type='text'>PowerShell example for LdapSessionOptions.VerifyServerCertificate</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I’ve started switching most of my management scripts over to PowerShell.&amp;#160; I previously had written a small C# command-line tool that would display the certificate expiration date of a Domain Controller’s LDAPS certificate.&amp;#160; This utility was based on &lt;a href="http://www.joekaplan.net/Example1ForSDSPSSLCertificates.aspx" target="_blank"&gt;Joe Kaplan’s sample&lt;/a&gt;.&amp;#160; As this utility was called as part of a much larger and more complex VBScript it only made sense to incorporate this functionality directly into PowerShell as well.&amp;#160; However, figuring out how to get PowerShell to deal with the VerifyServerCertificateCallback object was a more complex an undertaking than I had anticipated, and there were several times I almost gave up and kept the certificate date check as an external utility.&amp;#160; However, I did eventually figure it out and thought I’d share since there are no specific examples anywhere and few examples about PowerShell and callbacks in general.&lt;/p&gt;  &lt;p&gt;Within the .NET Framework, &lt;a href="http://msdn.microsoft.com/en-us/library/system.directoryservices.protocols.aspx" target="_blank"&gt;System.DirectoryServices.Protocols&lt;/a&gt; provides comparatively raw access to the LDAP APIs.&amp;#160; In Joe’s example, the &lt;a href="http://msdn.microsoft.com/en-us/library/system.directoryservices.protocols.ldapsessionoptions.verifyservercertificate.aspx" target="_blank"&gt;VerifyServerCertificate&lt;/a&gt; property is assigned to a new &lt;a href="http://msdn.microsoft.com/en-us/library/system.directoryservices.protocols.verifyservercertificatecallback.aspx" target="_blank"&gt;VerifyServerCertificateCallback&lt;/a&gt; object, which itself is a function that returns either True or False based on whatever logic one wants to employ.&lt;/p&gt;  &lt;p&gt;Most of the examples I found centered on web-server SSL certificates and ServerCertificateValidationCallback and were based on either C# which has no issues with callbacks, like Joe’s, or PowerShell v1 which had to do lots of unnatural things to use the callback.&lt;/p&gt;  &lt;p&gt;It turns out there are two important items to know about callbacks and PowerShell v2.&amp;#160; First, callbacks are implemented as a scriptblock.&amp;#160; Second, access to the callback parameters are provided via the args array.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;Add-Type -AssemblyName System.DirectoryServices.Protocols        &lt;br /&gt;$LDAPId = New-Object System.DirectoryServices.Protocols.LdapDirectoryIdentifier(($DC + &amp;quot;:636&amp;quot;), $true, $false)         &lt;br /&gt;$LDAPConnection = New-Object System.DirectoryServices.Protocols.LdapConnection($LDAPId)         &lt;br /&gt;$LDAPConnection.Credential = New-Object System.Net.NetworkCredential(&amp;quot;&amp;quot;, &amp;quot;&amp;quot;)         &lt;br /&gt;$LDAPConnection.AuthType = [system.directoryservices.protocols.authtype]::anonymous         &lt;br /&gt;$LDAPConnection.SessionOptions.SecureSocketLayer = $true         &lt;br /&gt;$LDAPConnection.SessionOptions.VerifyServerCertificate = {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $MyCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $args[1]         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $DCCertDate = $MyCert.NotAfter         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $true         &lt;br /&gt;}         &lt;br /&gt;Try {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $LDAPConnection.Bind()         &lt;br /&gt;} Catch {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $DCCertDate = &amp;quot;No Certificate Found&amp;quot;         &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;During execution, when the Bind method is called, the scriptblock attached to the VerifyServerCertificate property is called.&amp;#160; The LdapConnection parameter for the VerifyServerCertificateCallback delegate is contained in args[0] and the X509Certificate in args[1].&amp;#160; In this particular example I use the callback certificate to create a new certificate object, store the expiration date and return true, which allows the connection to succeed.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-5723429682730786570?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/5723429682730786570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2011/03/powershell-example-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/5723429682730786570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/5723429682730786570'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2011/03/powershell-example-for.html' title='PowerShell example for LdapSessionOptions.VerifyServerCertificate'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-2644410930286059360</id><published>2010-05-25T21:47:00.001-04:00</published><updated>2010-05-25T21:47:13.493-04:00</updated><title type='text'>Execute PowerShell Scripts with a Restricted Execution Policy</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;By default, PowerShell will default to an execution policy of &lt;a href="http://msdn.microsoft.com/en-us/library/dd347641.aspx" target="_blank"&gt;Restricted&lt;/a&gt;.&amp;#160; Hopefully this is not a surprise to anyone.&amp;#160; However, it is possible to execute scripts under this policy.&amp;#160; Simply start the shell using the ExecutionPolicy parameter.&lt;/p&gt;  &lt;p&gt;For example, in our server loads, we need to prompt for an administrative password during the post-install process.&amp;#160; Previously, in W2K3, we were able to use the &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2005/02/04/how-can-i-mask-passwords-using-an-inputbox.aspx" target="_blank"&gt;ScriptPW object&lt;/a&gt; to mask the input.&amp;#160; The object no longer exists in W2K8, so a different solution was needed.&amp;#160; Powershell provides the &lt;a href="http://technet.microsoft.com/en-us/library/dd347685.aspx" target="_blank"&gt;Read-Host&lt;/a&gt; cmdlet, which includes the AsSecureString parameter.&amp;#160; Using that cmdlet, I created a simple script that would prompt for the password.&lt;/p&gt;  &lt;p&gt;I then needed to run the script automatically, but didn’t want to change the default execution policy.&amp;#160; To solve this, one can specify a one-time execution policy when starting the shell.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;powershell -ExecutionPolicy RemoteSigned –File c:\postinstall\password.ps1&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-2644410930286059360?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/2644410930286059360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2010/05/execute-powershell-scripts-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/2644410930286059360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/2644410930286059360'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2010/05/execute-powershell-scripts-with.html' title='Execute PowerShell Scripts with a Restricted Execution Policy'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-6610052300547377626</id><published>2010-04-12T20:53:00.001-04:00</published><updated>2010-04-13T10:00:10.987-04:00</updated><title type='text'>Happy 10th PromoDay &lt;widgets&gt;.com</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;My forest[1] celebrated the ten-year anniversary of the initial promotion today.&amp;#160; We had upgraded from an NT4 multi-master configuration, so this was a new promotion to become the empty root.&amp;#160; The account domains were slowly upgraded over the next year.&amp;#160; Technically, the domain services as a whole are more than 10 years old, but the official NT4 dates are lost to the sands of time.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;c:\&amp;gt;adfind -config -f name=&amp;quot;Enterprise Configuration&amp;quot; whencreated -alldc &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;AdFind V01.40.00cpp Joe Richards (joe@joeware.net) February 2009 &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;Using server: xxxx.xxxx.com:389        &lt;br /&gt;Directory: Windows Server 2003         &lt;br /&gt;Base DN: CN=Configuration,DC=xxxx,DC=com &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;dn:CN=Enterprise Configuration,CN=Partitions,CN=Configuration,DC=xxxx,DC=com        &lt;br /&gt;&amp;gt;whenCreated: 2000/04/12-19:25:22 Eastern Daylight Time &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;1 Objects returned&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We held a party for it today, and even got a “PromoDay” cake.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_Sz8XUKMj3Ec/S8O_xo5N11I/AAAAAAAAACQ/FeMQi-TG9h0/s1600-h/cake_edited%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="cake_edited" border="0" alt="cake_edited" src="http://lh4.ggpht.com/_Sz8XUKMj3Ec/S8PAR1qt_0I/AAAAAAAAACU/FCnZXufza1g/cake_edited_thumb%5B3%5D.jpg?imgmax=800" width="644" height="431" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;[1] Not technically “my forest”.&amp;#160; It does belong to the widget company for which I work, and I didn’t even work for them 10 years ago, and had nothing to do with its creation.&amp;#160; &lt;a href="http://www.joeware.net/"&gt;joe&lt;/a&gt; was responsible for most of it [2].&amp;#160; These days there are 5 EAs with operational responsibility, and me with engineering responsibility who can likely continue to call it “ours”.&lt;/p&gt;  &lt;p&gt;[2] There are a lot of good stories about the early days of our AD.&amp;#160; This event brought out a few of them from ensuring joe didn’t promote the forest as joe.com to the buddy builds that were delivered almost daily as we pushed the scalability limits of Windows 2000 beyond what Microsoft had yet seen, but they’re joe’s to tell, not mine.&amp;#160; &lt;a href="http://blog.joeware.net/2010/04/12/2042/"&gt;Go read about them if you want&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-6610052300547377626?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/6610052300547377626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2010/04/happy-10th-promoday.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/6610052300547377626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/6610052300547377626'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2010/04/happy-10th-promoday.html' title='Happy 10th PromoDay &amp;lt;widgets&amp;gt;.com'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_Sz8XUKMj3Ec/S8PAR1qt_0I/AAAAAAAAACU/FCnZXufza1g/s72-c/cake_edited_thumb%5B3%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-4316069565016878253</id><published>2010-01-19T21:03:00.001-05:00</published><updated>2010-01-19T21:03:20.738-05:00</updated><title type='text'>User Account Control (UAC) and NSUpdate</title><content type='html'>&lt;p&gt;At work, I run my Vista SP2 system as a standard user with UAC turned on.&amp;#160; For the most part, UAC doesn’t cause me any problems in my day-to-day duties, except for one item.&amp;#160; Our DNS infrastructure runs on a BIND variant.&amp;#160; As such, nsupdate.exe is a common command-line support tool.&amp;#160; Similar to most other remote service management tools, the tool has no local security requirements.&amp;#160; However, attempting to run nsupdate on Vista creates an elevation prompt.&amp;#160; Using Windows Explorer, one can verify the executable is marked with the UAC shield.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_Sz8XUKMj3Ec/S1ZkZF6vhTI/AAAAAAAAACE/ZwF6lTpq164/s1600-h/bindsoftware%5B5%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="bindsoftware" border="0" alt="bindsoftware" src="http://lh6.ggpht.com/_Sz8XUKMj3Ec/S1ZkZ5J0siI/AAAAAAAAACI/_jyqEUDfLj4/bindsoftware_thumb%5B3%5D.png?imgmax=800" width="244" height="165" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;However, only nsupdate.exe is marked – none of the other BIND tools are marked.&amp;#160; Additionally, I found that renaming the file to something like nsupdat2.exe caused UAC to no longer prompt for elevation.&lt;/p&gt;  &lt;p&gt;It turns out, there’s logic in UAC for elevating based on filename, regardless of local security requirements.&amp;#160; This allows update installers to be elevated appropriately.&amp;#160; However, nsupdate.exe is an innocent victim of a flawed heuristic detection pattern, like a false-positive from an AV signature.&lt;/p&gt;  &lt;p&gt;To prevent UAC from forcing elevation of a process that doesn’t require it, this automatic prompting due to Installer Detection, can be turned off.&amp;#160; &lt;a title="http://technet.microsoft.com/en-us/library/cc709628(WS.10).aspx" href="http://technet.microsoft.com/en-us/library/cc709628(WS.10).aspx"&gt;http://technet.microsoft.com/en-us/library/cc709628(WS.10).aspx&lt;/a&gt; provides an overview of the feature and its possible configurations.&amp;#160; In local security policy, navigate to Local Policies, Security Options and set User Account Control: Detect application installations and prompt for elevation to Disabled.&amp;#160; When this policy is enabled, which is the default, any filename which contains “update” will trigger elevation.&amp;#160; When disabled, this detection is turned off, and attempting to use nsupdate.exe no longer causes an elevation prompt.&amp;#160; I see this as a much better solution than renaming the file.&amp;#160; Now I can use nsupdate.exe as a standard user.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-4316069565016878253?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/4316069565016878253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2010/01/user-account-control-uac-and-nsupdate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/4316069565016878253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/4316069565016878253'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2010/01/user-account-control-uac-and-nsupdate.html' title='User Account Control (UAC) and NSUpdate'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_Sz8XUKMj3Ec/S1ZkZ5J0siI/AAAAAAAAACI/_jyqEUDfLj4/s72-c/bindsoftware_thumb%5B3%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-2960620266497423962</id><published>2009-10-21T21:10:00.001-04:00</published><updated>2009-10-21T21:10:06.358-04:00</updated><title type='text'>Comment Spam from Paramount Defenses</title><content type='html'>&lt;p&gt;For those of you who know &lt;a href="http://www.joeware.net/"&gt;joe&lt;/a&gt;, perhaps you remember his &lt;a href="http://blog.joeware.net/2007/02/01/787/"&gt;past&lt;/a&gt; &lt;a href="http://blog.joeware.net/2006/07/18/447/"&gt;comments&lt;/a&gt; on &lt;a href="http://blog.joeware.net/2005/07/18/49/"&gt;Sanjay and Paramount Defenses&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Earlier today I answered an &lt;a href="http://www.activedir.org/"&gt;Active Dir&lt;/a&gt; question about how to tell when a machine was domain-joined by pointing the poster to my &lt;a href="http://dloder.blogspot.com/2009/04/who-told-ad-what-os-im-running.html"&gt;previous write-up on the domain-join process&lt;/a&gt;.&amp;#160; To be able to get the URL for my response, I opened the topic on my blog, which showed me the comments that had been added.&amp;#160; Imagine my surprise when I see a comment from someone named &lt;a href="http://www.blogger.com/profile/06459332367601415227"&gt;JM&lt;/a&gt; from a month ago.&amp;#160; It start with “Thanks for sharing your insightful thoughts and suggestions - very cool and helpful indeed.” (you couldn’t write a more generic opening if you tried) and then launches into a four paragraph sales pitch for GF.&lt;/p&gt;  &lt;p&gt;I’m sorry, but my blog is not a spot for Sanjay and his friends to try and peddle their wares when they don’t have the ability or skill to do it on their own without latching on to me via &lt;a href="http://en.wikipedia.org/wiki/Spam_in_blogs"&gt;comment spam&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Here’s the screen-shot of their intrusion before I whacked it.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_Sz8XUKMj3Ec/St-w6weaB9I/AAAAAAAAAB8/kdK5I3Y35us/s1600-h/spam%5B5%5D.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="spam" border="0" alt="spam" src="http://lh4.ggpht.com/_Sz8XUKMj3Ec/St-w7ek7ZOI/AAAAAAAAACA/-ulJ3vB7BW8/spam_thumb%5B3%5D.png?imgmax=800" width="244" height="142" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Actions like this make it easy to see exactly what kind of company and product they really have.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-2960620266497423962?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/2960620266497423962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/10/comment-spam-from-paramount-defenses.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/2960620266497423962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/2960620266497423962'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/10/comment-spam-from-paramount-defenses.html' title='Comment Spam from Paramount Defenses'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_Sz8XUKMj3Ec/St-w7ek7ZOI/AAAAAAAAACA/-ulJ3vB7BW8/s72-c/spam_thumb%5B3%5D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-7292074543940660293</id><published>2009-09-29T21:26:00.001-04:00</published><updated>2009-09-29T21:29:05.354-04:00</updated><title type='text'>Additional LDAPS Requirements from Vista/W2K8</title><content type='html'>&lt;p&gt;We have an ADAM instance that is protected by an SSL cert (LDAPS), and load-balanced behind a Cisco hardware device.&amp;#160; As a standard offering, we receive an SSL cert and a DNS alias for our “website”[1].&amp;#160; The DNS entry is similar to the following, with our public-facing name as an alias to the load-balancer:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New"&gt;C:\&amp;gt;nslookup adam.ad.test       &lt;br /&gt;Server:&amp;#160; UnKnown        &lt;br /&gt;Address:&amp;#160; 192.168.2.1 &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New"&gt;Non-authoritative answer:       &lt;br /&gt;Name:&amp;#160;&amp;#160;&amp;#160; adam.ciscogss.ad.test        &lt;br /&gt;Address:&amp;#160; 192.168.8.21        &lt;br /&gt;Aliases:&amp;#160; adam.ad.test&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The SSL cert is also issued with the public-facing name of adam.ad.test.&lt;/p&gt;  &lt;p&gt;This configuration functioned perfectly, for a while.&amp;#160; Eventually, we started having a few new application begin migrating to Windows Server 2008[2].&amp;#160; About this same time I also switched over to a Vista-based laptop as part of a pilot program within IT.&lt;/p&gt;  &lt;p&gt;Connecting to our ADAM instance from either of these platforms resulted in a failure.&amp;#160; But, connecting from XP or W2K3 continued to work flawlessly.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_Sz8XUKMj3Ec/SsKz2LUTE4I/AAAAAAAAAB0/YLh8EaasRbM/s1600-h/vistacerts%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="vistacerts" border="0" alt="vistacerts" src="http://lh6.ggpht.com/_Sz8XUKMj3Ec/SsKz2rCFxfI/AAAAAAAAAB4/IqWW6jzhNiw/vistacerts_thumb%5B1%5D.png?imgmax=800" width="244" height="167" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This was a highly unexpected failure.&amp;#160; I had no problems connecting to any SSL-protected website from Vista or W2K8.&amp;#160; Any of those websites had certs and DNS entries that would be identical to our own setup for ADAM.&amp;#160; If IE on Vista could connect to an https website whose name is an alias, why couldn’t LDP on Vista do the same?&lt;/p&gt;  &lt;p&gt;It turns out, Microsoft decided to tighten-up the requirements just for creating LDAPS connections, starting from the Vista codebase.&amp;#160; The problem is the certificate name didn’t match the DNS response.&amp;#160; After getting a new SSL cert for the public-facing name that included the load-balancer name as a Subject Alternative Name (SAN), the connections from Vista and W2K8 started working.&lt;/p&gt;  &lt;p&gt;So, if you ever run into the same situation, ADAM (or AD) must be protected with an SSL cert that matches all the names in the DNS resolution path.&lt;/p&gt;  &lt;p&gt;[1] Since it was a standard hosting offering, it was a little tricky at first to get our hosting team to understand our requirement for hosting the SSL port on 636, rather than 443.&lt;/p&gt;  &lt;p&gt;[2] Yes, my company can be a little slow at moving to new platforms.&amp;#160; We didn’t have anyone try and authenticate against the ADAM instance from Vista or W2K8 until about July 2009.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-7292074543940660293?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/7292074543940660293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/09/additional-ldaps-requirements-from.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/7292074543940660293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/7292074543940660293'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/09/additional-ldaps-requirements-from.html' title='Additional LDAPS Requirements from Vista/W2K8'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_Sz8XUKMj3Ec/SsKz2rCFxfI/AAAAAAAAAB4/IqWW6jzhNiw/s72-c/vistacerts_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-6011326100186104040</id><published>2009-09-29T20:41:00.001-04:00</published><updated>2009-09-29T20:41:10.494-04:00</updated><title type='text'>Computers in space</title><content type='html'>&lt;p&gt;If you want a fun, interesting read about the early days of computing, and how the requirements for manned-spaceflight helped push the state-of-the-art, you can find an insightful essay at &lt;a title="http://history.nasa.gov/computers/contents.html" href="http://history.nasa.gov/computers/contents.html"&gt;http://history.nasa.gov/computers/contents.html&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-6011326100186104040?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/6011326100186104040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/09/computers-in-space.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/6011326100186104040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/6011326100186104040'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/09/computers-in-space.html' title='Computers in space'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-3602434504497707417</id><published>2009-09-23T22:17:00.001-04:00</published><updated>2009-09-23T22:17:03.265-04:00</updated><title type='text'>Update on Exchange 2010 and AdminSDHolder</title><content type='html'>&lt;p&gt;The Microsoft Exchange Team recently &lt;a href="http://msexchangeteam.com/archive/2009/09/23/452595.aspx"&gt;blogged&lt;/a&gt; on the ACEs being applied by Exchange 2010, that I &lt;a href="http://dloder.blogspot.com/2009/08/exchange-2010-rc1-and-adminsdholder.html"&gt;discussed previously&lt;/a&gt;.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p align="justify"&gt;“[A]s some have correctly pointed out, that enables an elevation of privilege scenario that is unacceptable in any environment.&amp;#160; Microsoft agrees with this assessment and concurs that Exchange 2010 cannot ship with the permissions assigned to the AdminSDHolder role that allow for Active Directory forest privilege elevation.”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;It’s great to see, especially this close to the planned release, that Microsoft realized what a critical controls issue this would have been, and is correcting the problem.&lt;/p&gt;  &lt;p&gt;Bravo!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-3602434504497707417?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/3602434504497707417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/09/update-on-exchange-2010-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/3602434504497707417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/3602434504497707417'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/09/update-on-exchange-2010-and.html' title='Update on Exchange 2010 and AdminSDHolder'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-5943808131897453254</id><published>2009-08-24T21:52:00.001-04:00</published><updated>2009-08-24T21:55:46.811-04:00</updated><title type='text'>Exchange 2010 RC1 and AdminSDHolder</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;This post discusses Release Candidate software which may or may not reflect the final shipping version.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;With the recent release of &lt;a href="http://www.microsoft.com/exchange/2010/en/us/try-it.aspx" target="_blank"&gt;Exchange 2010 RC1&lt;/a&gt;, I threw it into a new sandbox to see what its schema and Forest/Domain Prep steps were like.&lt;/p&gt;  &lt;p&gt;A picture is worth a thousand words.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_Sz8XUKMj3Ec/SpND5ZPPADI/AAAAAAAAABs/rgUGDyHazCI/s1600-h/E2010_AdminSDHolder%5B3%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="E2010_AdminSDHolder" border="0" alt="E2010_AdminSDHolder" src="http://lh3.ggpht.com/_Sz8XUKMj3Ec/SpND6AcD1qI/AAAAAAAAABw/zjUeTtvyh1I/E2010_AdminSDHolder_thumb%5B1%5D.png?imgmax=800" width="244" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;After the PrepareAD steps have finished, &lt;a href="http://blogs.dirteam.com/blogs/jorge/archive/2006/05/16/981.aspx" target="_blank"&gt;AdminSDHolder&lt;/a&gt; has several new ACEs added to it.&amp;#160; I’ve highlighted the most inappropriate ACE: Write Property for member, granted to the new Exchange Windows Permissions group.&amp;#160; This makes it possible for an Exchange Organization Administrator to elevate themselves to Enterprise Administrator with two actions (left as a simple exercise to the reader).&lt;/p&gt;  &lt;p&gt;AdminSDHolder exists to protect the critical security groups, such as Enterprise Admins, from inadvertent&amp;#160; or accidental tampering by periodically setting the ACEs on those objects to known good values.&amp;#160; Since those values were originally defined by the authors of the AD code, they probably know a thing or two about what values are needed to protect AD.&amp;#160; With the new ACE on AdminSDHolder, AD itself now dutifully ensures that the new Exchange group can manage group membership for the Enterprise Admins group (along with Domain Admins, Account Operators and all other groups that were supposed to be “protected”).&lt;/p&gt;  &lt;p&gt;Beyond AdminSDHolder, PrepareAD also throws down identical ACEs on the domain head, including ACEs like Write DACL inherited to all objects.&amp;#160; But from a controls perspective, none are needed beyond the initial Write Property for member.&lt;/p&gt;  &lt;p&gt;If your organization has any rules for separation of duties between Exchange Admins and Enterprise Admins, the ACEs introduced by Exchange 2010 RC1 make that very difficult to enforce, if not impossible.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-5943808131897453254?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/5943808131897453254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/08/exchange-2010-rc1-and-adminsdholder.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/5943808131897453254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/5943808131897453254'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/08/exchange-2010-rc1-and-adminsdholder.html' title='Exchange 2010 RC1 and AdminSDHolder'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_Sz8XUKMj3Ec/SpND6AcD1qI/AAAAAAAAABw/zjUeTtvyh1I/s72-c/E2010_AdminSDHolder_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-6778200959038045515</id><published>2009-06-29T21:29:00.001-04:00</published><updated>2009-06-29T21:39:45.306-04:00</updated><title type='text'>Unencrypting GSS-API Encrypted Payloads</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In an earlier &lt;a href="http://dloder.blogspot.com/2009/04/who-told-ad-what-os-im-running.html"&gt;post&lt;/a&gt; I lamented the fact that Netmon couldn’t automatically use a server’s own private key to be able to decode SSL packets.&amp;#160; When working on something else, I ran across &lt;a href="http://blogs.technet.com/benw/archive/2008/12/15/disabling-ldap-encryption-and-signing-for-netmon-on-an-exchange-server.aspx" target="_blank"&gt;this post&lt;/a&gt; that details how to disable LDAP encryption.&amp;#160; I don’t know if it disables the encryption for NetLogonr or not, but thought someone may find the procedure useful.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-6778200959038045515?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/6778200959038045515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/06/unencrypting-gss-api-encrypted-payloads.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/6778200959038045515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/6778200959038045515'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/06/unencrypting-gss-api-encrypted-payloads.html' title='Unencrypting GSS-API Encrypted Payloads'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-2585470827549640743</id><published>2009-05-06T23:06:00.001-04:00</published><updated>2009-05-06T23:06:23.988-04:00</updated><title type='text'>My Vista SP2 Experience</title><content type='html'>&lt;p&gt;Install went rather well, but my Dell Latitude D620 experienced one issue.&amp;#160; The Intel Wireless device disappeared from device manager after the install completed, and the WiFi indicator light was not lit.&amp;#160; Reboot into BIOS setup, and verified the device was still enabled – which it was.&amp;#160; I ended up setting the WiFi catcher setting back to basic mode, which apparently reset the device enough that the WiFi indicator light was lit for the next reboot and my wireless was functional again.&amp;#160; Otherwise the install went smoothly.&amp;#160; Now it’s on to my W2K8 dev servers.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-2585470827549640743?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/2585470827549640743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/05/my-vista-sp2-experience.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/2585470827549640743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/2585470827549640743'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/05/my-vista-sp2-experience.html' title='My Vista SP2 Experience'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-8567435966581357482</id><published>2009-04-26T22:15:00.001-04:00</published><updated>2009-08-24T21:54:38.816-04:00</updated><title type='text'>Gotta Get Back In Time</title><content type='html'>&lt;p&gt;I’m just amazed by our &lt;a href="http://www.space.com/scienceastronomy/090422-space-blob.html"&gt;ability to peer back in time&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-8567435966581357482?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/8567435966581357482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/04/gotta-get-back-in-time.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/8567435966581357482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/8567435966581357482'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/04/gotta-get-back-in-time.html' title='Gotta Get Back In Time'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-278294252090140335</id><published>2009-04-22T23:29:00.000-04:00</published><updated>2009-04-22T21:03:18.072-04:00</updated><title type='text'>Who told AD what OS I’m running?</title><content type='html'>&lt;p&gt;Have any DOS 1.0 clients in your AD forest?  I do.&lt;/p&gt;&lt;p&gt; &lt;a href="http://lh3.ggpht.com/_Sz8XUKMj3Ec/Sef3gGlf56I/AAAAAAAAABA/wpxczjjQrW4/s1600-h/DOS%5B2%5D.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="DOS" border="0" alt="DOS" src="http://lh6.ggpht.com/_Sz8XUKMj3Ec/Sef3ge6tAAI/AAAAAAAAABI/vRZ0faahCfA/DOS_thumb%5B1%5D.png?imgmax=800" width="212" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;How’d that get there?&lt;/p&gt;&lt;p&gt;Easy answer.&lt;/p&gt;&lt;p&gt;With Write Property permissions on a computer object, anyone can write any value they desire to the various operatingSystem attributes.  However, a few days later our devious admin notices the truth has been revealed.&lt;/p&gt;&lt;p&gt;  &lt;a href="http://lh4.ggpht.com/_Sz8XUKMj3Ec/Sef3g4b19KI/AAAAAAAAABM/a6ZXKkXfH7A/s1600-h/Win7%5B5%5D.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="Win7" border="0" alt="Win7" src="http://lh6.ggpht.com/_Sz8XUKMj3Ec/Sef3hN-KaEI/AAAAAAAAABQ/vk3MlyqJS-0/Win7_thumb%5B4%5D.png?imgmax=800" width="212" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;How’d that get there?&lt;/p&gt;&lt;p&gt;Tougher answer.&lt;/p&gt;&lt;p&gt;Let’s start by reviewing the delegation model AD creates when creating a computer account and allowing a non-Domain Admin to perform a delegated join.  Using DSA.MSC, we can pre-create a computer account and delegate rights to our DelegatedAdmins group.  One bug to note here, the W2K3 version of DSA.MSC will ACL the delegated workstation account with some invalid GUIDs for the inherited object type.  We can see these with LDP as the zero GUIDs that don’t resolve to a real inherited object type.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_Sz8XUKMj3Ec/Sef3h3mPSeI/AAAAAAAAABU/GutnDDl1fwQ/s1600-h/LDPACLs%5B1%5D.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="LDPACLs" border="0" alt="LDPACLs" src="http://lh4.ggpht.com/_Sz8XUKMj3Ec/Sef3ieU_jQI/AAAAAAAAABY/7aM07kPz7Ow/LDPACLs_thumb.png?imgmax=800" width="244" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;The W2K3 version of DSACLs will also crash due to the invalid GUIDs and will not display the ACLs.  The W2K8 version does not crash, so we can see the output (which is a useful feature).&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;C:\&amp;gt;dsacls \\dc01.ad.test\cn=workstation1,cn=computers,dc=ad,dc=test&lt;br /&gt;Owner: AD\Domain Admins&lt;br /&gt;Group: AD\Domain Users &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;Access list:&lt;br /&gt;Allow AD\DelegatedAdmins              SPECIAL ACCESS&lt;br /&gt;                                      DELETE&lt;br /&gt;                                      READ PERMISSONS&lt;br /&gt;                                      LIST CONTENTS&lt;br /&gt;                                      READ PROPERTY&lt;br /&gt;                                      DELETE TREE&lt;br /&gt;                                      LIST OBJECT&lt;br /&gt;                                      CONTROL ACCESS&lt;br /&gt;Allow AD\DelegatedAdmins              SPECIAL ACCESS for Account Restrictions&lt;br /&gt;                                      WRITE PROPERTY&lt;br /&gt;Allow AD\DelegatedAdmins              SPECIAL ACCESS for sAMAccountName&lt;br /&gt;                                      WRITE PROPERTY&lt;br /&gt;Allow AD\DelegatedAdmins              SPECIAL ACCESS for Logon Information&lt;br /&gt;                                      WRITE PROPERTY&lt;br /&gt;Allow AD\DelegatedAdmins              SPECIAL ACCESS for description&lt;br /&gt;                                      WRITE PROPERTY&lt;br /&gt;Allow AD\DelegatedAdmins              SPECIAL ACCESS for displayName&lt;br /&gt;                                      WRITE PROPERTY&lt;br /&gt;Allow AD\DelegatedAdmins              SPECIAL ACCESS for Validated write to DNS host name&lt;br /&gt;                                      WRITE SELF&lt;br /&gt;Allow AD\DelegatedAdmins              SPECIAL ACCESS for Validated write to service principal name&lt;br /&gt;                                      WRITE SELF&lt;br /&gt;Allow NT AUTHORITY\SELF               SPECIAL ACCESS for Personal Information&lt;br /&gt;                                      WRITE PROPERTY&lt;br /&gt;                                      READ PROPERTY&lt;br /&gt;Allow NT AUTHORITY\SELF               SPECIAL ACCESS&lt;br /&gt;                                      CREATE CHILD&lt;br /&gt;                                      DELETE CHILD&lt;br /&gt;Allow NT AUTHORITY\SELF               SPECIAL ACCESS for Validated write to service principal name&lt;br /&gt;                                      WRITE SELF&lt;br /&gt;Allow NT AUTHORITY\SELF               SPECIAL ACCESS for Validated write to DNS host name&lt;br /&gt;                                      WRITE SELF&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I don’t see anything obviously allowing either the delegated admin or the computer account itself to be able to write the operatingSystem values.  Account Restrictions and Logon Information are both property sets.  Let’s see what attributes they contain.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;C:\&amp;gt;adfind -sc findpropsetrg:"Account Restrictions" &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;AdFind V01.40.00cpp Joe Richards (joe@joeware.net) February 2009 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;Using server: dc01.ad.test:389&lt;br /&gt;Directory: Windows Server 2003&lt;br /&gt;Base DN: cn=extended-rights,CN=Configuration,DC=ad,DC=test &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;dn:CN=User-Account-Restrictions,CN=Extended-Rights,CN=Configuration,DC=ad,DC=test&lt;br /&gt;&amp;gt;rightsGuid: 4c164200-20c0-11d0-a768-00aa006e0529 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;1 Objects returned &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;C:\&amp;gt;adfind -sc propsetmembers:4c164200-20c0-11d0-a768-00aa006e0529 -dn &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;AdFind V01.40.00cpp Joe Richards (joe@joeware.net) February 2009 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;Transformed Filter: (&amp;amp;(objectcategory=attributeschema)(attributeSecurityGUID=\00&lt;br /&gt;B\16L\C0\20\D0\11\A7h\00\AA\00n\05\29))&lt;br /&gt;Using server: dc01.ad.test:389&lt;br /&gt;Directory: Windows Server 2003&lt;br /&gt;Base DN: CN=Schema,CN=Configuration,DC=ad,DC=test &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;dn:CN=Account-Expires,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=ms-DS-User-Account-Control-Computed,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Pwd-Last-Set,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=User-Account-Control,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=User-Parameters,CN=Schema,CN=Configuration,DC=ad,DC=test &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;5 Objects returned &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;C:\&amp;gt;adfind -sc findpropsetrg:"Logon Information" &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;AdFind V01.40.00cpp Joe Richards (joe@joeware.net) February 2009 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;Using server: dc01.ad.test:389&lt;br /&gt;Directory: Windows Server 2003&lt;br /&gt;Base DN: cn=extended-rights,CN=Configuration,DC=ad,DC=test &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;dn:CN=User-Logon,CN=Extended-Rights,CN=Configuration,DC=ad,DC=test&lt;br /&gt;&amp;gt;rightsGuid: 5f202010-79a5-11d0-9020-00c04fc2d4cf &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;1 Objects returned &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;C:\&amp;gt;adfind -sc propsetmembers:5f202010-79a5-11d0-9020-00c04fc2d4cf -dn &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;AdFind V01.40.00cpp Joe Richards (joe@joeware.net) February 2009 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;Transformed Filter: (&amp;amp;(objectcategory=attributeschema)(attributeSecurityGUID=\10&lt;br /&gt;\20\20\5F\A5y\D0\11\90\20\00\C0O\C2\D4\CF))&lt;br /&gt;Using server: dc01.ad.test:389&lt;br /&gt;Directory: Windows Server 2003&lt;br /&gt;Base DN: CN=Schema,CN=Configuration,DC=ad,DC=test &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;dn:CN=Bad-Pwd-Count,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Home-Directory,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Home-Drive,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Last-Logoff,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Last-Logon,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Last-Logon-Timestamp,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Logon-Count,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Logon-Hours,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Logon-Workstation,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Profile-Path,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=Script-Path,CN=Schema,CN=Configuration,DC=ad,DC=test&lt;br /&gt;dn:CN=User-Workstations,CN=Schema,CN=Configuration,DC=ad,DC=test &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;12 Objects returned&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Even with the property sets, I still don’t see anything granting write access to the operatingSystem attributes.&lt;/p&gt;&lt;p&gt;We’re not sure who wrote the data, maybe when it was written can provide a clue.  The replication metadata will reveal when attributes received an originating update.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;C:\&amp;gt;repadmin /showobjmeta localhost cn=workstation1,cn=computers,dc=ad,dc=test &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;29 entries. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;Loc.USN                          Originating DC   Org.USN  Org.Time/Date        Ver Attribute &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;=======                          =============== ========= =============        === ========= &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13874             Default-First-Site-Name\DC01     13874 2009-04-08 22:57:54    1 objectClass &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13874             Default-First-Site-Name\DC01     13874 2009-04-08 22:57:54    1 cn &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13874             Default-First-Site-Name\DC01     13874 2009-04-08 22:57:54    1 instanceType &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13874             Default-First-Site-Name\DC01     13874 2009-04-08 22:57:54    1 whenCreated &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13878             Default-First-Site-Name\DC01     13878 2009-04-08 22:57:54    2 nTSecurityDescriptor &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13874             Default-First-Site-Name\DC01     13874 2009-04-08 22:57:54    1 name &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13883             Default-First-Site-Name\DC01     13883 2009-04-08 22:58:19    5 userAccountControl &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13875             Default-First-Site-Name\DC01     13875 2009-04-08 22:57:54    1 codePage &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13875             Default-First-Site-Name\DC01     13875 2009-04-08 22:57:54    1 countryCode &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13884             Default-First-Site-Name\DC01     13884 2009-04-08 22:58:19    3 dBCSPwd &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13874             Default-First-Site-Name\DC01     13874 2009-04-08 22:57:54    1 localPolicyFlags &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13875             Default-First-Site-Name\DC01     13875 2009-04-08 22:57:54    1 logonHours &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13884             Default-First-Site-Name\DC01     13884 2009-04-08 22:58:19    3 unicodePwd &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13884             Default-First-Site-Name\DC01     13884 2009-04-08 22:58:19    3 ntPwdHistory &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13884             Default-First-Site-Name\DC01     13884 2009-04-08 22:58:19    3 pwdLastSet &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13875             Default-First-Site-Name\DC01     13875 2009-04-08 22:57:54    1 primaryGroupID &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13885             Default-First-Site-Name\DC01     13885 2009-04-08 22:58:19    2 supplementalCredentials &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13874             Default-First-Site-Name\DC01     13874 2009-04-08 22:57:54    1 objectSid &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13875             Default-First-Site-Name\DC01     13875 2009-04-08 22:57:54    1 accountExpires &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13884             Default-First-Site-Name\DC01     13884 2009-04-08 22:58:19    3 lmPwdHistory &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13874             Default-First-Site-Name\DC01     13874 2009-04-08 22:57:54    1 sAMAccountName &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13874             Default-First-Site-Name\DC01     13874 2009-04-08 22:57:54    1 sAMAccountType &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13889             Default-First-Site-Name\DC01     13889 2009-04-08 22:58:23    1 operatingSystem &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13889             Default-First-Site-Name\DC01     13889 2009-04-08 22:58:23    1 operatingSystemVersion &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13889             Default-First-Site-Name\DC01     13889 2009-04-08 22:58:23    1 operatingSystemServicePack &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13887             Default-First-Site-Name\DC01     13887 2009-04-08 22:58:20    1 dNSHostName &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13887             Default-First-Site-Name\DC01     13887 2009-04-08 22:58:20    1 servicePrincipalName &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13874             Default-First-Site-Name\DC01     13874 2009-04-08 22:57:54    1 objectCategory &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;  13875             Default-First-Site-Name\DC01     13875 2009-04-08 22:57:54    1 isCriticalSystemObject &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;0 entries. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;Type    Attribute     Last Mod Time                             Originating DC  Loc.USN Org.USN Ver &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;======= ============  =============                           ================= ======= ======= === &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;        Distinguished Name &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;        =============================&lt;/span&gt; &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This shows us most of the attributes were written at the start of the join process.  Most have a version number of 1, with the same originating timestamp.  However, looking closely, we can see there are really four groups of updates.  The first were stamped at 22:57:54 and correspond to the creation of the computer object by the Domain Admin.  The second was stamped at 22:58:19 and represents the setting of the password secrets.  The third was stamped at 22:58:20 and represents the population of the dnsHostName and servicePrincipalName attributes.  The final group was timestamped three seconds later at 22:58:23, and shows the operatingSystem, operatingSystemVersion and operatingSystemServicePack attributes being set.  Since this group was updated later, that means it probably wasn’t done as part of the join process, which is good since we’re pretty sure we didn’t delegate the right to write to those attributes.&lt;/p&gt;&lt;p&gt;The join process has fairly decent debug data written to the %windir%\debug\netsetup.log file.  Cracking that logfile open shows us the following events.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;04/08 22:58:11 -----------------------------------------------------------------&lt;br /&gt;04/08 22:58:11 NetpValidateName: checking to see if 'ad.test' is valid as type 3 name&lt;br /&gt;04/08 22:58:11 NetpCheckDomainNameIsValid [ Exists ] for 'ad.test' returned 0x0&lt;br /&gt;04/08 22:58:11 NetpValidateName: name 'ad.test' is valid for type 3&lt;br /&gt;04/08 22:58:19 -----------------------------------------------------------------&lt;br /&gt;04/08 22:58:19 NetpDoDomainJoin&lt;br /&gt;04/08 22:58:19 NetpMachineValidToJoin: 'WORKSTATION1'&lt;br /&gt;04/08 22:58:19 NetpGetLsaPrimaryDomain: status: 0x0&lt;br /&gt;04/08 22:58:19 NetpMachineValidToJoin: status: 0x0&lt;br /&gt;04/08 22:58:19 NetpJoinDomain&lt;br /&gt;04/08 22:58:19     Machine: WORKSTATION1&lt;br /&gt;04/08 22:58:19     Domain: ad.test&lt;br /&gt;04/08 22:58:19     MachineAccountOU: (NULL)&lt;br /&gt;04/08 22:58:19     Account: ad.test\dloder&lt;br /&gt;04/08 22:58:19     Options: 0x25&lt;br /&gt;04/08 22:58:19     OS Version: 5.2&lt;br /&gt;04/08 22:58:19     Build number: 3790&lt;br /&gt;04/08 22:58:19     ServicePack: Service Pack 2&lt;br /&gt;04/08 22:58:19 NetpValidateName: checking to see if 'ad.test' is valid as type 3 name&lt;br /&gt;04/08 22:58:19 NetpCheckDomainNameIsValid [ Exists ] for 'ad.test' returned 0x0&lt;br /&gt;04/08 22:58:19 NetpValidateName: name 'ad.test' is valid for type 3&lt;br /&gt;04/08 22:58:19 NetpDsGetDcName: trying to find DC in domain 'ad.test', flags: 0x1020&lt;br /&gt;04/08 22:58:19 NetpDsGetDcName: found DC '\\dc01.ad.test' in the specified domain&lt;br /&gt;04/08 22:58:19 NetpJoinDomain: status of connecting to dc '\\dc01.ad.test': 0x0&lt;br /&gt;04/08 22:58:19 NetpGetLsaPrimaryDomain: status: 0x0&lt;br /&gt;04/08 22:58:19 NetpGetDnsHostName: Read NV Hostname: workstation1&lt;br /&gt;04/08 22:58:19 NetpGetDnsHostName: PrimaryDnsSuffix defaulted to DNS domain name: ad.test&lt;br /&gt;04/08 22:58:19 NetpLsaOpenSecret: status: 0xc0000034&lt;br /&gt;04/08 22:58:19 NetpGetLsaPrimaryDomain: status: 0x0&lt;br /&gt;04/08 22:58:19 NetpLsaOpenSecret: status: 0xc0000034&lt;br /&gt;04/08 22:58:20 NetpJoinDomain: status of setting machine password: 0x0&lt;br /&gt;04/08 22:58:20 NetpGetComputerObjectDn: Cracking DNS domain name ad.test/ into Netbios on \\dc01.ad.test&lt;br /&gt;04/08 22:58:20 NetpGetComputerObjectDn: Crack results:     name = AD\&lt;br /&gt;04/08 22:58:20 NetpGetComputerObjectDn: Cracking account name AD\WORKSTATION1$ on \\dc01.ad.test&lt;br /&gt;04/08 22:58:20 NetpGetComputerObjectDn: Crack results:     (Account already exists) DN = CN=workstation1,CN=Computers,DC=ad,DC=test&lt;br /&gt;04/08 22:58:20 NetpModifyComputerObjectInDs: Initial attribute values:&lt;br /&gt;04/08 22:58:20         DnsHostName  =  workstation1.ad.test&lt;br /&gt;04/08 22:58:20         ServicePrincipalName  =  HOST/workstation1.ad.test  HOST/WORKSTATION1&lt;br /&gt;04/08 22:58:20 NetpModifyComputerObjectInDs: Computer Object already exists in OU:&lt;br /&gt;04/08 22:58:20         DnsHostName  =&lt;br /&gt;04/08 22:58:20         ServicePrincipalName  =&lt;br /&gt;04/08 22:58:20 NetpModifyComputerObjectInDs: Attribute values to set:&lt;br /&gt;04/08 22:58:20         DnsHostName  =  workstation1.ad.test&lt;br /&gt;04/08 22:58:20         ServicePrincipalName  =  HOST/workstation1.ad.test  HOST/WORKSTATION1&lt;br /&gt;04/08 22:58:20 ldap_unbind status: 0x0&lt;br /&gt;04/08 22:58:20 NetpJoinDomain: status of setting DnsHostName and SPN: 0x0&lt;br /&gt;04/08 22:58:20 NetpGetLsaPrimaryDomain: status: 0x0&lt;br /&gt;04/08 22:58:20 NetpSetLsaPrimaryDomain: for 'AD' status: 0x0&lt;br /&gt;04/08 22:58:20 NetpJoinDomain: status of setting LSA pri. domain: 0x0&lt;br /&gt;04/08 22:58:20 NetpJoinDomain: status of managing local groups: 0x0&lt;br /&gt;04/08 22:58:20 NetpJoinDomain: status of setting netlogon cache: 0x0&lt;br /&gt;04/08 22:58:20 NetpJoinDomain: status of setting ComputerNamePhysicalDnsDomain to 'ad.test': 0x0&lt;br /&gt;04/08 22:58:20 NetpUpdateW32timeConfig: 0x0&lt;br /&gt;04/08 22:58:20 NetpJoinDomain: status of disconnecting from '\\dc01.ad.test': 0x0&lt;br /&gt;04/08 22:58:20 NetpDoDomainJoin: status: 0x0&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This confirms the data we saw from RepAdmin.  The NetpLsaOpenSecret occurs at 22:58:19, and dnsHostName and servicePrincipalName attributes were set at 22:58:20.  The join succeeds at 22:58:20, which is also the end of the logfile.  Obviously setting the OS attributes isn’t part of the join process.&lt;/p&gt;&lt;p&gt;For the ultimate truth, nothing beats a capture of packets on the wire.  With this, we can correlate everything we’ve seen with real network traffic.  First we see the join initiate and succeed, and it is easy to correlate the NetpGetComputerObjectDn in the logfile and its “cracking DNS domain name” comment with the DSRCrackNames Request in the packet capture. &lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_Sz8XUKMj3Ec/Sef3jXp4XFI/AAAAAAAAABc/69uxDIYqfLw/s1600-h/DRSCrack%5B4%5D.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="DRSCrack" border="0" alt="DRSCrack" src="http://lh3.ggpht.com/_Sz8XUKMj3Ec/Sef3jtXBOnI/AAAAAAAAABg/ihQWLM6-eU8/DRSCrack_thumb%5B5%5D.png?imgmax=800" width="244" height="75" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;The join process is followed by establishment of the secure channel, which matches the timestamp difference the metadata showed us.&lt;/p&gt;&lt;p&gt;This packet toward the end of the capture has a fairly large encrypted blob.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_Sz8XUKMj3Ec/Sef3k7Y6g8I/AAAAAAAAABk/t1uaypbAAiY/s1600-h/netlogonr%5B6%5D.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="netlogonr" border="0" alt="netlogonr" src="http://lh3.ggpht.com/_Sz8XUKMj3Ec/Sef3lu2dVxI/AAAAAAAAABo/d7U4YgOYOHg/netlogonr_thumb%5B7%5D.png?imgmax=800" width="244" height="134" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Too bad the parsers don’t automatically bust open the packets, since they were captured from one of the two systems involved in the secure communication, and should have access to the private keys.  However, doing a search for NetrLogonGetDomainInfo leads us to the MS-NRPC protocol specification that Microsoft released in 2008.  Specifically section 2.2.1.3.6 NETLOGON_WORKSTATION_INFO details that the structure does in fact contain both OsVersion and OsName values.&lt;/p&gt;&lt;p&gt;There we finally have it.  During the setup of the secure channel, the Microsoft clients embed details about their OS configuration.  The Domain Controller receiving this information dutifully applies it to the OS attributes of the computer object.  So even if an admin were granted full control over their computer object, they’ll be constantly fighting Windows’ attempts to ensure the correct OS information is written to the object.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-278294252090140335?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/278294252090140335/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/04/who-told-ad-what-os-im-running.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/278294252090140335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/278294252090140335'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/04/who-told-ad-what-os-im-running.html' title='Who told AD what OS I’m running?'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_Sz8XUKMj3Ec/Sef3ge6tAAI/AAAAAAAAABI/vRZ0faahCfA/s72-c/DOS_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-839603049883208712</id><published>2009-04-22T21:23:00.001-04:00</published><updated>2009-04-22T21:23:55.933-04:00</updated><title type='text'>The ID Element</title><content type='html'>&lt;p&gt;I &lt;a href="http://channel9.msdn.com/shows/identity/"&gt;saw this&lt;/a&gt; first on &lt;a href="http://blogs.dirteam.com/blogs/tomek/archive/2009/04/20/air-fire-water-earth-identity.aspx"&gt;tomek's blog&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Great interview with Stuart Kwan.&amp;#160; I loved his comment on Identity always being an ongoing, yet evolving problem; there will always be a need for solving identity problems as long as interconnected systems exist.&amp;#160; That's what keeps me interested in my job.&amp;#160; Identity really is that base foundation that all apps need.&amp;#160; Talking with my manager recently we had commented that where we are in our enterprise is a great position to hold because we essentially get to tour all areas of the business without ever changing jobs.&amp;#160; I doubt there are few other positions within an enterprise that are as fully connected to so many aspects of the business than those of an identity solutions architect.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-839603049883208712?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/839603049883208712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/04/id-element.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/839603049883208712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/839603049883208712'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/04/id-element.html' title='The ID Element'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4018181297398983593.post-15522751303475617</id><published>2009-04-22T20:59:00.001-04:00</published><updated>2009-04-22T20:59:35.835-04:00</updated><title type='text'>Post #1!</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;After a few years of reading the ActiveDir.org mailing list, and subscribing to the major AD blogs (&lt;a href="http://blog.joeware.net/"&gt;joe&lt;/a&gt;, &lt;a href="http://briandesmond.com/"&gt;Brian&lt;/a&gt;, &lt;a href="http://blogs.dirteam.com/blogs/jorge/default.aspx"&gt;Jorge&lt;/a&gt; – pretty much everyone on &lt;a href="http://www.activedir.org/"&gt;ActiveDir&lt;/a&gt;!) I’ve decided I’ve got enough years under my belt, and a big enough environment to give me enough topics to hopefully keep this interesting for a while.&amp;#160; Mostly I’m doing this as my small piece to give back to the community that been such a wonderful resource.&amp;#160; Feel free to let me know if you ever find these useful – or not.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4018181297398983593-15522751303475617?l=dloder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dloder.blogspot.com/feeds/15522751303475617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dloder.blogspot.com/2009/04/post-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/15522751303475617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4018181297398983593/posts/default/15522751303475617'/><link rel='alternate' type='text/html' href='http://dloder.blogspot.com/2009/04/post-1.html' title='Post #1!'/><author><name>David Loder</name><uri>http://www.blogger.com/profile/15741815450513900329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
