SQL Server GRANT SELECT permissions Not Working - sql-server

I'm having an issue giving a single user the ability to perform
select * from msdb..sysmail_profile
I get the following error:
Msg 229, Level 14, State 5, Line 1
The SELECT permission was denied on the object 'sysmail_profile', database 'msdb', schema 'dbo'
I've tried to grant permissions by using:
use msdb;
grant select on msdb.dbo.sysmail_profile to [My User];
but still no avail. However, if I do the exact same grant permission command for [Public], then the user is able to perform the needed select statement, but I don't want [Public] to have access to select from that table.
I have not found any Deny's anywhere for this user, yet I am still unable to give this single user SELECT permissions. Any thoughts?

I think your context is not switched. Try with EXECUTE AS and see if the issue still persists. For me, the below code worked successfully without issues.
use master
go
CREATE LOGIN TestLogin with password = 'YOURSTRONGPASSWORD'
GO
use msdb
go
CREATE USER TestLogin for login testlogin
GO
grant select on msdb.dbo.sysmail_profile to [testlogin]
GO
EXECUTE AS user = 'Testlogin'
go
SELECT * FROM msdb.dbo.sysmail_profile
go
Revert
go

make sure in security > logins > [myuser]> user mapping > check msdb
(if the user still does not have access try to revoke public server role because I think the default in public server role for msdb is denied)
use msdb;
REVOKE select on msdb.dbo.sysmail_profile to public;

Related

EXECUTE AS USER = 'dbo' Throws error. Why?

When I create a new database and I execute SELECT user it returns me that the user is dbo.
So I was creating a new user and executing the code as that user created. But when trying to change it again to dbo, it throws me an error that it doesn't exist, but I can see it. Why does this happens? I'm executing something wrong?
CREATE USER TestUser WITHOUT LOGIN
SELECT user --Returns dbo
SELECT * FROM sys.database_principals --I can see both, dbo and TestUser and some other users of the system
EXECUTE AS user = 'TestUser'
SELECT user --Returns TestUser
EXECUTE AS user = 'dbo'; -- Says that it doesn't exist
Error that throws:
Cannot execute as the database principal because the principal "dbo"
does not exist, this type of principal cannot be impersonated, or you
do not have permission.
Using Microsoft SQL Server Management Studio 14.0.17119.0
Because "you do not have permission". Everything after EXECUTE AS is done as the new user, including attempting to impersonate new users, and TestUser, not being a sysadmin, cannot impersonate dbo. REVERT instead.
The key is in the error message "this type of principal cannot be impersonated". Basically, user 'dbo' should be considered an alias or a role (database owner). So, when you create a database/table/etc by using your login you have the database owner privilege. For example, if you log in as user 'sa' and create a table, the full qualified table name is DataBaseName.dbo.TableName.
Why would you need to execute as 'dbo'? It would be better not to assign database owner rights to a bunch of users, but rather keep the users/roles/permissions well compartmented.

Is it possible to get "WITH EXECUTE AS " working under "dbo user/Administrator login" permissions (VIEW SERVER STATE needed)?

