Description
I find that Object Audit Logging feature does not work when COPY statement runs with setting pgaudit.log_rows=on. I think this is bug.
Note, Session Audit Logging feature works well. And When I run SELECT statement, Object Audit Logging feature works well too.
How to reproduce
- PostgreSQL version : 16.3
- pgaudit version : maser branch
Parameter settings to test this issue:
shared_preload_libraries='pgaudit'
pgaudit.role = 'auditmrole'
logging_collector = on
log_statement = 'all'
pgaudit.log = 'all'
Initial setting:
postgres=# create role auditmrole;
CREATE ROLE
postgres=# create table test(c1 int);
CREATE TABLE
postgres=# GRANT SELECT ON test TO auditmrole;
GRANT
Test1 : COPY with setting pgaudit.log_rows=on
SQL command:
postgres=# set pgaudit.log_rows=on;
SET
postgres=# copy test to stdout;
Results:
2024-05-10 05:16:34.467 UTC [58027] LOG: statement: copy test to stdout;
2024-05-10 05:16:34.467 UTC [58027] LOG: AUDIT: SESSION,3,1,READ,COPY,,,copy test to stdout;,<not logged>,0
-> This issue occurs. "AUDIT: OBJECT,1,1,READ,SELECT,TABLE,public.test,copy test to stdout;,,0" is not logged.
Test2 : COPY WITHOUT setting pgaudit.log_rows
SQL command:
postgres=# copy test to stdout;
Results:
2024-05-10 05:16:03.527 UTC [58027] LOG: statement: copy test to stdout;
2024-05-10 05:16:03.527 UTC [58027] LOG: AUDIT: SESSION,1,1,READ,COPY,,,copy test to stdout;,<not logged>
2024-05-10 05:16:03.527 UTC [58027] LOG: AUDIT: OBJECT,1,1,READ,SELECT,TABLE,public.test,copy test to stdout;,<not logged>
-> Object Audit Logging feature does work well even if I run COPY statement.
Test3 : SELECT with setting pgaudit.log_rows=on
postgres=# set pgaudit.log_rows=on;
SET
postgres=# select * from test;
c1
----
(0 rows)
2024-05-10 05:15:30.416 UTC [57791] LOG: statement: select * from test;
2024-05-10 05:15:30.416 UTC [57791] LOG: AUDIT: SESSION,9,1,READ,SELECT,,,select * from test;,<not logged>,0
2024-05-10 05:15:30.416 UTC [57791] LOG: AUDIT: OBJECT,9,1,READ,SELECT,TABLE,public.test,select * from test;,<not logged>,0
-> Object Audit Logging feature does work well even if I set pgaudit.log_rows=on.
According to my investigation, it looks like the logging COPY statement was pending in pgaudit_ExecutorCheckPerms_hook(), but it doesn't seem to be logged in the end.
https://github.com/pgaudit/pgaudit/blob/master/pgaudit.c#L1428-L1450
/* Check if the top item is SELECT/INSERT for CREATE TABLE AS */
if (auditEventStack->auditEvent.commandTag == T_SelectStmt &&
auditEventStack->next != NULL &&
auditEventStack->next->auditEvent.command == CMDTAG_CREATE_TABLE_AS &&
auditEventStack->auditEvent.rangeTabls != NULL)
{
/*
* First, log the INSERT event for CREATE TABLE AS here.
* The SELECT event for CREATE TABLE AS will be logged
* in pgaudit_ExecutorEnd_hook() later to get rows.
*/
log_select_dml(auditOid, rangeTabls, permInfos);
}
else
{
/*
* Save auditOid and rangeTabls to call log_select_dml()
* in pgaudit_ExecutorEnd_hook() later.
*/
auditEventStack->auditEvent.auditOid = auditOid;
auditEventStack->auditEvent.rangeTabls = rangeTabls;
auditEventStack->auditEvent.permInfos = permInfos;
}