I have read here Permissions for truncating a table that you need to grant ALTER permissions to the user(s) for them to be able to truncate a table. However, I am still having issues truncating the table with the user(s) being granted this role.
Any ideas why this is?
PS. I myself as the owner of the table am able to truncate by the way. Just no one else with ALTER permissions.
The link you are referring to is applicable to MS SQL Server. The link in the comment by Leila is also for SQL Server.
For Oracle the users must have the DROP ANY TABLE system privilege.
This in turn may not be what you want, as this system privilege is too destructive.
Tom Kyte has a solution for your problem:
Sure, this is what stored procedures are all about.
To selectively give someone the abilitly to truncate a specific table,
or all of the tables owned by some schema, you would code:
create or replace procedure do_the_truncate as begin execute immediate
'truncate table T'; end;
or (any of the tables owned by some schema, or if that schema has the
drop any table priv ANY table)
create or replace procedure do_the_truncate( p_tname in varchar2 ) as
begin execute immediate 'truncate table ' || p_tname; end;
and then just grant execute on that procedure to any user that needs
to run that command. Since stored procedures run with the base privs
of the OWNER of the procedure, you do not need any powerful privs like
"drop any table" to truncate that table.
You can further enhance the do_the_truncate stored procedure to have a list of allowed tables to be truncated to tighten the security in your system
Related
EDIT (8/25)
Thanks to #Alex Poole for providing the answer below but I wanted to share additional detail on these role limitations around PL/SQL objects as it helps explain not only how Oracle is managing things under the hood but why it handles permissions this way.
Now knowing where I was going wrong, I was able to identify this question which discusses the issue at length. This answer describes how the Oracle data structures store the permissions for evaluation.
In addition, someone linked an explanation from Tom Kyte which explains why this behavior was coded intentionally. Long story short: PL/SQL Definer's Rights do not respect role based permissions due to how the Oracle engine compiles these objects. If role based permissions were allowed then any REVOKE statements could have the ability of invalidating large swaths of PL/SQL objects, requiring a costly full database recompile.
Original Question
Could someone help me understand why I can call a dynamic sql script containing a reference to a DBMS_RANDOM procedure when the logic is called from an anonymous block, however, when I take that same logic and drop it into my own stored procedure, the previously runnable script fails to execute with a ORA-00904: "DBMS_RANDOM"."STRING": invalid identifier error?
I feel confident that my privileges are correct. I can run the script that is being passed as a variable directly without issue and run this logic as an anonymous PL/SQL block. Do I need to change my syntax with the stored proc or is it possible that this practice is prevented for security reasons?
Any explanation would be great but if you can point me to the Oracle documentation, I would be ecstatic. I have looked extensively, especially around Oracle's Dynamic SQL documentation but I haven't seen a description of this behavior. I am using Oracle 11g.
To recreate the behavior I am seeing:
Test Data Creation:
SPOOL ON;
SET SERVEROUTPUT ON SIZE UNLIMITED;
--Create Test Table
CREATE TABLE TEST_DYNAMIC_TBL (
ID NUMBER PRIMARY KEY,
MY_COL VARCHAR2(50));
--INSERT a line of data and confirm
INSERT INTO TEST_DYNAMIC_TBL VALUES(1, 'SOME TEXT');
COMMIT;
SELECT MY_COL FROM TEST_DYNAMIC_TBL;
MY_COL
SOME TEXT
PL/SQL Anonymous Block (Successful Example)
DECLARE
l_script VARCHAR2 (32767);
BEGIN
l_script := 'UPDATE TEST_DYNAMIC_TBL SET MY_COL = DBMS_RANDOM.STRING(''U'',5)';
DBMS_OUTPUT.put_line ('Script sent to Exec Immediate: ' || l_script);
EXECUTE IMMEDIATE l_script;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line (' ERROR: ' || SUBSTR (SQLERRM, 1, 64));
ROLLBACK;
END;
/
--Check value (This results in a successful update)
SELECT MY_COL FROM TEST_DYNAMIC_TBL;
Script sent to Exec Immediate: UPDATE TEST_DYNAMIC_TBL SET MY_COL = DBMS_RANDOM.STRING('U',5)
PL/SQL procedure successfully completed.
MY_COL
XFTKV
Your query value will vary depending on the seed that DBMS_RANDOM picked
Stored Procedure Example (Failure Example)
--Procedure created with identical logic
CREATE OR REPLACE PROCEDURE TEST_DYNAMIC
AS
l_script VARCHAR2 (32767);
BEGIN
l_script := 'UPDATE TEST_DYNAMIC_TBL SET MY_COL = DBMS_RANDOM.STRING(''U'',5)';
DBMS_OUTPUT.put_line ('Script sent to Exec Immediate: ' || l_script); -- This string will execute successfully if run directly
EXECUTE IMMEDIATE l_script;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (' ERROR: ' || SUBSTR (SQLERRM, 1, 64));
ROLLBACK;
END;
/
--Reset and verify Data
UPDATE TEST_DYNAMIC_TBL SET MY_COL = 'SOME TEXT';
COMMIT;
SELECT MY_COL FROM TEST_DYNAMIC_TBL;
--Execute through Procedure (Will throw error)
EXECUTE TEST_DYNAMIC;
--Check Value of Table
SELECT MY_COL FROM TEST_DYNAMIC_TBL;
Stored Procedure Results:
MY_COL
SOME TEXT
Script sent to Exec Immediate: UPDATE TEST_DYNAMIC_TBL SET MY_COL = DBMS_RANDOM.STRING('U',5)
ERROR: ORA-00904: DBMS_RANDOM: invalid identifier
PL/SQL procedure successfully completed.
MY_COL
SOME TEXT
It isn't about it being dynamic, it's about the privileges and how they were granted. You would see the same thing if you had a static insert using dbms_random (and in your example anyway there is no need for it to be dynamic).
It appears that you have execute privilege on dbms_random granted through a role, not directly to the package owner. From the documentation (emphasis added):
If the procedure owner grants to another user the right to use the procedure, then the privileges of the procedure owner (on the objects the procedure references) apply to the grantee's exercise of the procedure. The privileges of the procedure's definer must be granted directly to the procedure owner, not granted through roles. These are called definer's rights.
The user of a procedure who is not its owner is called the invoker. Additional privileges on referenced objects are required for an invoker's rights procedure, but not for a definer's rights procedure.
That only applies to stored PL/SQL - i.e. procedures, functions, packages, triggers etc. - not to anonymous blocks.
You can either get the privilege on dbms_random granted directly to the package owner, or change your procedure to use invoker's rights:
CREATE OR REPLACE PROCEDURE TEST_DYNAMIC
AUTHID CURRENT_USER
AS
...
In the latter case, anyone calling your procedure will then need the privilege on dbms_random - but they can have it through a role.
As access to that package is sometimes locked down, a direct grant to the owner might be preferable, but it depends on your security constraints.
The reason it requires a direct grant, I believe, is that roles can be enabled and disabled, and be default or not, and can be nested. If a direct grant is revoked then it's fairly straightforward to figure out that should invalidate the procedure. And that's possibly true if a role is revoked, but quite a lot more complicated.
But what role-derived privileges should be taken into consideration when the procedure is created - only those that are enabled in that session? Only default roles? Or all roles? (And remember there can be a chain of roles to think about to determine privileges, and you can get the same privilege from multiple roles.)
However you do it will confuse or upset someone - if only enabled then the owner logging in a future session might not be able to perform the actions the procedure does, and what if they want to recompile it? If only default then those defaults can change, with the same issues - or should that invalidate the procedure? If all roles then including disabled ones will be confusing and could have security implications.
And for any of those, role revocation would still have to figure out which privileges that removes - which aren't also granted directly or via another role! - and only once it's really sure which privileges have actually gone, see which objects that affects. Which could be a lot of work - think how many individual privileges could be affected by revoking DBA.
It's much simpler for the invoker - you only need to look at the active privileges from the enabled roles at the moment then call the procedure.
So while at first glance it seems odd that privileges granted through roles aren't included for stored PL/SQL, once you look at the implications and complications - both as it's created, but more what happens afterwards - it seems like a sensible restriction.
I am using Toad and Oracle SQL.
I am trying to create a table as
create global temporary table tmptbl
on commit preserve rows as select * from mySchem.MyTable;
But I get an error
ORA-01031: insufficient privileges tips
Probably because I don't have the rights to save into mySchem.
However how can I get around the problem so I save the table locally somehow and I am ok with it if the table disappears when I close Toad. I am looking for creating a temporary "work table" as we know from SAS.
This post was not a help:
How do you create a temporary table in an Oracle database?
You need to grant CREATE TABLE in addition to have SELECT privileges to read the source table. There is no need to be able to write to the tablespace used by the source table because the temporary table will be stored in the default temporary tablespace.
Oracle workaround:– grant rights to create a table.
create global temporary table tmptbl
on commit preserve rows as select * from mySchem.MyTable;
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.
What are min permission we need to truncate table ? Apart from DDLAdmin. And what is best pratice to give permission to the user to truncate the user on SQL 2008 R2
Truncate table documentation at books online here
Permissions
The minimum permission required is
ALTER on table_name. TRUNCATE TABLE
permissions default to the table
owner, members of the sysadmin fixed
server role, and the db_owner and
db_ddladmin fixed database roles, and
are not transferable. However, you can
incorporate the TRUNCATE TABLE
statement within a module, such as a
stored procedure, and grant
appropriate permissions to the module
using the EXECUTE AS clause. For more
information, see Using EXECUTE AS to
Create Custom Permission Sets.
MSDN:
The minimum permission required is
ALTER on table_name. TRUNCATE TABLE
permissions default to the table
owner, members of the sysadmin fixed
server role, and the db_owner and
db_ddladmin fixed database roles, and
are not transferable.
If you don't want to grant rights (which are excessive, really, and described in other answers) you can escalate permissions within a stored procedure...
CREATE PROC DoTruncate
WITH EXECUTE AS OWNER
AS
TRUNCATE TABLE Mytable
GO
And permission this instead with "normal" rights
I am having the below statement from stored procedure. It's giving Insufficient Privileges.
But If i run the create statement alone from the sql prompt it's creating table.
execute immediate 'create table TEST_ABC(
NO_AC NUMBER(8)
, ILL_PER VARCHAR2(15)
, INIT_C DATE
)';
What needs to be done to have priviliges to create table via execute immediate from stored procedure. Not sure how it's working from sql command prompt
Procedures don't inherit privileges granted via a role. More info here. Please check if that's what happening to you.
One way to solve this problem is to grant "CREATE TABLE" privilege directly to the account that owns the procedure.
Is the procedure created by the same user? If it is created by some one else and you have EXECUTE privilege alone, then the error is right (assuming the create procedure doesn't have AUTHID CURRENT USER clause).
Can you create any other table? If you can, then there is some issue. We would need more details to analyse.