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 통합 여부 확인 |
pgaudit은 감사 로그를 만들 뿐 — 보안 위반을 막지는 않습니다. 침입 탐지·예방은 별도 — pg_hba.conf, RLS, GRANT, TLS와 같이 운영해야 의미.
자동화 — 감사 대상 변경 감지
-- 감사 대상 객체 목록
SELECT table_schema, table_name
FROM information_schema.table_privileges
WHERE grantee = 'audit_role';월 단위 점검 — 새로 만들어진 민감 테이블이 audit_role에 GRANT됐는지 확인합니다.
정리
- pgaudit = 구조화된 감사 로그. PostgreSQL 기본 로그의 한계 보완
- 두 모드: session(카테고리 기반) + object(역할 기반)
- 운영 출발:
write, ddl, role— READ는 신중히 log_parameter는 보안 vs 디버깅 트레이드오프- 로그 라우팅·디스크 분리·보존 정책 동반 필요
- 감사 로그는 기록일 뿐, 예방은 RLS·GRANT·TLS와 함께
다음 절(9.7)에서는 외부 ID 제공자 통합 — LDAP, Kerberos, PAM, OAuth를 봅니다.