Friday, January 14, 2011

Best practices or experience with company wide Username policies and resolving duplicates

I am a programmer with an application that needs to be integrated into the new company wide Active Directory login scheme. This means changing all the usernames in our system to use the new scheme. The new scheme is "first initial, last name", so Joe Smith would have a username of jsmith. If John Smith now gets hired, he'll get jsmith2. BUT as soon as Joe leaves the company, his AD account is deleted, and jsmith is available again. So if Jill Smith now is hired, she would get jsmith. From an applications standpoint this causes problems in my view, because I could now have records relating to Joe and records relating to Jill that are indistinguishable, because they were both created by "jsmith".

I am therefore left to wonder if there is a standard or best practice that addresses this issue of reusing usernames in an organization wide directory, especially in larger companies. When bringing up my concerns at a meeting I was told that "there's no way [big company name] still has a record of every user that's left the company", and that struck me as crazy. So, is there a generally accepted solution to handling usernames? Or does every company make it up as they go?

  • Windows copes with this by using a GUID to identify every account. The username is just decoration. You'll find that the old jsmith and new jsmith have different GUIDs even though the usernames are the same.

    Can you associate a GUID with each account in your app? If I think about it I can probably tell you how to get at the GUID for a user. It will be an attribute of the user in active directory.

    JR

    Les : TRY to make the GUID the same as the user name. In your scenario, when Jill hires in, she gets the user name jsmith and the GUID jsmith3 (since the others are still in use). Just an idea - there may be implementation issues that could be problematic. For example, should a lookup of of GUID jsmith return 'no such user name'?
    Evan Anderson : The GUID is assigned by Active Directory and guaranteed to be unique in the forest by AD. If you're doing a bind or search against AD using the GUID in the search filter you'll receive no results back assuming that no object has that GUID assigned.
    Peter : ahhh, I might have misled everyone by using the term "my app". It is not so much "my app" as the "app i am responsible for enhancing/supporting". It is closed source software bought from a vendor. There is no room on the user record for any identifier besides a username, which everything else in the DB is tied to, including all the audit tables, security, etc. So for this to work, i'd need to force the user to log in using the GUID, but that breaks the desired policy as well.
  • There are several naming attributes in Active Directory:

    • sAMAccountName: This is the up to 20 character name that must be unique within the Domain but not within the forest.
    • userPrinicipalName: This is usually in the form of sAMAccountName@domain.name and I believe needs to be unique within the forest, but since the first part is unique within the domain, then @domain.name that should just happen.
    • displayName: What you see in ADUC MMC when you look at users.
    • DN: The actual LDAP DN of the user in the AD tree. This is how you would identify the user from an LDAP perspective, usually.

    DN is a bad one to key off of, since it will change if the user is moved or renamed. Sane is possible for userPrincipalName/sAMAccountName (if they get renamed).

    As another poster suggested, the really truly unique attribute of users is probably GUID, and is not nice and human readable, alas.

    From geoffc
  • Yes we keep every user ever hired. I usually reccommend a first initial,middle initial,lastname to minimize the number of JQPublic1 accounts but it happens, however from an AD perspective users are just numbers. You can see the number for any account with this script:

    strComputer = "."
    Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
    Set objAccount = objWMIService.Get ("Win32_UserAccount.Name='myusername',Domain='mydomain'")
    Wscript.Echo objAccount.SID
    

    as a free bonus here's how to turn a sid into a username:

    strComputer = "."
    Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
    Set objAccount = objWMIService.Get ("Win32_SID.SID='S-1-5-21-1454471165-1004336348-1606980848-5555'")
    Wscript.Echo objAccount.AccountName
    Wscript.Echo objAccount.ReferencedDomainName
    
    Matt Simmons : I'm very much considering this, as well. I've got a specific OU that I put my "active" users in that permits things like VPN login, in addition to their belonging in the custom "Employees" security group I created. I've considered an "inactive" OU for users' accounts that no longer have any permission to access the system.
    From Jim B
  • As others have mentioned, using the GUID attribute of the user's Active Directory account is a great idea. If you want human-readability, though, you should have a look at the docs for the iADsNameTranslate interface. You can get a lot of mileage out of it for dealing translating the various possible names of an AD account (GUID, SID, samAccountName, displayName, DN, etc).

    Example:

    Option Explicit
    
    ' Constants for the iADsNameTranslate object. (from http://msdn.microsoft.com/en-us/library/aa772267(VS.85).aspx)
    Const ADS_NAME_TYPE_NT4 = 3
    Const ADS_NAME_TYPE_GUID = 7
    
    Const ADS_NAME_INITTYPE_GC = 3
    
    Dim objNameTranslate 
    Dim strUserGUID
    
    ' Create a nametranslate object and init to talk to a global catalog server
    Set objNameTranslate = CreateObject("NameTranslate")
    objNameTranslate.Init ADS_NAME_INITTYPE_GC, ""
    
    ' We're looking for an "NT 4" account name type-- aka a samAccountName
    objNameTranslate.Set ADS_NAME_TYPE_NT4, "DOMAIN\username"
    
    ' Translate into the user's GUID
    strUserGUID = objNameTranslate.Get(ADS_NAME_TYPE_GUID)
    
    WScript.Echo strUserGUID
    

    This isn't just for user accounts. Every object in AD has a GUID, so if you need to "remember" a DN for, say, an LDAP search base (or a group, or anything) you can use the GUID such that if it gets moved around in AD (think about some admin going off and re-organizing OU's, or renaming groups) your "pointer" to it won't break (because the GUID never changes).

  • GUID is definitely the way to go. If you really need to present the person's name in a human-friendly format just do an AD lookup in code.

    From mh
  • Other have already posted script snippets and you'll find plenty of code snippets, for a variety of languages at the usual coding sites. Try searching those for things like "user to guid", "user to id", etc.

  • IMO, good practice is to never delete accounts, just disable them. that way they can't be re-used.

  • Peter, my own experience with this is - don't expect the username to be unique, unless you have a way to guarantee username uniqueness. As you say, it never really works out.

    The app, whatever it is, needs to use other relevant data to determine what makes the user unique within the context of whatever the app is doing. If you're doing an app to generate mail flyers, for instance, you probably don't want to send more than one flyer per unique postal address.

    Peter : unfortunately the app i support/enhance is one of those 'off the shelf' apps that uses username as its primary identifier in all the audit tables, so it has to be unique within the app.
    From quux

0 comments:

Post a Comment