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.
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.
I am looking for a database design that can track and manage users with attributes to systems.
Situation:
A user has access to many systems in the organization and within each system, different attributes such as date created, system login name, system user id, etc. Currently, we have a database that is a flat database so for every attribute is in one row and continues to grow as more system attributes are added. The current tool used is an Access database and the current column count is 231 columns (OMG)! This is getting out of hand.
Assumptions:
There are a lot of attributes to track and one specific table in a database shouldn't be so broad to accommodate those attributes. Creating a table for each system becomes a mess in itself because each system may change in terms of columns. We need an interface for the administrators to easily manage this.
Let me give an example:
User Sunny, who works at Google, has access to the DMV, IRS, and Whitehouse.
For the DMV, Sunny has a user name, a pin code, and authorized IP address field. For the IRS, Sunny has a tax ID number, an organization number, a clearance number, and an access expiration date. For the Whitehouse, Sunny has a user name, a password, an access schedule, a portal address, and a user type. As Sunny works at google for years and slowly things change. Sunny gets access to the NRA, HP, Facebook, and Intel. The IRS adds a department clearance information. Whitehouse requires an authorization ID. The administrators need to see what access Sunny has and looks into the system; easily they find what they need.
Conclusion
Modifying tables and adding attributes may change on a regular basis. Developing a single table to handle this seems like a chore. I need a database design that could accommodate changes like this.
Question
How should design a database to accommodate something like this?
Thanks in Advance!
PS. I asked a question that is similar to this but it was a question for a software that actually exists to do this.
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.
I'm looking for a stornger scheme than just password salting-and-hashing.
I want passwords file/DB that will not compromise:
Number of users
User names
User passwords
My basic idea is to hash and salt both the usernames and the passwords, and also to add 1000's of 'trap' entries into the database (for example, random user names ending with _xxxx with random passwords ending with _yyyy which won't be valid for real users).
Of course, when someone tries to log in, I'll have to check it against all lines in the database.
Is this scheme secure?
Notes:
The users are added manually. If a user has to be removed - the login names are stored in a safe.
I'm not sure if I can protect this scheme againt brute-force methods, but I think guessing both name and password is harder
Edit:
I'm protecting against a leak of the user/password file (as well as the application that read this file). As said, I need to protect the actual number of users, as well as their identities (or anything that may disclose their identities).
Number of users seems to be the hardest datapoint to protect. You can mask this by creating large numbers of fake users with nonsense names encrypted as you describe. These can serve double duty as the traps you describe, but then you need to be able to distinguish a trap from a real user which means it is possible for an attacker to do the same if they can compromise the trap-checker.
Who are you trying to secure it against?
Do you want to secure it against someone who compromises the DB, e.g by SQL injection, or a rogue sysadmin?
Do you want to secure it against someone who compromises the OS and gains access to the files that back the database tables?
The former can be mitigated by restricting access to the table to well-reviewed stored procedures, and tough DB access controls.
The latter can be mitigated by putting DB files on an encrypted partition, though this can slow down access and/or complicate startup.
Ironically, the larger the number of users, the more likely a brute force attacer is to stumble on a valid combination - and if they know that you have a lot of users with _xxxx or _yyyy in their usernames/passwords, that may give them a cryptographical advantage.
So, I would absolutely recommend that you give your bogus users no actual privileges, so that even a succesful guess yields no rights to the system.
Secondly, you might want to think about who you're protecting against, and how - it's widely accepted that a good hash/salt combination protects against most credible attacks; adding the username to that scheme just means you're protecting against attacks that don't currently exist.
On the other hand, you're doing nothing to protect against the far more common attack vector of "username on post-it note", "password = sex", etc.
The most common way to improve on "username/password" is to require users to have something physical.
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..)