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

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/

Related

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.

Giving permissions on SQL database

I am in the process of configuring database users for some new developers and I am running into some difficulties as I am reading lots of articles and it's not working out too well for me. I have tried various configurations manually and with T-SQL but I need a more efficient method.
My objective:
Some TSQL I can launch to give a database user the following permissions:
Grant permission to execute all Stored Procedures within the Database
Deny permission to View Definition of all of these stored procedures
Grant permission to SELECT, UPDATE, INSERT, DELETE from all tables within the database
Deny permission to View Definition of all of the tables in the database (I don't want them to view the data)
What I have tried:
I have achieved this manually but I have 200+ stored procedures and 100+ tables so I don't want to do it manually. From the T-SQL aspect I have managed to get the following to work:
USE database_name;
GRANT EXECUTE TO [security_account];
This works and allows the users to run the stored procedures but they cannot view the actual query code. I need the same logic for the tables as described above.
Thank you for your help.
I am not quite sure if this is a viable solution to your problem. But maybe it will get you at least closer to what you want. So, here is the setup I'd propose:
Do not grant anybody any permissions on any table.
Use stored procedures for DML.
Grant execute on all these stored procedures to public.
Setup one table in your database which lists all users which have access to your database including their login (suser_sname()) and their permissions (for example MayAlterTableUsers).
Implement into all stored procedures a check similar to this
if (
select isnull(MayAlterTableUsers, 0)
from tblUsers
where LoginName = suser_sname()
) > 0
begin
select N'Implementing the requested changes to tblUsers.'
end
else
begin
select N'You don''t have the required permission.'
end
Setup you views similar and grant select on all views to public
create view vShowAllUsers as
select *
from dbo.tblUsers
cross apply (
select MaySeeAllUsers
from dbo.tblUsers
where LoginName = suser_sname()
) as p
where p.MaySeeAllUsers = 1
In the end all views and all stored procedures will be publicly available but the handling of permission will be within each one of them. All permissions themselves will be within this table tblUsers. Since nobody has the possibility to alter this table tblUsers unless (of course) they are in this table with the appropriate permission, this DB setup is self-contained.

Restrict user to Stored Procedures

I need to restrict user access to SELECT, INSERT, UPDATE and DELETE, so that user should manage data only using stored procedures I provide.
So, for instance
SELECT * FROM Table1
should return
The SELECT permission was denied on the object 'Table1'
however, if there is stored procedure SelectTable1 defined as
CREATE PROCEDURE SelectTable1
AS
BEGIN
SELECT * FROM Table1
END
(the real one contains filtering and parameters, so it is not meaningless, like the one above)
user should execute it successfully and get the resultset.
But obviously, I have no success implementing this set of permissions. Can anybody point me to some specific tutorial? MSDN was not very helpful.
Database is SQL Server 2012 and all objects (tables and stored procedures) are in custom schema.
You can do it using GRANT EXEC either on specific procedures or on schemas or on a database.
The following example grants EXECUTE permission on stored procedure
HumanResources.uspUpdateEmployeeHireInfo to an application role called
Recruiting11.
USE AdventureWorks2012;
GRANT EXECUTE ON OBJECT::HumanResources.uspUpdateEmployeeHireInfo
TO Recruiting11;
GO
Thanks to Igor I've got to the right MSDN page, and followed rights links.
However, using ownership chains suggested was too complicated for me, so I used
WITH EXECUTE AS OWNER
on my stored procedures and that works very good. When I log on using restricted user I see only procedures, no tables at all and I can execute procedures, but not even select from tables.
Also, I want to mention this concept is very similar to setuid and thus was familiar to me.
I mark Igors reply as answer, because ownership chains seem to be more generic way, just wanted to share info I found.

How to create a Database Role to Allow Users to alter only a particular stored procedure in a db in SQL Server 2000

There is no built in database role that allows this kind of access. The db_datareader wouldn’t allow a user to see stored procedures or functions at all. The ddladmin database role would provide access to see the objects, but also to change them as well, which is not the intent here. To accomplish the desired result of this type of request requires that a new database role be created?
How to give full access on a particular stored procedure in SQL Server 2000? Example I have a stored procedure called sp_prg1 in database db1. I need to give full access only on sp_prg1 (which include altering the stored procedure) to a user.
how to give only alter permissions to only one stored procedure
this GRANT alter on [db].[dbo].[storedprocedure1] TO SingleObjectRole is not working

Permissions when using "Execute sp_Executesql"

I have a database where all access is controlled by stored procedures. The DBA would like to avoid giving users direct read/write access to the underlying tables, which I can understand. Hence all updating and selecting of data is done via stored procedures. Basically he has created one role that has EXECUTE permissions to all the stored procedures in the database and given users that role.
The problem is that one of the stored procedures dynamically builds a SQl Query and executes it via "Execute sp_Executesql". Without going into great detail the query is built dynamically because it changes significantly depending on many user input parameters. The stored procedure in question is only a SELECT sql statement however I am finding that just giving the stored procedure EXECUTE permission is not enough. The underlying tables referenced within the stored procedure that make use of "Execute sp_Executesql" need to have been given "datareader" access or else the stored procedure fails.
Any thoughts on how to correct this? I really wanted to restrict access to the tables to only stored procedures, but I need to find a way to work around the stored procedures that make use of "Execute sp_Executesq"l. Thank you.
In the wrapper proc you can use EXECUTE AS OWNER or EXECUTE AS SomeuserWithNoLogin
This will change the login context for the duration of the stored proc which includes sp_executesql.
If you use OWNER, it will work because you're already using ownership chaining.
If your DBA (good man!) does not want you running as dbo, then set up a user that has full read but no rights. EXECUTE AS <user> requires an entry is sys.database_principals
Like this:
CREATE USER SomeuserWithNoLogin WITH WITHOUT LOGIN
EXEC sp_addrolemember 'db_datareader', 'SomeuserWithNoLogin'
For more info, see EXECUTE AS Clause on MSDN and CREATE PROCEDURE
The real problem is that sp_Executesql is in the master database, not necessarily the database your working in. Your DBA has to give execute sp_Executesql permission to the calling procedure. Than anyone who has permission to call that procedure will be able to run the sp_Executesql.