diff --git a/docs/install.rst b/docs/install.rst
index 9ee736701d..636da72c97 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -75,6 +75,9 @@ worth checking the *Journalist Interface*. For this you will need:
the GPG private key, it is not possible to specify multiple
GPG keys.
+.. note:: The journalist notification is sent after the daily reboot
+ of the *Application Server*.
+
You will have to copy the following required files to
``install_files/ansible-base``:
diff --git a/install_files/ansible-base/roles/ossec/files/process_submissions_today.sh b/install_files/ansible-base/roles/ossec/files/process_submissions_today.sh
index 899d83df86..b55fb146fe 100755
--- a/install_files/ansible-base/roles/ossec/files/process_submissions_today.sh
+++ b/install_files/ansible-base/roles/ossec/files/process_submissions_today.sh
@@ -1,17 +1,35 @@
#!/bin/bash
+SENT_STAMP=/var/ossec/logs/journalist_notification_sent.stamp
+
function send_encrypted_alarm() {
/var/ossec/send_encrypted_alarm.sh "$1"
}
function main() {
+ if modified_in_the_past_24h "${SENT_STAMP}" ; then
+ logger "$0 journalist notification suppressed"
+ else
+ handle_notification "$@"
+ fi
+}
+
+function modified_in_the_past_24h() {
+ local stamp
+ stamp="$1"
+ test -f "${stamp}" && \
+ find "${stamp}" -mtime -1 | \
+ grep --quiet "${stamp}"
+}
+
+function handle_notification() {
local sender
local stdin
sender=${1:-send_encrypted_alarm}
stdin="$(< /dev/stdin)"
local count
- count=$(echo "$stdin" | perl -ne 'print scalar(<>) and exit if(/ossec: output/);')
+ count=$(echo "$stdin" | perl -ne "print scalar(<>) and exit if(m|ossec: output: 'head -1 /var/lib/securedrop/submissions_today.txt|);")
if [[ "$count" =~ ^[0-9]+$ ]] ; then
export SUBJECT="Submissions in the past 24h"
#
@@ -24,6 +42,7 @@ function main() {
echo "There has been no submission activity in the past 24 hours."
echo "You do not need to login to SecureDrop."
fi | $sender journalist
+ touch "${SENT_STAMP}"
else
export SUBJECT="SecureDrop Submissions Error"
(
@@ -34,33 +53,50 @@ function main() {
fi
}
+function forget() {
+ rm -f "${1:-$SENT_STAMP}"
+}
+
+function test_modified_in_the_past_24h() {
+ local stamp
+ stamp=$(mktemp)
+
+ modified_in_the_past_24h "${stamp}" || exit 1
+
+ touch --date '-2 days' "${stamp}"
+ ! modified_in_the_past_24h "${stamp}" || exit 1
+
+ forget "${stamp}"
+ ! modified_in_the_past_24h "${stamp}" || exit 1
+}
+
function test_send_encrypted_alarm() {
echo "$1"
cat
}
-function test_main() {
+function test_handle_notification() {
shopt -s -o xtrace
PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: '
- echo BUGOUS | main test_send_encrypted_alarm | \
+ echo BUGOUS | handle_notification test_send_encrypted_alarm | \
tee /dev/stderr | \
grep -q 'failed to find 0/1 submissions boolean' || exit 1
(
echo 'ossec: output'
echo 'NOTANUMBER'
- ) | main test_send_encrypted_alarm | tee /dev/stderr | grep -q 'failed to find 0/1 submissions boolean' || exit 1
+ ) | handle_notification test_send_encrypted_alarm | tee /dev/stderr | grep -q 'failed to find 0/1 submissions boolean' || exit 1
(
echo 'ossec: output'
echo '1'
- ) | main test_send_encrypted_alarm | tee /tmp/submission-yes.txt | grep -q 'There has been submission activity' || exit 1
+ ) | handle_notification test_send_encrypted_alarm | tee /tmp/submission-yes.txt | grep -q 'There has been submission activity' || exit 1
(
echo 'ossec: output'
echo '0'
- ) | main test_send_encrypted_alarm | tee /tmp/submission-no.txt | grep -q 'There has been no submission activity' || exit 1
+ ) | handle_notification test_send_encrypted_alarm | tee /tmp/submission-no.txt | grep -q 'There has been no submission activity' || exit 1
if test "$(stat --format=%s /tmp/submission-no.txt)" != "$(stat --format=%s /tmp/submission-yes.txt)" ; then
echo both files are expected to have exactly the same size, padding must be missing
diff --git a/install_files/securedrop-ossec-agent/var/ossec/etc/ossec.conf b/install_files/securedrop-ossec-agent/var/ossec/etc/ossec.conf
index a5061e48f8..25bac9df98 100644
--- a/install_files/securedrop-ossec-agent/var/ossec/etc/ossec.conf
+++ b/install_files/securedrop-ossec-agent/var/ossec/etc/ossec.conf
@@ -108,7 +108,7 @@
full_command
head -1 /var/lib/securedrop/submissions_today.txt | grep '^[0-9]*$'
- 86400
+ 90000
diff --git a/testinfra/ossec/alert-journalist-one.txt b/testinfra/ossec/alert-journalist-one.txt
new file mode 100644
index 0000000000..2020c83ef0
--- /dev/null
+++ b/testinfra/ossec/alert-journalist-one.txt
@@ -0,0 +1,14 @@
+OSSEC HIDS Notification.
+2018 May 06 20:18:24
+
+Received From: (app) 10.0.1.4->head -1 /var/lib/securedrop/submissions_today.txt | grep '^[0-9]*$'
+Rule: 400600 fired (level 1) -> "Boolean value indicating if there were submissions in the past 24h."
+Portion of the log(s):
+
+ossec: output: 'head -1 /var/lib/securedrop/submissions_today.txt | grep '^[0-9]*$'':
+0
+
+
+
+ --END OF NOTIFICATION
+
diff --git a/testinfra/ossec/alert-journalist-two.txt b/testinfra/ossec/alert-journalist-two.txt
new file mode 100644
index 0000000000..4c3e2f8cab
--- /dev/null
+++ b/testinfra/ossec/alert-journalist-two.txt
@@ -0,0 +1,39 @@
+OSSEC HIDS Notification.
+2018 May 06 20:18:24
+
+Received From: (app) 10.0.1.4->netstat -tan |grep LISTEN |grep -v 127.0.0.1 | sort
+Rule: 533 fired (level 7) -> "Listened ports status (netstat) changed (new port opened or closed)."
+Portion of the log(s):
+
+ossec: output: 'netstat -tan |grep LISTEN |grep -v 127.0.0.1 | sort':
+tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
+tcp 0 0 0.0.0.0:37294 0.0.0.0:* LISTEN
+tcp6 0 0 :::111 :::* LISTEN
+tcp6 0 0 :::44352 :::* LISTEN
+Previous output:
+ossec: output: 'netstat -tan |grep LISTEN |grep -v 127.0.0.1 | sort':
+tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
+tcp 0 0 0.0.0.0:48638 0.0.0.0:* LISTEN
+tcp6 0 0 :::111 :::* LISTEN
+tcp6 0 0 :::37312 :::* LISTEN
+
+
+
+ --END OF NOTIFICATION
+
+
+
+OSSEC HIDS Notification.
+2018 May 06 20:18:24
+
+Received From: (app) 10.0.1.4->head -1 /var/lib/securedrop/submissions_today.txt | grep '^[0-9]*$'
+Rule: 400600 fired (level 1) -> "Boolean value indicating if there were submissions in the past 24h."
+Portion of the log(s):
+
+ossec: output: 'head -1 /var/lib/securedrop/submissions_today.txt | grep '^[0-9]*$'':
+0
+
+
+
+ --END OF NOTIFICATION
+
diff --git a/testinfra/ossec/alert-ossec.txt b/testinfra/ossec/alert-ossec.txt
new file mode 100644
index 0000000000..4203a88c84
--- /dev/null
+++ b/testinfra/ossec/alert-ossec.txt
@@ -0,0 +1,22 @@
+OSSEC HIDS Notification.
+2018 May 06 20:18:24
+
+Received From: (app) 10.0.1.4->netstat -tan |grep LISTEN |grep -v 127.0.0.1 | sort
+Rule: 533 fired (level 7) -> "Listened ports status (netstat) changed (new port opened or closed)."
+Portion of the log(s):
+
+ossec: output: 'netstat -tan |grep LISTEN |grep -v 127.0.0.1 | sort':
+tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
+tcp 0 0 0.0.0.0:37294 0.0.0.0:* LISTEN
+tcp6 0 0 :::111 :::* LISTEN
+tcp6 0 0 :::44352 :::* LISTEN
+Previous output:
+ossec: output: 'netstat -tan |grep LISTEN |grep -v 127.0.0.1 | sort':
+tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
+tcp 0 0 0.0.0.0:48638 0.0.0.0:* LISTEN
+tcp6 0 0 :::111 :::* LISTEN
+tcp6 0 0 :::37312 :::* LISTEN
+
+
+
+ --END OF NOTIFICATION
diff --git a/testinfra/ossec/test_journalist_mail.py b/testinfra/ossec/test_journalist_mail.py
index 69dd319906..702007f6ea 100644
--- a/testinfra/ossec/test_journalist_mail.py
+++ b/testinfra/ossec/test_journalist_mail.py
@@ -64,17 +64,18 @@ class TestJournalistMail(TestBase):
def test_procmail(self, host):
self.service_started(host, "postfix")
- today_payload = (
- 'ossec: output: head -1 /var/lib/securedrop/submissions_today.txt'
- '\n1234')
- for (destination, payload) in (
- ('journalist', today_payload),
- ('ossec', 'MYGREATPAYLOAD')):
+ for (destination, f) in (
+ ('journalist', 'alert-journalist-one.txt'),
+ ('journalist', 'alert-journalist-two.txt'),
+ ('ossec', 'alert-ossec.txt')):
+ self.ansible(host, "copy",
+ "dest=/tmp/{f} src=testinfra/ossec/{f}".format(f=f))
+ assert self.run(host,
+ "/var/ossec/process_submissions_today.sh forget")
assert self.run(host, "postsuper -d ALL")
assert self.run(
host,
- "echo -e '{payload}' | "
- "mail -s 'abc' root@localhost".format(payload=payload))
+ "cat /tmp/{f} | mail -s 'abc' root@localhost".format(f=f))
assert self.wait_for_command(
host,
"mailq | grep -q {destination}@ossec.test".format(
@@ -82,7 +83,12 @@ def test_procmail(self, host):
self.service_stopped(host, "postfix")
def test_process_submissions_today(self, host):
- self.run(host, "/var/ossec/process_submissions_today.sh test_main")
+ assert self.run(host,
+ "/var/ossec/process_submissions_today.sh "
+ "test_handle_notification")
+ assert self.run(host,
+ "/var/ossec/process_submissions_today.sh "
+ "test_modified_in_the_past_24h")
def test_send_encrypted_alert(self, host):
self.service_started(host, "postfix")
@@ -109,8 +115,8 @@ def trigger(who, payload):
# encrypted mail to journalist or ossec contact
#
for (who, payload, expected) in (
- ('journalist', 'ossec: output\n1', '1'),
- ('ossec', 'MYGREATPAYLOAD', 'MYGREATPAYLOAD')):
+ ('journalist', 'JOURNALISTPAYLOAD', 'JOURNALISTPAYLOAD'),
+ ('ossec', 'OSSECPAYLOAD', 'OSSECPAYLOAD')):
assert self.run(host, "postsuper -d ALL")
trigger(who, payload)
assert self.run(
@@ -185,10 +191,15 @@ def test_journalist_mail_notification(self, host):
# empty the mailq on mon in case there were leftovers
#
assert self.run(mon, "postsuper -d ALL")
+ #
+ # forget about past notifications in case there were leftovers
+ #
+ assert self.run(mon, "/var/ossec/process_submissions_today.sh forget")
#
# the command fires every time ossec starts,
# regardless of the frequency
+ # https://github.com/ossec/ossec-hids/issues/1415
#
with app.sudo():
self.service_restarted(app, "ossec")
@@ -203,6 +214,21 @@ def test_journalist_mail_notification(self, host):
mon,
"test 1 = $(mailq | grep journalist@ossec.test | wc -l)")
+ assert self.run(
+ mon,
+ "grep --count 'notification suppressed' /var/log/syslog "
+ "> /tmp/before")
+
+ #
+ # The second notification within less than 24h is suppressed
+ #
+ with app.sudo():
+ self.service_restarted(app, "ossec")
+ assert self.wait_for_command(mon, """
+ grep --count 'notification suppressed' /var/log/syslog > /tmp/after
+ test $(cat /tmp/before) -lt $(cat /tmp/after)
+ """)
+
#
# teardown the ossec and postfix on mon and app
#