ORA-12406: unauthorized SQL statement for policy - sql

I am receiving the following error:
ORA-12406: unauthorized SQL statement for policy
I am executing a stored procedure that executes the following two Oracle Label Security stored procedures:
SA_COMPONENTS.CREATE_GROUP
SA_LABEL_ADMIN.CREATE_LABEL
In the same transaction, but not the same procedure, I am trying to insert into a table using the newly created label. This is when the error occurs. I Googled the error, but the description doesn't help me. I do not know what privilege or authorization I would have to give to make this work. If I split the stored procedure and the insert statement into two separate transactions, it works fine. I am looking for an explanation as to what is going on here.
ORA-12406: unauthorized SQL statement
for policy string Cause: The policy
did not authorize the database session
to perform the requested SQL
statement. Action: Grant the user or
program unit the necessary policy
privilege or additional
authorizations....

From your description and testing it appears that the SA_COMPONENTS and SA_LABEL_ADMIN packages are participating in the transaction (i.e. they insert or update information in system tables that are part of the Label Security architecture but do not commit) and this information needs to be committed prior the application table insert.

Related

How to run snowflake side effect functions like SYSTEM$GENERATE_SCIM_ACCESS_TOKEN within a procedure with owner rights?

Basically I want to do SCIM integration in snowflake. For that I have to use this command for getting the token which will be passed to Azure AD:
call system$generate_scim_access_token('<value>');
This command can only run with AccountAdmin. And running it with AccountAdmin I am able to get token but In future I will not be having rights of AccountAdmin, so for that what I did, I created a procedure with AccountAdmin and execute it as owner. So that, when ever any other role which is having the usage permission of this procedure calls this procedure it will be executed with AccountAdmin rights (because it was created with AccountAdmin) and hence in that procedure I can run system$generate_scim_access_token(''); and return result:
Create or Replace Procedure DB.mySchema.GenerateScimAccessToken()
RETURNS string
LANGUAGE javascript
execute as owner
AS
$$
var stmt = snowflake.createStatement( {sqlText: "select system$generate_scim_access_token('<value>');"} );
var resultSet = stmt.execute();
// moving pointer to row.
resultSet.next();
// returning column value
return resultSet.getColumnValue(1);
$$
But when ever i call this It gives me this error:
Execution error in store procedure GENERATESCIMACCESSTOKEN: SQL compilation error: Query called from a stored procedure contains a function with side effects [SYSTEM$GENERATE_SCIM_ACCESS_TOKEN]. At Statement.execute, line 3 position 24
Basically it says that the procedure is having a side effect function (SCIM is a side effect function) and running it with Owner rights is giving exception (There must be a restriction by snowflake for running side effect functions within procedure with owner rights). If we run it with caller it runs fine but we want to run it with owner.
There are many such commands which run only in the context of the caller as against the context of owner (for example the Show commands such as Show Tables).
A detailed description of what is supported in callers right vs owners rights is documented in the below kb article:
https://docs.snowflake.com/en/sql-reference/stored-procedures-rights.html
From an end-users perspective, the requirement here is reasonable. So you can make an improvement request to Snowflake by either raising a case with Snowflake support or raising an idea on the Snowflake's Idea portal: https://community.snowflake.com/s/ideas

How to Get the Text of SQL Statement in a Trigger

Do you know how to obtain the text of sql statement inside a trigger?
Thanks
Sorry to be the bearer of sad tidings, but I don't believe you can do that. No triggering event I'm aware of has visibility on the SQL statement text. The triggering events supported by Oracle (11g) are:
An INSERT, UPDATE, or DELETE statement on a specific table (or view, in some cases)
A CREATE, ALTER, or DROP statement on any schema object
A database startup or instance shutdown
A specific error message or any error message
A user logon or logoff
None of these, as far as I'm aware, have access to the text of the SQL statement. Docs here

Using Commit in a SQL Server Trigger

Currently I am working on a requirement which requires logging of input record into a staging table.
The requirement summery is as below:
Web Service will send a request which will insert a record into the level 1 staging table (StagingTable1).
A database trigger on StagingTable1 will process the validity of the record and raise an error
This error message gets acknowledged as Web Service response to other end system.
My challenge is to track these failed records in another staging table StagingTable2. But RAISERROR in a trigger is causing the entire transaction to rollback.
How this can be achieved?
Note: I tried temporary tables but it does not work. Pragma_autonomuos transactions are not possible in SQL Server as far as I know.
You can make the trigger put the record into the StagingTable2 - or not, so the absence of it will indicate an unsuccessful validation. You can even put error descriptions, along with row' key, into some other table, so that you will always know which ones failed to pass.
Or you can use Service Broker for that, if your servers are far enough away from each other.

permission problem on dynamic query running in a stored procedure

