Oracle Label Security(Oracle標籤安全性)

現在保護每一行的安全

 

發表時間:2005-1-16 20:05:38 作者:未知 來源:不詳 編輯:

 

作者:Darl Kuhn、Steve Roughton

Oracle Label Security(Oracle標籤安全性)按行來控制用戶的訪問。

絕大多數商業應用程序都必須處理安全性問題。應用程序經常需要限制對專用記錄的訪問、建立審計跟蹤,或者執行一個工作流過程,所有這些都要符合公司的安全策略。構建安全的軟件是一個富有挑戰性且複雜的工作,在整個機構內管理軟件的安全策略可能會更困難。

作爲模式(schema)設計人員,你可能會在表中添加安全性列並根據這些表創建用戶特定的視圖。作爲DBA,你可能會創建角色和權限來保護數據庫對象。而作爲開發人員,你可能會編寫PL/SQL包,將安全事務處理封裝在應用程序內。所有這些技術都很有效,但這些方法也都具有一定的缺點。例如,某人可能會無意中將專用數據導出至一個個人模式、原有的應用程序可能與安全對象不兼容,或者用戶可能會利用SQL*Plus繞過整個應用程序的安全性檢查。

Oracle9i數據庫有一個可以幫助解決這些問題的組件:Oracle Label Security。Oracle Label Security最早引入Oracle8i第三版(8.1.7),它是一個使你能夠建立並實施企業安全性策略的簡捷工具。

Oracle Label Security是內置於數據庫引擎中的過程與約束條件集,該數據引擎實施對在單個表或整個模式上的"行"級訪問控制。要利用Oracle Label Security,需要創建一個或多個安全策略,其中每一個安全策略都包含一組標籤。你可以用這些標籤來標明哪些用戶能夠訪問什麼類型數據。在創建了一個策略之後,將該策略應用於需要保護的表,並將這些標籤授予你的用戶,這樣,你就完成了整個過程。Oracle Label Security對查詢的修改是透明的,並且在即時計算訪問級別,以執行你的新策略。

當Oracle9i數據庫在解析各個SQL語句時,它也檢測各個表是否受到某個安全策略的保護。根據該用戶的訪問權限,Oracle9i數據庫向該語句的WHERE子句中添加安全性謂詞。因爲這些都發生在數據庫引擎的內部,所以不管該SQL語句的來源如何,用戶都不可能繞過該安全性機制。

它是如何工作的?

這裏有一個非常簡單的例子,可以說明Oracle Label Security是如何工作的。我們創建了名爲documents的表,並向其中填入了4個記錄,同時定義了兩個安全級別:PUBLLIC(公共)與INTERNAL(內部)。每個級別各有一個數字值:1000或2000。接着可以爲表的每一行指定一個級別。下面給出對該表進行的一個簡單SELECT:

 

SQL> SELECT * FROM documents;

DOCID DOCNAME LEVEL DOC_LABEL
----- ----------- -------- ---------
1 SHARE_WARE PUBLIC 1000
2 WEST_PAYROLL INTERNAL 2000
3 EAST_SALES INTERNAL 2000
4 COMP_PAYROLL INTERNAL 2000

 

現在假定在我們的數據庫中有兩個用戶:EMP與MGR。我們爲這些用戶指定如下訪問級別:

EMP 被指定爲 PUBLIC只讀。

MGR 被指定爲 PUBLIC與INTERNAL 讀/寫。
當這兩個用戶訪問該表時,EMP只能讀取第1行,而MGR可以對所有4行進行讀/寫操作。
 

當這兩個用戶訪問此 documents表時,其內部會發生什麼呢?假定EMP用戶運行下面的查詢:

 

SELECT * FROM documents;

 

Oracle9i數據庫對該查詢進行解析,並判定該表是受標籤安全性的保護。Oracle Label Security向該查詢中添加一個 WHERE 子句,以確保該EMP只能看到標記有 PUBLIC 訪問的行:

 

SELECT * FROM documents
WHERE doc_label = 1000;

 

下面是該 EMP 用戶在運行此查詢後所看到的內容:

 

DOCID DOCNAME LEVEL DOC_LABEL
----- ---------- ------ ---------
1 SHARE_WARE PUBLIC 1000

