보안#
AgensGraph의 보안 모델은 PostgreSQL의 것입니다. 롤·pg_hba.conf·TLS·GRANT·행 수준 보안이
모두 거기서와 똑같이 동작하며,
PostgreSQL의 클라이언트 인증 장과
데이터베이스 롤 장이 레퍼런스입니다.
이 페이지가 더하는 것은 그 장치들이 그래프에 어떻게 내려앉는가입니다. 그래프는 스키마이고 레이블은 테이블이므로, Cypher 쿼리에 필요한 권한이 짐작한 것과 늘 같지는 않습니다.
인증#
데이터 디렉터리의 pg_hba.conf가 누가 어디서 어느 데이터베이스에 어떻게 접속할 수 있는지
정합니다. 규칙은 위에서 아래로 대조하며 먼저 맞는 것이 이깁니다.
# TYPE DATABASE USER ADDRESS METHOD
local all all peer
host mydb appuser 10.0.0.0/24 scram-sha-256
hostssl mydb analyst 0.0.0.0/0 scram-sha-256
host all all 0.0.0.0/0 reject
고친 뒤에는 reload 하십시오:
ag_ctl -D $AGDATA reload
서버가 외부에서 닿을 수 있게 되기 전에 바로잡아야 할 것 셋입니다:
기본 trust 규칙을 바꾸십시오. initdb는 로컬 접속에 trust를 써 두는데, 이는 셸 계정이
있는 사람이면 누구나 슈퍼유저를 포함해 어떤 롤로도 접속할 수 있다는 뜻입니다. 로컬 유닉스 소켓
접속에는 peer를, 네트워크를 지나는 것에는 scram-sha-256을 쓰십시오.
md5가 아니라 scram-sha-256을 쓰십시오. 비밀번호를 만들거나 바꾸기 전에
password_encryption = scram-sha-256을 설정해, 저장되는 검증자가 강한 쪽이 되게 하십시오.
네트워크 접속에는 TLS를 요구하십시오. 규칙에는 hostssl을, postgresql.conf에는
ssl = on과 인증서·키를 둡니다. 가로채기를 실제로 막는 것은 클라이언트의
sslmode=verify-full입니다. require는 암호화만 합니다.
쓸 수 있는 방식은 PostgreSQL의 전체 목록 — peer·scram-sha-256·cert·ldap·gss·
sspi·pam·radius·ident·trust·reject — 이며 옵션도 같습니다.
PostgreSQL의 인증 방식 장을
참고하십시오.
접속이 거부되면 서버 로그가 이유를 말해 주며, 그 메시지는 클라이언트가 받는 것보다 구체적입니다. 규칙을 고치기 전에 그것을 확인하십시오.
롤#
롤은 클러스터 전체의 것입니다. 데이터베이스가 아니라 서버에 속합니다. LOGIN을 가진 롤이 다른
시스템에서 말하는 사용자입니다.
CREATE ROLE appuser LOGIN PASSWORD 'secret';
CREATE ROLE readonly; -- a group, no LOGIN
GRANT readonly TO appuser;
운영상 중요한 속성은 SUPERUSER·CREATEDB·CREATEROLE·REPLICATION·BYPASSRLS입니다.
애플리케이션 롤에는 그중 무엇도 주지 마십시오. ALTER ROLE … SET은 롤에 설정을 고정하는데,
graph_path를 강제하거나 정비용 롤 말고는 enable_graph_dml을 꺼 두는 깔끔한 방법입니다:
ALTER ROLE appuser SET graph_path = moviekb;
ALTER ROLE appuser SET enable_graph_dml = off;
그래프에 대한 권한#
그래프는 스키마이고 각 레이블은 테이블이므로 권한도 평범한 것들입니다. 놀랄 일은 다른 데서 옵니다. Cypher 쿼리는 자기가 이름을 댄 레이블보다 많은 객체에 손을 댑니다.
읽기#
읽기에는 그래프 스키마에 대한 USAGE와, 손대는 각 레이블에 대한 SELECT가 필요합니다. 어느
지점에서 어떤 권한이 필요해지는지 다음 순서로 확인하십시오. 스키마만 준 상태에서 시작합니다:
CREATE ROLE analyst;
GRANT USAGE ON SCHEMA moviekb TO analyst;
SET ROLE analyst;
이제 Cypher 읽기가 레이블 이름과 함께 테이블 권한 오류로 실패합니다:
MATCH (m:movie) RETURN count(m);
ERROR: permission denied for table movie
레이블에 권한을 주면 동작합니다:
RESET ROLE;
GRANT SELECT ON moviekb.movie TO analyst;
SET ROLE analyst;
MATCH (m:movie) RETURN count(m);
count
-------
18
레이블 없는 패턴에는 ag_vertex도 필요합니다. MATCH (n)은 그래프의 부모인 ag_vertex와
그 아래의 모든 레이블을 스캔하므로, movie는 읽을 수 있지만 ag_vertex는 읽지 못하는 롤은 이것을
실행하지 못합니다:
MATCH (n) RETURN count(n);
ERROR: permission denied for table ag_vertex
레이블 없는 간선에 대해서도 ag_edge에 같은 것이 적용됩니다. 그러므로 읽기 전용 분석가 롤에는
레이블을 하나씩 주기보다 스키마 전체에 주십시오:
RESET ROLE;
GRANT SELECT ON ALL TABLES IN SCHEMA moviekb TO analyst;
ALTER DEFAULT PRIVILEGES IN SCHEMA moviekb GRANT SELECT ON TABLES TO analyst;
다음 달에 만들어질 레이블까지 읽히게 하는 것이 ALTER DEFAULT PRIVILEGES 줄입니다.
쓰기#
정점이나 간선을 만들려면 레이블에 대한 INSERT와 **그 레이블 id 시퀀스에 대한 USAGE**가
필요합니다. 두 번째 것을 빠뜨리기 쉽습니다. INSERT만 준 경우입니다:
RESET ROLE;
GRANT INSERT ON moviekb.movie TO analyst;
SET ROLE analyst;
CREATE (:movie {title: 'X'});
ERROR: permission denied for sequence movie_id_seq
시퀀스를 더하면 쓰기가 통과합니다:
RESET ROLE;
GRANT USAGE ON SEQUENCE moviekb.movie_id_seq TO analyst;
SET과 REMOVE에는 레이블에 대한 UPDATE가 필요합니다. DELETE에는 DELETE가 필요합니다.
그리고 DETACH DELETE에는 ag_edge에 대한 권한이 필요합니다. 지울 간선을 그것으로 찾기
때문입니다:
ERROR: permission denied for table ag_edge
ag_edge나 ag_vertex를 가리키는 오류는 행 보안의 결과가 아니라 그래프의 부모 레이블에 대한
권한이 없다는 뜻입니다. 앞의 것으로 읽기 쉬우므로 알아 둘 만합니다.
그래프 전체를 읽고 쓰는 롤에 쓸 만한 권한 묶음입니다:
GRANT USAGE ON SCHEMA moviekb TO appuser;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA moviekb TO appuser;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA moviekb TO appuser;
ALTER DEFAULT PRIVILEGES IN SCHEMA moviekb
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO appuser;
ALTER DEFAULT PRIVILEGES IN SCHEMA moviekb GRANT USAGE ON SEQUENCES TO appuser;
레이블 만들기#
레이블을 만들려면 그래프 스키마에 대한 CREATE가 필요합니다. 그래프를 만들려면 데이터베이스에
대한 CREATE가 필요합니다.
행 수준 보안#
행 수준 보안은 레이블에서 동작하므로, 정책으로 어떤 롤이 어떤 정점이나 간선을 보고 쓰는지 제한할 수 있습니다:
ALTER TABLE moviekb.movie ENABLE ROW LEVEL SECURITY;
CREATE POLICY movie_visible ON moviekb.movie
FOR SELECT TO analyst
USING ((properties->>'genre') = 'Sci-Fi');
경고
2.17에서 쓰던 RLS 정책은 다시 시험하십시오. 2.18 이전에는 그래프 쓰기에 정책이 제대로
적용되지 않았습니다. UPDATE나 DELETE 정책의 USING 절이 결코 스캔되지 않는 릴레이션에 붙어
있어 아무것도 거르지 못했고, DELETE 정책이 아예 없는 롤이 행을 지울 수 있었습니다. INSERT
정책은 엉뚱한 행을 대상으로 검사됐고, 간선 생성은 아예 검사되지 않아 행 보안이 걸린 간선 레이블이
모든 삽입을 받아들였습니다.
2.18은 그 전부를 적용합니다. 그것이 올바른 동작이며, 지금 애플리케이션이 하고 있는 쓰기가 거부되기 시작할 수 있다는 뜻입니다. 업그레이드한 뒤가 아니라 전에 시험하십시오. 릴리스 노트를 참고하십시오.
실무에서 알아 둘 것 둘입니다:
정책 표현식은 레이블의 컬럼을 읽으므로
properties에서 동작하고, 승격된 컬럼에서도 동작합니다. 뒤쪽이 더 빠르고 정책이 인덱스를 쓸 수 있게 합니다.BYPASSRLS와 테이블 소유권은 둘 다 정책을 건너뜁니다. 애플리케이션 롤은 둘 다 가져서는 안 됩니다.
보안 태세의 일부인 설정 둘#
enable_graph_dml과 enable_graph_ddl은 기본으로 꺼져 있으며, Cypher가 아니라 SQL로 레이블에
쓰는 것과 레이블의 모양을 바꾸는 것을 막습니다. 꺼 두면 애플리케이션이 Cypher 경로에 머무르고,
그래프 자신의 검사 — 이를테면 간선의 양 끝점이 있는지 — 가 그대로 돕니다.
다만 이 설정이 그래프 정합성의 전부는 아니며, 그렇게 읽어서는 안 됩니다. COPY는 두 설정을
보지 않고 레이블에 씁니다. 설정과 무관하게 모든 경로에서 지켜지는 것은 행의 id가 그 행을 담은
레이블을 가리킨다는 것입니다. 이를 깨뜨리는 쓰기는 Cypher든 INSERT든 UPDATE든 COPY든
복제 반영이든 거부됩니다.
정비 작업 때 켰다가 다시 끄거나, ALTER ROLE … SET으로 롤마다 꺼 두십시오.
cypher_allow_unsafe_ddl도 마찬가지입니다. 서버 설정을 참고하십시오.
저장 데이터 암호화#
AgensGraph는 데이터 파일 자체를 암호화하지 않습니다. 파일시스템이나 블록 장치 암호화를 쓰거나,
투명 데이터 암호화가 요구되는 곳에는
Agens TDE를 쓰십시오. 컬럼 수준 암호화는
pgcrypto가 다루며, 속성은 평범한 jsonb 값이므로 다른 컬럼과 마찬가지로 pgcrypto 암호문을
담을 수 있습니다.