Software Architecture- System.DirectoryService – Improve the performance of AD access

April 30, 2012

Case Study: Currently Directory service library is implemented via System.DirectoryService
What is how can we improve the performance of AD access?
Solution: using System.DirectoryService.Protocol and VLV
Important Points:
>>VLV work really well when you want to do a one-level search of an OU. In other cases it gives wrong total count and is not super fast.
>>Using the System.DirectoryServices namespace should be avoided it due to heavy pollution of ADSI COM weirdness, and a variety of other performance and flexibility reasons — preferring instead to use System.DirectoryServices.Protocols wherever possible.
>>Total number of record estimate is calculated accurate till 10,000 limit. Incase of VLV records are normally fetched as sliding window to, it works in most of the cases.
>> Multiple types of indexes can be created on same field.
>> Can we force client to create related to indexes, can affect other applications because of it.!!
Must Read:
Summary of Sample Data is at:
https://docs.google.com/spreadsheet/pub?key=0Aii2BerWkpV4dGhsVnNKODAyUXFSNzNhV19jc0Zvc0E&output=html
(With thanks to Steve Kradel)
Ways out:
1 Porting our architecture to System.DirectoryServices.Protocols then implement VLV based in the new namespace.
Pros:

a, More efficient in terms of performance
b, More stable
Corns:
a, Major redo of directory Service library is required.
2 Continuing to integrate System.DirectoryService based VLV to application.
Pros:
a, It is the current implementation. So need little afford to implement VLV.
Corns:
a, Not very efficient in terms of performance and stability.

Conclusions :
1. Wrong Total Count:
Wrong number of total count is well known problem in searching domain.
Even in Google searching show the estimate number of pages. While searching, sometimes when you click on last pages, it shown nothing records and a custom message is shown. Basically in order to show fast results, search engine use approximation for total number of pages.
Reference:
http://support.google.com/webmasters/bin/answer.py?hl=en&answer=70920
So paging can be shown on basis of estimate. When user clicks (try to go) on bad page (that does not exist) a user friendly message can be shown.
2. Navigation Style:
Navigation should be such that user moves from ou to ou and objects from only one ou are shown at time. In this way we can avoid the limitation of sub-tree search at a time. This type of navigation suits in most of the applications.
3. A warm up search with exact ldap query returning one record can serve the purpose of getting right number of records. It can solve the problem on getting right number of records. (A suggestion given by Steve Kradel [email: skradel@zetetic.net ] )
4. A index creator screen is proposed that can help product admin to create and manage index for searching.
A careful and well analyzed index is very critical for performance of application. A bad index can kills the performance of other applications too.
Code of POC will be loaded soon.
Related Error:
“LDAP_UNAVAILABLE_CRIT_EXTENSION 0x0c Critical extension is unavailable.”

Advertisements

Software Architecture-Strategy for Performance tuning a .Net application

September 10, 2011

Strategy for Performance tuning a .Net application:
There are two parts to work in terms of performance tuning.
First part, is application specific optimization which refer to things required in terms of product under development. It requires deep product knowledge and code level awareness of product.
Second part, is technology specific optimization which refer to things provide by technology as tip to improve the performance.
For second part, following is list of acts to be taken.

1. Allocate a senior resource to act as PIG in SCRUM theory for this task.
2. Analyze the technologies used in application like c#, .Net, ASP .Net, WCF, MVC, IIS. Identify set of checklist which needs attention to be verified in application.
3. First step would be to review code in application. Second step would be to apply the checklist identified in step 2.
4. Bench mark the effect of each change in application (checklist) to analyze the performance.
5. QA team member can really help in it.

Online References for implementing checklist:

C# Performance:
Microsoft:
http://msdn.microsoft.com/en-us/magazine/cc500561.aspx
http://msdn.microsoft.com/en-us/library/ff647813.aspx
http://msdn.microsoft.com/en-us/library/ms973839.aspx
http://msdn.microsoft.com/en-us/library/ms973839
http://msdn.microsoft.com/en-us/library/ms973852
http://msdn.microsoft.com/en-us/magazine/cc163510.aspx
http://msdn.microsoft.com/library/ms973837.aspx
http://msdn.microsoft.com/library/ms973858.aspx

