views:

421

answers:

5

I have programmed a Windows Service in C# which should connect to an SQL-Server 2005 Express Database with System.Data.SqlClient.

As Microsoft prefers to use Windows Authentication over SQL Authentication I tried to connect to the DB with Trusted Conenction / Integrated Security.

However that doesn't work as I get a System.Data.SqlClient.SqlException: Login failed for user 'NT AUTHORITY\LOCAL SERVICE'.

Is it possible to login with a different Windows Account?

+1  A: 

You need to grant access to the LOCAL SERVICE account in SQL Express. As per my comment, my advice would be to create a new account which your service can run under and then add the relevant permissions inside SQL Express, in other words, don't run your service under LOCAL SERVICE.

James
I thought about that, but wouldn't then every service get access to my db?
räph
Every service running under that account yes. You should create a separate account and specify only the permissions it requires.
James
+2  A: 

If you want to use trusted windows authentication, the easiest thing to do is to run the service with a domain account (with the least privilleges required) that is permissioned to the sql server database.

Neerav
+5  A: 

At the moment, the service appears to currently run under the LocalService Account and this service account is not currently authorized on SQL.

The situation can be fixed in one of two ways: running the account under an account whichis authorized in SQL or add the LocalService account as a login in SQL. Specifically:

  • Change which account the service is ran as, in the Service management console. (ex: Computer Management | Services and Applications | Services then right-click for "Properties" on the service in question)
  • Alternatively, in "Microsoft SQL Management Studio", add the LSA account as a login and set this new principal (login) in a way that it can access the desired database objects.

Edit: The first approach is probably preferable, because the LocalService account is so pervasively found in the system that granting it access to SQL would expose SQL and the databases would a particular service or driver using it become compromised.
Instead by introducing a specific account one has more control over who accesses SQL objects and how. This of course bring the issue of configuring such an account, with regards to the privileges it should be granted, at the level of the system (not of SQL), and depending on what the underlying Service does, on may need to make this account rather powerful, hence a potential liability in other ways....

mjv
thanks. changing the user for the service sounds good. but how can that be done programmativally? I want to do that in my c# programm - not in the service management console..
räph
@räph: A while back I would have suggested looking into the ADSI API, but now you should be able to "mess with accounts" more easily with the .NET System.ServiceProcess.ServiceController class. Although I use this for starting/stopping services, I've never altered a service's setting in this fashion. Other approaches I've seen are spawning a net command (though I don't believe changing service is possible that way) and more recently with PowerShell (does allow changing a service properties, although I don't have experience with this either...).
mjv
LSA stands for *Local Security Authorithy*, not LocalService. http://msdn.microsoft.com/en-us/library/ms721592%28VS.85%29.aspx#_security_local_security_authority_gly#_security_local_security_authority_gly
Remus Rusanu
@Remus: You're quite right, thank you for pointing this out. I edited accordingly; my focus was on getting the account and SQL principal to match, so I didn't pay much heed to the LSA and its nature. Revisiting the answer prompted me to suggest that it probably preferable to use another account, and I think you'd agree with this. Also, do you have by chance a suggestion regarding the OP's search for a way to programmatically, in C#, alter some of the service's configuration parameters ?
mjv
LSA is a system component (lsass.exe), not ana ccount. I edited your post. To manipulate services programmatically in C# one uses the ServiceController class http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicecontroller.aspx. To set a specific service account the best way is to have a ServiceInstaller in the assembly and let the service configure itself appropiately: http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstaller.aspx. It is unadvisable to change a foreign service, after is installed, from an application.
Remus Rusanu
Thank you Remus for all these clarifications. I, and many of my colleagues, use "LSA" as a shorthand designating the LocalService Account, unaware that acronym was used, more officially, for the lsass Authority. My original mention of `Local Service Account` was therefore correct, the problem was with using `LSA`. Sorry for the confusion.
mjv
No worries. that's why I didn't downvote your post or anything similar, since it was basically correct. I just wanted to clarify the confusion since I, and many of my collegues, use LSA meaning the 'authority' :)
Remus Rusanu
SOLVED: In my c# prog I set ServiceProcessInstaller.Account to USER and assigned the service to a Windows User Account. After overcoming http://stackoverflow.com/questions/790795/error-1001-in-my-windows-service-app-setup-project it's working as desired!
räph
+3  A: 

When a Windows Service is started by the Service Control Manager, the process executes as a particular user just as with any other process running on the OS.

There are a number of "built-in" user accounts that are used for running Windows Services. You can see the complete set of Windows Services and the account they run as (called "Log On As" in Windows 7) if you look at the "Services" node within Computer Management".

From my experience, when we want a Windows Service to talk to the DB using integrated security we take the second approach below:

1) Assign one of the built-in accounts as the "Log On As" account and add this account as a login on the SQL Server instance with the appropriate DB permissions

2) Use/create a local or domain account for the Windows Service to use and then add this account as a login with the appropriate DB permissions. It is possible thru the installer to prompt for the user account credentials during the installation of the service.

I can't claim to be expert enough to point out all pros and cons of each approach, however it's worth considering the following:

  • with approach 1 all services and processes that run as the selected built-in account will have permission to access you database. This is not the case with approach 2.

  • with approach 1 the password configuration is managed by the machine itself but with approach 2 the password can be managed by the administrators and also conform to any required security policies in place.

I hope this helps

BrianB
+1  A: 

As mjv said, you need to either give Local Service Account access to the database or use a different account to run the service. You asked how you can change the account programmatically, which is accomplished by creating an Installer for the service and changing the Account property to "User" then specifying the Username and Password to run the service.

The following link contains information on creating the installer if you scroll to the bottom:

http://msdn.microsoft.com/en-us/library/aa984464(VS.71).aspx

While the following provides a little more detail about the Account property:

http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceprocessinstaller.account(VS.71).aspx

Hope this helps.

Waleed Al-Balooshi