The problem can be emulated this way:
DECLARE #C1 BIGINT,#C2 BIGINT;
PRINT SUSER_NAME()+ ' '+ USER_NAME();
SELECT #C1=transaction_id from sys.dm_tran_current_transaction (nolock)
PRINT #C1
EXECUTE AS USER = 'dbo';
PRINT SUSER_NAME()+ ' '+ USER_NAME();
SELECT #C2=transaction_id from sys.dm_tran_current_transaction (nolock)
PRINT #C2
REVERT;
Called from 'Administrator' login (db owner, linked to dbo user) returns:
Administrator dbo
2209599
Administrator dbo
Msg 297, Level 16, State 1, Line 7
The user does not have permission to perform this action.
The same user but different results. Why?
Details:
I have a SP that contains select from sys.dm_os_sys_info and therefore this SP's caller should have VIEW SERVER STATE permissions.
I have modified SP header with "WITH EXECUTE AS OWNER". Owner is standard 'dbo' database user linked to 'Administrator' server login. Administrator is a member of sysadmin and have effective permission 'VIEW SERVER STATE', but execution of my modified procedure brings the 'The user does not have permission to perform this action' error... I see there logic since DBO database user by itself doesn't have server permissions (even if Administrator login has). But what next?
I have tried:
GRANT VIEW SERVER STATE TO DBO - doesn't work because of 'dbo is
not a user-defined server role' error.
Create new user 'ServerStateViewer' linked to 'Administrator' - doesn't work becuase of 'the login already has an account under a different user name' (as I understand it - dbo user exits in the dabatabse)
Create new user 'ServerStateViewer' not linked to any login - doesn't work because I can't to add any server permissions to this user.
WITH EXECUTE AS 'Administrator' - doesn't work because of 'Administrator is not a database user' error.
So it seems I'm forced to create new server login. I am interesting, may be there are still other ways to get WITH EXECUTE AS working under dbo user / Administrator login permissions?
You'll need to use code signing. This is not a problem, since code signing is what you should be using to start with to grant permission to procedures... The proper sequence is this:
inspect the procedure code to ensure that you trust it
change the procedure to have an EXECUTE AS OWNER clause
create a certificate with a private key in the SP's database
sign the procedure with the private key of the certificate you created
drop the private key of the certificate (to prevent it from ever being used again)
copy the certificate into the master database
create a login from the certificate
grant AUTHENTICATE SERVER to the certificate derived login
grant any additional priviledge required by the procedure (e.g. VIEW SERVER STATE) to the certificate derived login
For an example see Signing an activate procedure.
Note that during development code signing can be a pain because you will have to re-sign the procedure after every change to it. For dev purposes, do not drop the private key right after signing, so it can be reused.

SQL Server: cannot access system tables

I have an MSSQL database and a "normal" user accessing it. When I try to use tables like sys.objects, I become a permission error:
select name from sys.objects
Msg 229, Level 14, State 5, Line 1
The SELECT permission was denied on the object 'objects', database 'mssqlsystemresource', schema 'sys'.
Why? The documentation says
In SQL Server 2005 and later versions, the visibility of the metadata
in catalog views is limited to securables that a user either owns or
on which the user has been granted some permission.
so I think I should be allowed to use sys.objects, even if it will list only the for me visible objects...
My user have been created with
CREATE LOGIN [factoryFX20_K_user] WITH PASSWORD=N'...', DEFAULT_DATABASE=[ff20121025], DEFAULT_LANGUAGE=[English], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON
EXEC sys.sp_addsrvrolemember #loginame = N'factoryFX20_K_user', #rolename = N'serveradmin'
USE [ff20121025]
CREATE USER [factoryFX20_K_user] FOR LOGIN [factoryFX20_K_user] WITH DEFAULT_SCHEMA=[factoryFX20_K_user]
The problem was ideed the same as in The SELECT permission was denied on the object 'sysobjects', database 'mssqlsystemresource', schema 'sys': my user had some "denying" roles.
The solution was to remove this roles of the user:
USE [ff20121025]
EXEC sp_droprolemember N'db_denydatawriter', N'factoryFX20_K_user'
EXEC sp_droprolemember N'db_denydatareader', N'factoryFX20_K_user'
Thanks Jon!

The EXECUTE permission was denied on the object 'xxxxxxx', database 'zzzzzzz', schema 'dbo'