i have this stored procedure, doing a select query with couple of inner joins (one of the tables is in another db). Now, i had to write this query as dynamic cause first i had to find which db the select query should run. Anyway, none of the tables have permissions on them, just giving permission to the stored procedure for the database role "personel" (which includes everyone).
But now, someone with a personel role runs this stored proc, they are getting the error "The SELECT permission was denied on the object 'tbl_table', database 'Db', schema 'dbo'." no difference in the schema, and there are other procs using the same table that are running normally.
Can using a dynamic query (exec (Use DB; select ...) ) be the reason for this? Like cause it is dynamic, i should give permissions to the tables also ?
Thanks
The short answer is yes.
When you compile a stored procedure, permissions of the user/login creating the stored procedure are checked. When someone else executes it, their ability to read those tables is no longer relevant (in most cases), but rather just their ability to execute the SP.
When executing the dynamic code, however, the permissions regarding the tables have to be checked there and then. This means that the executing user's permissions are being checked.
Yes, this can be the reason. Read this to get an explanation and a possible solution.

User Granted Access to Stored Procedure but Can't Run Query

I am working on a product that runs an SQL server which allows some applications to login and their logins are granted permission to run a stored procedure- AND NOTHING ELSE. The stored procedure is owned by an admin; the stored procedure takes a query and executes it, then the results are returned to the application.
Unfortunately I can't figure out why the application can call the stored procedure to which it's granted access, but the stored procedure cannot execute the SQL statement which was passed into it.
The stored procedure executes the passed in query when I'm logged in as an admin, but when I log in as the limited user it throws an exception in the execute statement.
For example:
EXEC [Admin].[STORED_PROC] #SQL_STATEMENT = 'SELECT * FROM table_x'
the STORED_PROC looks something like this:
BEGIN TRY
EXEC (#SQL_STATEMENT)
END TRY
BEGIN CATCH
-- some logging when an exception is caught, and the exception is caught here!!!
END CATCH
There is nothing inside the the try catch statement except that EXEC... and the SQL_STATEMENT works when I'm logged in as the Admin, but not when I'm logged in as the User.
Can anybody help me figure out what permissions I need to set in order to allow the User to run queries through the stored proc only?
So there have been some comments about allowing raw SQL statements to be executed via stored proc defeats the purpose of using a stored proc... but in reality what we're actually doing is we're passing an encrypted SQL statement into the stored proc and the stored proc gets the statement decrypted and THEN it executes it.
So yes, in reality raw SQL statements are not secure and they defeat the purpose of stored procs, but I don't know how to encrypt SQL queries that are passed through ODBC and run against a pre-2005 SQL Server.
In any case, I tried to put up some minimal safeguards to at least have some basic security.
Since you are using dynamic sql, SQL server can't tell which tables you are using, so you have to grant SELECT rights to all the tables as well
Users also need to have SELECT grant on the tables
Allowing raw SQL to be passed into a stored procedure and then executing is the very essence of data insecurity.
SQL Server security is structured so that arbitrary bits of SQL execute in their own security context. If you don't have the permission to run the query ad hoc, you also don't have the permission to run it through a stored procedure. In this, SQL Server is saving you from yourself.
Since your system allows access to stored procs and nothing else (which is good for security purposes and should not be changed) then you simply cannot under any circumstances use dynamic SQL because the rights are not at the table level and your dbas are unlikely to change that. This is not only to prevent SQL Injection attacks but to prevent possible internal fraud so any workplace which has considered this important will not be willing to compromise to make life easier for you. You simply need to redesign to never do anything dynamically. You have no other choice. If you write the procs to do what you want it to do in the first place, there is no need to send encypted sql.
When dynamic SQL is used through EXEC or sp_executesql within an SP, the EXEC permissions on the SP do not allow you to run arbitrary code in the dynamic sql. You either need to grant SELECT (yuck), or you might be able to impersonate another user using EXECUTE AS or SETUSER.
When normal SQL is used, EXEC permissions works fine, overridding ungranted SELECT persmissions. If you have DENY, though, I believe that trumps it.
Having said that, I'm still not sure you should use EXECUTE AS when the source of the SQL is outside the SP (or outside the database). For code-generation or dynamic sql which is safe from outside influence, EXECUTE AS can be a useful tool
This is most likely because of different schemas i.e. the user who logs in is not part of the Admin schema, or at least I would hope not.
The security technique that permits the type of access you are looking to achieve, i.e. to permit access to objects that are owned by the same schema, is called Ownership Chaining.
This principle is not best explained in a post.
Here is a link from Microsoft that explains the concept.
http://msdn.microsoft.com/en-us/library/ms188676(SQL.90).aspx
Here is a an outstanding article on security that provides examples and walkthroughs, for ownership chaining, amongst other techniques.
http://www.sommarskog.se/grantperm.html
I hope this is clear and assists you but please feel free to pose further questions.
Cheers, John