PostgreSQLの金融アプリの認証アプローチの選択


15

最初にいくつかの背景。

LedgerSMBプロジェクトは、PostgreSQLで実行されるオープンソースの財務会計ソフトウェアプロジェクトです。ユーザー定義関数に非常に大量のビジネスロジックを実装します。これらは、プログラムオブジェクトメソッドとデータベースの動作間の主要なマッピングツールとして機能します。現在、認証ユーザーとしてデータベースユーザーを使用します(一部は選択(これにより中央集中型のセキュリティロジックが可能になり、他のツールを記述してユーザーに与えられたアクセス許可を再利用できます))。また、一部は必要に応じて(SQL-Ledgerそのコードベースにセキュリティをレトロフィットするオプションはあまりありませんでした)。

これにより、LDAPからKerberos 5まで、PostgreSQLがアクセスできる合理的な数のシングルサインオンオプションにアクセスできます。パスワードが関係する場所でもPAMを使用できます。また、他のアプリケーションと統合したり、他のクライアントインターフェイスを許可したりするときに、アクセス許可を再利用できます。財務会計アプリケーションにとって、これは正味の勝利のように思えます。

明らかにコストがかかります。Webアプリケーションの場合、サポートできるHTTP認証のタイプは非常に限られています。たとえば、DIGESTは完全に除外されています。BASICが機能し、KRB5を簡単に実装できます(これは1.4でサポートされ、そのまま使用できるようにする予定です)。非常に強力な認証対策は、これを直接適切に管理することはできませんが、おそらく必要に応じてそれらをシムできます(たとえば、ユーザー名と特定のルートCAに一致するcnを持つBASIC +クライアント側SSL証明書)。

同時に、主に開発群衆から、そして時折、アプリケーションはデータベースではなくセキュリティバリアであるべきだと言うdbaからかなりの批判を受けています。私の見解では、セキュリティ境界は小さいほうが一般的に優れており、ビジネスロジックとセキュリティロジックの再利用が一緒になり、同じレベルでセキュリティロジックを再利用せずにビジネスロジックを再利用するのは危険だと思いますプログラムの。

ここで大きなトレードオフがありませんか?私が検討していない落とし穴はありますか?


1
pgsql-generalメーリングリストにクロスポストされています。ここから始まるスレッドを参照してください。
クレイグリンガー

回答:


17

認証承認を統合していると思います。

特にLedgerSMBは複数のクライアントからのアクセスを考慮して設計されているため、DBにセキュリティモデルを保持することは賢明であることに完全に同意します。ミドルウェアレイヤーを使用して3層に移行する予定がない限り、特にアカウンティングアプリのような場合、ユーザーをデータベースロールとして使用することは完全に理にかなっています。

これは、PostgreSQLがサポートする認証方法を使用して、データベースに対してユーザーを認証する必要があるという意味ではありませ。データベースのユーザー、ロール、および許可は、必要な場合にのみ許可に使用できます。

たとえば、Web UIの場合の動作は次のとおりです。

  • janeWeb UIサーバーに接続し、HTTPS X.509クライアント証明書ハンドシェイクやDIGEST認証など、希望する方法を使用して認証します。サーバーには、実際に受け入れられるユーザーからの接続がありますjane

  • サーバーは、固定のユーザー名/パスワード(またはKerberosなど)を使用してPostgreSQLに接続し、ユーザーとしてdbサーバーに対して自己を認証しますwebui。dbサーバーはwebui、ユーザーの認証を信頼しwebuiているため、適切なGRANTs が与えられています(以下を参照)。

  • その接続では、サーバーはSET ROLE jane;ユーザーの承認レベルを想定するために使用しますjane。までRESET ROLE;または別のSET ROLEが実行さ、接続はjaneand SELECT current_user()が報告するのと同じアクセス権で動作していますjane

  • サーバーは、それが持つ、データベース接続との間の関連性を維持SET ROLEjane、ユーザーのためのWebセッションをjane PostgreSQLの接続が新しいことなく、他のユーザーとの他の接続が使用することを許可しない、SET ROLEその間の。

あなたは今 認証サーバーの外に、しかし維持の権限をサーバーに。Pgは、ユーザーの存在を知る必要がありますが、ユーザーのパスワードや認証方法は必要ありません。

見る:

詳細

WebUIのサーバーコントロールのクエリを実行し、できるようにするつもりはないjaneので、実行して生のSQL(Iの希望を!)janeすることはできませんRESET ROLE; SET ROLE special_admin_user;。追加の安全のために私は拒否したサーバーへの声明フィルターを追加したいSET ROLERESET ROLE接続しない限り、または割り当てられていない接続のプールに入りました。

他のクライアントでPgへの直接認証を自由に使用できます。自由に組み合わせることができます。ユーザーは、Web経由でログインできるユーザーに対する権利を持ってGRANTいるwebui必要SET ROLEがあります。そして、それらのユーザーに必要な通常のCONNECT権利、パスワードなどを与えます。あなたがそれらのWeb専用にしたい場合は、REVOKEそのCONNECTデータベース上の権利(とからpublic)。

