硬核!Oracle標籤安全性


1、概述

在Oracle9i中有一個組件稱為Oracle Label Security,這個組件實現了基於自定義策略而對數據庫中的表甚或是整個Schema提供行級安全性功能。實際上Oracle Label Security是在Oracle8.1.7中提出的,在9i版本中功能得到了大幅度增強。

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

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


2、工作流程

首先我們瞭解一下實現Oracle Label Security的大體流程。

通過Oracle提供的一系列存儲過程,先創建一個policy,然後在policy中創建level,compartment,group,之後通過這些定義好的level,compartment,group再定義label,然後將policy綁定到某張表或者某個schema,最後再給相應的用戶設置label。

其中牽涉到幾個名詞,解釋一下:

Policy:就是安全策略,一個安全策略是level,compartment,group,label的集合。

Level:等級,這是最基礎的安全控制等級,必須設置。

Compartment:分隔(這不是官方翻譯),提供第二級的安全控制,是可選的。

Group:組(這不是官方翻譯),提供第三級的安全控制,是可選的。

Label:標籤,最終體現到每一行上的安全標籤,必須設置。只有用戶被賦予的標籤和此行上的標籤相同或者等級更高的時候,該行才能夠被用戶存取。

3、測試步驟

我們需要用到3個用戶,一個是擁有zftang_test_01表的test用戶,一個是用於設置OLS策略的LBACSYS用戶,另外一個是不受OLS策略制約的SYS用戶(用來方便的插入和更新測試數據)。

· 安裝Oracle Label Security(每個數據庫進行一次)

· 創建安全性策略

· 定義級別

· 定義區間(compartment)(可選)

· 定義分組(可選)

· 創建標籤

· 將標籤策略應用於表

· 指定用戶標籤

· 為表中的行指定合適的標籤

3.1、安裝Oracle Label Security

在安裝數據庫軟件的時候必須保證選擇了Oracle Label Security組件,否則所有功能都無法使用。如果當時沒有選擇,可以按照如下方法安裝OLC

1、重新運行Universal Installer進行安裝,選擇定製,下一步;

硬核!Oracle標籤安全性

2、勾選ORACLE LABEL SECRITY組建進行安裝;

硬核!Oracle標籤安全性

3、繼續下一步,完成安裝;

LBACSYS用戶可以利用$ORACLE_HOME/rdbms/admin/catols.sql創建。

以SYS用戶登陸PLSQL,打開命令行窗口,執行:@D:\\OraHome_1\\RDBMS\\ADMIN\\catols.sql;

硬核!Oracle標籤安全性

在這個腳本的最後會自動關閉數據庫,打開可以看到,最後面是(shutdown immediate)所以請不要在生產庫上直接測試。

再次打開數據庫,就可以使用LBACSYS用戶登錄了,默認密碼就是lbacsys,如果在生產環境中,請立刻修改默認密碼。

3.2、創建安全策略

使用lbacsys用戶登陸PLSQL,執行如下命令

SQL> EXEC sa_sysdba.create_policy('TEST_POLICY', 'TEST_LABEL');

第一個參數TEST_POLICY是安全策略的名稱,

第二個參數TEST_LABEL是即將添加到zftang_test_01表中的用於存儲標籤的字段名,這個字段將在後面apply table policy的時候自動添加,所以不必預先添加。

可以從DBA_SA_POLICIES視圖中查詢安全策略的情況。

select * from DBA_SA_POLICIES

硬核!Oracle標籤安全性


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

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


3.3、定義Level

EXEC sa_components.create_level('TEST_POLICY', 111,'READ111', 'Public Level'); EXEC sa_components.create_level('TEST_POLICY', 222,'READ222', 'Internal Level');

第一個參數是上一步創建的安全策略的名字。第二個參數是Level的等級,數字越大表示權限越高,比如此處具有'READ222'等級的就可以同時查看有'READ111'等級的數據。第三個參數是Level的短名,隨便定義。第四個參數是Level的長名,只是起到一個說明的作用,隨便定義。

可以從DBA_SA_LEVELS視圖中查詢安全等級的情況。

select * from DBA_SA_LEVELS

硬核!Oracle標籤安全性

3.4、定義Compartment

本步操作是可選項,看的有點暈, 測試了幾次沒搞透

3.5、定義Group

本步操作是可選項,看的有點暈, 測試了幾次沒搞透

3.6、創建Label

EXEC sa_label_admin.create_label('TEST_POLICY', '111','READ111', TRUE);EXEC sa_label_admin.create_label('TEST_POLICY', '222','READ222', TRUE);

參數依次是安全策略名,Label Tag,Label值,是否為data label。

其中Label Tag必須是不同於系統中任何策略number的數字。Label值是最關鍵的地方,通過組合前面幾步中定義的level

是否為data label是一個布爾值,只有為TRUE的時候,這個標籤才可以用於控制表數據的安全性。

