When querying with LDAP against our Active Directory structure to look up user accounts, some records (but not all) are missing certain key fields, specifically memberOf and userAccountControl (which has a bit flag that indicates whether the account is disabled or not).
Here's a few refining details:
If the query is set to filter on any
of those fields (such as getting a
list of non-disabled accounts in the
Marketing department group), they
disappear from the result set (since
as far as AD is concerned, they're
missing).
If the query is performed
with a highly-privileged domain
admin account, the query works just
fine.
The records with the problem is about 1/4 - 1/3 of the total user records. Most do seem to be newer records (we thought for a time that it was perhaps related to upgrading to 2003 on the domain controller server), although some older records seem affected as well.
A cursory look over two similar records, one whose entire record is viewable by any account, and another which isn't doesn't show any obvious differences.
So my best guess is that there's some sort of permission deny set (perhaps at the schema level?) which makes certain fields restricted. I should note that the domain administrators never knowingly set any such permissions.
UPDATE/RESOLUTION: ADSI Edit (in Windows 2003 Support Tools) helped me to nail it down to a change in the default permissions on the Authenticated User role. For some people, the role contained the Read Account Restrictions (which contains userAccountControl) and Read Group Membership (memberOf), and for others it didn't.
The original cause of the difference still isn't clear, although the fact that most of the "bad" records were created after a switch to Windows 2003 for the Domain Controller, that could be a factor.
SOLUTION: This is still a bit undecided, but will most likely be an updated Group Policy, combined with a script to update existing accounts.
You can check the permission on the specific field of the specific users with adsi edit. Somehow thay must have been changed, and you will have to restore them to default. Maybe they where changed in the ou level of some of the users. In this case you can mass fix them.
What is of interest is that both the attributes you suggested are sort of read only. Member (attribute on a group) is maintained in Active Directory. The MemberOf value on a User is calculated based on a query, and is not actually statically stored on the user object.
I am pretty sure userAccountControl is a read only attribute as well, via LDAP. (Other approaches are needed to manipulate it directly.).
Not sure if that helps, but might be a hint in the right direction. (Or else totally wrong..)
Related
I am trying to build a database that stores Active-Directory entries for users/employees.
Is it safe to assume to query on: (objectClass=person)
What attribute should I store as a unique identifier that isn't the DN? e.g. should I use mail or uid
Also when an employee gets de-activated is there a new attribute that gets added or are they simply removed entirely from AD?
The question asked by you seems to be somewhat opinion based, but I'll talk it from the context of general options available in AD and the usual practices followed.
Is it safe to assume to query on: (objectClass=person)?
All the users created do come under the category of (objectClass=person). But, then if you create a generic-user for having file-share access on a system (through ADUC(dsa.msc) / powershell / C#, etc) which would not be an employee, then in this case it would violate your search condition despite being a person class. I can think of so many other scenarios where it would be impossible to avoid generic-users creation (which would again lie in person objectClass), at least from the viewpoint of mid-sized company and above.
Hence, in such cases it is better to follow a naming convention in your environment to avoid any such confusion. One sample example could be, say set the UPN/sAMAccountName for non-employee users to start from genXXXX, and you'd be easily able to search all employee users henceforth.
What attribute should I store as a unique identifier that isn't the DN? e.g. should I use mail or uid?
There are unique identifiers already available in AD like objectGUID and objectSid. In a domain, the sAMAccountName/UPN values are also unique. But, you cannot rely on that for forest-level search.
objectSid for a user can change when the user is migrated to another domain, but objectGUID never changes. You can read more about SIDs versus GUIDs here.
Also when an employee gets de-activated is there a new attribute that
gets added or are they simply removed entirely from AD?
There is no automatic trigger at AD side. There is an attribute called lastLogontimeStamp which helps keep a track when a user or computer account has logged onto the domain (not the live scenario, but recent one - depending on if it keeps updating properly).
Someone has to manually disable/delete the account if an employee/user leaves the organisation. There are process setup in companies to deal with this scenario where the Access Management solutions are linked with AD modules, and take care of the entry and exit of the users and perform relevant action in AD.
Hope it gives a rough idea of management for the queries raised by you.
Looking at doing an integration and discussing the sAMAccountName attribute that is being populated in AD with usernames.
Currently the system is using first initial and last name if a duplicate account is detected with that username it adds a letter for example Robert McKay would be: rmckay. The first account created would work fine however if there is a second account it would be romckay and continue down a strange path of additional letters and numbers forcing uniqueness for the users. The client is wanting to move to a completely numeric username. Instead of rmckay it would now be 0000001 (for logins to everything that is AD connected or pulling from AD).
Also there are systems that derive their account login and generation from the sAMAccountName - so even though in the case of emails and systems where AD login has been setup the down stream systems that rely on the sAMAccountName will still required a login of: Employee ID + password vs friendly username + password.
Additionally there has been common consensus among the staff about user friendliness drop – however the one major concern was the issues that could arise for emails, however that will be addressed through the use of aliases. Anyone aware of anywhere that successfully was able to implement an Employee ID as sAMAccountName and found that the net result was positive (give the reduction in user friendliness?) Or can point to best practices that can be reviewed to share?
In our environment, we have 10 domains that were created separately back in the day, then brought together eventually under one forest. One one of the domains, they did something like that. The sAMAccountName was two consistent letters (always the same) followed by a 4-digit number unique to each user.
From what I was told, that requirement originally came from some mainframe application that used that username system. I don't know the details.
In recent years, though, we've been moving those away from it. It's pointless.
If you do have to do it, remember the userPrincipalName attribute, which can also be used for logging in. So even if the sAMAccountName is something awful, you can still make the userPrincipalName equal to their email address and users can then use that userPrincipalName to login. They won't even need to know what their sAMAccountName is.
I have a web application and I want to control which user can see what data. So I thought a user can belong to a group (ie. DBA, Middleware specialist, UNIX guys, etc.) and the logged in user can only see its data in the app.
I want LDAP to do the authentication. I assume there aren't such groups specified in LDAP (ie. I don't want to use LDAP groups as I cannot force the company LDAP to create groups and put the users in those groups).
What I think of is a flexible solution like being able to use a custom attribute on each user (let's say named 'acces_groups') what the groups can be enlisted comma separated string.
I read that the schema of an objectClass (like organizationalPerson) has to be altered to do that. But is there an easy way to add such a custom attribute to a user in LDAP (I am talking about an already working company LDAP)?
Or how would you solve this (without disrupting/breaking the current LDAP)?
I didn't say what kind of LDAP (OpenLDAP, active Directory, etc.) for a reason as I'd want a common solution here.
These are two possible solutions/implementations :
What you supposed : You can add a schema and not alter the organizationalPerson objectClass. (Because altering an already established schema will make your LDAP not standart)
Then you add this objectClas to all your users to allow them to use the attributes defined by this schema.
You can define the acces_groups attribute and make it multi-value. You could also define one attribute per flag you need dba, middleware, etc. and make it a boolean, etc.
Why I would not do any this :
This is a much more complicated and intrusive way to do it than using built in mechanisms that are readily available in LDAP.
If your LDAP administrator allows youto modify your LDAP schemas like that, it should be no problem to ask him to use groups instead as this method is much less complicated and time consuming to implement
To manage it on daily basis is just a pain because you have no integrity mechanism. All the "CRUD" operations on the "emulated" group will have to be done "manually"
If you want to delete a group, you will have to delete the attribute on all the users who have it set.
If you want to list the "group", you will have to search all the users who have the attribute set with the correct value
etc.
Using groups : You can indeed create groups such as dba, middleware, etc. and assign the users to those groups.
It will allow you the use of group member ship and automatically populate an attribute in your user with the group which he is part of
It is LDAP standart and only need dealing with data than dealing with LDAP configurations (which involves downtime, possible errors/setbacks, etc.)
If your company allows you to modify the LDAP configuration AND the data of the users, then it should also allows you to create groups and assigning people to it
I have an ASP.NET MVC + SQL Server application with 250 simultaneous users daily which uses AD/NTLM SSO to do all the authorization using a custom authorization security class that control access to controllers & Actions based on users & groups.
A dilemma recently came up where the 50K+ account records of the database are going to be managed by different groups to varying degree's:
All users will be able to view most records certain records can only
be edited by certain users/groups of specific departments There will
be an admin & support groups that will be able to edit any group owned records
etc.
This is not a problem of who has access to what features/forms/etc. in the controllers, but instead a dilemma of data ownership restrictions that must be imposed. I am guessing this means I need some additional layer of security for row level security.
I am looking for a pragmatic & robust way to tackle data ownership within the current application framework with minimal performance hits since it is likely the same thing will need to be imposed on other much larger tables of data. Initially there will be about 5 ownership groups, but creeping up to 25 to 100 in the near future.
Sadly there are no cut and dry business rules that are hard and fast that can be implemented here.. there is no rhyme or reason make sense of who owns what except the record primary key id.
To try to fix it I was thinking of creating a table of owner_roles and map it to the users table then create another table called accounts_ownership that looks something like:
tbl(PK),row(PK),owner(PK),view,create,modify,delete
accounts,1,hr,1,1,1,1
accounts,1,it,1,0,0,0
accounts,2,hr,1,1,1,1
accounts,2,it,1,1,1,1
accounts,3,it,1,0,0,0
But in doing so that would create a table that was 250K lines and could easily get some crappy performance. Looking at sites like Facebook and others this must be a common thing that has to be implemented, but I am hesitant to introduce a table like that since it could create serious performance issues.
The other way I thought this may be implemented is by adding an extra column to the accounts table that is a compound field that is comma separated that would contain the owner(s) with a coded set of rights ie.:
id owners
1 ,hr,
2 ,hr,
3 ,hr,it,
4 ,it,
And then add a custom class to search using the 'like' statement.. provided the logged in users role was "it" and the comma's were reserved and not allowed in owners names:
SELECT * FROM accounts WHERE owners LIKE '%,it,%'
... however this really just feels wrong from a DBA perspective (ugly as hell) and a maintenance nightmare.
Any practical approaches on how I could implement this without destroying my site?
Start with Role-based access control, you can possibly skip the roles from the pure definition but should be able to implement it like this:
Every user can be in one or more groups like admin, support, it, hr
Every data row has an owner like it, hr
On Access, check the access: an admin can see and edit all rows. Support+it sees every row and can edit those from it etc. This way you need only (user-groups + row-access) new rows in your database, not (user-groups * row-access).
User groups in your scenario should be possible to hardcode in your application, in a CMS there is generally a table defining what rights to assign to each user group - complicating the coding but very flexible.
Roles in the original concept allow a user to select what rights he/she wants to use, there would be a "Unlock with admin rights" or the like in your interface.
Primarily for performance reasons, I went with the less elegant approach listed. It took some doing, but there are careful application controls that had to be created to enforce things like no comma's in the id's.
We use Active Directory as the user store for our web application. All of our user information, such as first name, last name, email, phone, company, etc, is stored on the user record there.
Now we need to store a couple more pieces of info, except for these fields there aren't pre-existing fields on the schema that we can use. The fields we need are security question and security question answer.
I feel that we should extend the Active Directory schema to include these fields, thus keeping all of our user information in a single data store. However, our IT department feels that Active Directory should never be extended because they feel it is too dangerous and that Active Directory isn't intended to be used like this.
Who is right, and what is the philosophy for determining what types of attributes are ok to add to the schema?
Th
AD schema is meant to be extended. Casual AD admins have always been afraid of extending the schema especially because the word "permanent" usually followed. But the fact is that peramanent in ldap really is meaningless. If the new schema attributes or objects are never utilized then there is no adverse performance effect on the directory unless you can't bare the thought of looking at unused schema. The only risk of permanent schema is if it conflicts with existing or future schema and that is rare especially if you use unique naming such as "JohnsCompanySecurityAttribute1" etc. I worked at a hospital for 9 years and extending the schema was common place and is part of the value of AD or ADAM. Your IT guys can always temporarily take a couple DCs offline during the schema extension if they're still unconvinced. Here is some shameless self promotion related to heavy AD/AM usage in a sensitive clinical environment.
Active Directory initially had really crappy schema support. That is, you could not delete something, you could not change schema much.
With the later releases (2008 R2) you get the ability to do much more with schema. People using other directory services will not have this irrational fear.
Do consider encrypting the data as you store it.