PostgreSQL의 금융 앱에 대한 인증 방법 선택


15

먼저 몇 가지 배경.

LedgerSMB 프로젝트는 PostgreSQL에서 실행되는 오픈 소스 재무 회계 소프트웨어 프로젝트입니다. 우리는 프로그램 오브젝트 메소드와 데이터베이스 동작 사이의 주요 맵핑 도구로 작동하는 사용자 정의 함수에 매우 많은 양의 비즈니스 로직을 구현합니다. 현재 데이터베이스 사용자를 선택적으로 선택적으로 (중앙 집중식 보안 논리를 허용하므로 다른 도구를 작성하여 사용자에게 부여한 권한을 재사용 할 수 있도록), 필요에 따라 (SQL-Ledger에서 분기 한 후) 해당 코드베이스에 보안을 개선하기위한 옵션이 많지 않았습니다).

이를 통해 LDAP에서 Kerberos 5까지 PostgreSQL이 액세스 할 수있는 합리적인 수의 싱글 사인온 옵션에 액세스 할 수 있습니다. 암호가 관련된 경우 PAM을 사용할 수도 있습니다. 또한 다른 응용 프로그램과 통합하거나 다른 클라이언트 인터페이스를 허용 할 때 권한을 재사용 할 수 있습니다. 재무 회계 응용 프로그램의 경우 이것은 순 승리로 보입니다.

명백한 비용이 있습니다. 웹 애플리케이션의 경우 지원할 수있는 http 인증 유형으로 제한됩니다. 예를 들어 가장 좁습니다. BASIC은 잘 작동하며 KRB5를 충분히 쉽게 구현할 수있었습니다 (1.4를 지원하고 즉시 사용할 계획입니다). 필요한 경우 매우 강력한 인증 조치를 직접 관리 할 수는 없지만 (예 : 사용자 이름과 특정 루트 ca가 일치하는 cn을 가진 BASIC + 클라이언트 측 SSL 인증서).

동시에 우리는 대부분 개발 군중과 때로는 데이터베이스가 아니라 보안 장벽이되어야한다고 말하는 dba의 사람들로부터 상당한 비판을 받았습니다. 필자는 여전히 보안 경계가 작을수록 일반적으로 더 좋고 비즈니스 로직과 보안 로직을 재사용하면 동일한 수준에서 보안 로직을 재사용하지 않고 비즈니스 로직을 재사용하는 것이 위험하다고 생각합니다. 프로그램의.

여기서 주요한 절충점을 놓치고 있습니까? 내가 고려하지 않은 문제가 있습니까?


1
pgsql-general 메일 링리스트에 크로스 포스트되었습니다. 여기에서 시작하는 스레드를 참조 하십시오 .
Craig Ringer

답변:


17

나는 당신이 인증권한 부여를 생각하고 있다고 생각합니다 .

LedgerSMB가 여러 클라이언트의 액세스를 염두에두고 설계되었으므로 DB에 보안 모델을 유지하는 것이 현명하다는 데 전적으로 동의합니다. 당신이 미들웨어 층과 3 층을 갈 계획이 아니라면 그것은 만드는 완벽한 특히 회계 응용 프로그램 같은 것을 위해, 데이터베이스 역할로 사용자를하는 것이.

그렇다고 PostgreSQL 지원 인증 방법을 사용하여 데이터베이스에 대해 사용자를 인증 할 필요 는 없습니다 . 데이터베이스 사용자, 역할 및 권한 부여는 원하는 경우에만 권한 부여에 사용될 수 있습니다 .

예를 들어 웹 UI에서 작동하는 방법은 다음과 같습니다.

  • jane웹 UI 서버에 연결하고 원하는 방법을 사용하여 인증합니다 (예 : HTTPS X.509 클라이언트 인증서 핸드 셰이크 및 DIGEST 인증). 서버는 이제 사용자로부터 실제로 연결되어 jane있습니다.

  • 서버는 고정 사용자 이름 / 암호 (또는 Kerberos 또는 원하는 것을 사용)를 사용하여 PostgreSQL에 연결하여 사용자로서 자신을 db 서버에 인증합니다 webui. db 서버 webui는 사용자 인증을 신뢰 하므로 webui적절한 권한을 부여받습니다 GRANT(아래 참조).

  • 해당 연결에서 서버는 SET ROLE jane;사용자의 권한 수준을 가정하는 데 사용 합니다 jane. 까지 RESET ROLE;또는 또 다른 SET ROLE실행, 연결은 동일한 액세스 권한으로 작동 jane하고 SELECT current_user()등보고합니다 jane.

  • 서버가 가지고있는 데이터베이스 연결 사이의 관계 유지 SET ROLEjane사용자의 웹 세션 jane, PostgreSQL의 연결이 새없이 다른 사용자와 다른 연결에서 사용하는 것을 허용하지 SET ROLEinbetween을.

