13

Web アプリケーションをサポートするマルチテナント データベースで新しい行レベル セキュリティ機能を使用する最善の方法を把握しようとしています。

現在、アプリケーションは、実行しようとしているアクションに応じて、いくつかの異なる ROLE を使用できます。

アプリケーションが独自の ROLE を使用して接続を確立すると、アプリケーションは (ユーザーによって提供された) 認証パラメーターをさまざまな関数に渡します。この関数は、ユーザーが提供した認証パラメーターに基づいて行をフィルター処理します。このシステムは、何千人ものユーザーと連携するように設計されており、機能しているようです。ただし、それは反抗的に不格好です(そして遅いです)。

新しい行レベル セキュリティ機能を使用したい場合、(Web アプリケーションだけでなく) 実際のユーザーごとに新しい ROLE を作成して、データベースにアクセスする必要があるようです。

これは正しいです?もしそうなら、データベースに何千もの ROLE を作成するのは良い考えですか?


コメント内のa_horse_with_no_nameのリンクから更新します (ありがとう、そのスレッドはスポットです):

CREATE USER application;

CREATE TABLE t1 (id int primary key, f1 text, app_user text);
INSERT INTO t1 VALUES(1,'a','bob');
INSERT INTO t1 VALUES(2,'b','alice');
ALTER TABLE t1 ENABLE ROW LEVEL SECURITY;
CREATE POLICY P ON t1 USING (app_user = current_setting('app_name.app_user'));
GRANT SELECT ON t1 TO application;

SET SESSION AUTHORIZATION application;

SET app_name.app_user = 'bob';

SELECT * FROM t1;

 id | f1 | app_user
----+----+----------
  1 | a  | bob
(1 row)

SET app_name.app_user = 'alice';
SELECT * FROM t1;

 id | f1 | app_user
----+----+----------
  2 | b  | alice
(1 row)

SET app_name.app_user = 'none';
SELECT * FROM t1;

 id | f1 | app_user
----+----+----------
(0 rows)

current_setting('app_name.app_user')さて、これは構成パラメーター専用であるという印象を受けていたので、混乱しています...どこでapp_name定義されていますか?

4

1 に答える 1

9

セッション設定に基づいてセキュリティ ポリシーを設定することは、まずい考えです (私は CAPS と太字の両方が嫌いなので、私が言っていることを信じてください)。すべてのユーザーができるSET SESSION 'app_name.app_user' = 'bob'ので、誰かが「app_name.app_user」がドアであることがわかるとすぐに (私を信じてください、彼らはそうするでしょう)、あなたのセキュリティ全体がドアの外に出ます.

webadmin私が見る唯一の方法は、セッショントークンを格納するあなただけがアクセスできるテーブルを使用することです(タイプが思い浮かび、使いやすいようにuuidキャストします)。関数はtext( owner と仮定して) トークンとセッションting を設定し、所有されている (または適切な特権を持っている)テーブルは、そのテーブルとそのポリシーのセッション設定を参照します。login()SECURITY DEFINERwebadminSETwebadmin

残念ながら、ここでは一時 (セッション) テーブルを使用できません。一時テーブルではポリシーを構築できないため、「実際の」テーブルを使用する必要があります。これはパフォーマンスの低下のようなものですが、ハッキングの被害と比較検討してください...

実際には:

CREATE FUNCTION login (uname text, pwd text) RETURNS boolean AS $$
DECLARE 
  t uuid;
BEGIN
  PERFORM * FROM users WHERE user = uname AND password = pwd;
  IF FOUND THEN
    INSERT INTO sessions SET token = uuid_generate_v4()::text, user ....
       RETURNING token INTO t;
    SET SESSION "app_name.token" = t;
    RETURN true;
  ELSE
    SET SESSION "app_name.token" = '';
    RETURN false;
  END IF;
END; $$ LANGUAGE plpgsql STRICT;

これで、ポリシーは次のリンクにリンクされsessionsます。

CREATE POLICY p ON t1 FOR SELECT
  USING (SELECT true FROM sessions WHERE token = current_setting('app_name.token'));

( uuids は一意であると想定される可能性があるため、LIMIT 1. 順序付けやその他の魔法は必要ありませuuidん。 がテーブルにある場合、ポリシーは合格し、そうでない場合は失敗します。)uuidは推測することは不可能であり (いずれにせよ、あなたの生涯の中で)、取得することは不可能です。誰でもwebadmin

于 2016-01-29T18:15:05.497 に答える