你可能想知道:"爲什麼不根據某一列值,創建一個限制訪問的視圖呢?"事實上,如果你的應用程序只需要幾個級別,並沒有特殊的安全要求要考慮,那麼向你的表中添加一個安全性列,然後再利用視圖就可以了。

但假設你的系統要求發生了變化,你現在需要利用對改變數據集的定製的讀/寫許可跨多個機構來管理數個級別的用戶。此外,這些機構位於不同的國家,各自都有自己的法律和安全性限制。如果僅使用視圖,就很難滿足這些要求了。

幸運的是,Oracle Label Security就是爲了適應擴展而設計的,因此實施此類應用程序安全性可能比你預計的更容易。

一個練習示例

實施Oracle Label Security包括以下10個步驟:

安裝Oracle Label Security(每個數據庫進行一次)
創建安全性策略
定義級別
定義區間(compartment)(可選)
定義分組(可選)
創建標籤
將標籤策略應用於表
指定用戶標籤
指定正常授權級別的訪問
爲表中的行指定合適的標籤
在使用Oracle Label Security時,可以利用Oracle Enterprise Manager的Policy Manager圖形用戶界面(GUI)或者Oracle Label Security PL/SQL包。在我們的示例實施中,我們將利用PL/SQL包。相同的概念可以應用於上述兩種技術中的任一種。
 

步驟1;安裝Oracle Label Security
對於每一個數據庫只需要安裝一次Oracle Label Security。安裝過程包括4個步驟:

啓動Universal Installer。
選擇並安裝該Oracle Label Security選項。
以SYS身份按下面的方式運行$ORACLE_HOME/rdbms/ admin/catols.sql:
 

 

SQL> CONN sys/password AS SYSDBA;
SQL> @?/rdbms/admin/catols

 

注意:此catols.sql腳本在其最後一步對數據庫進行SHUTDOWN IMMEDIATE (立即關閉)。

重新啓動實例並運行
 

 

SQL> SELECT username FROM dba_users;

 

你將看到一個新的包括所有Oracle Label Security對象的 LBACSYS用戶。其缺省口令是LBACSYS (所以一定要更改該口令)。該用戶將管理你的安全策略。

步驟2:創建一個安全性策略
下一個任務是創建一個安全性策略。一個策略就是一個包括所有安全規則和訪問要求的存儲桶(bucket)。行級別的數據標籤和對這些行的模式訪問總是與一個策略相關聯。

在本例中,你需要定義對公司文檔的行級別的訪問。在此步驟內,創建一個名爲DOC_POLICY的策略。要創建一個策略,先以LBACSYS身份建立連接,然後利用 sa_sysdb.create_policy過程:

 

SQL> CONN lbacsys/lbacsys
SQL> EXEC sa_sysdba.create_policy
('DOC_POLICY','DOC_LABEL');

 

第一個參數DOC_POLICY是該策略的名字,第二個參數DOC_LABEL是一個列的名字,Oracle Label Security將把該列添加到你將在標籤控制下替換的表內。

爲了覈實你的策略已經創建,可按下面方式查詢DBA_SA_POLICIES :

 

SQL> SELECT policy_name, status
from DBA_SA_POLICIES;

POLICY_NAME STATUS
----------- -------
DOC_POLICY ENABLED

 

要禁用、重新啓用或者刪除一個策略,可利用以下過程:

 

SQL> EXEC sa_sysdba.disable_policy
('DOC_POLICY');
SQL> EXEC sa_sysdba.enable_policy
('DOC_POLICY');
SQL> EXEC sa_sysdba.drop_policy
('DOC_POLICY');

 

步驟3:定義級別
每個安全性策略都必須包含指定訪問表的不同等級的級別。在本例中,創建了兩個敏感度級別: PUBLIC與 INTERNAL。

 

SQL> EXEC sa_components.create_level
('DOC_POLICY', 1000,
'PUBLIC', 'Public Level');
SQL> EXEC sa_components.create_level
('DOC_POLICY', 2000,
'INTERNAL', 'Internal Level');

 

