Restrict SQL Server access for certain application - sql-server-2008

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

Related

Restrict permissions to execute a stored procedure

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

PHPMyAdmin: You might be lacking the necessary privileges to edit this routine

Error in processing request: No routine with name 'daily_difference' found in database 'chamelis_wp'. You might be lacking the necessary privileges to edit this routine.
If you are using phpMyAdMin (pma) under cPanel, this error results from the fact that cPanel creates a temporary user for every session to log into pma, and therefore the database. If you are working in a hosted environment where you cannot be granted SUPER privileges, and you are creating routines, you are in trouble. Read on.
Stored routines (procedures and functions) in MySQL/Mariadb have a property called DEFINER. This stores the username of the the database user who "owns" that routine. If a db user opens phpMyAdmin (pma) and creates a new routine without explicitly declaring the DEFINER, DEFINER will be populated with the current username. Only a db user that has SUPER permissions can create a routine and declare another user as the DEFINER. Non-SUPER users can only declare themselves as the DEFINER, or leave it blank and the db does it for them. So the db user that you are logged in as gets to be the DEFINER for all routines you create during that session.
The problem you have encountered arises because
a. only the DEFINER of a routine, or a user with SUPER permissions, can edit or export a routine. If a (non-SUPER) user logs in to pma and tries to edit or export an existing routine, then unless they are the DEFINER of that routine they get the error you are seeing, and they cannot access the routine.
b. Even if you have created database user accounts in cPanel, cPanel will not use any of these to launch pma. Under cPanel you are automatically logged using a temp username that it generates. You do not get to see the pma login page - the login happens off-screen - and you are taken straight into the pma home page. You have no control over the username/password used.
d. When you start a new cPanel session (e.g. at the start of each day's work), cPanel changes the temp db user name that it uses to log you into pma. cPanel usernames all have this pattern: "cpses_db...#localhost", where the dots are filled alphanumerics like "hmxbj8s2". I have just logged in and the pma home page tells me that the current database user is "cpses_dbhmxbj8s2#localhost". If I close pma, log out of cPanel, log back into cPanel then reopen pma, the db user name will change. I just did that and the db user for this new session is "cpses_db0z35t107#localhost".
e. If I had created a new routine during my previous session, then the DEFINER for that routine would still be "cpses_dbhmxbj8s2#localhost". Now that I am logged in as "cpses_db0z35t107#localhost", I cannot edit or export that routine. Without a backup or copy of that routine, I have completely lost access to it (it is now, effectively, "orphaned"). The only way to get access is to recreate it using a script without a DEFINER statement in the current session so the the current db user becomes the DEFINER. That user can now edit the routine. This means that every day you would have to recreate all the procedures you want to work on. If you forget to export all the routines changed during the previous session, then you have LOST THOSE CHANGES.
f. Another problem is that if you are also connecting to the database externally using e.g. MySQL Workbench, logging in using a db user you have created, then you can do everything except edit any routines created under pma because these have "cpses_db..." user as the DEFINER.
THE SOLUTIONS:
Install your own copy of pma in your hosted enviroment if that option is available in cPanel. This will have to be installed in a folder in the public-html section of the site so you can access it directly from your browser e.g. https://example.com/pmamyadmin/index.php. Login using a user you have created for your database. This user becomes the DEFINER for all your routines and so long as you always use this username, you can always access your routines. (Never use cPanel's pma!)
Be aware that having a copy of pma in the public_html section of your site introduces security issues. Definitely require passwords in pma's config and if practical use .htaccess to limit access to just your IP, etc. But that's another topic.
Always access the database externally (assuming your host permits this) using a local copy of pma or another client like MySQL Workbench. Again, this allows you to control the username for every session.
FINALLY
If neither of these works for you and you must use cPanel's pma, then export all your routines at the end of every session and recreate them (with no DEFINER statement) at the start of the next session. Currently pma doesn't include the DROP in the routine export function (there a change request in for this) so you have to use a database export to get them included. Unless you want a full backup anyway, you just need to export the structure of one table to get this export to work. Make sure you click the "Include DROP..." and "Include Routines..." in the export definition. Edit the export to delete the table definition and globally replace the "DEFINER=cpses_db...#localhost" with "" before using it to recreate the routines next session.
Hope that helps.
I FIX THIS ISSUE IN CPANEL
This shows that there is lack of routines ( Function, Procedures ) privilege for the current user. This will cause even the edit button of routines to be disabled.
In CPanel there is default user that you can not manage their privileges, So, you can not add or remove their privileges.
<<<<< HOW I FIX IT >>>>>:
FIRST
Drop all routines(Function, Procedure) that you have no privilege from your database
SECOND ( import sql file again )
Find the sql file used to import database and remove DEFINER=root#localhost everywhere.
Then import Edited sql file after remove DEFINER=root#localhost .
I think this solution can help someone.
Thanks
It sounds like you don't have permission to edit it, or you're trying to edit it from the wrong DB (schema). Run the following to see which DB it is on:
show function status like '%daily%';
show procedure status like '%daily%';
Are you trying to edit it by executing a statement or by using the gui? If by executing a statement, can you provide your statement? If by statement, make sure you've run this first:
use db_name_here;
Then try to edit your routine again.
Did your user create the procedure, or another user created it? You may not have permission to modify an user's procedure. You can see who created it by running:
show create procedure daily_difference;
Then see if you have permission to edit procedures by running the below statement - you need "ALTER ROUTINE" privilege:
show grants for Your_username_here;
If a user with super privilege created it, you won't be able to edit it - you'll need them to, or you will need to get super privilege.
I'm replying partly as I have a work around and partly for the comedy, as GoDaddy sent me this page as a solution to this problem where, yes the problem is defined but no, there's no solution.
I had to rebuild my SPs in phpMyadmin but for the DEFINER where root#localhost was present, using an account I had created and could use - account#localhost. cPanel doesn't expose the root account AFAIK.
I didn't have all my SPs' definitions elsewhere. But I found that in cPanel \ files \ backup \ the files from there of the MySQL DBs had the SP definitions. That may not be in your hosting package. Backing up from phpMyAdmin didn't help as I still lacked the privileges to make the back up with the definitions.

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.

stored procedures in phpmyadmin server

I have created stored procedures in **MySQL database on my local machine and when i generate the script to run it on the host server i have this error**
#1227 - Access denied; you need the SUPER privilege for this operation
and this is the code
CREATE DEFINER = `User_name`#`host_name` PROCEDURE `InsertOrder`
and this user_name take all the privilege ,so any one can help please?
As the manual says:
If you do not have the SUPER privilege, the only permitted user value is your own account, either specified literally or by using CURRENT_USER. You cannot set the definer to some other account.
You must either issue the command using an account which has the SUPER privilege, or else change the DEFINER to your current user account (which is the default if it's omitted).

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.