create proc with exec as 'dbo' not working crossing databases? - sql-server

There is a stored procedure
use db1
go
create proc SP1
-- with execute as 'dbo'
as
-- complex code omitted for the question
exec db2.SP2
-- calls other stored procs of other databases too
UserA has only permission to exec db1.dbo.SP1 and it got an error of no permission to exec db2.SP2 and got the following error.
The server principal "Domain\UserA" is not able to access teh database "db2" under the current security context.
I uncommented the line -- with execute as 'dbo' and the error message changed to
The server principal "Domain\DBA" is not able to access teh database "db2" under the current security context.
DBA is sysadmin and it's associate to dbo. It should have all the permissions?

Related

SQL xp_create_subdir for non-admin

I'd like to give a non-admin the ability to create folders on the SQL server's local hard disk using xp_create_subdir. Reason - need to create a folder structure so that manufacturing equipment can FTP large files. Meta data for the files is stored in SQL.
Server is SQL 2016 Express. OS is Windows 10 Pro.
I've found lots of explanations of how to get this to work but can't figure out what I'm missing. Using the SA account I've created a stored procedure like this:
use [DBname]
CREATE PROCEDURE dbo.usp_CreateDirectory
#directoryFullPath varchar(500)
WITH EXECUTE AS owner
AS
BEGIN
SET NOCOUNT ON;
EXEC master.dbo.xp_create_subdir #directoryFullPath;
END
GO
GRANT EXECUTE ON dbo.usp_CreateDirectory TO [TestUser]
GO
Code to run the stored procedure:
DECLARE #RC int
DECLARE #directoryFullPath varchar(500)
set #directoryFullPath = 'd:\FTP_Root\2020\08\22\'
EXECUTE #RC = dbo.usp_CreateDirectory
#directoryFullPath
GO
In Windows I've given NT Service\MSSQL${InstanceName} full access to d:\FTP_Root\
What am I missing? Running xp_create_subdir 'C:\FTP_Root\2020\08\22' in MSSMS works fine.
Running the stored procedure as SA or the non-admin TestUser gives this result:
Msg 229, Level 14, State 5, Procedure xp_create_subdir, Line 1 [Batch
Start Line 2] The EXECUTE permission was denied on the object
'xp_create_subdir', database 'mssqlsystemresource', schema 'sys'.
I found this on another site: https://www.sqlservercentral.com/forums/topic/xp_create_subdir-for-non-sysadmins
The headlines here are two main points
Although this post is old,
In order to solve this issue, you should make sure that your database is Trustworthy - since the SP xp_create_subdir is on different DB
You still need to set "with Execute as 'dbo'
alter database [DBNAME] set trustworthy on
- Guy-456224
And DO understand the security ramifications of using SET TRUSTWORTHY ON. It may not be a problem or... it may. "It Depends" but you won't know until you read about it.
- Jeff Moden
I completely agree with Jeff on this one. If you remotely care about security, understand what the TRUSTWORTHY setting does before adjusting it.
I think the larger question here is to ask why SQL Server needs to create the directory? Powershell could both query the database for the Directory Path and create the Directory. You could have a SQL Server Agent job that will execute this under the security context of either a SQL Server Proxy account, or the SQL Agent service account (I would pick the proxy account personally, but that's just me).

DbCreator role can restore a database but not then access it in MSSQL Server

I am working on a tool which is having restore command to restore MSSQL databases. Till now tool was restoring the databases with sysadmin privileges. However, as per new requirement I want to minimize the access privilege for this command i.e restore should be done with dbcreator role instead of sysadmin. With dbcreator I am able to restore the databases, however this command also does some post-operation on the restored databases i.e. updating some value in table. Post-operation is failing with lack of access, since db_owner is required for this user. How to grant db_owner to current user(dbcreator) on the restored databases who is not sysadmin at run time so that my restore command succeeds along with post-operation.
One way to follow security principles of least privilege and role-based access controls is to encapsulate the T-SQL commands that require elevated permissions in a stored procedure. One can then sign the proc with a certificate to confer additional permissions without granting those permissions directly to users. Only execute permissions on the signed stored procedure are required and authorized users are limited to the encapsulated functionality.
Below is an example script to create a stored procedure and DBRestore role using this technique. If your actual RESTORE command contains options that can't be parameterized (e.g. WITH MOVE file locations), you'll need to use dynamic SQL in the proc and take special care to ensure the values validated and/or obtained from a trusted source (e.g. configuration table instead of ad-hoc parameter value).
USE master
GO
--create certificate in master database
CREATE CERTIFICATE sysadmin_cert_login_cert
ENCRYPTION BY PASSWORD = '<cert-password>'
WITH SUBJECT = 'For sysadmin privileges';
GO
--create login from certificate
CREATE LOGIN sysadmin_cert_login FROM CERTIFICATE sysadmin_cert_login_cert;
--confer sysadmin permissions to certificate login
ALTER SERVER ROLE sysadmin
ADD MEMBER sysadmin_cert_login;
GO
--create role for restore user(s)
CREATE ROLE DBRestoreRole;
GO
--create restore proc in master database
CREATE PROC dbo.usp_RestoreDatabase
#DatabaseName sysname
, #BackupFilePath varchar(255)
AS
BEGIN TRY
RESTORE DATABASE #DatabaseName FROM DISK=#BackupFilePath WITH REPLACE;
--after restore, set database owner as desired
ALTER AUTHORIZATION ON DATABASE::RestoreTest TO sa;
--execute post restore DML
UPDATE RestoreTest.dbo.SomeTable
SET SomeColumn = 1;
END TRY
BEGIN CATCH
THROW;
END CATCH;
GO
--grant execute permission to DBRestoreRole
GRANT EXECUTE ON dbo.usp_RestoreDatabase TO DBRestoreRole;
--sign proc with sysadmin certificate
ADD SIGNATURE TO dbo.usp_RestoreDatabase BY CERTIFICATE sysadmin_cert_login_cert WITH PASSWORD='<cert-password>';
--optionally, remove ephemoral private key after signing
ALTER CERTIFICATE sysadmin_cert_login_cert REMOVE PRIVATE KEY;
GO
--create example DBRestoreRole login/user
CREATE LOGIN RestoreTestLogin WITH PASSWORD = '<login-password>';
CREATE USER RestoreTestLogin;
ALTER ROLE DBRestoreRole
ADD MEMBER RestoreTestLogin;
GO
--test execution
EXECUTE AS LOGIN = 'RestoreTestLogin';
GO
EXEC dbo.usp_RestoreDatabase
#DatabaseName = N'RestoreExample'
, #BackupFilePath = 'E:\BackupFiles\RestoreExample.bak';
GO
REVERT;
GO

SSRS call to stored procedure fails, Cannot find user 'dbo'

I've got a SSRS report that is calling a stored procedure in my database.
Locally everything works, I am connecting with Windows authentication locally to hit the database and there are no problems.
When the SSRS report is deployed it's set up to use a different login, and this login has the correct role to grant execute on stored procedures. However, when trying to view the report on SSRS server I get this message:
Cannot find the user 'dbo', because it does not exist or you do not have permission.
If I remove the role that allows the grant execute rights I get a more specific error saying that I don't have permission to execute the stored procedure. But once this role is put back on the user account SSRS runs as it goes back go showing an error
Cannot find the user 'dbo'
The role I have that is granted execute rights is granted by 'dbo' user, this is the database owner. I have found things online saying that it's possible that a database backup messed up some user logins. I have checked, and the database owner sid is the same as the sysuser sid for name = 'dbo', so I do not think this is the problem.
Does anyone else know what I might be able to try?
EDIT: Details on stored procedure: it is a simple select with some inner joins.
At the end of the stored procedure is the following, granting access to the role my SSRS user is part of:
GRANT EXECUTE
ON OBJECT::[dbo].[Application_LoadData] TO [SSRSUserRole]
AS [dbo];
A stored procedure includes all statements in the batch after the CREATE PROCEDURE. So a proc like this
CREATE PROCEDURE USP_FOO
AS
BEGIN
SELECT * FROM FOO
END
GRANT EXECUTE ON USP_FOO TO SOMEUSER AS DBO;
Will attempt to execute to GRANT every time the procedure is run, and will fail when not run by dbo.
The script to create the procedure should have a batch separator before the grant. eg:
CREATE PROCEDURE USP_FOO
AS
BEGIN
SELECT * FROM FOO
END
GO
GRANT EXECUTE ON USP_FOO TO SOMEUSER AS DBO;

Executing a stored procedure in SQL Server

I have a stored procedure called testSP in my SQL Server Express database.
I am able to execute it using
exec [db_owner].[testSP]
but if I use exec testSP it doesn't work.
What is the cause of this?
I have other databases which do not exhibit this behavior.
Thanks for your help.
Your user is set up with dbo as it's default schema. That's pretty normal
when you run
exec testSP
it's using your default schema which is dbo, so it is running this:
exec [dbo].[testSP]
which doesn't exist.
When you run
exec [db_owner].[testSP]
it find and runs that stored procedure
I don't know the background but I guess someone has incorrectly/accidentally created and used a schema called db_owner
In all the db's that work, I guess the objects are in the dbo schema or your user is set up to use the correct schema. Go look in the object browser and compare
If you want to move the stored procedure into the dbo schema run this:
ALTER SCHEMA dbo TRANSFER [db_owner].[testSP];
If you want to change your users default schema to db_owner run this:
ALTER USER [youruser] WITH DEFAULT_SCHEMA = db_owner;
I reckon the db_owner schema is an accident though.

Granting Select Rights to a Stored Procedure in SQL Server 2000

I want to give a user access to a stored procedure, but not to all the objects in the database the stored procedure needs to use.
What is the best way to give rights to the stored procedure to enable it to work, but only grant execute access to the user to run it.
I am using sql server 2000 sp4.
From MSDN
Users can be granted permission to
execute a stored procedure even if
they do not have permission to execute
the procedure's statements directly
try
exec grant exec ON 'myprocname' TO 'myusername'

Resources