🚧 Under construction — VoTechWorks is being built. A free tech program — complimentary, as our commitment to get America working.
voTechWorksGrade 13 · a vocational technology learning center, by urbanicity
newSchoolWorks.com › VoTechWorks › Technology & Design › Data Management / Database Administration › Database Security & Role Management › Lesson 6
TEC-DATA86-05 · Lesson 6 · 12 clock hours · lab

Auditing: pg_audit, Log Analysis & Incident Reporting

Objective. Learners enable session and object auditing using the pgaudit extension, reproduce a simulated unauthorized access attempt, query audit logs, and write a structured incident summary report.

⚠ Pending professional review

This lesson, its worked examples and its practice questions has not yet been verified by an industry-certified professional or by a certification or approval body. It is a study draft and may contain errors. Do not use it as instructions for work on a job site or on live equipment. Always follow your instructor, your supervising professional, and current official references and regulations.

VoTechWorks program approval and accreditation are still in progress. Credentials are issued only by the certifying bodies named in each program, after their own exams.

Why Database Auditing Matters

A database audit trail is a chronological record of who did what to which data, and when. Without it, a security incident cannot be properly investigated, and compliance with frameworks such as HIPAA, PCI-DSS, and SOX cannot be demonstrated. PostgreSQL does not capture fine-grained object-level events by default, so the pgaudit extension was created to fill that gap. Enabling pgaudit is one of the first hardening steps a DBA should take on any production instance that holds sensitive data.

How pgaudit Works

pgaudit hooks into PostgreSQL's standard logging infrastructure. It adds two layers of auditing:

Configuration happens in `postgresql.conf` (or `ALTER SYSTEM`) using the `pgaudit.log` parameter. Common category values include `READ`, `WRITE`, `DDL`, `ROLE`, `FUNCTION`, and `MISC`. You may combine them as a comma-separated string, for example:

```

shared_preload_libraries = 'pgaudit'

pgaudit.log = 'role, ddl, write'

```

After changing `shared_preload_libraries` you must restart the PostgreSQL service. Changes to `pgaudit.log` alone can be reloaded with `SELECT pg_reload_conf();`.

Audit records appear in the standard PostgreSQL log file alongside other server messages. Each audit line is prefixed with `AUDIT:` and includes the session ID, audit type (SESSION or OBJECT), statement class, command tag, and the SQL text. This means your log management pipeline (rotation, shipping to a SIEM) automatically captures audit events without a separate storage mechanism.

Installing and Enabling pgaudit

On most Linux distributions, pgaudit is available through the PostgreSQL PGDG package repository. Install the package that matches your PostgreSQL major version (e.g., `pgaudit16` for PostgreSQL 16), then add it to `shared_preload_libraries` and restart. Verify the extension is active by running:

```sql

CREATE EXTENSION IF NOT EXISTS pgaudit;

SELECT extname, extversion FROM pg_extension WHERE extname = 'pgaudit';

```

For object auditing, create a dedicated role with no login privilege and grant it SELECT or other privileges on the objects you want monitored. Then set `pgaudit.role = 'your_audit_role'` in the server configuration.

Reading and Querying Audit Logs

PostgreSQL writes logs as text files by default. Location is controlled by `log_directory` and `log_filename` in `postgresql.conf`. When `log_destination` includes `csvlog`, each line is parseable with standard tools. You can also load CSV logs into a table using `COPY` for SQL-based analysis:

```sql

CREATE TABLE pg_log_import (

log_time timestamptz, user_name text, database_name text,

process_id int, connection_from text, session_id text,

session_line_num bigint, command_tag text, session_start_time timestamptz,

virtual_transaction_id text, transaction_id bigint, error_severity text,

sql_state_code text, message text, detail text, hint text,

internal_query text, internal_query_pos int, context text,

query text, query_pos int, location text, application_name text

);

COPY pg_log_import FROM '/var/log/postgresql/postgresql.csv' CSV;

```

Once imported, filter for audit records:

```sql

SELECT log_time, user_name, message

FROM pg_log_import

WHERE message LIKE 'AUDIT:%'

ORDER BY log_time;

```

Recognizing Attack Patterns with STRIDE

When analyzing a log file for a security incident, organize your findings using the STRIDE threat model:

Classify each suspicious event by STRIDE category, then assign a severity (Critical, High, Medium, Low) based on the sensitivity of the affected object and the likelihood of harm.

Writing a Structured Incident Report

An incident report converts raw log evidence into a document that managers, auditors, and legal counsel can act on. A minimal one-page report includes:

