Skip to Main Content
  • Questions
  • Can FGA policy handlers rely on package state when SQL is executed in parallel?

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Alexey.

Asked: August 10, 2016 - 12:24 pm UTC

Last updated: August 18, 2016 - 2:37 am UTC

Version: 12.1.0.1.0

Viewed 1000+ times

You Asked

Hello,

My application uses FGA policy handlers to check access to the database tables.
FGA handlers rely on the package state representing the security context
such as current application user identity, access rights, and so on.

It works fine almost any time, except for the parallel queries. When I enforce
parallel query execution, my FGA policy handlers fail as if no package state
is known to the parallel query server:

ORA-12801: error signaled in parallel query server P000
ORA-28144: Failed to execute fine-grained audit handler
...

So the question is:

Can FGA policy handlers rely on the package state
when Oracle is executing queries in parallel?

My test setup is as follows:

-------------------------------
CREATE TABLE TEST_FGA_TABLE AS
SELECT 1 ID, 'One' NAME FROM DUAL UNION
SELECT 2 ID, 'Two' NAME FROM DUAL;

CREATE OR REPLACE PACKAGE TEST_FGA AS
PROCEDURE FGA_CHECK;
PROCEDURE SET_BYPASS_MODE(M NUMBER);
END TEST_FGA;

CREATE OR REPLACE PACKAGE BODY TEST_FGA AS
BYPASS_FGA_CHECK NUMBER := 0;

PROCEDURE FGA_CHECK IS
BEGIN
IF BYPASS_FGA_CHECK = 1 THEN
RETURN;
END IF;

RAISE_APPLICATION_ERROR(-20000, 'FGA check failed.');
END;

PROCEDURE SET_BYPASS_MODE(M NUMBER) IS
BEGIN
BYPASS_FGA_CHECK := M;
END;
END TEST_FGA;

CREATE OR REPLACE PROCEDURE TEST_FGA_TABLE_SELECT(object_schema VARCHAR2, object_name VARCHAR2, policy_name VARCHAR2) AS
BEGIN
TEST_FGA.FGA_CHECK;
END;

BEGIN
DBMS_FGA.ADD_POLICY
(
object_schema => USER,
object_name => 'TEST_FGA_TABLE',
policy_name => 'TEST_FGA_TABLE_SELECT',
handler_schema => USER,
handler_module => 'TEST_FGA_TABLE_SELECT',
enable => TRUE,
statement_types => 'SELECT',
audit_trail => DBMS_FGA.DB,
audit_column_opts => DBMS_FGA.ANY_COLUMNS
);
END;
-------------------------------

My security package has no pre-initialized state.
So this select yields an error, as it should:

SELECT * from TEST_FGA_TABLE;

ORA-28144: Failed to execute fine-grained audit handler
ORA-20000: FGA check failed.
ORA-06512: at "KERNEL.TEST_FGA", line 10
ORA-06512: at "KERNEL.TEST_FGA_TABLE_SELECT", line 3
ORA-06512: at line 1

So far so good. Now I initialize the security package as follows:

-- set bypass mode
BEGIN
TEST_FGA.SET_BYPASS_MODE(1);
END;

-- and now it works fine!
SELECT * FROM TEST_FGA_TABLE;

ID NAME
---------- ----
1 One
2 Two

2 rows selected.

When the security context is initialized, FGA check is passed.
But now I try to execute the same statement in parallel:

-- now it fails again!
SELECT /*+ PARALLEL(5)*/ * FROM TEST_FGA_TABLE;

ORA-12801: error signaled in parallel query server P000
ORA-28144: Failed to execute fine-grained audit handler
ORA-20000: FGA check failed.
ORA-06512: at "KERNEL.TEST_FGA", line 10
ORA-06512: at "KERNEL.TEST_FGA_TABLE_SELECT", line 3
ORA-06512: at line 1

And it fails as if no package state is known to the parallel query server P000.

P.S. My database version is as follows:

SELECT * FROM V$VERSION
-----------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
PL/SQL Release 12.1.0.1.0 - Production
CORE 12.1.0.1.0 Production
TNS for Linux: Version 12.1.0.1.0 - Production
NLSRTL Version 12.1.0.1.0 - Production

and Connor said...

That's correct. Each parallel slave is a brand new session, so whatever dependencies you have (in your case, package state) would need to be set before the slave will operate.

So you would need a login trigger to perform that work so that the slaves pick it up.

Perhaps an alternate approach (although I'm assuming your logic is more complex than the example you've provided). Perhaps an audit condition of (say):

sys_context('MY_CTX','BYPASS_MODE')='N'

so that you dont fire off the handler at all unless you needed to ?

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thanks for the clarification!

Alexey Yakovlev, August 18, 2016 - 2:05 am UTC

Thanks a lot,

our first version indeed used SYS_CONTEXT, but we decided to replace it with package variables (more convenient, type safe and compile-time checked). Too bad, now it looks like we have to switch back to using the context variables.

Regards, Alex
Connor McDonald
August 18, 2016 - 2:37 am UTC

Whilst SYS_CONTEXT will be better, my suggestion was not a simple replace-the-package-var. My suggestion was to see if its possible to NOT fire the FGA policy for the times where you want to allow people to see the data.

So rather than:

- policy fires all the time
- predicate says: "where authorised=Y"

we have a system where:

- policy fires only when authorised=N

Hope this helps.

More to Explore

Security

All of the vital components for a secure database are covered in the Security guide.