SQL Dynamic Query Insertion with SQL user which has execute permission on stored procedure - sql

I have a user in sql database which has execute permission on the stored procedure. On Store Procedure i am trying to insert into the table by : EXEC (#insertQuery)
But i get following error
System.Data.SqlClient.SqlException (0x80131904): The INSERT permission was denied on the object ''table_name'', database ''db name'', schema ''dbo''.Unexpected error occurred!
I have looked into EXECUTE AS Clause also this will work , Is there any method beside this ? Safe one .
Thank You

I think you want to use the WITH EXECUTE AS clause when you create the stored procedure. You can read about it here.
You can define the stored procedure to execute as the OWNER of the stored procedure. This is very, very handy. You can prevent users from directly modifying tables. But, you can give them access to stored procedures that can modify the tables.

An alternative to EXECUTE AS is with module signing. This requires more configuration than EXECUTE AS but has the advantage of retaining the callers identity without granting direct permissions to the user and can be extended for cross-database access.
Below is an example script gleaned from Erland Sommarskog's excellent and thorough article on Giving Permissions through Stored Procedures.
CREATE TABLE dbo.testtbl (a int NOT NULL,
b int NOT NULL);
INSERT dbo.testtbl (a, b) VALUES (47, 11);
GO
CREATE PROCEDURE example_sp AS
SELECT SYSTEM_USER, USER, name, type, usage FROM sys.user_token;
EXEC ('SELECT a, b FROM testtbl');
GO
-- Create the certificate.
CREATE CERTIFICATE examplecert
ENCRYPTION BY PASSWORD = 'All you need is love'
WITH SUBJECT = 'Certificate for example_sp',
START_DATE = '20020101', EXPIRY_DATE = '20200101';
GO
-- Create the certificate user and give it rights to access the test table.
CREATE USER examplecertuser FROM CERTIFICATE examplecert;
GRANT SELECT ON dbo.testtbl TO examplecertuser;
GO
-- Sign the procedure.
ADD SIGNATURE TO dbo.example_sp BY CERTIFICATE examplecert
WITH PASSWORD = 'All you need is love';
GO
--users need proc execute permissions but not table permissions
GRANT EXECUTE ON dbo.example_sp TO YourUserOrRole;
GO

Related

Privileges/security for stored procedure in DB2 LUW

UPDATED question:
The core of my problem is: The stored procedure I (User1) created is not able to select from the some specific table (table1 created by another user (User2)) due to:
CREATE OR REPLACE PROCEDURE TEST_SCHEMA.TEST_PROCEDURE(OUT r_count INTEGER)
LANGUAGE SQL
BEGIN
SET r_count = (SELECT COUNT(*) FROM TEST_SCHEMA.TABLE1);
END
OK. No rows were affected
SQLWarning: Code: 20480 SQL State: 0168Y
--- The newly defined object "TEST_SCHEMA.TEST_PROCEDURE" is marked as invalid because it references an object "TEST_SCHEMA.TABLE1" which is
not defined or is invalid, or the definer does not have privilege to
access it.. SQLCODE=20480, SQLSTATE=0168Y, DRIVER=4.22.29
However, when I select from table1 in a normal query window there is no problem, hence I thought something was wrong about the security option on the stored procedure
SELECT COUNT(*) FROM TEST_SCHEMA.TABLE1
Table and stored procedure names are fully qualified. The stored procedure is created and executed by user1. The privilege given to the user1, to select from table1 , is a group privilege.
The procedure creator must have the corresponding privilege on statically referenced table either directly or via roles.
CREATE PROCEDURE (SQL) statement:
Authorization
The privileges held by the authorization ID of the
statement must include at least one of the following authorities:
If the implicit or explicit schema name of the procedure does not exist, IMPLICIT_SCHEMA authority on the database.
If the schema name of the procedure refers to an existing schema, CREATEIN privilege on the schema.
DBADM authority
The privileges held by the authorization ID of the statement must also
include all of the privileges necessary to invoke the SQL statements
that are specified in the procedure body.
To replace an existing procedure, the authorization ID of the
statement must be the owner of the existing procedure (SQLSTATE
42501).
Group privileges are not considered for any table or view specified in
the CREATE PROCEDURE (SQL) statement.

Error during stored procedure creation in DB2 database

I am struggling with schemas while creating a stored procedure in DB2 database ( 10.5 version ).
My user name is XYZ but I have to create a Stored procedure for schema ABC.
When I am trying to execute the create procedure sql I get error message which looks like Schema related
Create procedure ABC.customInsert(
IN temp INTEGER
)
BEGIN
INSERT INTO ABC.One_Column_table VALUES ( temp );
END
Error Message:
Error:DB2 SQL error:SQLCODE:-551, SQLSTATE: 42501,
SQLERRMC:XYZ;INSERT;ABC.One_Column_table
My current schema was showing XYZ earlier. ( result of select current_Schema from sysibm.sysdummy1).
I have changed it to ABC. ( using SET CURRENT SCHEMA ABC). But still the same problem.
I am able to insert, select, create UDT etc in ABC schema but the problem exists only during stored procedure creation.
Any idea what am I doing wrong ?
Based on your error message, SQLCODE -551 means that the user "XYZ" does not have the "INSERT" privilege on the table "ABC.One_Column_table".
Since you imply that you, when connected as XYZ, can insert into the table by issuing simple INSERT statements, it is possible that you possess the INSERT privilege indirectly, via a group membership. Group privileges are ignored for SQL statements in stored procedures, functions or triggers, as explained in this IBM technote.
You have two options:
Grant the required privileges on ABC.One_Column_table to the user XYZ directly.
Create a role (using the CREATE ROLE statement), grant the table privileges to that role, then grant the role to the user XYZ.
If you are curious, such behaviour is caused by the fact that static SQL statement (e.g. in a stored procedure) authorization is checked only during compilation, and the compiled code can then be executed without additional authorization checks. Groups are maintained outside the DB2 database, by the operating system, and it is possible that group membership changes after the stored procedure is compiled and without the database security administrator's knowledge. If group privileges were effective for static SQL, it would allow users who weren't originally authorized to run particular statements (i.e. were not members of the authorized group at the compilation time) still execute those statements, thus creating a security risk.
Roles, on the other hand, are maintained within the database itself by the database security administrator and thus are part of the same security landscape.

Target tables in different schemas from store procedure but don't change code

Please can any one advise if it is possible to have a stored procedure in the [dbo] schema select data from one table in one schema for users accessing via one database role and for it to select data from a like-named table in another schema for users accessing via another database role?
For example if I have three schemas in my database:
dbo
green
red
I have two database logins [RedLogin] and [GreenLogin]. These connect to my database using respective database users [RedUser] and [GreenUser]. These users are members of the respective database roles [RedRole] and [GreenRole].
[RedUser] has a default schema of [red].
[GreenUser] has a default schema of [green].
[RedRole] has execute permission on [dbo] and select permission on
the [red] schema.
[GreenRole] has execute permission on [dbo] and select permission on
the [green] schema.
In the [green] schema I have a table called [User].
In the [red] schema I have a table called [User].
In the [dbo] schema I have a stored procedure called [User_GetAll]
that runs.
SELECT * FROM USER;
What I would like is:
For users who login with [Redlogin] and call the
[User_GetAll] get all users from the [red].[User] table.
For users who login with [Greenlogin] and call the
[User_GetAll] get all users from the [green].[User] table.
So I have a question. For example:
-[dbo] schema in the past, I had 100 stored procedures. And now, I don't want to change code in stored procedure because It's so much, so How can I do to address the problem? Please help me.
....................................................................................
Update:
For simple example:
I have a schema [dbo], and in that schema, I have created a stored procedure dbo.GetAccount:
CREATE PROCEDURE dbo.GetAccount
AS
BEGIN
SELECT * FROM tblAccountNet
END
Then, I have created a schema [ABC] with user named UserABC.
Now, I would like to login with UserABC and execute dbo.GetAccount for schema [ABC] to get all user of it and don't want to change code of dbo.GetAccount. So, how can I do?
These are my ideas to resolve it:
Create another stored procedure in [dbo] schema, and use it to read all other procedure to make them execute against schema with user when login. Can I do that? So, how can I do that?
Create a stored procedure to change schema of all [dbo] procedure to [ABC]. Can I do that?
Thanks for your help.
Your best bet here would be to use dynamic SQL. That is something which allows you to pass string variables into a script which then gets executed against the SQL engine. For example, if you had variables #dynamicsql and #usertype, you would build a dyanmic SQL string like:
#dynamicsql = 'SELECT * FROM '+#usertype+'.tblAccountNet'
Then you would execute this code in a stored procedure using EXEC(#dynamicsql). This would probably work, but it requires additional permissions for the user, and also opens you up to a whole world of security concerns, with the biggest one being SQL Injection attacks. So this would probably work, but it might be more trouble than it is worth.
http://xkcd.com/327/

The server principal Xuser is not able to access the database Ydb under the current security context. sql server 2008

I'm trying to figure out why my stored procedure is not working for selecting from another database's column.
Databases Kdb and Ydb have the same database owner. Stored procedures and tables in both databases created using that database owner account.
There is a stored procedure in Ydb trying to access a table in Kdb being executed by a minimal rights user (only has execute and connect on Ydb, no rights to Kdb).
Use [Ydb]
GO
ALTER PROCEDURE [dbo].[CreateSecureTableAEntry]
#fid int
AS
BEGIN
DECLARE #operatorId uniqueidentifier
DECLARE #orgName nvarchar(max)
SELECT #orgName = SUBSTRING(SYSTEM_USER,1,LEN(SYSTEM_USER)-4)
SELECT #operatorId = Id FROM Kdb.dbo.Organizations WHERE Kdb.dbo.Organizations.Name = #orgName
INSERT INTO TableA (operatorId, sourceFid) VALUES (#operatorId, #fid);
END
I have enabled cross database chaining on both Kdb and Ydb. I have made Ydb trustworthy.
This is clearly a permissions problem, but what else should I do while keeping permissions as tight as possible?
I resolved this problem successfully by incorporating the select query into a view inside Ydb and enabling the guest account on Kdb with the following query:
USE [Kdb];
GO
GRANT CONNECT TO guest;

SQL Server Execute Impersonation

What is the diffrence between...
execute as user = 'testuser'
AND
execute as login = 'testuser'
I am executing a cross database procedure under these logins and it works with the exececute as login but not the execute as user. It is saying the server principal "testuser" is nt able to access the database "xxx" under the securty context.
When i SELECT SYSTEM_USER after both commands I see that it is set to 'testuser'
execute as login provides impersonation to the entire server, since logins are on a server level. Since users are defined per database, execute as user impersonation applies only to a specific database, which is why you see the error when you cross databases.
The EXECUTE AS can be added to stored procs, functions, triggers, etc.
Example to Execute As:
CREATE PROCEDURE dbo.MyProcedure
WITH EXECUTE AS OWNER
In this case you are impersonating the owner of the module being called.
You can also impersonate SELF, OR the USER creating or altering the module OR...
impersonate CALLER , which will enable to module to take on the permissions of the current user, OR...
impersonate OWNER, which will take on the permission of the owner of the procedure being called OR...
impersonate 'user_name', which will impersonate a specific user OR...
impersonate 'login_name' with will impersonate a specific login.
Setting permission on objects like stored procedures can be accomplished with
GRANT EXECUTE ON <schema>.<procedurename> to <username>;
However, you may also want to grant security rights at both the login and user level.
You will want to determine and grant ONLY the necessary rights
for the objects that require access (such as execution). Consider use of the "EXECUTE AS" capability which enables impersonation of another user
to validate permissions that are required to execute the code WITHOUT having to grant all of the necessary rights to all of the underlying objects (e.g. tables).
MOST of the time, you will only need to grant EXECUTE rights to stored procs and then rights are granted to all objects referenced within the stored proc.
In this way, you do not need to give implicit rights (example: to update data or call additional procs). Ownership chaining handles this for you.
This is especially helpful for dynamic sql or if you need to create elevated security tasks such as CREATE TABLE. EXECUTE AS is a handy tool to consider for these.
This example may help clarify all of this:
--Create a user called NoPrivUser with public access to a database (e.g. dbadb)
USE [master]
GO
CREATE LOGIN [NoPrivUser] WITH PASSWORD=N'ABC5%', DEFAULT_DATABASE=[dbadb], CHECK_EXPIRATION=ON, CHECK_POLICY=ON
GO
USE [DBAdb]
GO
CREATE USER [NoPrivUser] FOR LOGIN [NoPrivUser]
GO
NOTE: CREATOR OR OWNER OF THIS PROCEDURE WILL REQUIRE CREATE TABLE RIGHTS within the target database.
use DBAdb
go
CREATE PROCEDURE dbo.MyProcedure
WITH EXECUTE AS OWNER
AS
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].MyTable') AND type in (N'U'))
CREATE TABLE MyTable (PKid int, column1 char(10))
INSERT INTO MyTable
VALUES (1,'ABCDEF')
GO
GRANT EXEC ON dbo.MyProcedure TO NoPrivUser;
GO
-- Now log into your database server as NoPrivUser and run the following.
use dbadb
go
EXEC dbo.MyProcedure
--(1 row(s) affected)
Now try to select from the new table while logged on as NoPrivuser.
You will get the following:
select * from MyTable
go
Msg 229, Level 14, State 5, Line 1 The SELECT permission was denied on
the object 'MyTable', database 'DBAdb', schema 'dbo'.
That is expected since you only ran the procedure under the security context of Owner while logged on as NoPrivUser.
NoPrivUser as no rights to actually read the table, Just to execute the procedure which creates and inserts the rows.
With the EXECUTE AS clause the stored procedure is run under the context of the object owner. This code successfully creates dbo.MyTable and rows are inserted successfully.
In this example, the user "NoPrivUser" has absolutey no granted rights to modify the table, or read or modify any of the data in this table.
It only takes on the rights needed to complete this specific task coded WITHIN the context of this procedure.
This method of creating stored procedures that can perform tasks that require elevated security rights without permanently assigning those rights come be very useful.
Login scope is at the server level while user scope is at the current database level
http://msdn.microsoft.com/en-us/library/ms181362.aspx