每個級別都有一個策略名、一個數字ID、一個縮寫名與一個全名。該數字ID表示敏感度級別--編號越高,表明敏感度越高。在本例中,INTERNAL 比PUBLIC的敏感度要高。爲了查看你所創建的級別,執行下面過程:

 

SQL> SELECT * FROM dba_sa_levels
ORDER BY level_num;

 

步驟4:定義區間(可選)
區間使你能夠將對一行數據的訪問精確限定在一個級別之內。在本例中,你具有閱讀敏感度級別相同的文檔,但是某一區間只能看到該級別的子集。下面你要創建FINANCE 與 HUMAN_RESOURCE區間:

 

SQL> EXEC sa_components.create_compartment
('DOC_POLICY', 200,
'FIN', 'FINANCE');
SQL> EXEC sa_components.create_compartment
&nb

sp; ('DOC_POLICY', 100,
'HR', 'HUMAN_RESOURCE');

 

區間有一個策略名、一個數字ID、一個縮寫名與一個全名。區間的數字ID並不指定其敏感度的級別。它僅用於在顯示訪問信息時對區間進行排序。要了解關於區間的信息,可以查詢DBA_SA_COMPARTMENTS視圖。

步驟5:定義分組(可選)
和使用區間類似,使用分組是將訪問限制在一個級別內的另一個可選用的方法。當有多個層次的用戶時(如在一個公司的機構設置圖中),組是非常有用的。

在創建一個分組時,必須定義一個層次(hierarchy)。在本例中,ALL_REGIONS是父,WEST_REGION和EAST_REGION是ALL_REGIONS的子。

 

SQL> EXEC sa_components.create_group
('DOC_POLICY', 10,
'ALL', 'ALL_REGIONS');
SQL> EXEC sa_components.create_group
('DOC_POLICY', 20, 'WEST',
'WEST_REGION', 'ALL');
SQL> EXEC sa_components.create_group
('DOC_POLICY', 30, 'EAST',
'EAST_REGION', 'ALL');

 

與區間類似,分組也具有一個數字ID、一個縮寫名和一個全名。此外編號(數字)並不表示任何敏感度,它僅用於在顯示分組信息時對其進行排序。要觀察關於分組的信息,可查詢DBA_SA_GROUPS視圖。

步驟6:創建標籤
一個標籤是級別、區間和分組的一個組合。每個標籤都必須包含一個級別,還可以包含(也可以不包含)區間和/或分組。該標籤使你能夠將數據的不同用戶所要求的各種不同類型訪問迅速地組合在一起。

標籤是級別、區間與分組的縮寫名的一個組合,並遵循以下語法:

 

級別: 區間, ... 區間_n:分組,.. 分組_n
 

級別、區間與分組都必須用冒號隔開。如果指定了一個以上的區間或組,它們必須用逗號隔開。

例如,可能有一些財務部門的用戶,他們只能訪問內部文檔。其標籤類似於:

 

INTERNAL:FIN(內部:財務)
創建4個標籤來指定相關要求,如下面所示:
SQL> EXEC sa_label_admin.create_label
('DOC_POLICY', '10000',
'PUBLIC', TRUE);
SQL> EXEC sa_label_admin.create_label
('DOC_POLICY', '20200',
'INTERNAL:HR:WEST', TRUE);
SQL> EXEC sa_label_admin.create_label
('DOC_POLICY', '20400',
'INTERNAL:FIN:EAST', TRUE);
SQL> EXEC sa_label_admin.create_label
('DOC_POLICY', '30900',
'INTERNAL:HR,FIN:ALL', TRUE);

在創建一個標籤時,必須爲其指定一個編號。該編號在數據庫的所有策略中是惟一的。要查看標籤信息,可查詢DBA_SA_LABELS視圖。

步驟7:將標籤策略應用於表
要將一個表置於標籤安全性控制之下,需要把該標籤策略賦給該表。在下面的過程中,將DOC_POLICY應用於用戶APP所擁有的DOCUMENTS表。Oracle Label Security將控制對該表的讀/寫訪問。

 

