G-1150
🆓Error
Always limit privileges of schema owners according to principle of least privileges.
Reason
The schema owner of a PinkDB application usually does not need system privileges at runtime. However, during development we want to connect as the schema owner (e.g. via proxy user). For this we need more system privileges, like CREATE TABLE or CREATE PROCEDURE. In any case, we do not need extensive privileges such as SELECT ANY TABLE' or even theDBA' role. Therefore, you should keep the list of allowed system privileges for schema owners to the absolute minimum.
Example
Non-Compliant Example
grant select any table to dbl_owner;
Compliant Solution - ★★★★★
-- grant read access explicitly to required tables/views
Tests
Test SQL query
with
upriv as (
-- system privileges granted to users
select u.username, p.privilege as priv
from dba_sys_privs p
inner join dba_users u
on u.username = p.grantee
union all
-- roles granted to users
select u.username, p.granted_role as priv
from dba_role_privs p
inner join dba_users u
on u.username = p.grantee
),
rpriv as (
-- roles without parent (=roots)
select role as priv, null as parent_priv
from dba_roles
where role not in (
select rrp.granted_role
from role_role_privs rrp
)
union all
-- roles granted to roles
select granted_role as priv,
role as parent_priv
from role_role_privs
union all
-- system privileges granted to roles
select privilege as priv,
grantee as parent_priv
from dba_sys_privs
where grantee in (
select r.role
from dba_roles r
)
),
rtree as (
-- provides priv_path and is_leaf for every role/priv in the hierarchy
select priv,
parent_priv,
sys_connect_by_path(priv, '/') || '/' as priv_path,
case
when connect_by_isleaf = '0' then
0
else
1
end as is_leaf
from rpriv
connect by prior priv = parent_priv
),
rgraph as (
-- provides per priv all its possible parent privs or in other words
-- provides per parent priv all its possible child privs
-- this allows to join with parent_priv to get all privs
select priv,
substr(priv_path, 2, instr(priv_path, '/', 2) - 2) as parent_priv,
is_leaf
from rtree
),
ugraph as (
-- extends the rgraph by users and their privs
-- distinct is required since a priv can be part of multiple roles
select distinct
upriv.username,
rgraph.priv
from upriv
join rgraph
on upriv.priv = rgraph.parent_priv
)
-- main
select username || '.' || priv as identifier,
'Schema ' || username || ' has unexpected privilege ' || priv || '.' as message
from ugraph
where priv not in (select dba_roles.role from dba_roles)
and priv not in (#AllowedSchemaSystemPrivileges#)
and username in (#SchemaNames#)Test results
| Identifier | Message | Migration |
|---|---|---|
| DBL_OWNER.SELECT ANY TABLE | Schema DBL_OWNER has unexpected privilege SELECT ANY TABLE. | - |
Parameters
Use parameters to customize the rule to your needs.
| Parameter | Description | Default Value |
|---|---|---|
| SchemaNames | Comma-separated list of database schemas owning the database objects of an application. | dbl_owner |
| AllowedSchemaSystemPrivileges | Comma-separated list of allowed system privileges for schema owners. | create session, create table, create procedure, create view, create public synonym, drop public synonym, select any dictionary, debug connect session, debug any procedure, create any context, debug connect any |
References
- related to PinkDB Feature 2
The owner of the database objects should also follow the principle of least privilege. Both at runtime and at design time.