このような認証/認可の分割を簡単にするために、新しく作成したすべてのユーザーに特別な役割assume_any_userGRANT割り当てています。次にGRANT assume_any_user、信頼できるWebフロントエンドなどで使用される実際のユーザー名にアクセスして、好きなユーザーになる権利を与えます。

ロールを作成することassume_any_userは重要ですNOINHERIT。そのため、webuiユーザーまたはユーザー自身が特権を持たずSET ROLE、実際のユーザーに対してのみデータベースに作用することができます。いかなる状況でwebuiも、スーパーユーザーまたはDB所有者であってはなりません

接続プーリングの場合、を使用SET LOCAL ROLEしてトランザクション内でのみロールを設定できるため、COMMITまたはの後に接続をプールに戻すことができますROLLBACKRESET ROLEそれでも動作することに注意してください。そのため、クライアントが必要なSQLを実行できるようにすることは安全ではありません。

SET SESSION AUTHORIZATIONこのコマンドの関連する強力なバージョンです。ロールのメンバーシップは必要ありませんが、スーパーユーザー専用のコマンドです。Web UIをスーパーユーザーとして接続することは望ましくありません。RESET SESSION AUTHORIZATIONSET SESSION AUTHORIZATION DEFAULTまたはSET SESSION AUTHORIZATION theusernameスーパーユーザーの権利を取り戻すために、逆にすることができます。これにより、特権を落とすセキュリティ障壁にもなりません。

SET SESSION AUTHORIZATIONスーパーユーザーではなくロールメンバーであれば機能しますが、元に戻せないコマンドは機能します。この時点では1つではありませんが、注意すれば認証と承認をかなりうまく分離できます。

例と説明

CREATE ROLE dbowner NOLOGIN;
CREATE TABLE test_table(x text);
INSERT INTO test_table(x) VALUES ('bork');
ALTER TABLE test_table OWNER TO dbowner;

CREATE ROLE assume_any_user NOINHERIT NOLOGIN;
CREATE ROLE webui LOGIN PASSWORD 'somepw' IN ROLE assume_any_user;

CREATE ROLE jane LOGIN PASSWORD 'somepw';
GRANT jane TO assume_any_user;
GRANT ALL ON TABLE test_table TO jane;

CREATE ROLE jim LOGIN PASSWORD 'somepw';
GRANT jim TO assume_any_user;

次にとして接続しwebuiます。あなたが何もしないことに注意してくださいtest_tableしかし、あなたができる SET ROLEためにjane、その後あなたがアクセスすることができますtest_table

$ psql -h 127.0.0.1 -U webui regress
Password for user webui:

regress=> SELECT session_user, current_user;
 session_user | current_user 
--------------+--------------
 webui        | webui
(1 row)



regress=> SELECT * FROM test_table;
ERROR:  permission denied for relation test_table

regress=> SET ROLE jane;
SET

regress=> SELECT session_user, current_user;
 session_user | current_user 
--------------+--------------
 webui        | jane
(1 row)

regress=> SELECT * FROM test_table;
  x   
------
 bork
(1 row)

webui できること SET ROLEに注意してください、jimすでにSET ROLEdになっjaneていjaneてもGRANT、役割を引き受ける権利が与えられていませんでしたjimSET ROLE有効なユーザーIDを設定しますがSET ROLE、他のロールへの機能は削除されません。これは、現在の有効なロールではなく、接続したロールのプロパティです。したがって、SET ROLEおよびRESET ROLEコマンドへのアクセスを慎重に制御する必要があります。AFAIK、SET ROLE接続を永続的にする方法はなく、本当にターゲットユーザーになることはできますが、それは確かに良いことです。

比較:

$ psql -h 127.0.0.1 -U webui regress
Password for user webui:

regress=> SET ROLE jane;
SET

regress=> SET ROLE jim;
SET
regress=> SELECT session_user, current_user;
 session_user | current_user 
--------------+--------------
 webui        | jim
(1 row)

に:

$ psql -h 127.0.0.1 -U jane regress
Password for user jane:

regress=> SET ROLE webui;
ERROR:  permission denied to set role "webui"
regress=> SET ROLE jim;
ERROR:  permission denied to set role "jim"

これはSET ROLE、特定の役割としてログインすることとまったく同じではないことを意味します。注意する必要があります。

webuiそのように編集されていないSET ROLEためdbowner、できませんGRANT

regress=> SET ROLE dbowner;
ERROR:  permission denied to set role "dbowner"

したがって、それ自体はかなり無力です。他のユーザーの権限を引き受けることができるのは、それらのユーザーがWebアクセスを有効にしている場合のみです。


1
ちなみにpgbouncer、詳細については、どのように機能するかを調べてください。
クレイグリンガー

2
ああ、DISCARD ALL権利をデフォルトに戻す別の方法です。私は本当にPgが持っていたSET ROLE NORESETか、または同様のものを望んでいた…
クレイグリンガー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.