이제하는 인증 서버 외부하지만 유지 권한을 서버에. Pg는 어떤 사용자가 있는지 알아야하지만 비밀번호 나 인증 방법은 필요하지 않습니다.

보다:

세부

webui 서버는 쿼리 실행을 제어하며 jane원시 SQL을 실행 하지 못하게 하므로 웹 UI를 통해 수행 jane할 수 없습니다 RESET ROLE; SET ROLE special_admin_user;. 추가 안전을 위해 나는 거부 서버에 문 필터를 추가 할 것 SET ROLERESET ROLE연결하지 않는 한 또는 할당되지 않은 연결 풀을 입력했다.

다른 클라이언트에서는 Pg에 대한 직접 인증을 계속 사용할 수 있습니다. 자유롭게 믹스 앤 매치 할 수 있습니다. 당신은 단지에있는 에 대한 사용자 권한을 웹을 통해 로그인 한 다음 해당 사용자에게 어떤 정상적인 제공 할 수 있습니다 사용자가 원하는 권한, 암호, 등. 웹 전용으로 만들려면 데이터베이스에 대한 권한 (및에서 )을 사용하십시오.GRANTwebuiSET ROLECONNECTREVOKECONNECTpublic

이러한 인증 / 권한 분할을 쉽게하기 위해 새로 만든 모든 사용자에게 특별한 역할 assume_any_userGRANT있습니다. 그런 다음 GRANT assume_any_user신뢰할 수있는 웹 프런트 엔드와 같은 항목에서 사용하는 실제 사용자 이름으로 자신이 좋아하는 사용자가 될 수있는 권한을 부여합니다.

역할을 수행 assume_any_user하는 것이 중요 NOINHERIT하므로 webui사용자 나 그 자체로는 권한이 없으며 SET ROLE실제 사용자 에게만 데이터베이스에 대해 작업 할 수 있습니다 . 어떠한 상황에서도 webui수퍼 유저 또는 DB 소유자 가되어서는 안됩니다 .

연결 풀링 인 SET LOCAL ROLE경우 트랜잭션 내에서만 역할을 설정하여 COMMIT또는 이후에 풀에 연결을 반환 할 수 있습니다 ROLLBACK. RESET ROLE여전히 작동 한다는 점에 유의하십시오 . 따라서 클라이언트가 원하는 SQL을 실행하도록하는 것은 여전히 ​​안전하지 않습니다.

SET SESSION AUTHORIZATION이 명령의 관련이지만 더 강력한 버전입니다. 역할 멤버 자격이 필요하지 않지만 수퍼 유저 전용 명령입니다. 웹 UI가 수퍼 유저로 연결되는 것을 원하지 않습니다. 그것은으로 반전 될 수있다 RESET SESSION AUTHORIZATION, SET SESSION AUTHORIZATION DEFAULT또는 SET SESSION AUTHORIZATION theusername이 두 특권-떨어 보안 장벽되지 않도록 수퍼 유저 권한을 회복 할 수 있습니다.

SET SESSION AUTHORIZATION역할은 수행했지만 수퍼 유저는 아닌 것처럼 작동했지만 되돌릴 수없는 명령은 훌륭했습니다. 이 시점에서 하나는 없지만주의를 기울이면 인증과 권한을 분리 할 수 ​​있습니다.

예와 설명

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 ROLEjane다음 사용자가 액세스 할 수 있습니다 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 ROLEjim이미 경우에도, SET ROLEd 내지 jane에도 불구하고 jane되지 않은 GRANT역할을 가정하는 권리를 에드 jim. SET ROLE효과적인 사용자 ID를 설정하지만 SET ROLE현재 역할이 아닌 연결된 역할의 속성 인 다른 역할에 대한 기능을 제거하지는 않습니다 . 결과적으로 SET ROLERESET 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주어진 역할로 로그인하는 것과 정확히 동일하지 않다는 것을 의미합니다 .

webuiSET ROLEdbowner그것이되지 않았기 때문에 GRANT그 권리 에드 :

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

따라서 자체적으로는 힘이 거의 없으므로 다른 사용자의 권한을 가질 수 있으며 해당 사용자가 웹 액세스를 활성화 한 경우에만 가능합니다.


1
btw 당신은 pgbouncer몇 가지 세부 사항 에 대한 작동 방식 을보고 싶을 수도 있습니다 .
Craig Ringer

2
아, DISCARD ALL권리를 불이행으로 되 돌리는 또 다른 방법입니다. 나는 정말로 Pg가 SET ROLE NORESET비슷 했으면 좋겠다 ...
Craig Ringer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.