可以從DBA_SA_LABELS視圖中查詢安全標籤的情況。

select * from DBA_SA_LABELS

硬核!Oracle標籤安全性

3.7、將策略賦予表

exec sa_policy_admin.apply_table_policy(policy_name => 'TEST_POLICY',schema_name => 'TEST',table_name => 'ZFTANG_TEST_01',table_options => 'LABEL_DEFAULT,READ_CONTROL,WRITE_CONTROL');

前三個參數表示我們將TEST_POLICY策略附加到TEST用戶的ZFTANG_TEST_01表上,執行這步操作的時候,Oracle會自動將第二步中定義的列添加到表中,如果這步執行成功,我們立刻用TEST用戶檢索ZFTANG_TEST_01表,會發現一條記錄都沒有了,這說明Label Security已經起作用了。

硬核!Oracle標籤安全性

第四個參數用於設定策略如何控制表的安全性。

LABEL_DEFAULT表示如果以後一個用戶新增數據的時候沒有指定Label那麼將會使用該用戶的default session label(這個default值在下面一步的用戶Label設定中定義);READ_CONTROL,WRITE_CONTROL表示對於表的讀寫操作都受到安全策略的制約;

HIDE表示不在desc表結構的時候顯示TEST_LABEL列名,如果想要顯示就省略HIDE字樣,

注意,一旦apply策略完成,那麼要修改table_options的值,比如想把HIDE去掉,那麼就必須先用sa_policy_admin.remove_table_policy函數刪除policy定義,然後重新apply。

3.8、將Label賦予用戶

使用sa_user_admin.set_user_labels存儲過程來將label賦予用戶,這個存儲過程有不少參數,但是必須輸入的只有policy_name,user_name,max_read_label三項,其它參數如果省略的話,都有默認值。

比如def_label參數(用戶新增數據的時候沒有指定Label時的默認Label)如果沒有設定,那麼默認為跟max_read_label相同。

我們通過給TEST用戶賦予不同的Label,來完成測試的目的。每次用LBACSYS用戶設置完TEST用戶的label,TEST用戶都必須重新登錄一次,設置才會生效。

--------這裡很重要,前期測試,沒有重新登陸,總感覺沒效果;

把LABEL=READ111的授於TEST用戶

EXEC sa_user_admin.set_user_labels(policy_name=> 'TEST_POLICY',user_name =>'TEST',max_read_label =>'READ111');

這個時候看查詢結果,TEST_LABEL=111的,這個用戶才能查詢到;

硬核!Oracle標籤安全性

其實表裡真實的數據是:

硬核!Oracle標籤安全性

把LABEL=READ222的授於TEST用戶

EXEC sa_user_admin.set_user_labels(policy_name=> 'TEST_POLICY',user_name =>'TEST',max_read_label =>'READ222');

執行查詢:

發現還是這三條數據,因為其它數據TEST_LABEL列未定義值;

通過SYS用戶,對數據進行賦值;

硬核!Oracle標籤安全性


這個時候,就可以看到所有的數據了;因為前面提到:

EXEC sa_components.create_level('TEST_POLICY', 111,'READ111', 'Public Level'); EXEC sa_components.create_level('TEST_POLICY', 222,'READ222', 'Internal Level');

第一個參數是上一步創建的安全策略的名字。第二個參數是Level的等級,數字越大表示權限越高,比如此處具有'READ222'等級的就可以同時查看有'READ111'等級的數據。第三個參數是Level的短名,隨便定義。第四個參數是Level的長名,只是起到一個說明的作用,隨便定義。

3.9、新增LEVEL

這裡考慮到一點,因為LEVEL的數據越大,級別越高,加入我需要新增一個LEVEL,用來控制用戶的訪問,就可以按照如下操作:

1、 定義LEVEL

EXEC sa_components.create_level('zftang_POLICY', 333,'PUBLIC', 'Public Level1');

-------創建一個LEVEL

2、 定義LABEL

EXEC sa_label_admin.create_label('TEST_POLICY', '333','READ333', TRUE);

3 、 將LABEL賦予用戶

在這裡,如果賦予TEST用戶READ111的LEVEL,那麼這個用戶只能看到值=111的數據;

如果賦予TEST用戶READ222的LEVEL,可以看到值=111,或者=222的數據

如果賦予TEST用戶READ333的LEVEL,就可以看到=111,222,333的數據;

EXEC sa_user_admin.set_user_labels(policy_name=> 'TEST_POLICY',user_name =>'TEST',max_read_label =>'READ111');

至此,這個Oracle Label Security 的實驗基本上是完成了,達到了我們預先計劃的目標。

而關於性能方面,如果表中數據量很大,那麼出於性能考慮,可能需要在Label列上(本例中的DOC_LABEL)添加合適的索引,根據cardinality的多少,選擇B-Tree或者bitmap索引。

結論


分享到:


相關文章: