The SELECT permission was denied on the object 'fn_dblog', database 'mssqlsystemresource', schema 'sys' - sql

I created a user and gave him access to run sp. That sp also has to update a table based on the type of work.
But when the user runs sp, it gives an error:
The SELECT permission was denied on the object 'fn_dblog', database 'mssqlsystemresource', schema 'sys'.
Does anyone have a solution to this problem?

The required permission to use the fn_dblog system table-valued function is sysadmin role membership.
Importantly, this function is undocumented so it should not be used in application code, especially to update a table.
EDIT:
Your comment indicates the function is used in a trigger. You could create a certificate and certificate user that's a sysadmin role member as described here and then sign the trigger with that certificate. That will confer sysadmin permissions to the trigger code and allow non-sysadmin users to use the function but only in the context of the trigger.
I would normally include an example T-SQL script in my answer but I want to strongly discourage you from going down the path of using the undocumented system function in app code.
You have a classic XY problem that needs to be solved differently. Ask a new question about how to provide the functionality you need without using fn_dblog. Include your existing code in the question.

Related

Run xp_create_subdir without admin privilidges

The Point: I want to be able to create a directory on the filesystem through a non-sysadmin SQL user.
I'm creating a web front-end for a deployment script which creates new databases from a specified template database.
Essentially I'm backing up said template database and then restoring this as a brand new database with a different name.
Our DB server has our client databases stored in sub-folders within our database store. If I were to use the default settings it would look something like:
D:\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\[ClientRef]\[ClientRef].mdf
D:\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\[ClientRef]\[ClientRef].ldf
I only have SQL access to the database server (via a programming language, hosted on a separate box) so I can't execute anything other than SQL.
My database user is extremely limited, however I would like to somehow grant this user to access/execute master.dbo.xp_create_subdir only. Is this possible at all?
I'm loathe to give our local DB user sys-admin rights, it has a limited user for a reason.
DB Server is Microsoft SQL Server 2008 R2.
Cheers, any help will be appreciated.
One possible solution is to write your own sproc that internally uses master.dbo.xp_create_subdir.
Create the sproc while logged in as an account that's a member of the sysadmin role and use "WITH EXECUTE AS SELF". Then grant permissions to that other account to execute this sproc. The database catalog where you create this wrapper-sproc must be marked as "trustworthy" or you'll still get the: User must be a member of 'sysadmin' server role. error.
E.g.
CREATE PROCEDURE [dbo].[sprocAssureDirectory] #directoryFullPath varchar(4000)
WITH EXECUTE AS SELF
AS
BEGIN
EXEC master.dbo.xp_create_subdir #directoryFullPath;
END
Just make sure you add any needed assertions/checks to your sproc that make sense for your application (e.g. the path can only be of a pattern that you expect).
Belated Update: Added the critical mention of marking the catalog as trustworthy.
You could give access for the user to use that stored proc explicitly. It is gonna be something like:
GRANT EXECUTE ON OBJECT::master.dbo.xp_create_subdir
TO <SQL USER>;
It sounds like that user is limited for a reason though and getting the extra permissions to run something like that can get a little push back from whoever is managing the DB. So be careful when dealing with getting the elevated privledges.

Impersonation denied from trustworthy database