Others:
http://www.techgalaxy.net/Docs/Dev/5ways.htm
http://www.codeproject.com/KB/cs/effective1.aspx

Blogs:
http://blogs.msdn.com/b/ricom/

ASP .Net Performance:
http://msdn.microsoft.com/en-us/magazine/cc163854.aspx
http://msdn.microsoft.com/en-us/library/ff647787.aspx
http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx
http://www.realsoftwaredevelopment.com/20-tips-to-improve-aspnet-application-performance/
http://wiki.asp.net/page.aspx/31/performance/

WCF Performance:
http://support.microsoft.com/kb/982897
http://msdn.microsoft.com/en-us/library/ee377061(v=bts.10).aspx
http://msdn.microsoft.com/en-us/library/ms735098.aspx

Blogs:
http://www.askives.com/wcf-performance.html
http://blog.thekieners.com/2010/05/04/optimize-data-contracts-for-better-wcf-performance/
http://merill.net/2008/10/wcf-performance-optimization-tips/
http://weblogs.asp.net/sweinstein/archive/2009/01/03/creating-high-performance-wcf-services.aspx
http://metallemon.hubpages.com/hub/WCF-Service-Performance
http://www.aspnet101.com/2010/08/wcf-performance-best-practices/
http://blogs.msdn.com/b/stcheng/archive/2011/01/05/wcf-wcf-performance-testing-information-share.aspx
http://webservices20.blogspot.com/2009/01/wcf-performance-gearing-up-your-service.html
http://blogs.msdn.com/b/wenlong/archive/2007/10/27/performance-improvement-of-wcf-client-proxy-creation-and-best-practices.aspx

MVC Performance:
http://www.codeproject.com/KB/aspnet/How_to_improve_performanc.aspx
http://weblogs.asp.net/gunnarpeipman/archive/2010/02/07/asp-net-mvc-performance-ii-optimizing-resources.aspx
http://www.slideshare.net/rudib/aspnet-mvc-performance
http://msmvps.com/blogs/kenlin/archive/2010/05/14/mvc-performance-in-iis-part-ii.aspx
http://blogs.msdn.com/b/marcinon/archive/2011/02/07/mvc-performance-tips.aspx


Software Architecture – To find lockedout users from active directory

August 6, 2011

Objective : To find lockedout users from active directory

General Implementation:
Generally LDAP filter for getting Lockout accounts list is as:
(&(objectCategory=Person)(objectClass=user)(lockoutTime:1.2.840.113556.1.4.804:=4294967295))
Where 4294967295 is the highest number you can get using 32 bits (Binary digits)
11111111111111111111111111111111 = 4,294,967,295
FFFFFFFF = 4,294,967,295

1.2.840.113556.1.4.804 is the LDAP_MATCHING_RULE_BIT_OR rule. The matching rule is true if any bits from the property match the value. This rule is like the bitwise OR operator.

LockoutTime is AD attribute which is the date and time (UTC) that this account was locked out. This value is stored as a large integer that represents the number of 100-nanosecond intervals since January 1, 1601 (UTC). A value of zero means that the account is not currently locked out.
So (lockoutTime:1.2.840.113556.1.4.804:=4294967295) means fetch those entries which has any date time value in form of large integer.
Problem:
However searching for any accounts that have a value for lockouttime is not an accurate method to use because an account is determined to be locked out if the CurrentTime – lockouttime exceeds the Lockout Duration.
It is only upon a successful logon that AD sets the value of lockouttime to zero, so it is possible for an account to still contain a value for lockouttime, yet the account is not locked.

Solution:
The correct LDAP filters with a dynamic calculation based on Active Directory Account Lockout policy.
To determine the users that are currently locked out, you have to query the lockoutDuration attribute stored on the domain object (e.g., dc=rallencorp,dc=com). This attribute defines the number of minutes that an account will stay locked before becoming automatically unlocked. You need to take this value and subtract it from the current time to derive a timestamp that would be the outer marker for which users could still be locked. You can then compare this timestamp with the lockoutTime attribute of the user object. The search filter to find all locked users once you’ve determined the locked timestamp would look something like this:

