I'm developing an application that manages information about users and save the data in a SQL Server. I would like to 'somehow' connect this application with our Active Directory, so all the changes this app will make will be reflected in the Active Directory too (if we add a new user in the app, it will be added also in the Active Directory)
Is it possible? if so, which are my options?
Thanks in advance
Don't do it. Let AD be the authoritative copy of your user base, and let the users always be created in AD first and then propagate to SQL. By letting users be added through a different path (SQL first) you open a huge can of worms with regard to security. If a user is defined in SQL but not in AD, what exactly is taht user? How can he log in? To what groups does he belong? IS he allowed access or not to this resource or that resource? How about cases when an user is added in AD and in SQL with different characteristics and then you need to reconcile.
Modify your application do always create the user in AD, in conformance with the AD policies and security requirements (password complexity being the most trivial example). Then let AD synchronize with SQL.
The way I chose to solve this problem was to add an event that was triggered when I saved my user object. The listener on this event would then send an update to Active Directory. In my case I was doing a one way sync to Active Directory and it was also a best effort attempt, meaning if it failed I was fine with it. If you need to do some more reliability around it you will want to wrap your SQL updates inside of a transaction and only commit after active directory is updated.
If you need a two way sync with Active Directory you will need to look at doing some sort of a background synchronization with Active Directory where you iterate over your users and check for updates in AD.
If you are doing a one-way sync to AD, I agree with Aaron that you should simply have a Trigger in SQL server. Note that this solution may suffer from some problems, like the user accounts already created, user name or password doesn't meet the AD complexity rule. You need to then find some ways to log the error. You may also need a tool to do initial provisioning of your database accounts.
If you want to do two-way sync, I suggest you to read up DirSync. You probably need to write a NT service to do it. I hope you don't store password in your database. I highly suggest you to use Windows authentication. If you do need to sync up the password, you may need to write your own passwordsync and install it in all the domain controllers in your machine.
If you are developing a solution for enterprise, you should look up the existing meta-directory solution products from Microsoft, MIIS, ILM, FIM.
They are all the same thing except with the names different. Many enterprise has adopted this as their meta directory solution. You just need to write up an extension to leverage on its provided infrastructures to do the identity synchronization.
Related
I have a windows service, and want to define two roles (administrator and reader) for all the users whoever tries to access my service. So that whoever is assigned with administrator role can have full control over my system, whereas reader can only do readonly operations.
So, looks like I have two options.
Approach using Database
I can simply use database to maintain and their corresponding roles. so, whenever I get a request based on user context, I can validate by querying the db and validate it.
It sounds simple option, but how to make it safe?
For ex, if some looks at my code in reflector, they can find out which table and manipulate the contents so that they can exploit this solution :(
Approach using Directory Services (AD LDS - LDAP)
Looks like Microsoft defined Active Directory lightweight Directory Service particularly for this purposes. I can probably define my own roles and probably add windows security principals to them so that only the AD LDS administrators can manipulate - looks like better approach.
But, I am not sure how to do this programmatically in c# - can any one give me pointers so that I can have a quick start?
Finally, which option is better/recommended and why?
Update:
Looks like these two User Group and Role Management in .NET with Active Directory , What does "active directory integration" mean in your .NET app? gives me some detail in what I am looking for, and it looks like its probably take some time before I consolidate these to define approach for my app :)
Best Regards!
This will get you the SID of the groups
You just need to determine the SID of the group you determine to be admin
System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
Debug.WriteLine(identity.Name);
foreach (System.Security.Principal.IdentityReference ir in identity.Groups) Debug.WriteLine(ir.Value);
working on an application that wants to now integrate active directory. should be able to import users from active directory, as well as reflect changes for example if a user is created/deleted/update etc in active directory the user should be created/deleted/updated in the database table the application reads from. I kno that LDap can be used to query the Active Directory to import users, but not sure how to cater for the other areas.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms677625%28v=vs.85%29.aspx
The previously supplied link is a good one. Of those ideas, my general suggestion is to use DirSync. It allows you to poll AD with a token and get all changes since the previous poll. All you have to do is remember the token (it comes back with the response to the query).
I'm trying to write a central reporting tool that will allow time tracking based on Windows users logging into a domain. Initially I was going to create a small executable that would run on 'all users' start-up on each computer, track the logged in username and update a central database.
The main problems with this would be having to manage the versions on a machine by machine basis and deal with rare but possible instances of the tool failing on specific machines and not being immediately obvious.
Instead I would prefer to create a centralised version but I'm finding the MSDN and Windows SBS 2003 docs very hard to dig through for the answer.
Basically I would like to hook into the 'login' and 'logout' functions on the server and track all information from there. Are there natural extension points here?
Obviously an alternative may be to parse the event logs for the information (but to this point I can't find any windows logs that say 'who' is logging in or out).
Any guidance on the direction or documentation to look at would be really appreciated.
Are there natural extension points here?
No. Or rather, you don't plug into login/logout unless you want to replace the login module (e.g. for a different authentication mechanism): not something trivial to do—too easy to open up security holes (and I expect not a good idea, if not impossible, in .NET).
But as Windows (all NT derived versions) includes the ability to log all logins and logouts, the information you need can be recorded in the Security event log. There are then a number of options for getting at the information.
First: enable audit of login/logout.
This is best done with group policy. For the local machine enable the options in SecPol.msc (local security policy MMC snapin): Local Policies | Audit Policy
Second: read the event log
In the Security Event Log look for logon events (id 4624), there is some documentation of these events here.
Automation of this (e.g. via a scheduled read of the event log) or forwarding events should be easy enough.
Not all logins will go to the dc. For example a laptop may use cached credentials to allow access when not on the domain.
You may also see multiple logins for the same user if they are accessing network resources. I think the most reliable approach would be to have the code running on each machine getting called from one of the login hooks.
You should look into the namespace called Microsoft.Win32.SystemEvents. There are many handlers there, but i believe what you want is the SessionSwitch event, which will tell you if the current user is logging on/off of the box or locks the screen. This is possible because windows switches to a different desktop when the screen is locked/unlocked, so you will be able to catch these.
Then, to get the user information, you could use the UserPrincipal from System.DirectoryServices.AccountManagement namespace using the machine's principal context.
Many desktop applications use SQL tables to manage their users permissions and roles. In fact they restrict access to some parts of application in their application code. It means they need a constant connection string to SQL server with maximum permissions.
My target is C# 2010, Sql Server 2005 or 2008.
What if with any reason someone find that connection string ?(Network tracing, Software hacking, Fired Employee or ...), He can change everything with just Managemenst Studio and you can't understand which client did it. If you want to change connectionstring. You must do it in many clients and in a bad design you need to recompile application.
So i want to know is it good idea to use real SQL login instead of username and password in tables ? make connection string for each user by SQL Logins ?
In this way there is no afraid to loose connection string. Also in SQL codes you can use GetUser() function to indicate which user really runed the query ?
But maybe the managing permission is difficult with this way because there is no simple table to manage permissions and users.
In one long sentence. I want to know What is the best way for authenticating desktop application users in a way that managing permission can be done and also sql server can log user activity ?
Whenever possible, use Windows Authentication.
Define Roles. Add Groups to Roles. Add Users to Groups (as per usual Windows way of managing file system permissions).
Choosing an Authentication Mode
See: Application Roles
You can encrypt sensitive sections of your app.config file. Last time I checked, you have to go through some hoops, but it's not that difficult to set up.
See for example this question
For best security, you need one dedicated database account per user; each account should only have the privilegeds necessary for the tasks that the corresponding user may perform. Normally you grant privileges to roles (e.g. "clerk", "manager", "supervisor") and grant those roles to the users. Obviously, it requires some work to identify which privileges each role needs. In many cases, it might be necessary to not allow direct access to some tables, but only to database views that hide some parts that should not be visible to that role, or to stored procedures that do some additional checks and make sure that each transaction is processed as a whole.
The basic setup is classic - you're creating a Windows Forms application that connects to a DB and does all kinds of enterprise-y stuff. Naturally, such an application will have many users with different access rights in the DB, and each with their own login name and password.
So how do you implement this? One way is to create a DB login for every application user, but that's a pretty serious thing to do, which even requires admin rights on the DB server, etc. If the DB server hosts several applications, the admins are quite likely not to be happy with this.
In the web world typically one creates his own "Users" table which contains all the necessary info, and uses one fixed DB login for all interaction. That is all nice for a web app, but a windows forms can't hide this master login information, negating security altogether. (It can try to hide, but all such attempts are easily broken with a bit of effort).
So... is there some middle way? Perhaps logging in with a fixed login, and then elevating priviledges from a special stored procedure which checks the username and password?
Added: OK, so integrated authentication and windows groups seem to be a fair choice in most situations, so I accepted the relevant answer. Still, if anyone can come up with a non-integrated authentication solution, they'll get an upvote from me.
For WinForms use Windows groups. No passwords are needed because the credentials are inferred from the Windows login using your application.
This is best practice
Basically:
The user belongs to a group (assumes single domain)
Group is a login in the SQL Instance
SQL login maps to a database user
DB User belongs to a DB role
Role has object permissions
It's worth reading up first before having someone try to capture all the information here
Edit:
If you have a workgroup, you can still do it by setting up sqlbox\bob, sqlbox\hans etc in a sqlbox local group.
When someone tries to connect (say bob on his PC) windows will ask them for their details. As long as bob knows his SQLbox account detailsm he can connect.
But then, I've not tried this in a workgroup setting...
In addition to using Windows Domain/AD Groups (put the AD groups in appropriate roles you create in SQL Server, so all account maintenance moves to AD), be sure to use the Application Name in your connection string - this allows you to see which applications are performing operations in the profiler etc.
Because when everyone is logging on as themselves from different applications - windows and web, it helps to know that it's actions taking place through an application and not just any user's ad hoc query through ODBC and Excel, say (if you allow users access to certain views for data export or report writing).
Can't you use Active Directory Groups to make the management of the db connections easier?
From MSDN...
The name can be a Windows user name or a Windows group name, of the form DOMAIN\Name.
That way you may have a few groups, read-only, editor, manager, admin etc. It's how I have achieved similar things in that past with Click-Once apps.
It really is the best choice for what you are doing.
I am assuming this is an existing app? If it was new I would otherwise say to go client server with web-services or similar.
PK :-)
With regards to wanting to hide your authentication and use a single application login with WinForms, if the login has very little privilege - select only on views and execute only on stored procedures, anyone who manages to reverse engineer your encryption of the login information in your application will only be able to perform the same functions they could perform in your application. If you absolutely have to raise the level on the security, you could authenticate each stored proc against your users table (poassing user and hash to each SP). Also, rotate the central application login on a regular basis.
All this is a lot more difficult than using integrated authentication and implementing AD platform in your environment. So you're effectively writing your own directory and authentication instead of using one off the shelf.
In addition to gbn's update about workgroup versus domain, you can run the application with RUNAS /NETONLY /USER:SERVER\USER with user credentials on the domain or server which your machine is not a member of. At the point that the application makes the connection to the database, the remote credentials will be authenticated and used. I have an application which actually checks to see how it was run and if it not run with a particular switch, it prompts for username and password and then re-runs itself using the Windows API using a function equivalent to RUNAS /NETONLY /USER:DOMAIN\USER. This is because our workstations are not currently on the domain (or on a domain with a trust relationship) of the SQL Server. In this case, you could still manage the security in local groups on the SQL Server or groups on the domain of the SQL Server. You would basically just lose out on the automated authentication token.