I have a strange scenario that I am currently unable to explain. I live in hope that it's just "the Friday feeling" or that some kindly sole here will bail my brain out and save me from endless loops of "but why!?" :)
Two servers, running SQL Server 2005, with DNS Entries of:
1. ServerA
2. ServerB
(Well, they're not really called that, but it will suffice...)
On both SQL Server Instances there are Linked Servers configured pointing to the other server.
For obvious security reasons the LinkedServer Security configuration is set to:
- Be made using the login's current security context
The other "Linked Server Options" are...
Collation Compatible: True
Data Access: True
RPC: True
RPC Out: True
Use Remote Collation: True
Collation Name: <blank>
Connection Timeout: 30
Command Timeout: 10
A login is created with the same password on both Instances. The logins are given the appropriate execute permissions to the relevant stored procedures.
I write some code, and execute it under that login and it all works hoorah
But when I create an Agent Job to run these stored procedures it all goes wrong. The owner of the Agent Job is 'automated_job_login' but my error logging gives the following:
- Login failed for user 'automated_job_login'
(Again that name has been altered to protect the guilty.)
I can't figure out for the life of me why it will work when I log in as that user, but the job errors when connecting to the linked server. (It's definately at the point of the linked server connection.)
To make things more confusing, if I change the Linked Server Security configuration to "Be made using this secuirty context:" and specify 'automated_job_login' with the correct password, it works fine.
I'm missing something, I know I must be, but I can't find what. I've read documentation until my eyes bleed and I've failed. Please help me :)
[Leaving the Linked Server Secuiry option as "Be made using this secuirty context:" is not an option as this would give all users of that server unnaceptable levels of access to the other server.]
The SQL agent job may be owned by your login, but it is not executed in that login context. It's in the SQL Agent service account context
Because you have SQL Server 2005, you could use EXEC AS USER = 'mylogin' as a stored proc option.
Otherwise, you have to set the database user name using the #database_user_name parameter of sp_add_jobstep. In SSMS, you can set the context. Job ownership is slighty different to setting ths, IIRC.
Related
I am a beginner with SQL so I struggle with the MSDN description for creating a linked server in Management Studio.
I whant to link a SQL Server into another to use everything from ServerB on ServerA to e.g. provide one location other systems can connect to.
Both servers are in the same domain and both server have several databases inside.
When I start creating a linked server on ServerA in the general tap I select a name for the linked server and select SQL Server as Server type.
But I struggle on the Security tap. I have on both servers sa privilege so what is to set here?
Or which role should I take/crate for this connection?
My plan is to create views in a certain DB on ServerA with has also content of ServerB inside.
This views will be conusumed from an certain AD service user.
I already added this service user to the security on ServerA where the views are stored.
Do I also have to add this user somewhere on the linked ServerB?
I would recommend that you use Windows Authentication. Activate Security Delegation.
In the Security tab, choose "Add". Select your Windows user and check "Impersonate".
As a quick and dirty solution, you can choose "Be made using this security context" from the options list and enter a SQL Login which is valid on the remote server. Since quick and dirty solutions tend to last, i would strongly recommend to spend some time on impersonation.
In Server Objects => right click New Linked Server
2. The “New Linked Server” Dialog appears. (see below).
3. For “Server Type” make sure “Other Data Source” is selected. (The
SQL Server option will force you to specify the literal SQL Server
Name)
Type in a friendly name that describes your linked server (without spaces). – Select “Microsoft OLE DB Provider for SQL Server”
Product Name – type: SQLSERVER (with no spaces)
Datasource – type the actual server name, and instance name using this convention: SERVERNAMEINSTANCENAME
ProviderString – Blank
Catalog – Optional (If entered use the default database you will be using)
Prior to exiting, continue to the next section (defining security)
Click OK, and the new linked server is created
The easiest way would be to specify to make the connection using the current context, i.e. the user loging on to ServerA:
EXEC master.dbo.sp_addlinkedserver #server = N'ServerB', #srvproduct=N'SQL Server'
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname=N'ServerB',#useself=N'True',#locallogin=NULL,#rmtuser=NULL,#rmtpassword=NULL
This however assumes that users accessing the linked server connection have the correct privileges on ServerB (part 2 of your question) - otherwise you'd need to use impersonation as described by Martin K.
I have been asked to maintain a site created in ASP classic that uses a SQL Server database.
I was given the database in the form of a backup. I restored the database on my local computer and created a DSN connection to it. However when I attempt to load my site, the stored procedures the site relies on give an error that execute permission was denied.
The stored procedures in question have a user named UserSecure showing as the only person with EXECUTE permission, I have tried creating a user by that name but that does not work, even though I can manually login to SQL Server Management Studio using UserSecure trying to connect from the web page using those credentials gives a login failed error.
If I run sp_helplogins my Windows credentials are shown as being owner of the database, and I can in fact execute from within SSMS but not from an ADO connection.
On another note the connection in the webpage was coded like this, I am not familiar with the application part of the connection. Perhaps this is part of the problem? I have tried connecting with a DSN and DSN-less connection and can connect but not do anything with the database?
You should make sure the database server login is mapped to the appropriate database user (this problem crops up often when dealing with database backups). If it is not, then you need to fix the mapping. Fortunately, there is a command called sp_change_users_login that you can use to fix this problem.
First, check if your login is mapped to your database user. Using SQL Server Management Studio (assuming SQL Server 2008), look under Security/Logins for UserSecure. If you see it in the list, double click on it and select User Mapping. From there, locate the database you are trying to connect to, and see if UserSecure is mapped to that database. If it is not, you may be able to fix it using the following command (assuming UserSecure is the name of both the login and the user):
EXEC sp_change_users_login AUTO_FIX, UserSecure
See MSDN for more info on sp_change_users_login:
http://msdn.microsoft.com/en-us/library/ms174378.aspx
One issue that has bitten me a few times:
If your stored procedure (or view) requires permission from a user (let's say userA), and the stored procedure calls another database's table or view (say viewB), it is not sufficient to just make a login on viewB's database, you must also explicitly grant userA permission to select/execute/etc. on viewB (which in turn requires a user on viewB's database)
So in your case, you may need to explicitly grant UserSecure execute permission on a stored procedure on an existing database referenced by the one you restored.
This may not be the most elegent fix, but I quit focusing on the one procedure and instead granted execute permission to the guest user on the entire DB. Since this is only running on my personal machine security is not an issue and it seems to have fixed the problem.
Know the problem all too well,
The ID of the user(name) will be different from the backed up database to the restored one. MSSQL stores the ID of the user and not the username (text), so the ID will be different (99% of the time) per machine and backup. So when the ID does not match you don't have access.
All you need to do is delete the user and recreate it, make sure you do it in both places:
Delete the user from the database first:
DATABASE -> SECURITY -> USERS -> Right click (username) + delete
Then goto
SECURITY -> LOGINS -> Right click (username) + delete
Then recreate the user and give the account the correct permissions and you're all good.
I am attempting to migrate from SQL Server 2005 to SQL Server 2008. Both of these database instances are hosted on 3rd party shared servers that I do not have full permissions to. They are using mixed mode authentication.
I am running into trouble setting up the new database the same way the old one was set up. Specifically, the new web-based control panel doesn't allow a dbo to be specified when creating a new database and then when using Red Gate SQL Compare to sync up the schemas I am having problems because some objects (that don't explicitly specify dbo in the script) are being created with the prefix of the user account rather dbo.
I have poured over the documentation trying to find a way to force my login "user1" as dbo to the "db1" database. I came to the conclusion that the script should look like this:
ALTER AUTHORIZATION ON DATABASE::db1 TO user1
Before running this script, the login "user1" already exists, but is not a user for database "db1". Note I had to submit this script to the support of my hosting company in order to run it. According to the hosting company the statement successfully executes, however when I compare the databases using SQL Compare the user "user1" has not been physically added to the database like it was under SQL Server 2005. When trying to add it using the script:
CREATE USER [user1] FOR LOGIN [user1] WITH DEFAULT_SCHEMA=[dbo]
I get the error message:
"The login already has an account under a different username"
I have tried dropping all of the other users from the database, but the error message still persists - which I find odd.
While I could just fix the scripts by explicitly specifying dbo, this would inevitably be a time bomb waiting to go off because if any new script were introduced that didn't explicitly specify dbo there would be a failure during synchronization. Since some of the scripts are from 3rd parties, this is not a good solution.
So my questions: Is there another statement that I need to run in order to add "user1" to the database as a user that is dbo? Is there anything that has changed in the implementation between SQL Server 2005 and SQL Server 2008 R2 that could cause these inconsistencies?
I am unfortunately not able to test to find an answer to the second one because I don't have another SQL Server 2008 database to test with and I don't have full access to do anything I want on this one.
The old database was created through a control panel which forced dbo to be specified and the new one doesn't allow dbo to be specified when creating a database.
From what i have gathered the following should suffice.
ALTER USER [user1] WITH DEFAULT_SCHEMA=[dbo]
The create wasnt working as it already existed.
Have a SQL Server 2008 db which I connect to the Windows Authentication .. has worked good for 7-8 months .. but now when I come to work today it no longer worked to connect, without that I had done something
Error message was:
Can not open user default database. Login failed.
Login failed for user 'Jimmy-PC \ Jimmy'.
where the first is the computer name and the second is the user. The problem seems to be that it tries to connect to the default database. Have tried to change it without success .. I do not have sql server management tools for sql 2008 but only to 2005, someone who has similar experience? who have not touched anything said over the weekend and it worked last Friday without any problems.
The user's default database is offline. the thing that changed since yesterday is that your database had failed, for whatever reason.
You need to log in with a different account, one that does not have a default database, and inspect the state of the database. If you do not have such an account, then you can use an administrator account. If the administrators group is not granted login into SQL Server then see this article Troubleshooting: Connecting to SQL Server When System Administrators Are Locked Out.
Once you can log in, the only tool you need is sqlcmd.exe, which is installed on your machine. Look into sys.databases, the state_desc column will tell if a database is offline. You can try a to ALTER DATABASE ... SET ONLINE and see if it recovers, but that would be unlikely. Your best choice will be to apply your disaster recovery plan and restore the database from the backups you keep for it.
It is strange that it just stopped working. Have you checked the status of the user's default database? Make sure the database exists and is online.
To find the user's default database run the following command using sqlcmd.exe
select dbname from syslogins where name = 'Jimmy-PC \ Jimmy'
I have seen this error when recovering a system and the user's default database hadn't been restored yet and another time when a database was in "Recovery" mode.
I would also make sure that the windows account is not disabled.
If you find that you need to change the user's default database you can use a T-SQL command, see the following question:
How do I set the default database in Sql Server from code?
I get a strange behaviour when I combine impersonation with database links in SQL Server 2005. First, I connect to a database server using simple SQL Server Authentication with Login 'John'. On this server, a server link remote_sqlserver is defined. I already have SELECT privileges for mydb in this server. When I simply query a table on a DB on this server link:
SELECT count(*)
FROM remote_sqlserver.mydb.dbo.mytable -- Works!
After that, I try impersonation with the same Login (don't ask why would one do that, I'm just experimenting ;) )
EXECUTE AS LOGIN = 'John'
SELECT count(*)
FROM remote_sqlserver.mydb.dbo.mytable -- Error: "Login failed for user: 'John'"
When I revert, it works again:
REVERT
SELECT count(*)
FROM remote_sqlserver.mydb.dbo.mytable -- Works!
Do you have any idea, why I get an error with impersonation, although the same Login can query the table without impersonation?
BTW: After "impersonation as self", if I query a local database, (of course, for which I have enough privileges) I don't get any error. It only happens when I query a remote DB via server link.
You should read the Books Online article "Extending Database Impersonation by Using EXECUTE AS".
When you use EXECUTE AS to access a remote server, the remote server has to be configured to trust the caller. Even though the the "parent" and "child" logins are the same (i.e. "John") since you are using EXECUTE AS the trust relationships have to be set up. The authentication "path" is different even though the login is the same.
Wouldn't it be interesting if authentication would work by simple means of trusting who you say you are? One would say "I'm John, give me all the money in my account" and the bank would pay up the cash. Now, fortunately, the authentication systems used everywhere will be just a tad more demanding and when one shows up and say "I'm John", he will be challenged "Hullo John, so... what is your password?".
Exactly the same thing goes on here. You may notice that when you say EXECUTE AS Login = 'John' you did not provide a password. So the SQL Server instance may have been 'fooled' that you're "John", but nobody outside SQL will believe you (and the "fooling" inside SQL is a long story of trust and privileges in fact, what really happens is more like "I am the SYSADMIN and I SAY that thou shall believe this user is John!".
If you want to access anything outside the SQL Server system and be John, then you need to specify John's password. The usual way is by using a credential object, with CREATE CREDENTIAL.
If you haven't already, it might be worth having a quick read up on EXECUTE AS and Ownership Chains in case they can shed any light on the problems you're having