(&(objectcategory=Person)(objectclass=user)(lockoutTime>=DerivedTimestamp))

For any users that have a lockoutTime that is less than the derived timestamp, their account has already been automatically unlocked per the lockoutDuration setting.

Where DerivedTimestamp = ( Now-LockoutDurationFromDomainPolicy)
[While accounting for local time zones and daylight savings time.]

So in this way, we can avoid problem in previous ldap filter.

Use of Windows Time Service Tool named W32tm.exe for diagnostic purpose to Convert an NT system time, in (10^-7)s intervals from 0h 1-Jan 1601, into a readable format as below.

w32tm /ntte

Code:
Class for getting the domain policy will be as:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;

namespace MyDirectoryServices.MyDirectory
{

    /*     
     This class get the domain poilcy from domain controller
     All policy attributes can be get via that.
     Make a public property and user it, as done for LockoutDuration
     Reference: http://en.csharp-online.net/User_Management_with_Active_Directory%E2%80%94Determining_Domain-Wide_Account_Policies
     */

    [Flags]
    public enum PasswordPolicy
    {
        DOMAIN_PASSWORD_COMPLEX = 1,
        DOMAIN_PASSWORD_NO_ANON_CHANGE = 2,
        DOMAIN_PASSWORD_NO_CLEAR_CHANGE = 4,
        DOMAIN_LOCKOUT_ADMINS = 8,
        DOMAIN_PASSWORD_STORE_CLEARTEXT = 16,
        DOMAIN_REFUSE_PASSWORD_CHANGE = 32
    }

    public class DomainPolicy
    {
        public static string pLockoutTime = "lockoutTime";
        public static string pLockoutDuration = "lockoutDuration";
        public const long pNeverExpireConstant = 9223372036854775807;  // Used for AD attribute accountexpire, to show as never expires value
    
        ResultPropertyCollection attribs;

        public DomainPolicy()
        {
            // hardcoded domain name
            String pathRootDSE = String.Format("LDAP://softcom.imanami.lab");
            DirectoryEntry dse = new DirectoryEntry(pathRootDSE);
            
            //properties to fetch
            string[] policyAttributes = new string[] {
                  "lockoutDuration", "objectClass", 
                      "distinguishedName"
                        };

            DirectorySearcher ds = new DirectorySearcher(
              dse,
              "(objectClass=domainDNS)",
              policyAttributes,
              SearchScope.Base
              );

            // search
            SearchResult result = ds.FindOne();

            //do some quick validation...							  
            if (result == null)
            {
                throw new ArgumentException(
                  "domainRoot is not a domainDNS object."
                  );
            }

            this.attribs = result.Properties;
        }

        //for some odd reason, the intervals are all stored
        //as negative numbers. We use this to "invert" them
        private long GetAbsValue(object longInt)
        {
            return Math.Abs((long)longInt);
        }

        /// <summary>
        /// LockoutDuration of domain policy
        /// </summary>
        public TimeSpan LockoutDuration
        {
            get
            {
                string val = pLockoutDuration;
                //this should fail if not found
                var value = this.attribs[val][0];
                if (value == null)
                    return TimeSpan.MinValue;

                var result = (long)value;
                if (result == pNeverExpireConstant || result == 0)
                    return TimeSpan.MaxValue;

                var finalResult = TimeSpan.FromTicks(result);
                return finalResult;
            }
        }
    }
    
}

