9.6 감사 (pgaudit)
pgaudit은 PostgreSQL의 표준 감사 로그 확장입니다. PostgreSQL 기본 로그(log_statement)는 쿼리 텍스트만 남기지만, 컴플라이언스 감사에는 누가, 언제, 어떤 객체에, 어떤 작업을 했는지의 구조화된 정보가 필요합니다. pgaudit가 이를 채웁니다.
기본 log_statement와의 차이
| 항목 | log_statement | pgaudit |
|---|---|---|
| 로깅 단위 | 쿼리 텍스트 전체 | 객체별 구조화 |
| 카테고리 분류 | 없음 | READ, WRITE, FUNCTION, ROLE, DDL, MISC |
| 객체별 필터 | 없음 | 가능 |
| 트랜잭션 ID·세션 정보 | log_line_prefix 필요 | 항상 포함 |
| SQL 텍스트 정규화 | 없음 | parameterized 가능 |
설치
PGDG 패키지에 포함되어 있습니다.
sudo dnf install -y pgaudit_17 # RHEL/Rocky
sudo apt-get install -y postgresql-17-pgaudit # Debian/Ubuntupostgresql.conf:
shared_preload_libraries = 'pgaudit' # 다른 라이브러리와 콤마로restart 후 데이터베이스 단위 활성:
CREATE EXTENSION pgaudit;두 가지 모드
| 모드 | 동작 |
|---|---|
| session | 세션 단위 — pgaudit.log 파라미터로 카테고리 지정 |
| object | 객체 단위 — pgaudit.role 역할에 GRANT된 객체만 |
session audit
ALTER SYSTEM SET pgaudit.log = 'write, ddl, role';
SELECT pg_reload_conf();| 카테고리 | 포함 |
|---|---|
READ | SELECT, COPY FROM |
WRITE | INSERT, UPDATE, DELETE, COPY TO |
FUNCTION | 함수 호출 |
ROLE | GRANT, REVOKE, CREATE ROLE 등 |
DDL | CREATE/DROP/ALTER |
MISC | DISCARD, FETCH, CHECKPOINT |
ALL | 위 전부 |
-READ | READ 제외 |
운영 권장 출발: write, ddl, role — 변경 작업만 기록. READ까지 켜면 로그가 폭증합니다.
object audit
특정 역할에게 GRANT된 객체에만 감사 로그 생성합니다.
-- 감사 역할
CREATE ROLE audit_role NOLOGIN;
ALTER SYSTEM SET pgaudit.role = 'audit_role';
SELECT pg_reload_conf();
-- 감사 대상 객체 — audit_role에 GRANT
GRANT SELECT, INSERT, UPDATE, DELETE ON sensitive_data TO audit_role;이제 sensitive_data 테이블의 모든 변경이 자동으로 로깅됩니다. 민감 테이블만 골라 감사할 수 있습니다.
로그 형식
2026-05-23 10:00:00.000 KST [12345] alice@app_main LOG: AUDIT: SESSION,1,1,WRITE,UPDATE,TABLE,public.users,UPDATE users SET email = $1 WHERE id = $2,"<not logged>"| 컬럼 | 의미 |
|---|---|
AUDIT: SESSION 또는 OBJECT | 모드 |
1,1 | session id, statement id |
WRITE | 카테고리 |
UPDATE | 명령 |
TABLE | 객체 종류 |
public.users | 객체 |
UPDATE users ... | SQL (parameterized) |
"<not logged>" | 파라미터 — pgaudit.log_parameter로 켤 수 있음 |
자주 쓰는 설정
# postgresql.conf
shared_preload_libraries = 'pgaudit'
pgaudit.log = 'write, ddl, role'
pgaudit.log_catalog = off # pg_catalog 자동 쿼리 제외
pgaudit.log_client = on # 클라이언트 IP 포함
pgaudit.log_level = log # log/info/notice/warning
pgaudit.log_parameter = off # 파라미터 노출 (개인정보 위험 시 off)
pgaudit.log_relation = on # 객체 정보 명시
pgaudit.log_statement_once = on # 같은 statement 중복 로그 방지log_parameter = on은 SQL injection 진단·재현에 유용하지만 비밀번호·개인정보가 로그에 평문으로 흐를 수 있어 신중히 진행합니다.
로그 라우팅
pgaudit은 PostgreSQL의 일반 로그와 같은 곳으로 출력됩니다(postgresql-*.log). 별도 파일이 필요하면 log_destination을 분리하거나 외부 수집기(Fluent Bit, Loki, Datadog)로 라우팅합니다.
log_destination = 'stderr, csvlog'
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d.log'CSV 로그는 구조화라 분석 도구가 더 잘 다룹니다.
운영 시 주의
| 주의 | 메모 |
|---|---|
| READ까지 켜면 로그 폭증 | TPS 큰 시스템에서 1TB/일 가능 |
log_parameter = on은 개인정보 노출 | 컴플라이언스에서 마스킹 필요 |
| 로그 디스크 분리 권장 | 데이터 디스크와 같으면 IO 경합 |
| 외부 수집 권장 | 로컬 로그는 회전·압축·보존 정책 |
| 감사 로그 자체에 대한 권한 | 일반 사용자 읽기 불가 |
컴플라이언스와의 매핑
| 표준 | pgaudit 활용 |
|---|---|
| PCI-DSS | 카드 데이터 테이블 object audit |
| HIPAA | 의료 데이터 SELECT/WRITE 모두 audit |
| GDPR | 개인정보 컬럼이 든 테이블 object audit |
| 한국 개인정보보호법 | 접속·접근 로그 1년 보존 |
대안과 짝
| 도구 | 보완하는 것 |
|---|---|
기본 log_statement | 가벼운 디버깅 — pgaudit 없이도 사용 가능 |
auto_explain | 슬로우 쿼리의 EXPLAIN 자동 |
| 외부 SIEM (Splunk, ELK) | pgaudit 로그를 수집·분석 |
| 클라우드 매니지드 audit | RDS/NCP/Azure는 자체 감사 기능 — pgaudit 통합 여부 확인 |
자동화 — 감사 대상 변경 감지
-- 감사 대상 객체 목록
SELECT table_schema, table_name
FROM information_schema.table_privileges
WHERE grantee = 'audit_role';월 단위 점검 — 새로 만들어진 민감 테이블이 audit_role에 GRANT됐는지 확인합니다.
정리
pgaudit은 PostgreSQL 기본 로그의 한계를 메우는 구조화된 감사 로그입니다. 카테고리로 거르는 session 모드와 역할에 GRANT된 객체만 잡는 object 모드가 있고, 운영은 보통 write, ddl, role로 시작해 READ는 신중히 켭니다. 감사 로그는 사건을 기록할 뿐 위반을 막지는 못하므로, 예방은 RLS·GRANT·TLS와 함께 굴려야 합니다.
log_parameter는 보안과 디버깅 사이의 트레이드오프- 로그 라우팅·디스크 분리·보존 정책을 함께 설계