尝试限制对 Oracle DB 的访问以进行 运行 查询 - 设计建议

Trying to limit access to Oracle DB for running queries - Design suggestion

我正在开发 oracle DB 的 Web 界面,其中:-

  1. 用户可以请求访问特定模式
  2. 如果他被授予访问权限,他应该能够 运行 仅查询该架构。 (所有其他查询,如 Other schemas、sys table、all_tables、dual 应被拒绝)

我创建了一个只读用户,可以访问该数据库中的任何 table(NOT SYS)。

现在,我面临的问题是:- 1. 如果该数据库有两个模式 schema1 和 schema2 并且用户可以根据元数据访问 schema1 并且如果他尝试 运行 schema2.table 它将 运行 因为 read_only用户拥有 any_table 权限。 2. 他可以 运行 查询 all_tables(不空闲)

这可以通过以下任一方式解决:- 方法 1:为每个模式创建用户并向该用户授予 schema.table* 权限。 问题 :- 1. 如果有 100 个模式,将有 100 个这样的用户。 2. 如果schema中有一个新的table,需要给新的tables.

赋予明确的权限

方法 2:我正在考虑使用 Regex 方法来解析用户提供的查询,并且只允许 schema1.table 如果他被批准用于 say schema1。如果他尝试 运行 schema2.table 它将失败。

问题:- 可能有很多极端情况,例如子查询、联接等。

有没有更好的办法解决这个问题

您似乎在描述一个普通的客户端-服务器场景。

如果您的最终用户是您所描述的数据库模式,那么您应该实施数据库 "roles"。分配对象对数据库 "roles" 的访问权限,然后根据您的安全定义将这些 "roles" 分配给最终用户。

http://docs.oracle.com/database/121/SQLRF/statements_6014.htm

要避免 "schema1.table" 和 "schema2.table",您可以实施数据库同义词。

https://docs.oracle.com/database/121/SQLRF/statements_7001.htm

同时使用 "roles" + "synonyms" 您将拥有足够的控制权(安全性)并且易于管理。

这里有一些 Oracle 安全指南:

http://docs.oracle.com/cd/B28359_01/network.111/b28531/guidelines.htm#DBSEG009

http://www.oracle.com/technetwork/articles/entarch/arch-approach-inf-sec-360705.pdf

忘记解析吧,准确解析 Oracle SQL 几乎是不可能的。相反,使用 PLAN_TABLE 填充 EXPLAIN PLAN 查找依赖项。

  1. 为每个语句生成一个唯一的 ID。
  2. 通过运行explain plan set statement_id = 'UNIQUE_ID' for $$SELECT_STATEMENT$$.
  3. 生成每条语句的执行计划
  4. 查询 PLAN_TABLE 以查找查询引用的架构。

根据一些快速测试,这似乎适用于 tables、系统 tables、DUAL、同义词和视图。

至少在这些情况下它不会起作用。

  1. 从计划中完全删除 table 的优化器转换。例如,下面的查询引用了 TABLE3,尽管它没有出现在 执行计划,因为它没有被使用。这些都是罕见的情况,可能不是真正的问题。

    select *
    from table1
    where exists (select (select count(*) from table3) from table2);
    
  2. 过程代码,如函数和类型,不会出现在执行计划中。保护自定义程序代码可能需要不同的方法。例如,可能需要在游标中用SELECT语句动态创建一个临时过程,然后递归地检查DBA_DEPENDENCIES

例子

创建示例架构。

create table table1(a number);
create table table2(a number primary key);

此查询仅使用本地 table,因此只有 returns 一个用户。

explain plan set statement_id = '1' for
select *
from table1
join table2
    on table1.a = table2.a;

select distinct object_owner
from plan_table
where statement_id = '1'
    and object_owner is not null;

OBJECT_OWNER
------------
JHELLER

此查询引用系统 tables 和 returns SYS 架构,并且验证失败。

explain plan set statement_id = '2' for
select (select count(*) from all_objects)
from table1
join table2
    on table1.a = table2.a;

select distinct object_owner
from plan_table
where statement_id = '2'
    and object_owner is not null;

OBJECT_OWNER
------------
JHELLER
SYS

此查询使用 DUAL,应该无法通过验证。检测 DUAL 有点棘手,因为它不是真正的 table.

explain plan set statement_id = '3' for
select (select count(*) from dual)
from table1
join table2
    on table1.a = table2.a;

select distinct object_owner
from plan_table
where statement_id = '3'
    and object_owner is not null
union all
select distinct 'SYS'
from plan_table
where statement_id = '3'
    and operation = 'FAST DUAL';

OBJECT_OWNER
------------
JHELLER
SYS

免责声明

在大多数情况下我不推荐这个解决方案。我同意 Justin 对此请求的担忧。如果遵循标准的 Oracle 安全方法,管理数百个模式和对象可能会更简单。并且最好尽快与不合理的 "security" 请求作斗争。不幸的是,在实践中,这些战斗通常都会失败。