1. Date and time of the detected event (use the database server's timezone and note it).

2. Affected objects – schema, table, or function names.

3. Account involved – database role and, if known, the OS or application account behind it.

4. Evidence from the log – paste exact log lines; do not paraphrase.

5. Recommended remediation – specific, actionable steps such as revoking a privilege, resetting credentials, or enabling row-level security.

Always cite the exact log line (including session ID and timestamp) so findings can be verified independently. Vague statements like "suspicious activity was observed" are not sufficient.

Safety and Professional Responsibility

Audit logs may contain personally identifiable information (PII) and confidential business data. Handle log excerpts with the same care as the production data itself: store them on encrypted media, share them only with authorized personnel, and destroy copies securely when the investigation is closed. Never share raw logs in a public forum or upload them to untrusted analysis tools. When working in a lab environment, use only synthetic or anonymized data so no real user information is exposed during exercises.

Key terms10

pgauditAn open-source PostgreSQL extension that provides detailed session and object-level audit logging by hooking into the server's logging infrastructure.
Session auditingA pgaudit mode that records SQL statements executed within a database session, filtered by configured statement class categories such as READ, WRITE, or DDL.
Object auditingA pgaudit mode that records statements affecting specific database objects based on privileges granted to a designated audit role.
STRIDEA threat-modeling framework whose six categories — Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, and Elevation of Privilege — help classify security events found in logs.
shared_preload_librariesA PostgreSQL configuration parameter that lists extensions to be loaded when the server starts; pgaudit must appear here to function, requiring a server restart to take effect.
Incident reportA structured document recording the timeline, affected assets, evidence, and recommended remediation steps for a detected security event.
Privilege escalationAn attack pattern in which a user gains database permissions beyond those legitimately assigned, often by exploiting GRANT commands, role membership, or misconfigured objects.
pg_reload_conf()A PostgreSQL function that causes the server to re-read postgresql.conf without a full restart, allowing certain parameter changes — including pgaudit.log — to take effect immediately.
Severity classificationA rating (such as Critical, High, Medium, or Low) assigned to a security event based on the sensitivity of the affected data and the potential for harm if the threat were realized.
Log_destinationA PostgreSQL configuration parameter controlling where log output is sent; setting it to include 'csvlog' produces structured CSV files that can be imported into a table for SQL-based analysis.
In class: Lab: install and configure the pgaudit extension; set pgaudit.log = 'role, ddl, write' in postgresql.conf; create an audit_test user, run a series of authorized and unauthorized SQL commands as that user, then query the PostgreSQL log file to locate and extract the audit records for those commands. · Log-analysis exercise: instructor provides a sanitized 200-line PostgreSQL log excerpt containing embedded simulated attack patterns (repeated failed logins, privilege escalation attempt, unusual after-hours SELECT on sensitive table); learners highlight events of interest, classify each by STRIDE category, and rank by severity. · Incident report writing: learners compose a one-page structured incident summary using a provided template (date/time, affected objects, account involved, evidence from log, recommended remediation); peer-reviewed before submission.
Materials: pgaudit extension and documentation (github.com/pgaudit/pgaudit), PostgreSQL 16 logging documentation, sample log file (provided), incident report template, word processor
Check: Learner submits log excerpt with all simulated attack events highlighted and correctly classified (pass = 4 of 5 events identified) plus incident report scored by instructor rubric requiring correct evidence citation, severity classification, and at least two actionable remediation steps.

Practice check8

Answer each question, then check it. Nothing is recorded; this is your own practice.

PostgreSQL CE — Installation and Configuration
1. After adding pgaudit to shared_preload_libraries in postgresql.conf, what must a DBA do before the extension becomes active?
PostgreSQL CE — Security and Auditing
2. A DBA sets pgaudit.log = 'write, ddl'. Which of the following statements will pgaudit capture?
DAMA CDMP — Data Security
3. In the STRIDE model, repeated failed login attempts against a database account are best classified as which threat category?
DAMA CDMP — Data Security
4. A security analyst finds a log entry showing a low-privilege user executing GRANT ALL ON TABLE salary TO self_created_role; at 2:00 AM. Which STRIDE category applies?
PostgreSQL CE — Monitoring and Logging
5. Which SQL statement correctly filters a log import table named pg_log_import to show only pgaudit records?
DAMA CDMP — Data Governance and Compliance
6. When writing an incident report, why is it important to paste exact log lines rather than paraphrasing them?
PostgreSQL CE — Security and Auditing
7. An organization must demonstrate who accessed a specific table containing protected health information over the past 90 days. Which pgaudit mode is most appropriate for this requirement?
DAMA CDMP — Data Security
8. A lab student's log excerpt shows a SELECT on the payroll table at 11:45 PM by a user whose normal shift ends at 5:00 PM. How should this event be classified in the incident report?
Record this lesson on my transcript. Sign in with your key and enrollment email to record lessons (enroll free if you have no key). This page stays open to read and practise.