Restrict permissions to execute a stored procedure - sql-server-2008

Here is the context.
two databases, database1 and database2.
an asp.net web application that accesses database1 using user user1 (SQL Server authentication).
a stored procedure sp1 in database1 that needs to modify some sensitive data in database2 through a stored procedure sp2 defined in database2. In other words sp1 calls database2..sp2.
I created a SQL Server user2 login that is mapped to user2 in database1 and user2 database2. user2 in database2 has the permission to execute sp2.
I want user1 to be able to modify the database2 only through the sp1. I don't want user1 to be able to run: exec database2..sp2.
Here is some code that I tried:
USE [database2];
GO
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
CREATE PROCEDURE [dbo].[sp2]
WITH
EXEC AS CALLER AS
SELECT current_user
GO
GRANT EXECUTE ON [dbo].[sp2] TO [user2]
GO
In database1 I ran:
use database1
go
drop procedure sp1
go
create procedure sp1
as
declare #m nvarchar(4000)
select current_user as usr
execute as login='user2'
begin try
execute database2.dbo.sp2
end try
begin catch
set #m = error_message()
print #m
revert
end catch
go
grant execute on dbo.sp1 to user1
go
execute as login='user1'
go
execute dbo.sp1
go
revert
go
Unfortunately this (i.e. exec dbo.sp1 in the context of login='user1') doesn't work, it returns:
Cannot execute as the server principal because the principal "user2" does not exist, this type of principal cannot be impersonated, or you do not have permission
I also tried to compile sp1 with with execute as 'user2', however, it doesn't work.
Is there another way I can make this work?
Thanks
Update:
If I run this:
GRANT IMPERSONATE ON User::user2 to [User1];
GO
then the script works but it means User1 can now execute Database2..sp2.
What I want in a way is something like this: grant impersonate on User::user2 to [sp1], i.e grant the impersonation permission to a procedure but I am not sure it's possible.
I found this thread which I think it is relevant to my case as well.

ok, based on the thread I mentioned it is possible.
Here are the scripts to achieve this:
use database1
go
CREATE CERTIFICATE [PermissionsCert]
AUTHORIZATION [dbo]
ENCRYPTION BY PASSWORD = 'WeakPassword'
WITH SUBJECT = 'Used to test granting permissions to code',
EXPIRY_DATE = '2099-12-31';
ADD SIGNATURE TO [dbo].[sp1]
BY CERTIFICATE [PermissionsCert]
WITH PASSWORD = 'WeakPassword';
BACKUP CERTIFICATE [PermissionsCert] TO FILE = 'k:\Sql_Backup\PermissionsCert.cer'
use database2
go
CREATE CERTIFICATE PermissionsCert
FROM FILE = 'k:\Sql_Backup\PermissionsCert.cer'
CREATE USER [PermissionsUser] FROM CERTIFICATE [PermissionsCert];
grant execute on dbo.sp2 to [PermissionsUser]
go
I modified sp1 as follows:
alter procedure sp1
as
declare #m nvarchar(4000)
select current_user as usr
--execute as user='user2'
begin try
execute Database2.dbo.sp2
end try
begin catch
set #m = error_message()
print #m
revert
end catch
go
This works now:
execute as login='user1'
go
execute dbo.sp1
go
revert
go
However, this fails, which is what I want:
execute as login='user1'
go
execute database2.dbo.sp2
go
revert
go

Related

Privilege error while creating MySQL trigger