I am using EXECUTE AS to allow a least-privilege user to run some SQL stored procedures as a sysadmin. I know that I need TRUSTWORTHY=ON on the source database (the one running the stored procedures) in order to impersonate the sysadmin on other databases on my server. However, even with impersonation granted and TRUSTWORTHY=ON, I still get the following error when trying to touch other databases as the impersonated user:
The server principal [least_privileged user] is not able to access the database XXX under the current security context.
(And yes, I know that module signing is the more secure option. I'm not looking to go that route.)
Can anyone help me?
Use execute as owner.
Make sure the procedure is in the dbo schema.
Make sure the database owner has sysadmin rights on the instance. I
have noticed that SQL logins work better for this purpose than ones
from Windows.
Check trustworthy=on for the database.
This way, you don't need additional impersonation grants, but it is a way less secure solution. It will work, though.

SQL Server signature on stored procedure using certificate

I'm confused by the example at this link. A similar example exists here but I prefer the first one. Briefly here is the summary of my confusion:
A user (examplecertuser) is created from the certificate.
Rights are granted to the user (examplecertuser) created from the certificate.
A signature is added to the stored procedure using the certificate.
Then a test is done using a separate login (testuser) that has no relation to the previous. This is what I don't understand.
I'm not sure why the examplecertuser is created or what purpose it serves. More importantly, since no connection is made between the login (testuser) and the certificate created user (examplecertuser), this means that ANY LOGIN is able to run the stored procedure. I verified this by creating another login and having it also run the stored procedure.
I am looking into this to avoid database ownership chaining as per all the recommendations I read. My goal is to grant a user the ability to run a stored procedure which spans several databases but limit them to just running that stored procedure. Using the example I see listed, I think I would be granting everyone the ability to run the stored procedure with no way to limit others from it.
To rephrase the question in a more direct format, "how do you use the sample in the link to only allow selected logins to run the stored procedure?" The user (examplecertuser) seems to be the key to authorization but I don't see any linke between the user and a login.
Code signing gives you the ability to grant permissions to an underlying object under certain circumstances (as opposed to any time). Say, for instance, that I have a table with sensitive information in it. I don't want just anybody selecting from it (that is, writing "select * from myTable"), but I'm okay with giving them access through a stored procedure (so I can limit what they can select with business logic). So I go through the exercise of signing the stored procedure. I can still grant (or deny) execute permissions on the procedure to individual users. But when the permissions are checked for the underlying objects that the stored procedure accesses, it will apply the permissions of the module signing user (examplecertuser in your example).
With respect to your specific questions
Only users that are granted execute permission on the stored procedure will be able to run it
In order have this permission span multiple databases, you'll need to create the certificate and associated user in each database.

How do I grant a database role execute permissions on a schema? What am I doing wrong?

I am using SQL Server 2008 Express edition.
I have created a Login , User, Role and Schema.
I have mapped the user to the login, and assigned the role to the user.
The schema contains a number of tables and stored procedures.
I would like the Role to have execute permissions on the entire schema.
I have tried granting execute permission through management studio and through entering the command in a query window.
GRANT EXEC ON SCHEMA::schema_name TO role_name
But When I connect to the database using SQL management studio (as the login I have created) firstly I cannot see the stored procedures, but more importantly I get a permission denied error when attempting to run them.
The stored procedure in question does nothing except select data from a table within the same schma.
I have tried creating the stored procedure with and without the line:
WITH EXECUTE AS OWNER
This doesn't make any difference.
I suspect that I have made an error when creating my schema, or there is an ownership issue somewhere, but I am really struggling to get something working.
The only way I have successfully managed to execute the stored procedures is by granting control permissions to the role as well as execute, but I don't believe this is the correct, secure way to proceed.
Any suggestions/comments would be really appreciated.
Thanks.
There are couple of issues that I can see in your case.
First of all you would need View Definition granted for you to be able to see the objects in the Management studio.
I would recommend this if you want the role to have all permissions,
GRANT EXECUTE, SELECT, INSERT, UPDATE, DELETE, VIEW DEFINITION
ON Schema::SchemaName TO [RoleName/LoginName]
Also make sure the owner of your user-defined schema is "dbo".

In SQLServer, why doesn't granting object permissions add the user to db properly?

This is my setup:
SQL server 2005
UserA already setup as user on the server but not on databaseA.
GRANT Execute ON [GetOrders] TO [UserA] AS [dbo]
As you can see, i have missed out a step. I haven't added UserA to the database yet. This doesn't fail and lets me grant execute on the object.
I believe in 2000 it would have thrown an error and not allowed me to do this.
Now, I have all these objects with the correct permissions set but the users cannot see the database. To resolve this i have to remove the users from the database, re-add them properly and then give permissions.
Why is this allowed and is there a way to either prevent it or have it create the db login automatically whenever a new user is given object permissions.
thanks.
This is the part throwing you off.
TO [UserA] AS [dbo]
Ditch the "as dbo" part. It's granting the right to the dbo user. Without the "AS [dbo]" part it will throw an error.
It's probably allowed to give DBAs the flexibility to modify the users and permissions when the database is not attached to your production server. I don't believe you have to re-add the users. Take a look at this guy's script: http://www.lazycoder.com/weblog/2007/06/04/re-associate-sql-users-with-logins/