<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Alex Tcherniakhovski - Security</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/alextch/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/alextch/feed.xml</link>
    <description />
    <lastBuildDate>Mon, 20 Jul 2015 15:50:03 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Using PostSharp in FIM Synchronization rules to reduce code complexity, and improve readability.</title>
      <link>https://docs.microsoft.com/archive/blogs/alextch/using-postsharp-in-fim-synchronization-rules-to-reduce-code-complexity-and-improve-readability</link>
      <pubDate>Thu, 02 Aug 2012 08:59:00 GMT</pubDate>
      <dc:creator><![CDATA[Alex Tcherniakhovski]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alextch/2012/08/02/using-postsharp-in-fim-synchronization-rules-to-reduce-code-complexity-and-improve-readability/</guid>
      <description><![CDATA[This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script...]]></description>
      <content:encoded><![CDATA[<p>This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm</p>
<p>Maintainability of FIM Sync rules is probably one of the most often raised issues by the customers, especially when the rules were developed by someone else. For this reason, I try my best to make the rules as modular and self-documenting as possible. Recently I came across Aspect Oriented Development framework, which I believe will go a long way in improving the quality of my deliverables. In this blog I would like to share my experience in using <a href="https://www.sharpcrafters.com/">PostSharper</a> to improve expressiveness and modularity of FIM Sync Rules. Of course, the framework is applicable to a wide range of scenarios. Before I go any further I would suggest that you explore <a title="https://www.sharpcrafters.com/" href="https://www.sharpcrafters.com/">https://www.sharpcrafters.com/</a> for some ideas and samples of how Aspect Oriented Development could benefit you. In a nutshell though, the Aspect model allows us to focus code on what matters, thus clearly expressing the intent of our code, while modularizing cross-cutting concerns.</p>
<!--more-->
<p>Let me show you, as an example, a method I recently re-factored using Aspects. The main intent of the function is to determine whether an AD account could be safely deleted. The method leverages two helper methods which evaluate the status of the identity from AD and HR point of view. The details of the implementation are not important here. What is important that this method is only applicable to certain types of accounts (normal user objects and not system accounts, etc. ), and that it requires userAccountControl attribute to be passed to it. I also anticipate that more granular rules will be applied in the future to filter the application of this function.</p>
<p>So without Aspects, I would typically create multiple if conditions which would determine if the object meets certain requirements and that all required parameters where passed to the method. Trust me when I say this, that doing this would significantly reduce the readability and maintainability of this code. In addition, I have several other methods which may require the same logic.</p>
<p>So with <a href="https://www.sharpcrafters.com/">PostSharp</a> I created several Aspects (ApplicableToPrimaryAccontsOnlyAspect and RequiresUserAccountControlAttributeAspect), which are declaratively applied to the method. The Aspects themselves are implemented as separate modules (classes) which could be re-used declaratively throughout my project. The Aspects are &ldquo;weaved&rdquo; into the method code by PostSharper and are executed on the method entry boundary.</p>
<p>As you can see, the intent the the pre-conditions of the method are very clearly expressed, thanks to the Aspects.</p>
<p><span style="font-size: x-small;" size="2">[ApplicableToPrimaryAccountsOnlyAspect] <br />[RequiresUserAccountControlAttributeAspect] <br />public static void ARSSafeToDeleteFlagRule(CSEntry csEntry, MVEntry mvEntry) <br />{ <br />&nbsp;&nbsp;&nbsp; if (AreActiveDirectoryConditionsForSettingSafeToDeleteFlagMet(csEntry) &amp;&amp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AreHRConditionsForSettingSafeToDeleteFlagMet(mvEntry)) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mvEntry["SafeToDeleteFlag"].BooleanValue = true; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mvEntry["SafeToDeleteFlag"].BooleanValue = false; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />}</span></p>
<p>&nbsp;</p>
<p>Here is the implementation of the ApplicableToPrimaryAcccountOnlyAspect.</p>
<p>There are two points worth mentioning here:</p>
<p>1. In the OnMethodBoundaryAspect Aspect we have access to the parameters passed to the method, hence the parameter validation logic could be extracted from the main method (by main method here I mean the method to which the Aspect is attached).</p>
<p>2. Based on the outcome of the validation logic, we can change the flow behavior of the main method. In this example, if the account is not Primary I simply exit the main method.</p>
<p><span style="font-size: x-small;" size="2">using System; <br />using PostSharp.Aspects; <br />using Microsoft.MetadirectoryServices;</span></p>
<p><span style="font-size: x-small;" size="2"></span></p>
<p><span style="font-size: x-small;" size="2">[Serializable] <br />public class ApplicableToPrimaryAccountsOnlyAspect : OnMethodBoundaryAspect <br />{ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public override void OnEntry(MethodExecutionArgs args) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>var csEntry = args.Arguments[0] as CSEntry; <br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (csEntry == null) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new Exception( <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "ApplicableToPrimaryAccountsOnlyAspect received unexpected argument, was expecting CSEntry"); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-size: x-small;" size="2"></span></p>
<p><span style="font-size: x-small;" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!csEntry["AccountClassification"].IsPresent) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new Exception( <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "ApplicableToPrimaryAccountsOnlyAspect received a CSEntry without classification"); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-size: x-small;" size="2"></span></p>
<p><span style="font-size: x-small;" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!csEntry["AccountClassification"] <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .StringValue.Equals(GlobalSettingsConfig.Constants.PrimaryAccountCode)) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>args.FlowBehavior = FlowBehavior.Return; <br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />}</span></p>
<p>References: <a title="https://www.sharpcrafters.com/postsharp/documentation" href="https://www.sharpcrafters.com/postsharp/documentation">https://www.sharpcrafters.com/postsharp/documentation</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Programmatically confirming projection and join operation in FIM Synchronization Service during integration testing</title>
      <link>https://docs.microsoft.com/archive/blogs/alextch/programmatically-confirming-projection-and-join-operation-in-fim-synchronization-service-during-integration-testing</link>
      <pubDate>Wed, 18 Jul 2012 11:34:00 GMT</pubDate>
      <dc:creator><![CDATA[Alex Tcherniakhovski]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alextch/2012/07/18/programmatically-confirming-projection-and-join-operation-in-fim-synchronization-service-during-integration-testing/</guid>
      <description><![CDATA[&#160;




The objective of this blog is to provide FIM Synchronization Service integration...]]></description>
      <content:encoded><![CDATA[<blockquote>   <pre>&#160;</pre>
</blockquote>

<!--more-->

<p>The objective of this blog is to provide FIM Synchronization Service integration testers with tools to automate validation of projection and join operations.</p>

<p>&#160;</p>

<p>This posting is provided &quot;AS IS&quot; with no warranties, and confers no rights. 
  <br />Use of included script samples are subject to the terms specified at <a href="https://www.microsoft.com/info/cpyright.htm">https://www.microsoft.com/info/cpyright.htm</a></p>

<h2>Integration testing Pattern</h2>

<p>FIM Sync Service integration pattern follows a simple model</p>

<ol>
  <li>Introduce changes to the connected systems</li>

  <li>Invoke run profiles</li>

  <li>Validate that projection, join, attribute flow rule, etc. rules were executed as expected</li>
</ol>

<p>Ideally all 3 parts should be fully automated, but in this blog we will look at automating step 3. For automation of run profiles from C#, see my other post <a href="https://blogs.msdn.com/b/alextch/archive/2012/07/06/sample-c-code-to-invoke-execution-of-a-run-profile-on-forefront-identity-server-synchronization-service.aspx">here</a>.</p>

<h2>What utilities do we need to make assertions about the correctness of rule execution?</h2>

<p>For simplicity sake, let’s assume that we are working with two connected systems: HR (SQL table) and Active Directory, and that we wrote two helper classes: HRHelper and ActiveDirectoryHelper, which automate testing of those systems (i.e. allow us to add, delete, modify objects for testing). Let’s also assume that HR projects, and AD joins on employeeID. In order to ensure that our FIM rules are configured properly (in an automated fashion), we will need the following facilities:</p>

<ol>
  <li>MetaverseHelper Class, which allows us to locate MVEntries based on anchor attributes</li>

  <li>ConnectorSpace.Helper Class, which allows us to check if a csEntry identified by a DN is linked to an MVEntry, previously located by the MetaverseHelper Class</li>
</ol>

<p>In our example, if HR Record was successfully projected, then we should be able to locate in the Metaverse, one and only one, MVEntry which contains the employeeID in question (assuming, there exist and import attribute flow which sends emploeeID to the Metaverse). Also, if Active Directory MA produced a join, then we should be able to locate a link between the CSEntry and the MVEntry.</p>

<p>Code sample below illustrates this pattern.</p>

<p>// Introduce changes to the connected systems</p>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">var dn = ActiveDirectoryHelper.CreateNewAccount(ADAccountInfo adAccountInfo);
var employeeID = HRHelper.CreateNewHRRecord(HRAccountInfo hrAccountInfo);
</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&#160;</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">// Run FIM Sync Cycle </pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">RunProfileInvoker.RunFullCycle();

</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">// Validate Projection and Joins
</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">mms_metaverse mvEntryFoundByDN;
mms_metaverse mvEntryFoundByEmployeeID;
</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">// Assumes that there is an import attribute flow of employeeID to the Metaverse</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">Assert.IsTrue(MetaverseHelper.TryToGetMVEntryByEmployeeID(employeeID, out mvEntryFoundByEmployeeID));</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">// Assumes that there is an import attribute flow of distinghuishedName to the Metaverse</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">Assert.IsTrue(MetaverseHelper.TryToGetMVEntryByActiveDirectoryDN(dn, out mvEntryFoundByDN));</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">// Make sure that the two queries above returned the same MVEntry, thus confirming the join.

Assert.IsTrue(mventryFoundByGUID.object_id == mvEntryFoundByEmployeeID.object_id);
</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">// As an extra check, confirm that the csEntry corresponding the AD DN is in fact linked to the MVEntry 
</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">Assert.IsTrue(ConnectorSpaceHelper.IsCsEntryConnectedToMVEntry(
		mvEntryFoundByDN.object_id,
 		dn,
		ActiveDirectoryMAName);
</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&#160;</pre>

<h2>Important Note on accessing FIMSynchronization database</h2>

<p>Sample code provided in this blog makes direct calls to the FIMSynchronizationService database. Such direct access is not supported in the production environment, hence the samples provided here should only be used in a test environment.</p>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&#160;</pre>

<h2>Metaverse Helper</h2>

<p>Physically FIM Metaverse manifests itself as mms_metaverse table in the FIMSynchronizationService database. Each Metaverse attribute is represented as a column in this table (ex. employeeID). Using Entity Framework, it is fairly simple to define helper methods to query this table.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6648.image_3889E4CC.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6648.image_5F00_3889E4CC.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8306.image_thumb_4921DFBA.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8306.image_5F00_thumb_5F00_4921DFBA.png" width="303" height="405" /></a></p>

<p>Sample below assumes that both employeeID and activeDirectoryDN (distinghuishedName) are flown into the Metaverse.</p>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"><font size="2">namespace FIMTestCasesDriver.EnvironmentHelpers.FIM
{
    using System;
    using System.Linq;

    public static class MetaverseHelper
    {
        private static readonly FIMEntities FIMEntities = new FIMEntities();
        
        public static bool TryToGetMVEntryByEmployeeID(string employeeID, out mms_metaverse mvEntryOut)
        {
            try
            {
                mvEntryOut = FIMEntities.mms_metaverse.AsNoTracking().Single(<br />&#160;&#160; mvEntry =&gt; mvEntry.employeeID == employeeID);
                return true;
            }
            catch (Exception)
            {
                mvEntryOut = null;
                return false;
            }
        }

        public static bool TryToGetMVEntryByActiveDirectoryDN(string dn, out mms_metaverse mvEntryOut)
        {
                      
            try
            {
                mvEntryOut = FIMEntities.mms_metaverse.AsNoTracking().Single(
                    mvEntry =&gt; mvEntry.activeDirectoryDN == dn);
                return true;
            }
            catch (Exception)
            {
                mvEntryOut = null;
                return false;
            }
        }
    }
}</font>
</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&#160;</pre>

<p><span style="font-family: segoe ui;" face="Segoe UI">See my other </span><a href="https://blogs.msdn.com/b/alextch/archive/2012/07/09/testing-with-entity-framework-dbcontext-and-notracking-option.aspx"><span style="font-family: segoe ui;" face="Segoe UI">post</span></a>&#160;<span style="font-family: segoe ui;" face="Segoe UI">for the explanation on why the AsNoTracking option was used.</span></p>

<h2>Asserting Referential Relationship in Metaverse</h2>

<p>Often FIM is required to maintain or calculate hierarchical relationships. In order to write integration tests, which validate our reference building logic we will need another helper method. </p>

<p>Internally FIM maintains referential relationships in the mms_mv_link table, which has a very simple structure. For example, the first row of the sample data depicted in the screenshot could be interpreted as – MVEntry identified as CFD95…. is a direct report of an MVEntry of CBD95… The object_id and reference_id could in turn be linked to the mms_metaverse table to get additional information.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1460.image_62EC680E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1460.image_5F00_62EC680E.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8637.image_thumb_27B88C43.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8637.image_5F00_thumb_5F00_27B88C43.png" width="611" height="434" /></a></p>

<h3>Testing Pattern</h3>

<p>In the <em>arrange</em> part of the test, we would set a reference attribute value in a connected system. The sample below creates a new AD account by using a helper class ActiveDirectoryStateMachine, and links this account to an existing account by populating value of <em>manager</em> attribute. This is followed by a series of Asserts, which ensure that we are dealing with a brand new account for the direct report, and that the MVEntry for the manager exists.</p>

<p>Execute FIM Run profiles - RunProfileInvoker.RunFullCycle();</p>

<p>The <em>assertion</em> part of the test uses the MetaverseHelper function DoesReferenceRelationshipExist, which takes as an input MVEntries of the origin of the reference (direct report) and the destination (manager), plus the name of the attribute on which the referential relationship is built. To get the MVEntries of the objects in question, we leverage the TryToGetMVEntryByActiveDirectoryDN helper method.</p>

<p><font size="2">[TestClass]
    <br />&#160;&#160;&#160; public class FIMShouldReflectManagerToDirectReportsRelationshipFeature : SyncTestHarness

    <br />&#160;&#160;&#160; {

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; private mms_metaverse mvEntryManager;</font></p>
<font size="2"></font>

<p><font size="2">&#160;&#160;&#160;&#160;&#160;&#160;&#160; [TestInitialize]
    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void TestSetup()

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ActiveDirectoryStateMachine.TransitionFromNotInADToEnabled();

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var managerDN = (string)ActiveDirectoryStateMachine.GetAttributeValue(&quot;manager&quot;);

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Assert.IsFalse(string.IsNullOrEmpty(managerDN));

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; mms_metaverse mvEntry;

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Assert.IsFalse(MetaverseHelper.TryToGetMVEntryByActiveDirectoryDN(

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ActiveDirectoryStateMachine.DistinguishedName,

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; out mvEntry));

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Assert.IsTrue(MetaverseHelper.TryToGetMVEntryByActiveDirectoryDN(

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; managerDN,

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; out mvEntryManager));

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</font></p>
<font size="2"></font>

<p><font size="2">&#160;&#160;&#160;&#160;&#160;&#160;&#160; [TestMethod]
    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void FIMConsumesManagerInfoFromAD()

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; RunProfileInvoker.RunFullCycle();</font></p>
<font size="2"></font>

<p><font size="2">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; mms_metaverse mvEntryDirectReport;
    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Assert.IsTrue(MetaverseHelper.TryToGetMVEntryByActiveDirectoryDN(

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ActiveDirectoryStateMachine.DistinghuishedName,

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; out mvEntryDirectReport));</font></p>
<font size="2"></font>

<p><font size="2">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Assert.IsTrue(MetaverseHelper.DoesReferenceRelationshipExist(
    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; mvEntryDirectReport,

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; mvEntryManager, 

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; GlobalSettingsConfig.MVAttributeNames.ManagerAttributeName));

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }

    <br />&#160;&#160;&#160; }</font></p>

<p><font size="2">// The function below assumes that the mms_mv_link was imported into your project</font></p>

<p><font size="2">// See Appendix for details on connecting to the FIMSynchronizationService database via EntityFramework</font></p>

<p><font size="2">public static bool DoesReferenceRelationshipExist(
    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; mms_metaverse source,

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; mms_metaverse destination,

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string attributeName)

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (from reference in FIMEntities.mms_mv_link

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; where reference.attribute_name.Equals(attributeName) &amp;&amp;

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; reference.object_id == source.object_id &amp;&amp;

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; reference.reference_id == destination.object_id

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; select reference).Any();

    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</font></p>

<h2>ConnectorSpaceHelper</h2>

<p>This class makes use of three tables:</p>

<ul>
  <li><strong>mms_connectorspace</strong> – where CSEntries are stored. There are several important points related to this table:</li>
</ul>

<ol>
  <ol>
    <li>The actually attribute values of a CsEntry are packaged in a binary blob stored in the hologram column. To decode this blob we need to use WMI call against MIIS_CSObject, see TryToGetCsEntryGuid function for details.</li>

    <li>The objectGUID which uniquely identifies a CSEntry, is not stored in a column, but is packaged inside the hologram blob, hence the need for WMI call. We need this GUID to validate a join.</li>

    <li>Only RDN of a CsEntry is stored in a column, which makes no difference in case of HR MA where the anchor is based on employeeID, but certainly something to keep in mind in case of AD MA.</li>

    <li>Since an MVEntry could be joined to multiple CsEntries in different connector spaces, MAGuid is also required for unique CsEntry object identification.</li>
  </ol>
</ol>

<blockquote>
  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6330.image_150D4067.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6330.image_5F00_150D4067.png"><img style="display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/2022.image_thumb_5AB1CA85.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/2022.image_5F00_thumb_5F00_5AB1CA85.png" width="717" height="322" /></a></p>
</blockquote>

<ul>
  <li>mms_csmv_link – where the links between CSEntries and MVEntries are recorded (both mvEntry and CsEntry objects are uniquely identified by a GUID). Each row in this table represents a join.</li>
</ul>

<blockquote>
  <p>mv_object_id comes from the mms_metaverse, and cs_object_id is stored in the mms_connectorspace (inside the hologram)</p>
</blockquote>

<blockquote>
  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0451.image_4A5652CC.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0451.image_5F00_4A5652CC.png"><img style="display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4744.image_thumb_56E3FFE8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4744.image_5F00_thumb_5F00_56E3FFE8.png" width="717" height="303" /></a></p>
</blockquote>

<ul>
  <li>mms_management_agent – we the information on the MAs is stored. We will only need to access this table to get the mapping between the MA name and MA GUID.</li>
</ul>

<blockquote>
  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5734.image_1BB0241D.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5734.image_5F00_1BB0241D.png"><img style="display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5756.image_thumb_1AD7BE33.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5756.image_5F00_thumb_5F00_1AD7BE33.png" width="341" height="121" /></a></p>

  <p>&#160;</p>
</blockquote>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">namespace FIMTestCasesDriver.EnvironmentHelpers.FIM
{
    using System;
    using System.Globalization;
    using System.Linq;
    using System.Management;

    public static class ConnectorSpaceHelper
    {
        private static readonly ManagementScope FIMWmiNameSpace =
            new ManagementScope(&quot;root\\MicrosoftIdentityIntegrationServer&quot;);

        private static readonly FIMEntities FIMEntities = new FIMEntities();

        public static bool IsCsEntryConnectedToMvEntry(
            Guid mvEntryGuid,
            string csEntryDN,
            string maName)
        {
            Guid csEntryGuid;
            Guid maGUID;

            if (!TryToGetMAGuid(maName, out maGUID))
            {
                throw new Exception(
                    string.Format(&quot;Unable to find MAGuid for MAName:{0} in TryToGetCsEntryGuid&quot;, maName));
            }

            if (!TryToGetCsEntryGuid(csEntryDN, maGUID, out csEntryGuid))
            {
                return false;
            }

            return (from link in FIMEntities.mms_csmv_link
                    where link.mv_object_id == mvEntryGuid &amp;&amp; link.cs_object_id == csEntryGuid
                    select link).Count() == 1;
        }

        private static bool TryToGetMAGuid(string maName, out Guid maGUID)
        {
            maGUID = (from ma in FIMEntities.mms_management_agent 
                      where ma.ma_name == maName 
                      select ma.ma_id).Single();
            return true;
        }

        private static bool TryToGetCsEntryGuid(
            string csEntryDN,
            Guid maGUID,
            out Guid csEntryGUID)
        {
            var csQueryString = string.Format(
                CultureInfo.CurrentCulture, &quot;DN='{0}' and MaGuid='{{{1}}}'&quot;, csEntryDN, maGUID);
                   
            var csQuery = new SelectQuery(&quot;MIIS_CSObject&quot;, csQueryString);
            var csSearcher = new ManagementObjectSearcher(FIMWmiNameSpace, csQuery);
            var csObjects = csSearcher.Get();

            if (csObjects.Count &gt; 1)
            {
                throw new Exception(string.Format(<br />&#160; &quot;Multiple connectors for the same DN detected{0}&quot;, csEntryDN));           </pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">	   }

            if (csObjects.Count == 0)
            {
                csEntryGUID = Guid.Empty;
                return false;
            }

            var guid = string.Empty;
            foreach (ManagementObject csObject in csObjects)
            {
                guid = csObject[&quot;Guid&quot;].ToString();
                break;
            }

            csEntryGUID = new Guid(guid);
            return true;
        }
    }
}
</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&#160;</pre>

<h2>Appendix</h2>

<h2>Connecting to FIMSynchronizationService database via Entity Framework</h2>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"> In order to get samples to work you will need to add FIM Sync Service Entity model into your test project</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">1. Using nuget add EntityFramework 4.1 into your test project</pre>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8473.image_7258DC1E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8473.image_5F00_7258DC1E.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1440.image_thumb_6A6139BC.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1440.image_5F00_thumb_5F00_6A6139BC.png" width="717" height="98" /></a></p>

<p>2. In your project add new item of type “ADO.NET Entity Data Model”</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/3583.image_0FEAB71E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/3583.image_5F00_0FEAB71E.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1524.image_thumb_60B8CB86.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1524.image_5F00_thumb_5F00_60B8CB86.png" width="717" height="512" /></a></p>

<p>3. Create a new SQL connection to the server which hosts FIM Sync database</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0044.image_460C2F6D.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0044.image_5F00_460C2F6D.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7206.image_thumb_2BCBC649.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7206.image_5F00_thumb_5F00_2BCBC649.png" width="528" height="477" /></a></p>

<p>4. Select the tables referenced in the samples</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8054.image_4165FEE6.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8054.image_5F00_4165FEE6.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5734.image_thumb_0E29C57D.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5734.image_5F00_thumb_5F00_0E29C57D.png" width="532" height="476" /></a></p>

<p>5. Once the model is imported navigate to the edmx file, right-click and select to add “Code Generation Item”</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1033.image_32DADCF4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1033.image_5F00_32DADCF4.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8877.image_thumb_30BDDE2B.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8877.image_5F00_thumb_5F00_30BDDE2B.png" width="717" height="368" /></a></p>

<p>6. Select “EF 4.X DbContext Generator”</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5734.image_58A0DD8A.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5734.image_5F00_58A0DD8A.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4670.image_thumb_7E2A5AEB.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4670.image_5F00_thumb_5F00_7E2A5AEB.png" width="717" height="512" /></a></p>

<h2>References</h2>

<p><a title="https://openldap-ma.sourceforge.net/" href="https://openldap-ma.sourceforge.net/">https://openldap-ma.sourceforge.net/</a>, the sample for decoding the hologram blob comes from this project.</p>]]></content:encoded>
    </item>
    <item>
      <title>Testing with Entity Framework dbContext, and NoTracking option</title>
      <link>https://docs.microsoft.com/archive/blogs/alextch/testing-with-entity-framework-dbcontext-and-notracking-option</link>
      <pubDate>Mon, 09 Jul 2012 07:19:27 GMT</pubDate>
      <dc:creator><![CDATA[Alex Tcherniakhovski]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alextch/2012/07/09/testing-with-entity-framework-dbcontext-and-notracking-option/</guid>
      <description><![CDATA[This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script...]]></description>
      <content:encoded><![CDATA[<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"><blockquote><p><font size="1">This posting is provided "AS IS" with no warranties, and confers no rights. </font></p><pre><font size="1">Use of included script samples are subject to the terms specified at </font><a href="https://www.microsoft.com/info/cpyright.htm"><font size="1">https://www.microsoft.com/info/cpyright.htm</font></a></pre><pre>During unit or integration tests, which involve database modifications, the following pattern is often utilized - </pre><pre>var preChangeIntroducedValue = GetValueFromDB();</pre><pre>// introduce change</pre><pre>var postChangeIntoroducedValue = GetValueFromDB();</pre><pre>// Assert something about the relationship between pre and post values</pre><pre>If using Entity Framework for accessing database, it is important to remember that if the value in the database</pre><pre>changes between the calls to GetValueFromDB, Entity Framework will return the value originally placed into the </pre><pre>preChangeIntroduceValue, hence your tests will be probably fail, even though the logic might be correct. The reason</pre><pre>for this is the cashing/tracking mechanism built-in into Entity Framework. To address this use AsNoTracking</pre><pre>option as illustrated by the example below.</pre><pre>&nbsp;</pre><pre>        private static readonly FIMEntities FIMEntities = new FIMEntities();
</pre><p>             
        public static bool TryToGetMVEntryByEmployeeID(string employeeID, out mms_metaverse mvEntryOut)
        {
            try
            {
                mvEntryOut = FIMEntities.mms_metaverse.<strong>AsNoTracking().</strong>Single(mvEntry =&gt; mvEntry.employeeID == employeeID);
                return true;
            }
            catch (Exception)
            {
                mvEntryOut = null;
                return false;
            }
        </p></pre><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>References:</p><p><a href="https://blogs.msdn.com/b/adonet/archive/2011/02/05/using-dbcontext-in-ef-feature-ctp5-part-11-load-and-asnotracking.aspx">Using DbContext in EF 4.1 Part 11: Load and AsNoTracking</a></p></blockquote>]]></content:encoded>
    </item>
    <item>
      <title>Sample C# code to invoke execution of a run profile on Forefront Identity Server Synchronization Service</title>
      <link>https://docs.microsoft.com/archive/blogs/alextch/sample-c-code-to-invoke-execution-of-a-run-profile-on-forefront-identity-server-synchronization-service</link>
      <pubDate>Fri, 06 Jul 2012 07:04:09 GMT</pubDate>
      <dc:creator><![CDATA[Alex Tcherniakhovski]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alextch/2012/07/06/sample-c-code-to-invoke-execution-of-a-run-profile-on-forefront-identity-server-synchronization-service/</guid>
      <description><![CDATA[During integration testing of FIM Synchronization Service it is often useful to programmatically...]]></description>
      <content:encoded><![CDATA[<!--more--><div align="left"><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">During integration testing of FIM Synchronization Service it is often useful to programmatically invoke run profiles of </pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">FIM Sync Service, and later query the Metaverse and/or Connector spaces for the results of the run to validate proper </pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">rule execution. The sample below shows how to programmatically invoke run profiles.</pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">Note that profiles run synchronously. </pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&nbsp;</pre></div><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"><font size="1">This posting is provided "AS IS" with no warranties, and confers no rights. </font></pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"><font size="1">Use of included script samples are subject to the terms specified at </font><a href="https://www.microsoft.com/info/cpyright.htm"><font size="1">https://www.microsoft.com/info/cpyright.htm</font></a></pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&nbsp;</pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">namespace FIMTestCasesDriver.EnvironmentHelpers.FIM
{
    using System.Management;

    public static class RunProfileInvoker
    {
        private const string FimSyncServiceWMINameSpace = "root\\MicrosoftIdentityIntegrationServer";
        private const string FimSyncServiceMAObjectSpace = "MIIS_ManagementAgent.Name";

        private const string FullImportAndFullSyncProfileName = "full import and full sync";

        private const string ExportAndDeltaImportStageOnlyProfileName = "export and delta import stage only";

        private const string ActiveDirectoryMAName = "AD";
        private const string ADLDSMAName = "ADLDS";
        private const string HRMAName = "HR";
        private const string RegistrationMAName = "Registration";

        public static void RunFullCycle()
        {
            RunProfile(
                ActiveDirectoryMAName,
                FullImportAndFullSyncProfileName);

            RunProfile(
                RegistrationMAName,
                FullImportAndFullSyncProfileName);

            RunProfile(
                HRMAName,
                FullImportAndFullSyncProfileName);

            RunProfile(
                ActiveDirectoryMAName,
                ExportAndDeltaImportStageOnlyProfileName);

            RunProfile(
                ADLDSMAName,
                ExportAndDeltaImportStageOnlyProfileName);
        }

        private static void RunProfile(
            string maName,
            string runProfileName)
        {
            var managementObject = new ManagementObject(
                FimSyncServiceWMINameSpace,
                string.Format("{0}=" + "'{1}'", FimSyncServiceMAObjectSpace, maName),
                null);
            var inParameters = managementObject.GetMethodParameters("Execute");
            inParameters["RunProfileName"] = runProfileName;
            managementObject.InvokeMethod("Execute", inParameters, null);
        }
    }
}
</pre>]]></content:encoded>
    </item>
    <item>
      <title>How to set Active Directory Password from Java application</title>
      <link>https://docs.microsoft.com/archive/blogs/alextch/how-to-set-active-directory-password-from-java-application</link>
      <pubDate>Tue, 15 May 2012 07:46:57 GMT</pubDate>
      <dc:creator><![CDATA[Alex Tcherniakhovski]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alextch/2012/05/15/how-to-set-active-directory-password-from-java-application/</guid>
      <description><![CDATA[&#160;  This posting is provided &quot;AS IS&quot; with no warranties, and confers no rights. Use of...]]></description>
      <content:encoded><![CDATA[<h3>&#160;</h3>  <p>This posting is provided &quot;AS IS&quot; with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at <a href="https://www.microsoft.com/info/cpyright.htm">https://www.microsoft.com/info/cpyright.htm</a></p>  <h4>Business Scenario</h4>  <p>Many Java applications now utilize Active Directory as a source of authentication, in some situations it may be required to set Active Directory password from within Java applications. I encountered a scenario where majority of the users of a Java application were on Active Directory, but for a small percentage of users that do not log-in to Active Directory from their desktops we needed to provide a functionality within the application to set user passwords. </p>  <!--more-->    <h4>Prerequisites</h4>  <ul>   <li>This scenario was only tested against a Windows 2003 Domain </li>    <li>JKD 1.5.0_03 was used to run the sample code </li>    <li>You will need to connect to Active Directory with a user account that has permissions to reset passwords </li>    <li>PKI Certificates used in this scenario were issued by Microsoft Certificate Server configured in Active Directory integrated mode</li> </ul>  <h4>Setup SSL trust between Active Directory Domain Controller(s) and Java application</h4>  <p>Active Directory Domain Controllers will only allow password set operations over an SSL channel, therefore both parties should have a common trusted root certificate in their certificate stores. The simplest way to accomplish this is to export a trusted root certificate from a Domain Controller and import it into Java certificate store on the client machine. </p>  <h5>Configuring SSL on Active Directory Domain Controllers</h5>  <p>Active Directory Domain Controllers automatically enroll for domain controller certificate and utilize it for secure LDAP communications if Active Directory integrated Microsoft Certificate Server is deployed within the Forest. So in other words, if you deployed Microsoft Certificate Server in Active Directory integrated mode, then you don't need to do anything else on Active Directory side, all domain controllers will use SSL on port 636.</p>  <p>For instructions on how to setup Microsoft Certificate Server follow this <a href="https://www.microsoft.com/technet/prodtechnol/windowsserver2003/library/ServerHelp/7a2c636a-bf86-479a-8729-d9b005514ee6.mspx">link</a>.</p>  <h5>Importing Trusted Root Certificate on a Java client machine</h5>  <p>On the client side we need to import a mutually trusted root certificate into Java certificate store. In our case we will export the root certificate issued by Microsoft Certificate Server and import it into Java store on the client.</p>  <p>1. On a Domain Controller log-in as an administrator and open Internet Explorer. Go to Tools-&gt;Internet Options-&gt;Content and click on Certificates</p>  <p><img border="0" src="https://alextch.members.winisp.net/resetadpasswordfromjava/IE01.jpg" width="399" height="446" /></p>  <p>2. Switch to Trusted Root Certificate Authorities Tab and Select the certificate issued by your Active Directory integrated Certificate Server. Click on Export</p>  <p><img border="0" src="https://alextch.members.winisp.net/resetadpasswordfromjava/IE02.jpg" width="500" height="458" /></p>  <p>3. Choose Base-64 encoded X.509(.CER)</p>  <p><img border="0" src="https://alextch.members.winisp.net/resetadpasswordfromjava/IE03.jpg" width="497" height="378" /></p>  <p>4. Specify file name for the exported certificate</p>  <p><img border="0" src="https://alextch.members.winisp.net/resetadpasswordfromjava/IE04.jpg" width="500" height="382" /></p>  <p>5. Finish the export and copy the exported .cer file to the Java client machine</p>  <p>6. At the client machine execute the following command. </p>  <p><img border="0" src="https://alextch.members.winisp.net/resetadpasswordfromjava/keytool.jpg" width="641" height="154" /></p>  <p>Note the location of the jks file, you will need to reference it later on in the code.</p>  <p>Alias and keystore password are arbitrary values</p>  <h4>Sample program to change Active Directory user password from Java</h4>  <p>Now that SSL staff is out of the way compile this sample code and run it from the Java client</p>  <p>This code was developed by <a href="https://homepages.ucalgary.ca/~mortis/">Jeremy Mortis</a> here is link to the <a href="https://homepages.ucalgary.ca/~mortis/software/ADConnection.txt">original code</a></p>  <p>import javax.naming.*;   <br />import javax.naming.directory.*;    <br />import javax.naming.ldap.*;    <br />import java.util.*;    <br />import java.security.*;    <br />public class ADConnection {    <br />DirContext ldapContext;    <br />String baseName = &quot;,cn=users,DC=fabrikam,DC=com&quot;;    <br />String serverIP = &quot;10.1.1.7&quot;;    <br />public ADConnection() {    <br />try {    <br />Hashtable ldapEnv = new Hashtable(11);    <br />ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, &quot;com.sun.jndi.ldap.LdapCtxFactory&quot;);    <br />ldapEnv.put(Context.PROVIDER_URL, &quot;ldap://&quot; + serverIP + &quot;:636&quot;);    <br />ldapEnv.put(Context.SECURITY_AUTHENTICATION, &quot;simple&quot;);    <br />ldapEnv.put(Context.SECURITY_PRINCIPAL, &quot;cn=administrator&quot; + baseName);    <br />ldapEnv.put(Context.SECURITY_CREDENTIALS, &quot;PA$$w0rd&quot;);    <br />ldapEnv.put(Context.SECURITY_PROTOCOL, &quot;ssl&quot;);    <br />ldapContext = new InitialDirContext(ldapEnv);    <br />}    <br />catch (Exception e) {    <br />System.out.println(&quot; bind error: &quot; + e);    <br />e.printStackTrace();    <br />System.exit(-1);    <br />}    <br />}    <br />public void updatePassword(String username, String password) {    <br />try {    <br />String quotedPassword = &quot;\&quot;&quot; + password + &quot;\&quot;&quot;;    <br />char unicodePwd[] = quotedPassword.toCharArray();    <br />byte pwdArray[] = new byte[unicodePwd.length * 2];    <br />for (int i=0; i&lt;unicodePwd.length; i++) {    <br />pwdArray[i*2 + 1] = (byte) (unicodePwd[i] &gt;&gt;&gt; 8);    <br />pwdArray[i*2 + 0] = (byte) (unicodePwd[i] &amp; 0xff);    <br />}    <br />ModificationItem[] mods = new ModificationItem[1];    <br />mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,    <br />new BasicAttribute(&quot;UnicodePwd&quot;, pwdArray));    <br />ldapContext.modifyAttributes(&quot;cn=&quot; + username + baseName, mods);    <br />}    <br />catch (Exception e) {    <br />System.out.println(&quot;update password error: &quot; + e);    <br />System.exit(-1);    <br />}    <br />}    <br />public static void main(String[] args) {    <br />Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());    <br />// the keystore that holds trusted root certificates    <br />System.setProperty(&quot;javax.net.ssl.trustStore&quot;, &quot;c:\\myCaCerts.jks&quot;);    <br />System.setProperty(&quot;javax.net.debug&quot;, &quot;all&quot;);    <br />ADConnection adc = new ADConnection();    <br />adc.updatePassword(&quot;Java User2&quot;, <a href="mailto:pass@word3">pass@word3</a>);    <br />}    <br />}</p>]]></content:encoded>
    </item>
    <item>
      <title>Sample C# code to create SHA1 Salted (SSHA) password hashes for OpenLDAP</title>
      <link>https://docs.microsoft.com/archive/blogs/alextch/sample-c-code-to-create-sha1-salted-ssha-password-hashes-for-openldap</link>
      <pubDate>Sat, 12 May 2012 07:36:32 GMT</pubDate>
      <dc:creator><![CDATA[Alex Tcherniakhovski]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alextch/2012/05/12/sample-c-code-to-create-sha1-salted-ssha-password-hashes-for-openldap/</guid>
      <description><![CDATA[This posting is provided &quot;AS IS&quot; with no warranties, and confers no rights.

Use of...]]></description>
      <content:encoded><![CDATA[<pre><em>This posting is provided &quot;AS IS&quot; with no warranties, and confers no rights.</em></pre>

<pre><em>Use of included script samples are subject to the terms specified at </em><a href="https://www.microsoft.com/info/cpyright.htm"><em>https://www.microsoft.com/info/cpyright.htm</em></a> </pre>

<pre>&#160;</pre>

<p>Since SSHA (Salted SHA1) is now most commonly used in storing password hashes in OpenLDAP, folks who need to create accounts on this system from .NET (ex. Forefront Identity Manager FIM), may find this sample useful. </p>

<!--more-->

<p>&#160;</p>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&#160;</pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">      public static string GenerateSaltedSHA1(string plainTextString)
      {
            HashAlgorithm algorithm = new SHA1Managed();
            var saltBytes = GenerateSalt(4);
            var plainTextBytes = Encoding.ASCII.GetBytes(plainTextString);

            var plainTextWithSaltBytes = AppendByteArray(plainTextBytes, saltBytes);
            var saltedSHA1Bytes = algorithm.ComputeHash(plainTextWithSaltBytes);
            var saltedSHA1WithAppendedSaltBytes = AppendByteArrays(saltedSHA1Bytes, saltBytes);
           
            return &quot;{SSHA}&quot; + Convert.ToBase64String(saltedSHA1WithAppendedSaltBytes);
      } 

        
       private static byte[] GenerateSalt(int saltSize)
       {
            var rng = new RNGCryptoServiceProvider();
            var buff = new byte[saltSize];
            rng.GetBytes(buff);
            return buff; 
       }
</pre>

<blockquote>
  <pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"> private static byte[] AppendByteArray(byte[] byteArray1, byte[] byteArray2)
 {
      var byteArrayResult =
              new byte[byteArray1.Length + byteArray2.Length];

      for (var i = 0; i &lt; byteArray1.Length; i++)
           byteArrayResult[i] = byteArray1[i];
      for (var i = 0; i &lt; byteArray2.Length; i++)
           byteArrayResult[byteArray1.Length + i] = byteArray2[i];

      return byteArrayResult;
  }
  </pre>
</blockquote>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&#160;</pre>

<h2>References</h2>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"><a href="https://www.obviex.com/samples/hash.aspx">How To: Hash Data with Salt (C#/VB.NET)</a>  </pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"><b><a href="https://www.openldap.org/faq/data/cache/347.html">What are {SHA} and {SSHA} passwords and how do I generate them? (from OpenLDAP documentation)</a></b></pre>

<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"><strong></strong>&#160;</pre>]]></content:encoded>
    </item>
    <item>
      <title>Sample code to query OpenLDAP directory via .NET System.DirectoryServices.Protocols</title>
      <link>https://docs.microsoft.com/archive/blogs/alextch/sample-code-to-query-openldap-directory-via-net-system-directoryservices-protocols</link>
      <pubDate>Mon, 07 May 2012 07:00:22 GMT</pubDate>
      <dc:creator><![CDATA[Alex Tcherniakhovski]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alextch/2012/05/07/sample-code-to-query-openldap-directory-via-net-system-directoryservices-protocols/</guid>
      <description><![CDATA[This posting is provided "AS IS" with no warranties, and confers no rights.Use of included script...]]></description>
      <content:encoded><![CDATA[<pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"><em><font size="1">This posting is provided "AS IS" with no warranties, and confers no rights.</font></em></pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;"><em><font size="1">Use of included script samples are subject to the terms specified at </font></em><a href="https://www.microsoft.com/info/cpyright.htm"><em><font size="1">https://www.microsoft.com/info/cpyright.htm</font></em></a> </pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">The sample code below provides a helper class, which performs a paged search against an LDAP directory.</pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">I tested this code against OpenLDAP 2.4.31. The code is based on the samples provided by Ethan Wilansky, </pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">see link at the end of the post. </pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&nbsp;</pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">using System.Collections.Generic;
using System.DirectoryServices.Protocols;
using System.Globalization;
using System.Net;
using System.Security;

namespace OpenLDAPNextUID
{
    public class LDAPHelper
    {
        private readonly LdapConnection ldapConnection;
        private readonly string searchBaseDN;
        private readonly int pageSize;

        public LDAPHelper(
            string searchBaseDN,
            string hostName,
            int portNumber,
            AuthType authType,
            string connectionAccountName,
            SecureString connectionAccountPassword,
            int pageSize)
        {
            
            var ldapDirectoryIdentifier = new LdapDirectoryIdentifier(
                hostName,
                portNumber,
                true,
                false);
            
            var networkCredential = new NetworkCredential(
                connectionAccountName,
                connectionAccountPassword);

            ldapConnection = new LdapConnection(
                ldapDirectoryIdentifier,
                networkCredential) 
                {AuthType = authType};

            ldapConnection.SessionOptions.ProtocolVersion = 3;
            
            this.searchBaseDN = searchBaseDN;
            this.pageSize = pageSize;
        }

        public IEnumerable&lt;SearchResultEntryCollection&gt; PagedSearch(
            string searchFilter,
            string[] attributesToLoad)
        {

            var pagedResults = new List&lt;SearchResultEntryCollection&gt;();

            var searchRequest = new SearchRequest
                    (searchBaseDN,
                     searchFilter,
                     SearchScope.Subtree,
                     attributesToLoad);


            var searchOptions = new SearchOptionsControl(SearchOption.DomainScope);
            searchRequest.Controls.Add(searchOptions);

            var pageResultRequestControl = new PageResultRequestControl(pageSize);
            searchRequest.Controls.Add(pageResultRequestControl);

            while (true)
            {
                var searchResponse = (SearchResponse)ldapConnection.SendRequest(searchRequest);
                var pageResponse = (PageResultResponseControl)searchResponse.Controls[0];

                yield return searchResponse.Entries;
                if (pageResponse.Cookie.Length == 0)
                    break;

                pageResultRequestControl.Cookie = pageResponse.Cookie;
            }

            
        }
    }
}
</pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&nbsp;</pre><h2>Example of using the helper class</h2><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">using System;
using System.DirectoryServices.Protocols;
using System.Security;

namespace OpenLDAP
{
    class Program
    {
        static void Main(string[] args)
        {
            var password = new[]{'P','a','s','s','w','@','r','d'};
            var secureString = new SecureString();
            foreach (var character in password)
                secureString.AppendChar(character);

            var baseOfSearch = "dc=fabrikam,dc=com";
            var ldapHost = "ubuntu.fabrikam.com";
            var ldapPort = 636; //SSL
            var connectAsDN = "cn=admin,dc=fabrikam,dc=com";
            var pageSize = 1000;

            var openLDAPHelper = new LDAPHelper(
                baseOfSearch,
                ldapHost,
                ldapPort,
                AuthType.Basic, 
                connectAsDN,
                secureString,
                pageSize);

            var searchFilter = "nextUID=*";
            var attributesToLoad = new[] {"nextUID"};
            var pagedSearchResults = openLDAPHelper.PagedSearch(
                searchFilter,
                attributesToLoad);

            foreach (var searchResultEntryCollection in pagedSearchResults)
                foreach (SearchResultEntry searchResultEntry in searchResultEntryCollection)
                    Console.WriteLine(searchResultEntry.Attributes["nextUID"][0]);

            Console.Read();

        }
    }
}
</pre><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&nbsp;</pre><h3>Links</h3><p><a href="https://msdn.microsoft.com/en-us/library/bb332056.aspx">Introduction to System.DirectoryServices.Protocols (S.DS.P) by Ethan Wilansky</a></p><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">&nbsp;</pre>]]></content:encoded>
    </item>
    <item>
      <title>Configuring OpenLDAP pass-through authentication to Active Directory</title>
      <link>https://docs.microsoft.com/archive/blogs/alextch/configuring-openldap-pass-through-authentication-to-active-directory</link>
      <pubDate>Wed, 25 Apr 2012 18:25:47 GMT</pubDate>
      <dc:creator><![CDATA[Alex Tcherniakhovski]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alextch/2012/04/25/configuring-openldap-pass-through-authentication-to-active-directory/</guid>
      <description><![CDATA[This posting is provided &quot;AS IS&quot; with no warranties, and confers no rights. Use of...]]></description>
      <content:encoded><![CDATA[<p>This posting is provided &quot;AS IS&quot; with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm </p>  <p>From <a href="https://www.openldap.org/doc/admin24/security.html#Pass-Through authentication">OpenLDAP 2.4 Administration guide</a><em>, “Since OpenLDAP 2.0 slapd has had the ability to delegate password verification to a separate process. This uses the sasl_checkpass function so it can use any back-end server that Cyrus SASL supports for checking passwords. The choice is very wide, as one option is to use saslauthd(8) which in turn can use local files, Kerberos, an IMAP server, another LDAP server, or anything supported by the PAM mechanism”.</em></p>  <p>This particular functionality of OpenLDAP should be of special interest for environments where long term co-existence between OpenLDAP and Active Directory is required. By establishing pass-through authentication the following advantages could be achieved:</p>  <ul>   <li>Great end-user experience. No need to remember multiple passwords</li>    <li>Increased security, due to the reduction of the attack surface (one less password store in the environment)</li>    <li>Single password policy</li> </ul>  <p>The rest of the post will expand on the instructions provided by the <a href="https://www.openldap.org/doc/admin24/security.html#Pass-Through authentication">OpenLDAP 2.4 Administration guide</a> on establishing pass-through authentication from OpenLDAP to Active Directory. Specifically, will will leverage the capability of SASL to use LDAP as an authentication back-end. In our case, Active Directory will play a role of such authentication back-end.</p>  <h2>Lab environment used for documenting the steps</h2>  <ul>   <li>OpenLDAP version of 2.4.25 running on Ubuntu Server 11</li>    <li>OpenLDAP was installed and configured using <a href="https://help.ubuntu.com/11.10/serverguide/openldap-server.html">Ubuntu OpenLDAP Server documentation page</a></li>    <li>Active Directory on Windows Server 2008 R2</li> </ul>  <h2>Active Directory Configuration</h2>  <p>In order to secure authentication requests coming from OpenLDAP to Active Directory we need to ensure that LDAPS (Secure LDAP) is enabled on Active Directory Domain Controllers.</p>  <p>If you already established Windows based PKI, specifically Active Directory Enterprise CA, your Domain Controllers are already listening on LDAPS port. This occurs automatically, via auto-enrollment process.</p>  <p>You can confirm check whether your Domain Controllers are listening on LDAPS port by: </p>  <p>1. Checking local certificate store on a domain controller, and ensuring that there is a certificate with the template of DomainController. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8255.image_09B1404C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8255.image_5F00_09B1404C.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8664.image_thumb_567506E2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8664.image_5F00_thumb_5F00_567506E2.png" width="540" height="337" /></a></p>  <p>2. Launching<em> lpd.exe</em>, and choosing SSL option</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/3465.image_0D6EE51C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/3465.image_5F00_0D6EE51C.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7178.image_thumb_33D0C867.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7178.image_5F00_thumb_5F00_33D0C867.png" width="352" height="237" /></a></p>  <p>In case of a successful connection you should see output similar to this</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1212.image_60E5B535.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1212.image_5F00_60E5B535.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4527.image_thumb_6B36D995.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4527.image_5F00_thumb_5F00_6B36D995.png" width="568" height="178" /></a></p>  <p>&#160;</p>  <p>For details on configuring PKI on Windows Server 2008 see <a href="https://technet.microsoft.com/en-us/library/cc772393(v=ws.10).aspx">Technet documentation</a></p>  <p>If you leverage PKI on a non-Windows based platform, see <a href="https://support.microsoft.com/kb/321051">this article</a> on how to enable LDAPS using 3rd party certificates on Active Directory Domain Controllers.</p>  <h2>&#160;</h2>  <h2>Building CA trust to Active Directory CA</h2>  <p>LDAP client on the OpenLDAP server will need to validate the chain of trust of the certificates utilized by the Domain Controllers. </p>  <p>To be more specific the TLS_CACERT directive in the <em>/etc/ldap/ldap.conf</em> needs to point to a certificate of a CA, which signed the SSL certificates for the Active Directory Domain Controllers. If a multi-tiered CA structure is utilized, then all certificates of the CAs in the chain need to be included in the <a href="https://support.ssl.com/index.php?/Knowledgebase/Article/View/19">PEM encoded</a> certificate.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7167.image_0A0D4D74.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7167.image_5F00_0A0D4D74.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8228.image_thumb_229CEAC4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8228.image_5F00_thumb_5F00_229CEAC4.png" width="420" height="52" /></a></p>  <p>In this walkthrough I will assume that OpenLDAP is utilizing an SSL certificates signed by a CA, different from the CA utilized in the Active Directory environment. TLS_CACERT directive points to a certificate of this CA utilized in the Unix environment.</p>  <p>To accommodate this scenario, we need to make the LDAP client on the OpenLDAP server trust both CAs: the one which singed the certificate for the OpenLDAP server, and the CA which singed the certificates for the Domain Controllers. We will leverage the fact that PEM encoded certificates can contain multiple entries.</p>  <h3>Exporting Active Directory Root CA certificate and making it available on the OpenLDAP server</h3>  <p>1. Locate the certificate of the CA which signed the SSL certificates of the Domain Controller.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0724.image_6FCCE44F.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0724.image_5F00_6FCCE44F.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4503.image_thumb_6E884B70.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4503.image_5F00_thumb_5F00_6E884B70.png" width="571" height="330" /></a></p>  <p>2. Export it in Base-64 encoded format</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1768.image_0C1A2670.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1768.image_5F00_0C1A2670.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4571.image_thumb_7245F040.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4571.image_5F00_thumb_5F00_7245F040.png" width="484" height="432" /></a></p>  <p>3. Save the certificate </p>  <p>4. Copy the certificate to the OpenLDAP server. I used <a href="https://winscp.net/eng/index.php">WinSCP</a> to accomplish this.</p>  <p>5. Concatenate the two certificates into a new joined one.</p>  <p>In this example /etc/ssl/certs/cacert.pem is the certifcate of the CA which signed the SSL cert for OpenLDAP and ad.cer is the certificate we copied in the previous step.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7711.image_228CC4F7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7711.image_5F00_228CC4F7.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/3414.image_thumb_500DE4BA.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/3414.image_5F00_thumb_5F00_500DE4BA.png" width="551" height="66" /></a></p>  <p>If you open the resulting PEM file in a text editor you should see two sections of “BEGIN CERTIFICATE” </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7282.image_7D22D188.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7282.image_5F00_7D22D188.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1488.image_thumb_2D69A63F.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1488.image_5F00_thumb_5F00_2D69A63F.png" width="352" height="426" /></a></p>  <p>5. Update TLS_CACERT directive to point to the new “joined” certificate</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4628.image_6965C227.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4628.image_5F00_6965C227.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/2475.image_thumb_16E6E1EB.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/2475.image_5F00_thumb_5F00_16E6E1EB.png" width="462" height="65" /></a></p>  <p>6. At this stage you should be able to issue a query over SSL to a Domain Controller. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6366.image_4F255903.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6366.image_5F00_4F255903.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8836.image_thumb_4799E996.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8836.image_5F00_thumb_5F00_4799E996.png" width="514" height="70" /></a></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0728.image_3FA24734.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0728.image_5F00_3FA24734.png"><img style="margin: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4604.image_thumb_6D2366F7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4604.image_5F00_thumb_5F00_6D2366F7.png" width="207" height="122" /></a></p>  <p>The example above assumes that DNS resolution works across Windows and Unix environments. Remember that SSL certificates are sensitive to host names, hence the name of the host (-H parameter in the query) should match the subject name in the certificate</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0486.image_534F30C8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0486.image_5F00_534F30C8.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0871.image_thumb_64535EAB.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0871.image_5F00_thumb_5F00_64535EAB.png" width="586" height="370" /></a></p>  <h2>Configure SASLAUTHD</h2>  <p>1. Install SASL command-line tools. Other components of SASLAUTHD are installed as part of OpenLDAP installation.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6747.image_7412F3AF.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6747.image_5F00_7412F3AF.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/2626.image_thumb_486229B3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/2626.image_5F00_thumb_5F00_486229B3.png" width="348" height="39" /></a></p>  <h3>Configure SASLAUTHD via <em>/etc/default/saslautd</em></h3>  <p>Set automatic start of the SASLAUTHD service</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5756.image_0D9A80DD.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5756.image_5F00_0D9A80DD.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6811.image_thumb_6587D1BD.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6811.image_5F00_thumb_5F00_6587D1BD.png" width="488" height="49" /></a></p>  <p>Enable LDAP authentication mechanism</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/2117.image_15CEA674.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/2117.image_5F00_15CEA674.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/3666.image_thumb_1BA94A0D.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/3666.image_5F00_thumb_5F00_1BA94A0D.png" width="421" height="61" /></a></p>  <h3>Give OpenLDAP service account access to SASLAUTHD service </h3>  <p>1. To determine the account under which SLAPD is running check SLAPD_USER parameter in <em>/etc/default/slapd</em></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6862.image_0BBA0549.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6862.image_5F00_0BBA0549.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8831.image_thumb_0592B8AE.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8831.image_5F00_thumb_5F00_0592B8AE.png" width="706" height="232" /></a></p>  <p>2.&#160; Add OpenLDAP service account to the sasl group</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/2158.image_3494F485.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/2158.image_5F00_3494F485.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/3323.image_thumb_05CF3BE3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/3323.image_5F00_thumb_5F00_05CF3BE3.png" width="348" height="33" /></a></p>  <h2>Setup up connection and search parameters to Active Directory for SASLAUTHD</h2>  <p>Create and edit /etc/saslauthd.conf</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5270.image_320BC2C7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5270.image_5F00_320BC2C7.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1145.image_thumb_377A336B.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1145.image_5F00_thumb_5F00_377A336B.png" width="693" height="130" /></a></p>  <p>In this above sample configuration:</p>  <ul>   <li><em>tfs.fabrikam.com</em> is an Active Directory domain controller. Multiple ldaps urls could be specified.</li>    <li>sAMAccountName is an Active Directory attribute guaranteed to be unique in an Active Directory domain. </li>    <ul>     <li>sAMAccountName = %u, could be expanded to read sAMAccountName = UID. </li>      <li>Essentially, this directive specifies how objects will be linked across two systems. In this particular example, we assume that UID and sAMAccounName attributes, for a specific user, will have the same value, hence provide the mapping. This consistency should either be enforced procedurally or via a synchronization service (ex. Forefront Identity Manager)</li>      <li>sAMAccountName attribute was chosen arbitrarily, any other unique attribute could be utilized.</li>   </ul> </ul>  <blockquote>   <p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5736.image_13FD8F06.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5736.image_5F00_13FD8F06.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8551.image_thumb_78E4BFF7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8551.image_5F00_thumb_5F00_78E4BFF7.png" width="421" height="181" /></a><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5315.image_2133F24C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5315.image_5F00_2133F24C.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/2843.image_thumb_1B78D8A6.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/2843.image_5F00_thumb_5F00_1B78D8A6.png" width="339" height="192" /></a></p> </blockquote>  <ul>   <li>cn=saslauthd,cn=Users,dc=fabrikam,dc=com is a DN of an Active Directory account, in which context SASLAUTHD will perform queries against Active Directory. This account does not require any special privileges. </li> </ul>  <blockquote>   <p>Let’s look at the sequence of events which would take place while performing authentication for the query below, based on the configuration directives in our sample /etc/saslauthd.conf</p> </blockquote>  <blockquote>   <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8524.image_4A0EE188.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8524.image_5F00_4A0EE188.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1643.image_thumb_3A8BCFB9.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1643.image_5F00_thumb_5F00_3A8BCFB9.png" width="648" height="90" /></a></p>    <ol>     <li>SLAPD locates the object with DN of<em> cn=johnd,ou=People,dc=fabrikam,dc=com</em></li>      <li>If the object with this DN has value of <a href="mailto:{SASL}johnd@fabrikam.com">{SASL}johnd@fabrikam.com</a> in the <em>userPassword</em> property, SLAPD will hand over authentication to SASLAUTHD (pass-through authentication).</li>      <li>SASLAUTHD will query Active Directory for an object which <strong>sAMAccountName</strong> value equals&#160; to <strong>johnd</strong> (value of UID attribute in OpenLDAP). </li>      <li>If such object is found, SASLAUTHD will attempt to authenticate against Active Directory using the DN and password of the located object (password was provided by the end-user in the query). </li>      <li>If authentication to Active Directory is successful, user is automatically authenticated against OpenLDAP.</li>   </ol> </blockquote>  <h3>Test SASLAUTHD</h3>  <p>Successful test.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/3225.image_53A729F1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/3225.image_5F00_53A729F1.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5025.image_thumb_16A2F85F.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5025.image_5F00_thumb_5F00_16A2F85F.png" width="491" height="54" /></a></p>  <p>For the –u parameter specify a valid sAMAccountName value in Active Directory. </p>  <p>Unsuccessful test, wrong password provided.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7178.image_29777C09.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7178.image_5F00_29777C09.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0333.image_thumb_0F3712E5.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0333.image_5F00_thumb_5F00_0F3712E5.png" width="496" height="35" /></a>&#160; </p>  <p>If you run into issues with this test, see the troubleshooting section at the end of this post.</p>  <h2>Configure SLAPD to utilize SASLAUTHD</h2>  <p>Now we need to tell SLAPD to utilize SASLAUTHD for authentication. This is accomplished by creating and editing /etc/ldap/sasl2/slapd.conf</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1616.image_6D6B3A53.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1616.image_5F00_6D6B3A53.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4024.image_thumb_05FAD7A4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4024.image_5F00_thumb_5F00_05FAD7A4.png" width="619" height="101" /></a></p>  <h2>Setup default REALM in SLAPD cn=config</h2>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0211.image_6E13F07D.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0211.image_5F00_6E13F07D.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7230.image_thumb_73EE9416.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7230.image_5F00_thumb_5F00_73EE9416.png" width="623" height="25" /></a></p>  <p>Provide olcSaslRealm directive</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1263.image_3FD9F4C3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1263.image_5F00_3FD9F4C3.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5040.image_thumb_0FCFA342.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5040.image_5F00_thumb_5F00_0FCFA342.png" width="643" height="222" /></a></p>  <h2>Configure user object to be authenticated via SASL</h2>  <p>&#160;</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7271.image_13F97B07.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7271.image_5F00_13F97B07.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0334.image_thumb_318B5606.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0334.image_5F00_thumb_5F00_318B5606.png" width="606" height="305" /></a></p>  <h2>Troubleshooting</h2>  <p>If things go wrong, several log files and debug options could help.</p>  <p>1. Checking /var/log/auth.log. Here you will find details on the LDAP authentication failures</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7824.image_1C4D2A91.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7824.image_5F00_1C4D2A91.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6724.image_thumb_4A77007E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6724.image_5F00_thumb_5F00_4A77007E.png" width="740" height="335" /></a></p>  <p>2. Checking&#160; SASLAUTHD error messages in /var/log/syslog</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/1512.image_63CEDDEB.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/1512.image_5F00_63CEDDEB.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6283.image_thumb_5A92A2AA.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6283.image_5F00_thumb_5F00_5A92A2AA.png" width="729" height="231" /></a></p>  <p>Running ldapsearch with debug option, may help when troubleshooting certificate trust chain validation.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0508.image_4B2F1ACE.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0508.image_5F00_4B2F1ACE.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6765.image_thumb_6A058EAC.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6765.image_5F00_thumb_5F00_6A058EAC.png" width="849" height="37" />&#160;</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Detecting cross-nested groups in Active Directory with SSIS and SQL</title>
      <link>https://docs.microsoft.com/archive/blogs/alextch/detecting-cross-nested-groups-in-active-directory-with-ssis-and-sql</link>
      <pubDate>Thu, 12 Apr 2012 09:47:53 GMT</pubDate>
      <dc:creator><![CDATA[Alex Tcherniakhovski]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alextch/2012/04/12/detecting-cross-nested-groups-in-active-directory-with-ssis-and-sql/</guid>
      <description><![CDATA[This posting is provided &quot;AS IS&quot; with no warranties, and confers no rights. Use of...]]></description>
      <content:encoded><![CDATA[<p><font size="1">This posting is provided &quot;AS IS&quot; with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm</font> </p>  <p>Cross-nested groups, <em>in my</em> <em>definition,</em> constitute a scenario where GroupA is nested into GroupB, and GroupB is nested into GroupA (GroupA &lt;-&gt; GroupB). </p>  <p><strong>Why would you consider detecting this condition</strong>:</p>  <ul>   <li>Since Active Directory group structure is intended to be hierarchical, cross-nesting is typically an oversight of an administrator, and should be corrected</li>    <li>Cross-nested groups should, in most cases, be converted into a single group or nested into a mutual parent (of course removing the cross-nesting at the same time). </li>  </ul>  <p>Overall, elimination and/or reduction of cross-nesting may help in the following areas:</p>  <ul>   <li>simplification of group management</li>    <li>dealing with token bloat </li>    <li>reduce attack surface</li> </ul>  <h2>Reporting environment setup</h2>  <p>The instructions for setting up the environment will be very similar to what I described in my previous post <a href="https://blogs.msdn.com/b/alextch/archive/2012/03/22/reporting-on-privileged-active-directory-accounts-with-sql-server.aspx">Reporting on privileged Active Directory accounts with SQL Server</a>. The SSIS package and the SQL schema are essentially the same for both scenarios. I suggest you follow that walkthrough first. </p>&#160;&#160; <h3>LDAP Query</h3>  <p>Below is the LDAP query which SSIS Active Directory Source component will use to get the data we need. </p>  <p>(|(objectCategory=Person)(objectCategory=group))</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5277.SNAGHTMLad5988_5C4125CE.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5277.SNAGHTMLad5988_5F00_5C4125CE.png"><img style="margin: 0px; display: inline;" title="SNAGHTMLad5988" alt="SNAGHTMLad5988" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/3515.SNAGHTMLad5988_thumb_08E9DFA8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/3515.SNAGHTMLad5988_5F00_thumb_5F00_08E9DFA8.png" width="483" height="167" /></a></p>  <p>Technically speaking, we don’t need the user objects for this specific query, but since we may also want to run some other reports, I included user objects as well.</p>  <h3>SQL Query</h3>  <p>The logic behind the query in vwCrossNestedSecurityGroups view is to self-join the Members table based on the reversed combination of groupDN and memberDN. For example, record groupA –&gt; groupB will try to find a record groupB-&gt;groupA (crossing).</p>  <p>To simplify the query I created an underlying view, which filters-out user members from the Members table (vwDirectGroupMembers), hence focusing only on the group nesting.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/2541.image_2D2EC42A.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/2541.image_5F00_2D2EC42A.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7331.image_thumb_12822811.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7331.image_5F00_thumb_5F00_12822811.png" width="663" height="567" /></a></p>  <p>Notice that in the query I filter-out distribution lists (groupType &lt; 0). Security groups the groupType of –214748364X (X varies based on the scope of the group). If you are interested in distribution lists as well, simply remove&#160; the WHERE clause.</p>&#160;&#160; <h3>Note on hardware</h3>  <p>When I ran this query against the Members table with 9 millions rows, the memory utilization on my lab machine went from 2G to 9.5G, which I guess was to be expected.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4113.image_68BEAD1D.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4113.image_5F00_68BEAD1D.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4617.image_thumb_61333DB0.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4617.image_5F00_thumb_5F00_61333DB0.png" width="90" height="181" /></a></p>  <p>Just something to keep in mind if you are working with a large data set.</p>&#160;&#160; <h2>Links</h2>  <p><a href="https://skydrive.live.com/redir.aspx?cid=61cd494b84d3415e&amp;resid=61CD494B84D3415E!1181&amp;parid=61CD494B84D3415E!1174">SQL script which will generate the required database schema</a></p>  <p><a href="https://skydrive.live.com/redir.aspx?cid=61cd494b84d3415e&amp;resid=61CD494B84D3415E!1183&amp;parid=61CD494B84D3415E!1182">SSIS Project</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Debuggin ASP.NET application in IIS - building development environment</title>
      <link>https://docs.microsoft.com/archive/blogs/alextch/debuggin-asp-net-application-in-iis-building-development-environment</link>
      <pubDate>Fri, 23 Mar 2012 13:56:00 GMT</pubDate>
      <dc:creator><![CDATA[Alex Tcherniakhovski]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alextch/2012/03/23/debuggin-asp-net-application-in-iis-building-development-environment/</guid>
      <description><![CDATA[This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script...]]></description>
      <content:encoded><![CDATA[<p><span style="font-family: Verdana;" face="Verdana"><em>This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at </em></span><a href="https://www.microsoft.com/info/cpyright.htm"><span style="font-family: Verdana;" face="Verdana"><em>https://www.microsoft.com/info/cpyright.htm</em></span></a></p>
<p><span style="font-family: Verdana;" face="Verdana">When you application is deployed into production it will be probably accessed like this </span><a href="https://myapp.mycompnay.com"><span style="font-family: Verdana;" face="Verdana">https://myapp.mycompnay.com</span></a><span style="font-family: Verdana;" face="Verdana">. It will also be subjected to various IIS configuration settings: authentication, authorization, custom routing, etc. But when you develop and test it, probably, lives in IIS express; and accessed like something like this </span><a href="https://localhost/myapp:400004"><span style="font-family: Verdana;" face="Verdana">https://localhost/myapp:400004</span></a><span style="font-family: Verdana;" face="Verdana">.</span></p>
<p><span style="font-family: Verdana;" face="Verdana">Since most of the walkthroughs demonstrate configuration of the development environment using IIS Express, I would like to document the steps of using IIS 7.5 and creating the URL structure which resembles your desired end state. I am doing this because I myself had to spent considerable amount of time in accomplishing what might appear as a simple task.</span></p>
<p><span style="font-family: Verdana;" face="Verdana">The overall process can be divided into three stages:</span></p>
<ul>
<li><span style="font-family: Verdana;" face="Verdana">OS/Browser configuration</span></li>
<li><span style="font-family: Verdana;" face="Verdana">IIS configuration</span></li>
<li><span style="font-family: Verdana;" face="Verdana">Visual Studio configuration</span></li>
</ul>
<p>&nbsp;</p>
<h2>OS and Browser</h2>
<p><span style="font-family: Verdana;" face="Verdana">Let&rsquo;s assume that in production our application will be accessed as </span><a href="https://myapp.mycompany.com"><span style="font-family: Verdana;" face="Verdana">https://myapp.mycompany.com</span></a><span style="font-family: Verdana;" face="Verdana">. In order to mimic the same URL structure in our development environment we need to perform the following steps:</span></p>
<ul>
<li><span style="font-family: Verdana;" face="Verdana">Add an entry to the hosts file for myapp.mycompnay.com. This step is required unless, your DNS server will resolve myapp.mycompany.com to your development server.</span></li>
</ul>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/3426.image_7E9CB6C3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/3426.image_5F00_7E9CB6C3.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8625.image_thumb_5FB61D18.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8625.image_5F00_thumb_5F00_5FB61D18.png" width="682" height="398" /></a></p>
<ul>
<li><span style="font-family: Verdana;" face="Verdana">If your application will be using Windows Integrated Authentication, you need to disable LSA loopback (</span><a href="https://support.microsoft.com/kb/896861"><span style="font-family: Verdana;" face="Verdana">KB896861</span></a><span style="font-family: Verdana;" face="Verdana">), otherwise you will be getting access deny errors due to the host name mismatch. </span></li>
<li><span style="font-family: Verdana;" face="Verdana">Also to prevent credential prompts in IE add <a href="https://myapp.mycompany.com"><span style="font-family: Verdana;" face="Verdana">https://myapp.mycompany.com</span></a><span style="font-family: Verdana;" face="Verdana"> to the local intranet zone in IE.</span></span></li>
</ul>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5670.image_5D991E4F.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5670.image_5F00_5D991E4F.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/2330.image_thumb_27B42935.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/2330.image_5F00_thumb_5F00_27B42935.png" width="639" height="267" /></a><span style="font-family: Verdana;" face="Verdana">&nbsp;</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8304.image_1AD9D317.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8304.image_5F00_1AD9D317.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0207.image_thumb_79E6606F.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0207.image_5F00_thumb_5F00_79E6606F.png" width="407" height="524" /></a></p>
<ul>
<li><span style="font-family: Verdana;" face="Verdana">Create a folder where your application files will reside</span></li>
</ul>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6253.image_386BAE16.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6253.image_5F00_386BAE16.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5008.image_thumb_0286B8FC.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5008.image_5F00_thumb_5F00_0286B8FC.png" width="474" height="236" /></a></p>
<ul>
<li><span style="font-family: Verdana;" face="Verdana">Optional, but recommended, add a user account which we will be used to run the application pool for your web application</span></li>
</ul>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0602.image_61934654.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0602.image_5F00_61934654.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/4812.image_thumb_0EA83323.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/4812.image_5F00_thumb_5F00_0EA83323.png" width="438" height="367" /></a></p>
<h2>&nbsp;</h2>
<h2>Create IIS Site</h2>
<p><span style="font-family: Verdana;" face="Verdana">Create application pool</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6560.image_544CBD41.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6560.image_5F00_544CBD41.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/2844.image_thumb_7EB8EE5E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/2844.image_5F00_thumb_5F00_7EB8EE5E.png" width="305" height="95" /></a></p>
<p><span style="font-family: Verdana;" face="Verdana">The name could be arbitrary, but make sure to select the .NET framework version in which you will be developing your app.</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7711.image_0BB2CE70.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7711.image_5F00_0BB2CE70.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/2437.image_thumb_361EFF8D.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/2437.image_5F00_thumb_5F00_361EFF8D.png" width="259" height="238" /></a></p>
<p><span style="font-family: Verdana;" face="Verdana">Once the pool is created, open Advanced Settings, and change the identity of the pool to the name of the user account you created in previous steps.</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6646.image_71063256.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6646.image_5F00_71063256.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5483.image_thumb_08BD69BD.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5483.image_5F00_thumb_5F00_08BD69BD.png" width="717" height="353" /></a></p>
<p><span style="font-family: Verdana;" face="Verdana">Create new Site</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0358.image_2D6E8134.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0358.image_5F00_2D6E8134.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7230.image_thumb_65ACF84C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7230.image_5F00_thumb_5F00_65ACF84C.png" width="279" height="147" /></a></p>
<p><span style="font-family: Verdana;" face="Verdana">The name of the site is arbitrary.</span></p>
<p><span style="font-family: Verdana;" face="Verdana">Choose the name of the application pool you created in the previous step.</span></p>
<p><span style="font-family: Verdana;" face="Verdana">The value in the host name field should correspond to the record you added to your host file.</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7120.image_4B6C8F28.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7120.image_5F00_4B6C8F28.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/7215.image_thumb_4E9E7710.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/7215.image_5F00_thumb_5F00_4E9E7710.png" width="447" height="434" /></a></p>
<h2>Configure Visual Studio</h2>
<p><span style="font-family: Verdana;" face="Verdana">In Visual Studio create a new Web Site</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6138.image_1A89D7BD.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6138.image_5F00_1A89D7BD.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5141.image_thumb_00B5A18E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5141.image_5F00_thumb_5F00_00B5A18E.png" width="530" height="134" /></a></p>
<p><span style="font-family: Verdana;" face="Verdana">In the location of the site select HTTP, then click on Browse.</span></p>
<p><span style="font-family: Verdana;" face="Verdana">Select IIS and then select the site</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8371.image_5836BF79.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8371.image_5F00_5836BF79.png"><img style="display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/6622.image_thumb_645839A0.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/6622.image_5F00_thumb_5F00_645839A0.png" width="808" height="561" /></a></p>
<p><span style="font-family: Verdana;" face="Verdana">If required, enable Windows Integrated authentication in the web.config or IIS Manager</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0456.image_;F1A2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0456.image_5F00_3B00F1A2.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/5226.image_thumb_1A79B1F0.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/5226.image_5F00_thumb_5F00_1A79B1F0.png" width="387" height="51" /></a></p>
<p>Test by debugging the app.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/0358.image_329D1C4B.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/0358.image_5F00_329D1C4B.png"><img style="margin: 0px; display: inline;" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/34/metablogapi/8787.image_thumb_43351739.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-34-metablogapi/8787.image_5F00_thumb_5F00_43351739.png" width="717" height="124" /></a></p>]]></content:encoded>
    </item>
  </channel>
</rss>