V-72985

Severity: Medium

Generated

2019-05-20 15:48:11.984914

Status

Passed

PostgreSQL must generate time stamps, for audit records and application data, with a minimum granularity of one second.

NIST 800-53

STIG # Description Result
AU-8 AU-8: Time Stamps passed

Guidance

Without sufficient granularity of time stamps, it is not possible to adequately determine the chronological order of records.

Time stamps generated by PostgreSQL must include date and time. Granularity of time measurements refers to the precision available in time stamp values. Granularity coarser than one second is not sufficient for audit trail purposes. Time stamp values are typically presented with three or more decimal places of seconds; however, the actual granularity may be coarser than the apparent precision. For example, PostgreSQL will always return at least millisecond timestamps but it can be truncated using EXTRACT functions: SELECT EXTRACT(MINUTE FROM TIMESTAMP ‘2001-02-16 20:38:40’);.

Check

Note: The following instructions use the PGDATA environment variable. See supplementary content APPENDIX-F for instructions on configuring PGDATA.

First, as the database administrator (shown here as “postgres”), verify the current log_line_prefix setting by running the following SQL:

$ sudo su - postgres $ psql -c “SHOW log_line_prefix”

If log_line_prefix does not contain %m, this is a finding.

Next check the logs to verify time stamps are being logged:

$ sudo su - postgres $ cat ${PGDATA?}/pg_log/ < 2016-02-23 12:53:33.947 EDT postgres postgres 570bd68d.3912 >LOG: connection authorized: user=postgres database=postgres < 2016-02-23 12:53:41.576 EDT postgres postgres 570bd68d.3912 >LOG: AUDIT: SESSION,1,1,DDL,CREATE TABLE,,,CREATE TABLE test_srg(id INT);, < 2016-02-23 12:53:44.372 EDT postgres postgres 570bd68d.3912 >LOG: disconnection: session time: 0:00:10.426 user=postgres database=postgres host=[local]

If time stamps are not being logged, this is a finding.

Fix

Note: The following instructions use the PGDATA environment variable. See supplementary content APPENDIX-F for instructions on configuring PGDATA.

PostgreSQL will not log anything if logging is not enabled. To ensure that logging is enabled, review supplementary content APPENDIX-C for instructions on enabling logging.

If logging is enabled the following configurations must be made to log events with time stamps:

First, as the database administrator (shown here as “postgres”), edit postgresql.conf:

$ sudo su - postgres $ vi ${PGDATA?}/postgresql.conf

Add %m to log_line_prefix to enable time stamps with milliseconds:

log_line_prefix = ‘< %m >’

Now, as the system administrator, reload the server with the new configuration:

SYSTEMD SERVER ONLY

$ sudo systemctl reload postgresql-9.5

INITD SERVER ONLY

$ sudo service postgresql-9.5 reload

Test Results

  Result
PostgreSQL query: SHOW log_line_prefix; output should include "%m" passed
Command: `sed -nre '/2019-05-16 08:11.*LOG:\s+starting tests for V-72985/,$p' /var/vcap/sys/log/postgresql/Thu.pg_log` stdout should match /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} [A-Z]{3}/ passed

Code

control "V-72985" do

  title "PostgreSQL must generate time stamps, for audit records and application
data, with a minimum granularity of one second."
  desc  "Without sufficient granularity of time stamps, it is not possible to
adequately determine the chronological order of records.

Time stamps generated by PostgreSQL must include date and time. Granularity of time
measurements refers to the precision available in time stamp values. Granularity
coarser than one second is not sufficient for audit trail purposes. Time stamp
values are typically presented with three or more decimal places of seconds;
however, the actual granularity may be coarser than the apparent precision. For
example, PostgreSQL will always return at least millisecond timestamps but it can be
truncated using EXTRACT functions: SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16
20:38:40');."

  impact 0.5
  tag "severity": "medium"
  tag "gtitle": "SRG-APP-000375-DB-000323"
  tag "gid": "V-72985"
  tag "rid": "SV-87637r1_rule"
  tag "stig_id": "PGS9-00-007700"
  tag "cci": "CCI-001889"
  tag "nist": ["AU-8 b", "Rev_4"]

  tag "check": "Note: The following instructions use the PGDATA environment
variable. See supplementary content APPENDIX-F for instructions on configuring
PGDATA.

First, as the database administrator (shown here as \"postgres\"), verify the
current log_line_prefix setting by running the following SQL:

$ sudo su - postgres
$ psql -c \"SHOW log_line_prefix\"

If log_line_prefix does not contain %m, this is a finding.

Next check the logs to verify time stamps are being logged:

$ sudo su - postgres
$ cat ${PGDATA?}/pg_log/<latest_log>
< 2016-02-23 12:53:33.947 EDT postgres postgres 570bd68d.3912 >LOG: connection
authorized: user=postgres database=postgres
< 2016-02-23 12:53:41.576 EDT postgres postgres 570bd68d.3912 >LOG: AUDIT:
SESSION,1,1,DDL,CREATE TABLE,,,CREATE TABLE test_srg(id INT);,<none>
< 2016-02-23 12:53:44.372 EDT postgres postgres 570bd68d.3912 >LOG: disconnection:
session time: 0:00:10.426 user=postgres database=postgres host=[local]

If time stamps are not being logged, this is a finding."

  tag "fix": "Note: The following instructions use the PGDATA environment variable.
See supplementary content APPENDIX-F for instructions on configuring PGDATA.

PostgreSQL will not log anything if logging is not enabled. To ensure that logging
is enabled, review supplementary content APPENDIX-C for instructions on enabling
logging.

If logging is enabled the following configurations must be made to log events with
time stamps:

First, as the database administrator (shown here as \"postgres\"), edit
postgresql.conf:

$ sudo su - postgres
$ vi ${PGDATA?}/postgresql.conf

Add %m to log_line_prefix to enable time stamps with milliseconds:

log_line_prefix = '< %m >'

Now, as the system administrator, reload the server with the new configuration:

# SYSTEMD SERVER ONLY
$ sudo systemctl reload postgresql-9.5

# INITD SERVER ONLY
$ sudo service postgresql-9.5 reload"

  sql = postgres_session(PG_DBA, PG_DBA_PASSWORD, PG_HOST)
  log_directory_query = sql.query('SHOW log_directory;', [PG_DB])
  log_directory = log_directory_query.output
  current_log_command = "ls -1t #{log_directory}/*.pg_log | head -1"
  current_log = command(current_log_command).stdout.strip
  control = File.basename(__FILE__, File.extname(__FILE__))
  message = "starting tests for #{control}"
  message_sql = "DO language plpgsql $$ BEGIN "\
    "RAISE LOG '#{message}'; END $$;"
  start = Time.now.strftime('%Y-%m-%d %H:%M')
  get_logs = "sed -nre '/#{start}.*LOG:\\s+#{message}/,$p' #{current_log}"

  log_line_prefix_escapes = ['%m']

  log_line_prefix_escapes.each do |escape|
    describe sql.query('SHOW log_line_prefix;', [PG_DB]) do
      its('output') { should include escape }
    end
  end

  sql.query(message_sql, [PG_DB])
  timestamp = Regexp.new('\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} [A-Z]{3}')

  describe command(get_logs) do
    its('stdout') { should match timestamp }
  end
end