{"id":12338,"date":"2019-03-31T19:07:21","date_gmt":"2019-03-31T17:07:21","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/"},"modified":"2019-03-31T19:07:21","modified_gmt":"2019-03-31T17:07:21","slug":"auditing-with-edb-postgre-enterprise","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/","title":{"rendered":"Auditing with EDB Postgres Enterprise"},"content":{"rendered":"<p>It might be that there is a requirement to audit operations in the database. Maybe because of legal requirements, maybe because of security requirements or whatever. I&#8217;ve already written a <a href=\"\" target=\"_blank\" rel=\"noopener noreferrer\">post in the past describing what you can do in community PostgreSQL<\/a>, this post is specific to EDB Postgres. The auditting features come be default in EDB Postgres and you do not need to install any extension such as <a href=\"\" target=\"_blank\" rel=\"noopener noreferrer\">pgaudit<\/a>. <\/p>\n<p><!--more--><\/p>\n<p>I am using EDB Postgres Enterprise version 11.2 for this post but it should work the same in previous versions:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\nenterprisedb@edb1:\/var\/lib\/edb\/ [pg1] psql -X postgres\npsql.bin (11.2.9)\nType \"help\" for help.\n\npostgres=# select version();\n                                                                    version                                                                    \n-----------------------------------------------------------------------------------------------------------------------------------------------\n PostgreSQL 11.2 (EnterpriseDB Advanced Server 11.2.9) on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit\n(1 row)\n<\/pre>\n<p>The parameter which controls if auditing is enabled or not is &#8220;edb_audit&#8221;:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# show edb_audit;\n edb_audit \n-----------\n \n(1 row)\n\npostgres=# \n<\/pre>\n<p>When it is not set (the default) auditing is enabled. You have two options to enable it:<\/p>\n<ul>\n<li>csv: Enabled autiting and will write the audit records to a csv file<\/li>\n<li>xml: Enabled autiting and will write the audit records to a csv file<\/li>\n<\/ul>\n<p>Before enabling auditing you should think about where you want to store the audit files. It should be a location only the operating system user which runs EDB Postgres should have access to. You might think of $PGDATA but do you really want to have all the audit files included in every base backup you will be doing in the future? A better location is outside $PGDATA so you can keep the audit files separated. Lets go with &#8220;\/var\/lib\/edb\/audit&#8221; for the scope of this post:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# ! mkdir \/var\/lib\/edb\/audit\npostgres=# ! chmod 700 \/var\/lib\/edb\/audit\npostgres=# alter system set edb_audit_directory = '\/var\/lib\/edb\/audit';\nALTER SYSTEM\npostgres=# alter system set edb_audit='csv';\nALTER SYSTEM\npostgres=# select name,context from pg_settings where name in ('edb_audit_directory','edb_audit');\n        name         | context \n---------------------+---------\n edb_audit           | sighup\n edb_audit_directory | sighup\n(2 rows)\n<\/pre>\n<p>Both parameter changes can be made active by reloading the server, a restart is not required:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# select pg_reload_conf();\n pg_reload_conf \n----------------\n t\n(1 row)\n<\/pre>\n<p>The default file name that will be used for the audit logs is:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# show edb_audit_filename;\n edb_audit_filename  \n---------------------\n audit-%Y%m%d_%H%M%S\n(1 row)\n<\/pre>\n<p>Lets keep that as it is which is sufficient for the scope of this post. Now you need to think about what you want to audit. There are several options available:<\/p>\n<ul>\n<li>edb_audit_connect: Logs all connections to the instance, either successful, failed or all<\/li>\n<li>edb_audit_disconnect: The opposite of edb_audit_connect, logs all disconnections\/li&gt;\n<li>edb_audit_statement:  Here you have several options to log SQL statements such as insert,truncate, whatever, more on that later<\/li>\n<li>edb_audit_tag: When set, adds a string value to all audit log files<\/li>\n<\/ul>\n<p>We start with logging connections and disconnections. When we set edb_audit_connect to all, we should see all connections to a database, no matter if successful or failed:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# alter system set edb_audit_connect = 'all';\nALTER SYSTEM\npostgres=# select context from pg_settings where name = 'edb_audit_connect';\n context \n---------\n sighup\n(1 row)\npostgres=# select pg_reload_conf();\n pg_reload_conf \n----------------\n t\n(1 row)\n<\/pre>\n<p>From now on we should have the audit information in the log file for every successful connection and every connection attempt that failed. Is it true?<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# ! psql edb\npsql.bin (11.2.9)\nType \"help\" for help.\n\n[local]:5444 enterprisedb@edb=# q\npostgres=# ! psql -U dummy edb\npsql.bin: FATAL:  role \"dummy\" does not exist\npostgres=# \n<\/pre>\n<p>That should have produced two lines in the latest audit file:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nenterprisedb@edb1:\/var\/lib\/edb\/audit\/ [pg1] pwd\n\/var\/lib\/edb\/audit\nenterprisedb@edb1:\/var\/lib\/edb\/audit\/ [pg1] ls -latr\ntotal 8\ndrwx------. 5 enterprisedb enterprisedb 183 Mar 24 14:24 ..\n-rw-------. 1 enterprisedb enterprisedb 611 Mar 24 14:38 audit-20190324_143640.csv\ndrwx------. 2 enterprisedb enterprisedb  72 Mar 24 14:38 .\n-rw-------. 1 enterprisedb enterprisedb 412 Mar 24 14:41 audit-20190324_143805.csv\nenterprisedb@edb1:\/var\/lib\/edb\/audit\/ [pg1] cat audit-20190324_143805.csv\n2019-03-24 14:40:54.683 CET,\"enterprisedb\",\"edb\",1534,\"[local]\",5c9788e6.5fe,1,\"authentication\",2019-03-24 14:40:54 CET,5\/133,0,AUDIT,00000,\"connection authorized: user=enterprisedb database=edb\",,,,,,,,,\"\",\"\",\"\"\n2019-03-24 14:41:16.617 CET,\"dummy\",\"edb\",1563,\"[local]\",5c9788fc.61b,1,\"authentication\",2019-03-24 14:41:16 CET,5\/136,0,AUDIT,00000,\"connection authorized: user=dummy database=edb\",,,,,,,,,\"\",\"\",\"\"\n<\/pre>\n<p>a<br \/>\nAs expected, we can see the successful connection request and in addition the one that failed. When we want to log disconnections as well, we can do so:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# alter system set edb_audit_disconnect = 'all';\nALTER SYSTEM\npostgres=# select pg_reload_conf();\n pg_reload_conf \n----------------\n t\n(1 row)\npostgres=# ! psql edb\npsql.bin (11.2.9)\nType \"help\" for help.\n\n[local]:5444 enterprisedb@edb=# q\npostgres=# \n<\/pre>\n<p>In the same audit file as before:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n2019-03-24 14:47:42.447 CET,\"enterprisedb\",\"edb\",1929,\"[local]\",5c978a7a.789,2,\"idle\",2019-03-24 14:47:38 CET,,0,AUDIT,00000,\"disconnection: session time: 0:00:03.708 user=enterprisedb database=edb host=[local]\",,,,,,,,,\"psql.bin\",\"\",\"\"\n<\/pre>\n<p>The duration of the session is logged as well. So far for the basic auditing features. Logging connections and disconnections is a good start but probably not enough. You might soon come to a point where you want to have more information, such as what the user was doing exactly in the database. This is where &#8220;edb_audit_statement&#8221; comes into the game. You can set it to something simple like &#8220;all inserts&#8221; or &#8220;all updates&#8221;:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\npostgres=# alter system set edb_audit_statement = 'insert';\nALTER SYSTEM\npostgres=# select pg_reload_conf();\n pg_reload_conf \n----------------\n t\n(1 row)\n\npostgres=# create table t1 ( a int );\nCREATE TABLE\npostgres=# insert into t1 values(1);\nINSERT 0 1\n<\/pre>\n<p>Looking at the audit file:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n2019-03-24 14:55:36.744 CET,,,9004,,5c977540.232c,3,,2019-03-24 13:17:04 CET,,0,LOG,00000,\"received SIGHUP, reloading configuration files\",,,,,,,,,\"\",\"\",\"\"\n2019-03-24 14:55:53.460 CET,\"enterprisedb\",\"postgres\",31899,\"[local]\",5c97827a.7c9b,6,\"idle\",2019-03-24 14:13:30 CET,4\/477,0,AUDIT,00000,\"statement: insert into t1 values(1);\",,,,,,,,,\"psql.bin\",\"INSERT\",\"\"\n<\/pre>\n<p>The insert is logged. You may also spot a potential issue here: Depending on how the statement is written the actual values (1 in this case) is written to the log. This might open another security hole if the audit files are not handled with care. You can not prevent that using prepared statements and in fact the &#8220;prepare&#8221; part is logged as well:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# prepare stmt as insert into t1 values($1);\nPREPARE\npostgres=# execute stmt(2);\nINSERT 0 1\npostgres=# select * from t1;\n a \n---\n 1\n 2\n(2 rows)\n<\/pre>\n<p>The entries in the audit log:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n2019-03-24 14:58:50.395 CET,\"enterprisedb\",\"postgres\",31899,\"[local]\",5c97827a.7c9b,7,\"idle\",2019-03-24 14:13:30 CET,4\/478,0,AUDIT,00000,\"statement: prepare stmt as insert into t1 values($1);\",,,,,,,,,\"psql.bin\",\"PREPARE\",\"\"\n2019-03-24 14:59:02.952 CET,\"enterprisedb\",\"postgres\",31899,\"[local]\",5c97827a.7c9b,8,\"idle\",2019-03-24 14:13:30 CET,4\/479,0,AUDIT,00000,\"statement: execute stmt(2);\",\"prepare: prepare stmt as insert into t1 values($1);\",,,,,,,,\"psql.bin\",\"EXECUTE\",\"\"\n<\/pre>\n<p>Although we only asked to log &#8220;inserts&#8221;, the prepare and execute statements are logged as well. If we prepare an update it is not logged (what is correct):<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\npostgres=# prepare stmt2 as update t1 set a = $1;\nPREPARE\npostgres=# execute stmt2(2);\nUPDATE 5\n<\/pre>\n<p>The last line in the audit file is still this one:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n2019-03-24 15:02:33.502 CET,\"enterprisedb\",\"postgres\",31899,\"[local]\",5c97827a.7c9b,9,\"idle\",2019-03-24 14:13:30 CET,4\/487,0,AUDIT,00000,\"statement: execute stmt(5);\",\"prepare: prepare stmt as insert into t1 values($1);\",,,,,,,,\"psql.bin\",\"EXECUTE\",\"\"\n<\/pre>\n<p>The power of edb_audit_statement comes when you want to audit multiple kinds of statements but do not want to set it to &#8220;all&#8221; (this would log all the statements):<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\npostgres=# alter system set edb_audit_statement='insert,update,delete,create table,drop view';\nALTER SYSTEM\npostgres=# select pg_reload_conf();\n pg_reload_conf \n----------------\n t\n(1 row)\n<\/pre>\n<p>This should log all inserts, updates and deletes and in addition every create table or drop view:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# create table t2 ( a int );\nCREATE TABLE\npostgres=# insert into t2 values(1);\nINSERT 0 1\npostgres=# update t2 set a = 2;\nUPDATE 1\npostgres=# delete from t2 where a = 2;\nDELETE 1\npostgres=# truncate t2;\nTRUNCATE TABLE\npostgres=# create view v1 as select * from t2;\nCREATE VIEW\npostgres=# drop view v1;\nDROP VIEW\n<\/pre>\n<p>We should see entries for the insert, the update and the delete, but not for the truncate. The drop view should be logged as well:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n2019-03-24 15:08:46.245 CET,\"enterprisedb\",\"postgres\",31899,\"[local]\",5c97827a.7c9b,10,\"idle\",2019-03-24 14:13:30 CET,4\/496,0,AUDIT,00000,\"statement: create table t2 ( a int );\",,,,,,,,,\"psql.bin\",\"CREATE TABLE\",\"\"\n2019-03-24 15:08:59.713 CET,\"enterprisedb\",\"postgres\",31899,\"[local]\",5c97827a.7c9b,12,\"idle\",2019-03-24 14:13:30 CET,4\/498,0,AUDIT,00000,\"statement: insert into t2 values(1);\",,,,,,,,,\"psql.bin\",\"INSERT\",\"\"\n2019-03-24 15:09:21.299 CET,\"enterprisedb\",\"postgres\",31899,\"[local]\",5c97827a.7c9b,13,\"idle\",2019-03-24 14:13:30 CET,4\/499,0,AUDIT,00000,\"statement: update t2 set a = 2;\",,,,,,,,,\"psql.bin\",\"UPDATE\",\"\"\n2019-03-24 15:09:29.614 CET,\"enterprisedb\",\"postgres\",31899,\"[local]\",5c97827a.7c9b,14,\"idle\",2019-03-24 14:13:30 CET,4\/500,0,AUDIT,00000,\"statement: delete from t2 where a = 2;\",,,,,,,,,\"psql.bin\",\"DELETE\",\"\"\n2019-03-24 15:12:51.652 CET,\"enterprisedb\",\"postgres\",31899,\"[local]\",5c97827a.7c9b,15,\"idle\",2019-03-24 14:13:30 CET,4\/503,0,AUDIT,00000,\"statement: drop view v1;\",,,,,,,,,\"psql.bin\",\"DROP VIEW\",\"\"\n<\/pre>\n<p>Fine. Using edb_audit_statement we have control of what exactly we want to log. What we did now was valid for the whole instance, can we modify auditing to a specific role? Yes, this is possible:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\nedb=# alter user enterprisedb set edb_audit_statement = 'truncate';\nALTER ROLE\nedb=# create role test;\nCREATE ROLE\nedb=# alter role test set edb_audit_statement = 'truncate';\nALTER ROLE\n<\/pre>\n<p>The same is true on the database level:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\nedb=# alter database edb set edb_audit_statement = 'truncate';\nALTER DATABASE\n<\/pre>\n<p>Lets do a small test and create user and then set edb_audit_statement on the user level, and reset it on the instance level:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\nedb=# create user u1 with login password 'u1';\nCREATE ROLE\nedb=# alter user u1 set edb_audit_statement = 'create table';\nALTER ROLE\nedb=# alter system set edb_audit_statement = 'none';\nALTER SYSTEM\nedb=# select pg_reload_conf();\n pg_reload_conf \n----------------\n t\n(1 row)\n<\/pre>\n<p>Create table statements from that user should now be logged:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\nedb=# c edb u1\nYou are now connected to database \"edb\" as user \"u1\".\nedb=&gt; create table t1 ( a int );\nCREATE TABLE\n<\/pre>\n<p>The statement is indeed logged:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\n2019-03-24 15:44:19.793 CET,\"u1\",\"edb\",6243,\"[local]\",5c9797b7.1863,1,\"idle\",2019-03-24 15:44:07 CET,5\/30177,0,AUDIT,00000,\"statement: create table t1 ( a int );\",,,,,,,,,\"psql.bin\",\"CREATE TABLE\",\"\"\n<\/pre>\n<p>Does the same work for a role?<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\nedb=&gt; c edb enterprisedb\nYou are now connected to database \"edb\" as user \"enterprisedb\".\nedb=# create role r1;\nCREATE ROLE\nedb=# alter role r1 set edb_audit_statement = 'drop table';\nALTER ROLE\nedb=# grant r1 to u1;\nGRANT ROLE\nedb=# c edb u1\nYou are now connected to database \"edb\" as user \"u1\".\nedb=&gt; drop table t1;\nDROP TABLE\nedb=&gt; \n<\/pre>\n<p>No, in this case the drop statement is not logged. You can set the parameter for a role, but is does not have any effect. <\/p>\n<p>The last test for today: What happens when the directory we configured for the audit files is removed? <\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\nenterprisedb@edb1:\/var\/lib\/edb\/ [pg1] pwd\n\/var\/lib\/edb\nenterprisedb@edb1:\/var\/lib\/edb\/ [pg1] ls -l\ntotal 0\ndrwx------. 4 enterprisedb enterprisedb 51 Mar 24 13:16 as11\ndrwx------. 2 enterprisedb enterprisedb 72 Mar 24 14:38 audit\ndrwxrwxr-x. 3 enterprisedb enterprisedb 17 Mar 24 13:09 local\nenterprisedb@edb1:\/var\/lib\/edb\/ [pg1] mv audit\/ audit_org\nenterprisedb@edb1:\/var\/lib\/edb\/ [pg1] ls -l\ntotal 0\ndrwx------. 4 enterprisedb enterprisedb 51 Mar 24 13:16 as11\ndrwx------. 2 enterprisedb enterprisedb 72 Mar 24 14:38 audit_org\ndrwxrwxr-x. 3 enterprisedb enterprisedb 17 Mar 24 13:09 local\n<\/pre>\n<p>These two inserts should generate audit records:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\nedb=&gt; create table t2 ( a int );\nCREATE TABLE\nedb=&gt; create table t3 ( a int );\nCREATE TABLE\nedb=&gt; \n<\/pre>\n<p>Nothing happens, not even a log entry in the server log file. I would have at least expected to get a warning that the directory does not exist. Lets restart the instance:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nenterprisedb@edb1:\/var\/lib\/edb\/as11\/data\/log\/ [pg1] pg_ctl -D \/var\/lib\/edb\/as11\/data\/ restart -m fast\nwaiting for server to shut down.... done\nserver stopped\nwaiting for server to start....2019-03-24 15:51:59 CET LOG:  listening on IPv4 address \"0.0.0.0\", port 5444\n2019-03-24 15:51:59 CET LOG:  listening on IPv6 address \"::\", port 5444\n2019-03-24 15:51:59 CET LOG:  listening on Unix socket \"\/tmp\/.s.PGSQL.5444\"\n2019-03-24 15:51:59 CET LOG:  redirecting log output to logging collector process\n2019-03-24 15:51:59 CET HINT:  Future log output will appear in directory \"log\".\n done\nserver started\n<\/pre>\n<p>And again: Nothing. But the audit directory is being recreated once the server starts:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nenterprisedb@edb1:\/var\/lib\/edb\/ [pg1] ls -l\ntotal 0\ndrwx------. 4 enterprisedb enterprisedb 51 Mar 24 13:16 as11\ndrwx------. 2 enterprisedb enterprisedb 39 Mar 24 15:51 audit\ndrwx------. 2 enterprisedb enterprisedb 72 Mar 24 14:38 audit_org\ndrwxrwxr-x. 3 enterprisedb enterprisedb 17 Mar 24 13:09 local\n<\/pre>\n<p>Changing the permissions so that the enterprisedb user can not write anymore to that directory will prevent the server from restarting:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nenterprisedb@edb1:\/var\/lib\/edb\/ [pg1] sudo chown root:root audit\nenterprisedb@edb1:\/var\/lib\/edb\/ [pg1] ls -l\ntotal 0\ndrwx------. 4 enterprisedb enterprisedb 51 Mar 24 13:16 as11\ndrwx------. 2 root         root         39 Mar 24 15:51 audit\ndrwx------. 2 enterprisedb enterprisedb 72 Mar 24 14:38 audit_org\ndrwxrwxr-x. 3 enterprisedb enterprisedb 17 Mar 24 13:09 local\nenterprisedb@edb1:\/var\/lib\/edb\/ [pg1] pg_ctl -D \/var\/lib\/edb\/as11\/data\/ restart -m fast\nwaiting for server to shut down.... done\nserver stopped\nwaiting for server to start....2019-03-24 15:55:44 CET LOG:  listening on IPv4 address \"0.0.0.0\", port 5444\n2019-03-24 15:55:44 CET LOG:  listening on IPv6 address \"::\", port 5444\n2019-03-24 15:55:44 CET LOG:  listening on Unix socket \"\/tmp\/.s.PGSQL.5444\"\n2019-03-24 15:55:44 CET FATAL:  could not open log file \"\/var\/lib\/edb\/audit\/audit-20190324_155544.csv\": Permission denied\n2019-03-24 15:55:44 CET LOG:  database system is shut down\n stopped waiting\npg_ctl: could not start server\nExamine the log output.\n<\/pre>\n<p>Hope that helps&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It might be that there is a requirement to audit operations in the database. Maybe because of legal requirements, maybe because of security requirements or whatever. I&#8217;ve already written a post in the past describing what you can do in community PostgreSQL, this post is specific to EDB Postgres. The auditting features come be default [&hellip;]<\/p>\n","protected":false},"author":29,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[229],"tags":[713,77],"type_dbi":[],"class_list":["post-12338","post","type-post","status-publish","format-standard","hentry","category-database-administration-monitoring","tag-enterprisedb","tag-postgresql"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Auditing with EDB Postgres Enterprise - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Auditing with EDB Postgres Enterprise\" \/>\n<meta property=\"og:description\" content=\"It might be that there is a requirement to audit operations in the database. Maybe because of legal requirements, maybe because of security requirements or whatever. I&#8217;ve already written a post in the past describing what you can do in community PostgreSQL, this post is specific to EDB Postgres. The auditting features come be default [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-03-31T17:07:21+00:00\" \/>\n<meta name=\"author\" content=\"Daniel Westermann\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@westermanndanie\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Daniel Westermann\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/\"},\"author\":{\"name\":\"Daniel Westermann\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\"},\"headline\":\"Auditing with EDB Postgres Enterprise\",\"datePublished\":\"2019-03-31T17:07:21+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/\"},\"wordCount\":938,\"commentCount\":0,\"keywords\":[\"enterprisedb\",\"PostgreSQL\"],\"articleSection\":[\"Database Administration &amp; Monitoring\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/\",\"name\":\"Auditing with EDB Postgres Enterprise - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"datePublished\":\"2019-03-31T17:07:21+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Auditing with EDB Postgres Enterprise\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\",\"name\":\"Daniel Westermann\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"caption\":\"Daniel Westermann\"},\"description\":\"Daniel Westermann is Principal Consultant and Technology Leader Open Infrastructure at dbi services. He has more than 15 years of experience in management, engineering and optimization of databases and infrastructures, especially on Oracle and PostgreSQL. Since the beginning of his career, he has specialized in Oracle Technologies and is Oracle Certified Professional 12c and Oracle Certified Expert RAC\/GridInfra. Over time, Daniel has become increasingly interested in open source technologies, becoming \u201cTechnology Leader Open Infrastructure\u201d and PostgreSQL expert. \u00a0Based on community or EnterpriseDB tools, he develops and installs complex high available solutions with PostgreSQL. He is also a certified PostgreSQL Plus 9.0 Professional and a Postgres Advanced Server 9.4 Professional. He is a regular speaker at PostgreSQL conferences in Switzerland and Europe. Today Daniel is also supporting our customers on AWS services such as AWS RDS, database migrations into the cloud, EC2 and automated infrastructure management with AWS SSM (System Manager). He is a certified AWS Solutions Architect Professional. Prior to dbi services, Daniel was Management System Engineer at LC SYSTEMS-Engineering AG in Basel. Before that, he worked as Oracle Developper &amp;\u00a0Project Manager at Delta Energy Solutions AG in Basel (today Powel AG). Daniel holds a diploma in Business Informatics (DHBW, Germany). His branch-related experience mainly covers the pharma industry, the financial sector, energy, lottery and telecommunications.\",\"sameAs\":[\"https:\/\/x.com\/westermanndanie\"],\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/daniel-westermann\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Auditing with EDB Postgres Enterprise - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/","og_locale":"en_US","og_type":"article","og_title":"Auditing with EDB Postgres Enterprise","og_description":"It might be that there is a requirement to audit operations in the database. Maybe because of legal requirements, maybe because of security requirements or whatever. I&#8217;ve already written a post in the past describing what you can do in community PostgreSQL, this post is specific to EDB Postgres. The auditting features come be default [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/","og_site_name":"dbi Blog","article_published_time":"2019-03-31T17:07:21+00:00","author":"Daniel Westermann","twitter_card":"summary_large_image","twitter_creator":"@westermanndanie","twitter_misc":{"Written by":"Daniel Westermann","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/"},"author":{"name":"Daniel Westermann","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66"},"headline":"Auditing with EDB Postgres Enterprise","datePublished":"2019-03-31T17:07:21+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/"},"wordCount":938,"commentCount":0,"keywords":["enterprisedb","PostgreSQL"],"articleSection":["Database Administration &amp; Monitoring"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/","url":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/","name":"Auditing with EDB Postgres Enterprise - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2019-03-31T17:07:21+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/auditing-with-edb-postgre-enterprise\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Auditing with EDB Postgres Enterprise"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66","name":"Daniel Westermann","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","caption":"Daniel Westermann"},"description":"Daniel Westermann is Principal Consultant and Technology Leader Open Infrastructure at dbi services. He has more than 15 years of experience in management, engineering and optimization of databases and infrastructures, especially on Oracle and PostgreSQL. Since the beginning of his career, he has specialized in Oracle Technologies and is Oracle Certified Professional 12c and Oracle Certified Expert RAC\/GridInfra. Over time, Daniel has become increasingly interested in open source technologies, becoming \u201cTechnology Leader Open Infrastructure\u201d and PostgreSQL expert. \u00a0Based on community or EnterpriseDB tools, he develops and installs complex high available solutions with PostgreSQL. He is also a certified PostgreSQL Plus 9.0 Professional and a Postgres Advanced Server 9.4 Professional. He is a regular speaker at PostgreSQL conferences in Switzerland and Europe. Today Daniel is also supporting our customers on AWS services such as AWS RDS, database migrations into the cloud, EC2 and automated infrastructure management with AWS SSM (System Manager). He is a certified AWS Solutions Architect Professional. Prior to dbi services, Daniel was Management System Engineer at LC SYSTEMS-Engineering AG in Basel. Before that, he worked as Oracle Developper &amp;\u00a0Project Manager at Delta Energy Solutions AG in Basel (today Powel AG). Daniel holds a diploma in Business Informatics (DHBW, Germany). His branch-related experience mainly covers the pharma industry, the financial sector, energy, lottery and telecommunications.","sameAs":["https:\/\/x.com\/westermanndanie"],"url":"https:\/\/www.dbi-services.com\/blog\/author\/daniel-westermann\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/12338","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/29"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=12338"}],"version-history":[{"count":0,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/12338\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=12338"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=12338"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=12338"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=12338"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}