SQL> EXEC sa_policy_admin.apply_table_policy -
( policy_name => 'DOC_POLICY' -
, schema_name => 'APP' -
, table_name => 'DOCUMENTS' -
, table_options => 'LABEL_DEFAULT,
READ_CONTROL,WRITE_CONTROL');

在運行此過程時,Oracle9i數據庫向documents表中添加一個名爲DOC_LABEL的列。這個列的名字是在步驟2中創建該安全策略時定義的。如果你描述該documents表,你將看到如下所示的新的DOC_LABEL列:

 

SQL> DESC app.documents

Name Type
--------- ------------
DOCID NUMBER
DOCNAME VARCHAR2(30)
DOC_LABEL NUMBER(10)

 

當你應用該策略時,你也可以通過在TABLE_OPTIONS參數中指定HIDE,取消來自用戶的該列:

 

table_options&n

bsp; => 'LABEL_DEFAULT,
READ_CONTROL,WRITE_CONTROL,HIDE'

 

這個TABLE_OPTIONS參數使你能夠定義將把什麼類型的控制應用到該表上。LABEL_DEFAULT指明,如果沒有爲一個 INSERT語句提供標籤,那麼將使用缺省的會話行標籤。READ_CONTROL參數規定該 SELECT, UPDATE和DELETE訪問在整個標籤內是有效的。WRITE_CONTROL參數決定哪些INSERT, UPDATE活動是通過一個標籤獲得授權的。

要確定哪些策略已經被應用到了哪些表和模式,可以查詢DBA_SA_TABLE_POLICIES視圖。

步驟8:指定用戶標籤
現在需要定義在一個策略中哪些用戶具有什麼類型的訪問權限。這也是你給一個用戶指定最大讀/寫權限的地方。在本例中,你爲3個用戶指定標籤如下:

MGR被賦予了最高級別的讀/寫權限。
HR_EMP被賦予了對 HR WEST 文檔的某個讀/寫訪問權限。
EMP被賦予了PUBLIC 讀/寫訪問權限。
代碼清單1給出了用於爲各個用戶指定標籤的語法。
 

這些過程將一個用戶映射到訪問級別和被指定了標籤的行。爲了查看用戶及訪問級別,可查詢DBA_SA_USER_LABELS視圖。

步驟9:指定正常授權級別的訪問
要確保CRUD(CREATE, READ, UPDATE, 和 DELETE)訪問已經準備就序。Label Security是與正規的表授權一起工作的。在完成CRUD授權之前,用戶不能進行SELECT, INSERT, UPDATE, 或 DELETE 或DELETE操作。當一個SQL查詢訪問一個表時,Oracle Label Security將首先檢查CRUD訪問是否合適,然後,如果有一個安全策略被應用於一個表,則它將確保該訪問被執行。下面所列的是對用戶進行合適的CRUD授權的過程:

 

SQL> CONN app/app
SQL> GRANT SELECT ON documents TO emp;
SQL> GRANT SELECT, UPDATE ON documents
TO hr_emp;
SQL> GRANT SELECT, UPDATE, INSERT
ON documents TO mgr;

 

步驟10:指定合適的標籤
現在,確保爲每個行都指定一個合適的標籤。在本例中,將從頭開始加載數據。既可以用其數字形式加載該標籤,也可以用CHAR_TO_LABEL函數來加載。本例對這兩種方法都進行了說明。以MGR身份建立連接,將該數據插入到APP.DOCUMENTS表中:

 

SQL> CONN mgr/mr_bigg
SQL> INSERT INTO app.documents VALUES
(1, 'SHARE_WARE',CHAR_TO_LABEL
('DOC_POLICY','PUBLIC'));
SQL> INSERT INTO app.documents VALUES
(2, 'WEST_PAYROLL', 20200);
SQL> INSERT INTO app.documents VALUES
(3, 'EAST_SALES', 20400);
SQL> INSERT INTO app.documents VALUES
(4, 'COMP_PAYROLL', 30900);

 

如果表中已經有了數據,那麼你需要用合適的標籤值來更新該標籤列(DOC_LABEL)。因爲該表已經處於Oracle Label Security 控制之下,所以必須用一個具有權限的模式來更新該標籤列。當然,也可以暫時禁用該策略,先更新該標籤列,然後再重新啓用該策略。如果用SQL*Loader向一個受保護的表中插入數據,則先要確保加載的用戶(模式)具有合適的標籤寫入權限。

對一個表啓用了標籤安全性控制後,如果沒有合適的標籤權限,即便是表的所有者也不能讀取或寫入。該規則的一個變體是,表的所有者可以在沒有Oracle Label Security DELETE許可的條件下截短其數據。

操作數據

現在當你以不同的用戶身份連接時,請注意你只能按照你的安全性策略和CRUD訪問所規定的那樣操作數據:

 

SQL> CONN mgr/mr_bigg
SQL> SELECT docname, doc_label
FROM app.documents;
DOCNAME DOC_LABEL
------------- ---------
SHARE_WARE 10000
WEST_PAYROLL 20200
EAST_SALES 20400
COMP_PAYROLL 30900

 

如果以HR_EMP身份連接,則相同的查詢將返回以下內容:

 

DOCNAME DOC_LABEL
------------- ---------
SHARE_WARE 10000
WEST_PAYROLL 20200

 

如果以 EMP身份連接,相同的查詢則只返回以下內容:

 

DOCNAME

DOC_LABEL
------------- ---------
SHARE_WARE 10000

 

當任一SQL語句訪問該APP.DOCUMENTS表時,Oracle9i數據庫首先驗證CRUD訪問,然後施以Oracle Label Security限制。這樣,用戶只能執行經授權的操作。

DBA應考慮的事項

如果你是一位DBA,那麼還有另外一些需要考慮的事項。當你導出受Label Security保護的數據時,只能使用一個具有所賦予的適當讀取權限的模式導出該數據。例如,如果你想以SYSTEM身份導出APP.DOCUMENTS 表,將會得到以下消息:

 

EXP-00079: Data in table "DOCUMENTS" is protected.(表"DOCUMENTS"中的數據受到保護)

Conventional path may only be exporting partial table.(常規的路徑只能導出部分表)

. . exporting table DOCUMENTS 0 rows exported(導出表DOCUMENTS中的0行被導出)
 

你不能將一個安全性策略應用於該SYSTEM 模式。你將需要利用一個對錶中受標籤保護的所有行有讀取權限的非SYSTEM模式。例如,如果你有一個用來導出你的數據庫的EXPUSER 模式,則你需要授予它對受策略保護的所有行的特殊READ權限:

 

SQL> EXEC sa_user_admin.set_user_privs
('DOC_POLICY','EXPUSER','READ');

要授予一個模式對受策略保護的數據的完全讀取和寫入權限,則可以利用FULL關鍵詞:

 

SQL> EXEC sa_user_admin.set_user_privs
('DOC_POLICY','EXPUSER','FULL');

注意:任何被授予SYSDBA權限的模式(如SYS)都可以看到所有數據,而不管這些數據是否受Label Security保護。

無論你有什麼特殊權限(如FULL,全權),你都不能利用導出實用程序來備份LBACSYS模式。如果你試圖導出LBACSYS,你將收到一個出錯提示:"LBACSYS is not a valid username.(LBACSYS不是一個有效用戶名)"。因此,你需要利用數據庫的一個物理備份(熱備份、冷備份或RMAN)來備份LBACSYS的對象。

在將受標籤保護的數據導入另一個數據庫之前,需要先安裝Oracle Label Security。還需要預先創建策略和標籤,並確保導入的模式(用戶)具有完全的寫入權限。具體細節,請參見Oracle Label Security管理員指南第12章。

如果有大量受Label Security保護的數據,那麼你就需要一個調優策略。根據標籤基數(cardinality)的不同,你可能希望考慮向標籤列中增加一個B樹索引或一個位映射索引。例如,如果標籤的基數較高,那麼就應當使用一個B樹索引。

Oracle建議對LBACSYS模式的對象以及應用程序表和索引進行分析,以改進由基於成本的優化器所生成的執行計劃。我們建議在對安全性策略進行任何改變後,對LBACSYS對象進行分析。

結論

Oracle9i數據庫中的Oracle Label Security提供了一種對數據進行細粒度訪問控制的安全的方法。這一特性被封裝在數據庫引擎中,所以不可能繞過它,它提供了一種實施和維護複雜"行"級別安全性所需要的安全的方法。

發佈了142 篇原創文章 · 獲贊 2 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章