I'm having problems executing a function.
Here's what I did:
Create a function using SQL Server Management Studio. It was successfully created.
I then tried executing the newly created function and here's what I get:
The EXECUTE permission was denied on
the object 'xxxxxxx', database
'zzzzzzz', schema 'dbo'.
Sounds like you need to grant the execute permission to the user (or a group that they a part of) for the stored procedure in question.
For example, you could grant access thus:
USE zzzzzzz;
GRANT EXEC ON dbo.xxxxxxx TO PUBLIC
Best solution that i found is create a new database role i.e.
CREATE ROLE db_executor;
and then grant that role exec permission.
GRANT EXECUTE TO db_executor;
Now when you go to the properties of the user and go to User Mapping and select the database where you have added new role,now new role will be visible in the Database role membership for: section
For more detail read full article
In SQL Server Management Studio, go to security->schema->dbo:
Double-click dbo, select the Permissions page, then click the "View database permissions" link in blue:
Select the user for whom you want to change permissions, and look for the "Execute" permission under the "explicit" tab:
Choose the appropriate permission by checking the appropriate box.
you need to run something like this
GRANT Execute ON [dbo].fnc_whatEver TO [domain\user]
This will work if you are trying to Grant permission to Users or roles.
Using Microsoft SQL Server Management Studio:
Go to: Databases
Right click on dbo.my_database
Choose: Properties
On the left side panel, click on: Permissions
Select the User or Role and in the Name Panel
Find Execute in in permissions and checkmark: Grant,With Grant, or Deny
Giving such permission can be dangerous, especially if your web application uses that same username.
Now the web user (and the whole world wide web) also has the permission to create and drop objects within your database. Think SQL Injection!
I recommend granting Execute privileges only to the specific user on the given object as follows:
grant execute on storedProcedureNameNoquotes to myusernameNoquotes
Now the user myusernameNoquotes can execute procedure storedProcedureNameNoquotes without other unnecessary permissions to your valuable data.
You don't have the right to execute it, although you have enough permissions to create it.
For more information, see GRANT Object Permissions (Transact-SQL)
If you have issues like the question ask above regarding the exception thrown when the solution is executed, the problem is permission, not properly granted to the users of that group to access the database/stored procedure. All you need do is to do something like what i have below, replacing mine with your database name, stored procedures (function)and the type of permission or role or who you are granting the access to.
USE [StableEmployee]
GO
GRANT EXEC ON dbo.GetAllEmployees TO PUBLIC
/****** Object: StoredProcedure [dbo].[GetAllEmployees] Script Date: 01/27/2016 16:27:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[GetAllEmployees]
as
Begin
Select EmployeeId, Name, Gender, City, DepartmentId
From tblEmployee
End
here is how to give permission for one user not public,
Direct Query:
Use MyDatabase
Grant execute on [dbo].[My-procedures-name] to [IIS APPPOOL\my-iis-pool]
Go
You can give everybody execute permission:
GRANT Execute on [dbo].your_object to [public]
"Public" is the default database role that all users are a member of.
If you make this user especial for a specific database, then maybe you do not set it as db_owner in "user mapping" of properties
I have faced the same problem and I solved as give db_owner permission too to the Database user.
The general answer is to grant execute permission as explained above. But that doesn't work if the schema owner of SP is different to underlying objects.
Check schema owners by:
select name, USER_NAME(s.principal_id) AS Schema_Owner from sys.schemas s
To change the owner of an schema you can:
ALTER AUTHORIZATION ON SCHEMA::YOUR_SCHEMA TO YOUR_USER;
Examples:
ALTER AUTHORIZATION ON SCHEMA::Claim TO dbo
ALTER AUTHORIZATION ON SCHEMA::datix TO user1;
Finally if within your SP you are truncating a table or changing structure you may want to add WITH EXECUTE AS OWNER in your SP:
ALTER procedure [myProcedure]
WITH EXECUTE AS OWNER
as
truncate table etl.temp
If you only need to grant a single function then (only db admin can do it):
Open Management studio
Find function/procedure you want to grant in Object Eplorer (dbname-Programmability-[Functions/Stored Procedures]-...)
Right click on function or procedure name and open Properties
In Properties select Permissions, add user (or schema) you want and Grant him Execute permission.
I believe this is most secure way how to do it because you only grant to user execution of this function. Nothing else!
I think you have to select the object you want to grant access to, then right-click, and select properties. Select permission on the modal window that will be displayed then click on Search, on the newly revealed window, select browse, select the user you want to grant access and click on ok. it will display for you a list of permission and the grant status, and then you can choose to grant or deny
This shows that you don't have access to perform any action on the specified database table. To enable this, Go to Security -> Schema and check.
you'd better off modifying server roles, which was designed for security privileges. add sysadmin server role to your user. for better security you may have your custom server roles. but this approach will give you what you want for now.
Object Explorer -> Server -> Security -> Logins
Right click on your desired user
Go to Server Roles on left hand side
Make sure sysadmin is checked
Hit OK and restart your SQL server
Good luck

Sql server execute permission; failure to apply permissions

I've just migrated from SQL2000 to SQL2008 and I have started getting an execute permission issue on a stored proc which uses sp_OACreate.
The rest of the system works fine with the db login which has been setup and added to the database.
I've tried:
USE master
GO
GRANT EXEC ON sp_OACreate TO [dbuser]
GO
But this fails with the following error:
Msg 15151, Level 16, State 1, Line 1
Cannot find the user 'dbuser', because
it does not exist or you do not have
permission.
I'm logged into the server as sa with full permissions. I can execute a similar sql statement and apply the permissions to a server role, however not a login/user.
How do I apply the changes to the specific user/login?
I can apply the permissions to the public role and it resolves my issue; however this seems to be a security issue to me which I don't really want to apply to the live server.
Leading on from John's answer I checked the user listings on the Master database and my user wasn't there. Whether it had been deleted or lost some how I don't know. Something may have gone crazy with the migration of the dbs to the new server instance.
Anyway; re-creating the user and associating it to the specific login enabled me to run the following statements on the master database to allow for the execution of the stored procs.
USE MASTER
GO
GRANT EXECUTE ON [sys].[sp_OADestroy] TO [dbuser]
GO
GRANT EXECUTE ON [sys].[sp_OACreate] TO [dbuser]
GO
GRANT EXECUTE ON [sys].[sp_OAMethod] TO [dbuser]
GO
GRANT EXECUTE ON [sys].[sp_OASetProperty] TO [dbuser]
GO
Thanks for all the help and pointers. Hope this helps other people in the future.
The error suggests that the User "dbuser" does not exist in the master database.
I assume the user exists within the master database?
You can check by using the following T-SQL
USE MASTER;
GO
SELECT *
FROM sys.sysusers
WHERE name = 'dbuser'
If the user turns out not to exist, simply use the CREATE USER statement and create a user called "dbuser". The user will automatically be mapped to a Login of the same name, provided one exists.
Your problem could be related to orphaned users.
Try
USE MASTER
GO
EXEC sp_change_users_login 'Report'
This will return one row per orphaned user name. Then,
EXEC sp_change_users_login 'Update_One', 'dbuser', 'dbuser'
Here is some code I'm using the verify that (current user) has EXECUTE permission on sp_OACreate etc:
use master;
select state_desc,name from
sys.database_permissions a
left join
sys.all_objects b
on a.major_id = b.object_id
where name like 'sp_OA%';
As pointed out by #John Sansom and #WestDiscGolf the user has to exist in the Master database and the execution rights must granted in the Master database, hence use Master is required. The query above will return records if the user has execute permissions and empty set if they do not. (Execution in the user database will also return empty set.)
I couldn't figure out a way check these permissions using fn_my_permissions, which is supposedly the right tool for jobs like this.
Check if your user has permissions for the database you use. You can do this by Security -> Logins -> Select User and open the properties window. Then select "User Mapping" from the right menu. Now check the databases that you want the given user to have access to. After that select from the bottom part of the window "Database role membership" and check "db_owner". Now the user will be the owner of the database and will be able to execute queries, store procedures and so on.
UPDATE:
Add user for the database by selecting your database -> security -> users -> right click "New User"
Or you can use this query
CREATE LOGIN AbolrousHazem
WITH PASSWORD = '340$Uuxwp7Mcxo7Khy';
USE AdventureWorks2008R2;
CREATE USER AbolrousHazem FOR LOGIN AbolrousHazem;
GO
Here are more details http://msdn.microsoft.com/en-us/library/ms173463.aspx

Resources