The code to get list of locked out accounts will be as:

 DomainPolicy dc = new DomainPolicy();
            
            // Print LockoutDuration from domain policy
            Console.WriteLine(" lockout" + dc.LockoutDuration);

            // get difference timestamp 
            DateTime dateTimeStamp = DateTime.Now.Subtract(-dc.LockoutDuration);

            // Hard coded domain name
            String pathRootDSE = String.Format("LDAP://dc=softcom,dc=imanami,dc=lab");

            DirectoryEntry dse = new DirectoryEntry(pathRootDSE);

            // list of properties to fetch
            string[] policyAttributes = new string[] {
            "distinguishedName" , "cn","lockoutTime"
                  };

            // filter to search the items
            string filterString = string.Format("(&(objectCategory=Person)(objectClass=user)(lockoutTime>={0}))", dateTimeStamp.ToFileTimeUtc().ToString());

            DirectorySearcher ds = new DirectorySearcher(
              dse,
              filterString,
              policyAttributes,
              SearchScope.Subtree
              );

            //search
            SearchResultCollection result = ds.FindAll();

            // loop n print users
            foreach (SearchResult item in result)
            {
                Console.WriteLine("Item: " + item.Properties["cn"][0].ToString() + " " + item.Properties["distinguishedName"][0].ToString() + " " + item.Properties["lockoutTime"][0].ToString());
            }
            //wait...
            Console.ReadLine();
       

Happy exploring AD related application architecture.

References:
http://msdn.microsoft.com/en-us/library/ms676843(v=vs.85).aspx
http://support.microsoft.com/kb/269181
http://technet.microsoft.com/en-us/library/cc773263(WS.10).aspx


Software Architecture-Sharepoint Server 2010-First piece of code with SPSite and SPWeb

May 22, 2011

Environment: Visual Studio 2010 + Sharepoint Server 2010

As part of career direction, I have decided to include Sharepoint as my skillset. So I explored the Sharepoint as end user for the last few weeks. Today I have programmed first piece as sharepoint developer…..Hurrahh..As I had experienced with many other CMS solutions like PHPNuke,Joomla,DotnetNuke and custom build. So basic concept was not new while exploring the sharepoint.

My First Program was targeting to explore the Server Side Object Model specially the class of SPSite which represent the site collection in Sharepoint and SPWeb which target a web site.

      const string siteUrl = "http://win2k8-ultimate/sites/Call";
      using (SPSite siteCollection = new SPSite(siteUrl)) {

          foreach (var item in siteCollection.AllWebs)
          {
              Console.WriteLine("Item of Site collections: " + item.ToString());
          }
        SPWeb site = siteCollection.RootWeb;
        Console.WriteLine("Root Site:" + site.Name + " " + site.PortalName);
          //Gets or sets the description for the site.
        Console.WriteLine("Desc: " + site.Description);
        /// Gets a list of the groups that are associated with the website.
        foreach (var item in site.AssociatedGroups)
        {
            Console.WriteLine(" Related Group: " + item.Name);
        }
        //Gets a collection that contains all the groups in the site collection.
        foreach (var item in site.SiteGroups)
        {
            Console.WriteLine("Sitegroup Name: "+ item.ToString());
        }
        //Gets the users who have been given contribute permissions to the website.
        Console.WriteLine(" Member Group: " + site.AssociatedMemberGroup.Name);
        //Gets or sets the associated owner groups of the website.
        Console.WriteLine(" Owner Group: " + site.AssociatedOwnerGroup.Name);
        //Gets or sets the associated visitor group of the website.
        Console.WriteLine(" Vistor Group: " + site.AssociatedVisitorGroup.Name);

        //Gets the collection of all lists that are contained in the website.
        foreach (SPList list in site.Lists) {
          if (!list.Hidden) {
            Console.WriteLine("Items of List: "+list.Title);
          }

          //Gets the collection of all list definitions and list templates that are available for creating lists on the website.
          foreach (SPListTemplate item in site.ListTemplates)
          {
              Console.WriteLine("Item of List templates: " + item.Name);
          }
            //Gets the collection of user objects that represents all users who are either members of the site or who have browsed to the site as authenticated members of a domain group in the site.
          foreach (var item in site.AllUsers)
          {
              Console.WriteLine("User of site:( Direct + via Group ) " + item.ToString());
          }
          //Gets the collection of user objects that are explicitly assigned permissions in the website.
          foreach (var item in site.Users)
          {
              Console.WriteLine(" USer of site:(Only Direct users) " + item.ToString());
          }
          //Gets the collection of all users that belong to the site collection.
          foreach (var item in site.SiteUsers)
          {
              Console.WriteLine("user of whole site collection:" + item.ToString());
          }
            //Gets the collection of the website administrators.
          foreach (var item in site.SiteAdministrators)
          {
              Console.WriteLine(" site admins: " + item.ToString() );
          }

            //Gets the collection of Features that are currently activated in the website.
          foreach (var item in site.Features)
          {
              Console.WriteLine("Feature of site: " + item.Definition.DisplayName);
          }
          //  Gets the collection of field objects that represents all the fields in the website.
          foreach (var item in site.Fields)
          {
              Console.WriteLine("feild of site:" + item.ToString());
          }
            //Gets the collection of all files in the root directory of the website.
          foreach (var item in site.Files)
          {
              Console.WriteLine("files of site: "+ item.ToString());
          }
          //Gets the collection of all first-level folders in the website.
          foreach (var item in site.Folders)
          {
              Console.WriteLine("Folders of site:"+ item.ToString() );
          }
            //Gets the collection of modules that are used on the website.
          foreach (var item in site.Modules)
          {
              Console.WriteLine("module of site: " + item.ToString());
          }
        }
        Console.ReadLine();
      }

