2011-10-13 57 views
2

如果你想要血腥的細節繼續閱讀,否則所有我問的是,如果你可以限制什麼用戶能夠在他們的SQL語句上運行EXPLAIN命令,像GRANT解釋到比利會很好,但似乎並不存在。PostgreSQL限制誰可以執行解釋計劃

我的目標是加密列中的數據,對加密列進行索引,因爲它可用於搜索,並將加密密鑰隱藏於所有最終用戶(可與系統管理員或DBA共同見過)。在PostgreSQL中有哪些方法可以做到這一點?如果沒有辦法做到這一切,你有什麼樣的事情來試圖到達那裏?我下面列出的當前方法幾乎讓我在那裏,但是當解釋計劃在查詢上運行時,加密密鑰被暴露。這就是爲什麼我想知道是否可以限制用戶使用解釋的權限。

所以這裏是一個小小的設置來演示我在說什麼。 假設我在數據庫表的一列中加密了一些數據,則將通過gui前端屏幕或通過pg_admin即席查詢來搜索此列。

CREATE TABLE test(id serial,my_data TEXT); 

--Fill table with enough data to need an index. 
DO $$ 

DECLARE counter INTEGER := 0; 
BEGIN 
    WHILE(counter < 1000) 
    LOOP 
     EXECUTE 'INSERT INTO test(my_data) 
       SELECT pgp_sym_encrypt(''avalue' || CAST(counter AS TEXT) || '''' || ', ''apasswordwithsomeentropy'',''compress-algo=1, cipher-algo=aes256'');'; 
     counter := counter + 1; 
    END LOOP; 
END$$; 

ANALYZE test; 

CREATE INDEX index1 
    ON test 
    USING btree 
    (my_data); 

這個選擇仍然必須做一個全表掃描,我想避免。

SELECT id, 
     my_data, 
     pgp_sym_decrypt(cast(my_data as bytea),'apasswordwithsomeentropy') 
FROM test 
WHERE pgp_sym_decrypt(cast(my_data as bytea),'apasswordwithsomeentropy') = 'avalue114'; 

"Seq Scan on test (cost=0.00..665.00 rows=61 width=246)" 
" Filter: (pgp_sym_decrypt((my_data)::bytea, 'apasswordwithsomeentropy'::text) = 'avalue114'::text)" 

所以,如果我做什麼用的函數索引,以加快此查詢了。我使用get_password函數沒有使用密碼硬編碼創建索引。請記住,我不希望用戶查看索引定義並查看密碼。假設用戶不能從密碼中選擇或執行get_password(),只有具有額外特權的單個帳戶可以。而get_password()函數僅用於函數索引中。所以我的理解是用戶不需要執行該功能的權限?

CREATE TABLE password 
(
    password_id serial NOT NULL, 
    password_value text 
); 

INSERT INTO password(password_value) 
SELECT 'apasswordwithsomeentropy'; 
from get_password(); 

CREATE FUNCTION get_password() RETURNS TEXT 
    AS 'select password_value 
    from password 
    where password_id = 1' 
    LANGUAGE SQL 
    IMMUTABLE; 

CREATE INDEX index2 ON test (pgp_sym_decrypt(cast(my_data as bytea),get_password())); 

現在,當我運行選擇數據庫使用索引2,我得到的結果很好,快速,因爲我想。問題是,當我對select查詢執行解釋計劃時,index2顯示平面文本中的密碼。

SELECT id, 
     my_data, 
     pgp_sym_decrypt(cast(my_data as bytea),'apasswordwithsomeentropy') 
FROM test 
WHERE pgp_sym_decrypt(cast(my_data as bytea),'apasswordwithsomeentropy') = 'avalue114'; 


"Bitmap Heap Scan on test (cost=4.73..171.49 rows=61 width=246)" 
" Recheck Cond: (pgp_sym_decrypt((my_data)::bytea, 'apasswordwithsomeentropy'::text) = 'avalue114'::text)" 
" -> Bitmap Index Scan on index2 (cost=0.00..4.72 rows=61 width=0)" 
"  Index Cond: (pgp_sym_decrypt((my_data)::bytea, 'apasswordwithsomeentropy'::text) = 'avalue114'::text)" 

我唯一能想到的就是創建Web服務到數據庫,以防止用戶直接與數據庫交互。但作爲應用程序的內部,如果有些用戶有時仍然可以使用pg_admin,但不會看到諸如解釋計劃等所有內容,那將會很不錯。這些用戶不知道解釋計劃是什麼,也不會使用它們。

我不斷創建一個Web服務來包裝所有需要在通過Web服務調用的函數中運行的查詢,但這需要額外的時間才能在正式的開發環境中發佈並帶走廣告-hoc查詢方法並添加另一個層來維護。有任何想法嗎?由於

+0

我不確定你在問什麼。索引一列加密數據有什麼好處?您必須解密列才能執行任何有意義的搜索。 – 2011-10-13 21:06:59

+1

@Michael:不,不一定。如果您使用相同的算法,則不用解密該字段,而是加密搜索字符串 - 加密字段應與您的加密搜索字符串匹配。 – vol7ron

+0

@ StarShip3000:我沒有閱讀你的整篇文章。根據您的字段的大小,您是否考慮過現有的散列算法(MD5/SHA),並閱讀了salting。 – vol7ron

回答

1

在一個側面說明,你可能要改變

SELECT id, 
     my_data, 
     pgp_sym_decrypt(cast(my_data as bytea),'apasswordwithsomeentropy') 
FROM test 
WHERE pgp_sym_decrypt(cast(my_data as bytea),'apasswordwithsomeentropy') = 'avalue114'; 

SELECT id, 
     my_data, 
     pgp_sym_decrypt(cast(my_data as bytea),'apasswordwithsomeentropy') 
FROM test 
WHERE pgp_sym_encrypt(cast('avalue114' as bytea),'apasswordwithsomeentropy') = my_data; 

這樣的Postgres並不需要解密每個my_data您比較。如果pgp_sym_encrypt是確定性的並且可以被緩存(不確定postgres是否可以處理這個),你的目標數據將被加密一次,只有匹配的列將被解密。

我們已經改變了哪裏的條件,所以計劃可能會改變,你可以請嘗試發送新的計劃?