I want to execute the following trigger in the dev environment. This trigger works fine locally (local user does not have super privilege and log bin is enabled). Here is the trigger
DELIMITER $$
USE `myschema`$$
CREATE
DEFINER=`user`#`localhost`
TRIGGER `myschema`.`roles_BEFORE_INSERT`
BEFORE INSERT ON `myschema`.`roles`
FOR EACH ROW
BEGIN
IF (NEW.role_id IS NULL) THEN
-- Find max existed role id
SELECT
MAX(role_id) INTO #max_role_id
FROM
roles;
IF (#max_role_id IS NULL) THEN
-- Set first role id
SET NEW.role_id = CONCAT('RID', '0001');
ELSE
-- Set next role id
SET NEW.role_id = CONCAT(SUBSTR(#max_role_id, 1, 3), LPAD(SUBSTR(#max_role_id, 4) + 1, 4, '0'));
END IF;
END IF;
END$$
I am getting the following error while executing the above script in dev environment where I do not have access to check whether user has what privileges and log bin is enabled or not. Could you please tell me is there any way I can specify super privilege or setting the log bin enable query along with the above script itself. I am having a hard time as the issue is not reproducible in local environment. Any help is appreciated.
SQL State : HY000
Error Code : 1419
Message : You do not have the SUPER privilege and binary logging is enabled
(you might want to use the less safe log_bin_trust_function_creators variable)
Someone who has SUPER privilege must grant it to you, or create your trigger themselves. It's the same kind of thing as Administrator priv on Windows or root priv on *nix.
To check current user grants:
login with user in mysql and
mysql> show grants;
to check supper user:
mysql>select user,host from mysql.user where super_priv='y';
to check bonlog:
mysql> show global variables like "log_bin";
Fix:
you can fix it by enabling log_bin_trust_function_creators
mysql> set global log_bin_trust_function_creators =ON;
read the official doc for more details.
https://dev.mysql.com/doc/refman/5.7/en/replication-options-binary-log.html#sysvar_log_bin_trust_function_creators

How to create logs in a stored procedure

I want to put the logs in some stored procedures in our database to monitor the working of stored procedures. I am new to SQL Server 2008. The logs should be created on the production server.
I had tried this link:
http://www.codeproject.com/Articles/18469/Creating-Log-file-for-Stored-Procedure
but get the error message:
The EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'.
Please provide me some needful.
First of all are you sure you want to log data to text file? May be it will be better to store log into separate table ?
If you want to work with text file:
Look at description xp_cmdshell
The Windows process spawned by xp_cmdshell has the same security rights as the SQL Server service account.
Check the security rights for this account.
xp_cmdshell can be enabled and disabled by using the Policy-Based Management or by executing sp_configure.
Check you have it enabled.
EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO
EXEC sp_configure 'xp_cmdshell', 1
GO
RECONFIGURE
GO
When it is called by a user that is not a member of the sysadmin fixed server role, xp_cmdshell connects to Windows by using the account name and password stored in the credential named ##xp_cmdshell_proxy_account##. If this proxy credential does not exist, xp_cmdshell will fail.
You need to create proxy account.
EXEC sp_xp_cmdshell_proxy_account [MyDomain\SQLServerProxy], 'usdcu&34&23'
Add permissions to use this SP:
USE master;
GRANT EXECUTE on xp_cmdshell to Current_user
Here is a more detailed information.
granting permissions using the master database to the object should do
Use Master
grant execute on xp_cmdshell to 'user'
Using xp_cmdshell for logging is bad for both security and performance. Please delete that codeproject link from your browser and forget you ever saw it. Seriously, it is badness.
If you want to log calls to procs, either:
Set up a table for this (as demas also suggested). You can have a DATETIME field defaulted to GETDATE() or GETUTCDATE(). You can have a field for the Proc Name, a field for parameters. Whatever.
or
Use SQLCLR to create a stored procedure that does a simple File.Write of the info. You can use Impersonation (something xp_cmdshell can't do) to have the security context be that of the person running the proc and not the Log On account of the SQL Server process. This approach is far more efficient and contained than xp_cmdshell, even when not using Impersonation.
or
Do a combination of the log table + SQL CLR [or something else]: You can log to the table for immediate writing. And then set up a SQL Agent job to archive entries over X days old to a file using SQLCLR or some other means. This way the table doesn't grow too big with info that is probably older than you need anyway for researching problems that are currently happening.

Restrict SQL Server access for certain application

I want to deny the access the DB as SA from SSMS but allow them to make changes through the other application when logged in as SA. I used the following code but system throwing error. Please suggest me to correct the following code.
CREATE TRIGGER [Tr_ServerLogon]
ON ALL SERVER FOR LOGON
AS
BEGIN
declare #appname VARCHAR(512)
SET #appname = APP_NAME()
if ('.Net SqlClient Data Provider'=#appname)
GRANT DELETE ON [dbname].[dbo].[tablename] TO [username]
else
DENY DELETE ON [dbname].[dbo].[tablename] TO [username]
END
GO

Stored procedure with EXECUTE AS cannot run xp_cmdshell

I have a sql server user, proxyAccount, which I configured as xp_cmdshell_proxy_account
In a stored procedure I use xp_cmdshell, and when I execute the stored procedure with this account, everything works fine.
However, if I add:
WITH EXECUTE AS 'proxyAccount'
to the stored procedure, I get the following error when I execute it:
The xp_cmdshell proxy account information cannot be retrieved or is invalid. Verify that the '##xp_cmdshell_proxy_account##' credential exists and contains valid information.
What might be the problem? Why can't proxyAccount run xp_cmdshell when set to EXECUTE AS, but being able to run it otherwise?
The problem was solved by the following steps:
Creating a new account that uses Windows Authentication (not using SQL Server Authentication)
Set this new account to xp_cmdshell proxy
Grant xp_cmdshell permission to the old proxyAccount

Cannot bulk load because the file could not be opened. Operating system error code 1326(Logon failure: unknown user name or bad password.)

bulk upload from csv test file
"\servername\wwwroot\Upload\LDSAgentsMap.txt"
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[sp_CSVTest_BulkInsert] ( #Path NVARCHAR(128) )
AS
DECLARE #Sql NVARCHAR(256)
SET #Sql = 'BULK
INSERT CSVTest
FROM ''' + #Path + ''' WITH
(
FIELDTERMINATOR = '','',
ROWTERMINATOR = ''\n''
)'
--PRINT #Sql
EXEC(#Sql)
GO
path is "\servername\wwwroot\Upload\LDSAgentsMap.txt"
note
this is in shared hosting and database user have blukadmin and public service role
This can occur when the Windows user account that SQL runs under (e.g. SqlServerAccount) doesn't have permissions to access the shared file (\servername\wwwroot\Upload\LDSAgentsMap.txt).
One way we've worked through this is to go to the machine where shared file resides. On that machine, add a Windows user account with the same user name and password as the account that SQL runs under.
For example,
If your database resides on MyDatabaseServer, and runs under a Windows user account SqlServerAccount with password Foo, then go to the machine where your shared file resides, e.g. MyFileServer, and create a Windows user account named SqlServerAccount with password Foo.
Last step: go into the folder share on MyFileServer and go into sharing properties for that folder. (On Win7, right-click the folder->Properties->Sharing->Advanced Sharing). Then add read permission for SqlServerAccount that you created.
I was getting this error from SSIS when trying to execute a stored procedure which performed a bulk insert.
I fixed it by adding the SQL Server port number to the connection string in SSIS, forcing SSIS to access SQL Server through TCP/IP instead of Named Pipes.