Comment s explains everything in the above code.
Note:
1. Visual Studio project by default target .Net 4 framework. It needs to be changed to .Net 3.5 framework.
2. Project properties >> Build >> Target plateform needs to be changed to x64.
3. User which is running to code must be site collection administrator, otherwise Access denied exception will be thrown by code.


Software Architecture-www.oodesign.com – Do visit it

April 10, 2011

While googling about “Liskov’s Substitution Principle”, I landed on site:
http://www.oodesign.com
There are many sites on net which explain OOD-Object Oriented Design, but above is the best because of its simplicity in words. Both a starter and experienced professional can benefit from it equally.
Do visit it.


Software Architecture – What is exactly Tuple in C# – Compare with classes, structures,Array,ArrayList,List

March 20, 2011

In previous post at Software Architecture – C# – 4.0 – New Feature – Tuple , I introduced Tuples. During a presentation Badar-one of my team mate asked me question that why we need a new type tuple-When there are already classes,structures,Array,ArrayList,List. So I posting my reply.

Actually Microsoft is growing C# as most prowerfull programming langauge, so they contionously extend the core language element. Tuple has been there in Pythone and F# previously, now with c# 4.0, it is also part of core c# syntyx.

Comparsion with Class/Structure:
So problem defination is that we want to group together related values/ types into one type.
First thing comes in mind to have Class and contain all elements to be grouped in side a class. Sounds good,but there are cases when there no objec t oriented concept related to grouping. Class comes with heavy concepts like Encapsulation,Pholymorphism,abstraction,inheritence,constructor and a lot more… So when grouping is required but there is no OO sense, then Tuples are best choice.
You may point out that Structures are also there. Again there have attached concepts like inheritence,constrcutor,methods,properties and lot more. So when just grouping is required but no Object oriented concepts, tuples are the best choices.

Comparsion with Array/ArrayList/List:
No..No you can’t compare Tuple with Array/ArrayList/List.Because of simple point that Tupe is treated as data type and Array/ArrayList/List are treated as data strcutures. Just visualise the basic course with “Data Structure” in BCS, you will know the differenc e. Array/Arraylist/List are affilated with general concepts of Data structure like sorting , searc hing and a lot more. For Tuple we don’t have any such concept. It is simple Grouping og related values/types.

Getting and Setting elements in tupes is totally different from other Data strcutures like Array,ArrayList/List.

Secondly, elements in array are not strongly types(Require a type casting),but elements of Tuples are strongly typed.


Software Architecture-New Features of Visual Studio 2010 / .Net 4.0

February 27, 2011

Presentation
Topic: New Features of Visual Studio 2010 / .Net 4.0
Date: 28 Feb 2010
By: Shahzad Sarwar