Skip to content

Commit

Permalink
Use actual hostname in Postfix configuration
Browse files Browse the repository at this point in the history
The legacy "ossec.server" value of the Postfix myhostname setting does
not match our current recommended mon server hostname ("mon"), so
prevents correct rewriting of the from address when sending to the
SMTP relay.

This changes the "postfix_hostname" Ansible variable to use the value
of "monitor_hostname". The "postfix_from_address" still uses
"ossec_from_address" if configured, but now defaults to
sasl_username@sasl_domain if sasl_domain is supplied, enabling another
chance for a valid rewrite of ossec@mon. If neither ossec_from_address
nor sasl_domain is specified, postfix_from_address will be empty, and
in that case the playbook will now remove an existing
/etc/postfix/generic database.
  • Loading branch information
rmol committed May 6, 2021
1 parent 84b7042 commit ee87e05
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 17 deletions.
8 changes: 5 additions & 3 deletions install_files/ansible-base/roles/postfix/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
# Email address listed in the FROM line when sending OSSEc email alerts.
# Some mail servers require that this match the account that authenticated
# to send mail. Using the `ossec_from_address` for backwards-compatibility.
postfix_from_address: "{{ ossec_from_address|default('') }}"
# to send mail. Using the `ossec_from_address` for
# backwards-compatibility.
sasl_id: "{% if sasl_domain %}{{ sasl_username }}@{{ sasl_domain }}{% endif %}"
postfix_from_address: "{{ ossec_from_address|default(sasl_id) }}"

# Apt dependencies for the ossec server package
postfix_dependencies:
Expand All @@ -11,7 +13,7 @@ postfix_dependencies:
- mailutils

# Configuration info for procmail and postfix
postfix_hostname: ossec.server
postfix_hostname: "{{ monitor_hostname }}"

# Whether to enable Postfix for sending mail. Required in prod,
# but unnecessary in staging contexts, where SASL authentication
Expand Down
15 changes: 13 additions & 2 deletions install_files/ansible-base/roles/postfix/tasks/install_postfix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,26 @@
tags:
- postfix

- name: Create mapping for outbound address.
- name: Create outbound mapping for postfix_from_address in /etc/postfix/generic.
copy:
content: "ossec@{{ postfix_hostname }} {{ postfix_from_address }}"
content: "ossec@{{ postfix_hostname }} {{ postfix_from_address }}\n"
dest: /etc/postfix/generic
notify: update generic_maps
when: postfix_from_address != ""
tags:
- postfix

- name: Remove /etc/postfix/generic database because postfix_from_address is empty.
file:
state: absent
dest: "{{ item }}"
with_items:
- /etc/postfix/generic
- /etc/postfix/generic.db
when: postfix_from_address == ""
tags:
- postfix

- name: Configure SASL password for SMTP relay.
template:
src: sasl_passwd
Expand Down
52 changes: 50 additions & 2 deletions install_files/securedrop-ossec-server/DEBIAN/postinst
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,72 @@ set -x
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package

configure_postfix_myhostname() {
if [ -f /etc/postfix/main.cf ]
then
sed -i -E "s/^myhostname\\s*=\\s*ossec.server.*$/myhostname = $(hostname -f)/" /etc/postfix/main.cf
fi
}

configure_postfix_generics() {
if [ -f /etc/postfix/main.cf ]
then
python3 - <<EOF
import pathlib
import re
import sys
try:
sasl_id = open("/etc/postfix/sasl_passwd").readline().split()[1].split(":")[0]
except:
print("Could not extract SASL ID from /etc/postfix/sasl_passwd")
sys.exit(0)
try:
maincf = open("/etc/postfix/main.cf").read()
hostname = open("/etc/hostname").readline().strip()
rewrite_target = sasl_id
generic = pathlib.Path("/etc/postfix/generic")
if generic.is_file():
rewrite_target = generic.open().readline().split()[1]
if '@' in rewrite_target:
with generic.open("w") as g:
g.write("ossec@{} {}\n".format(hostname, rewrite_target))
else:
generic.unlink(missing_ok=True)
pathlib.Path("/etc/postfix/generic.db").unlink(missing_ok=True)
except Exception as e:
print("Could not update /etc/postfix/generic:", e)
print('Please run "securedrop-admin install" from the admin workstation to correct.')
sys.exit(0)
EOF
if [ -f /etc/postfix/generic ]
then
postmap /etc/postfix/generic
fi
fi
}

case "$1" in
configure)
GROUP="ossec"
OSSEC_HOME="/var/ossec"

configure_postfix_myhostname
configure_postfix_generics

# Ensure the correct file permissions and ownership are set for the
# config files.
chown root:${GROUP} ${OSSEC_HOME}/etc/local_decoder.xml
chmod 440 ${OSSEC_HOME}/etc/local_decoder.xml

chown root:${GROUP} ${OSSEC_HOME}/rules/local_rules.xml
chmod 440 ${OSSEC_HOME}/rules/local_rules.xml

# Ensure correct gnupg directory permissions and ownership
chown -R ossec:${GROUP} ${OSSEC_HOME}/.gnupg
find ${OSSEC_HOME}/.gnupg -type f -exec chmod 600 {} \;
find ${OSSEC_HOME}/.gnupg -type d -exec chmod 700 {} \;

# Replace localhost with 127.0.0.1 for smtp_server due to
# https://github.com/ossec/ossec-hids/issues/1145
sed -i -e "s/<smtp_server>localhost<\/smtp_server>/<smtp_server>127.0.0.1<\/smtp_server>/g" /var/ossec/etc/ossec.conf
Expand Down
18 changes: 11 additions & 7 deletions molecule/testinfra/mon/test_postfix.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,18 @@ def test_postfix_headers(host, header):

def test_postfix_generic_maps(host):
"""
Regression test to check that generic Postfix maps are not configured
by default. As of #1565 Admins can opt-in to overriding the FROM address
used for sending OSSEC alerts, but by default we're preserving the old
`ossec@ossec.server` behavior, to avoid breaking email for previously
existing instances.
Check configuration of Postfix generic map when sasl_domain is set
and ossec_from_address is not specified.
"""
assert not host.file("/etc/postfix/generic").exists
assert not host.file("/etc/postfix/main.cf").contains("^smtp_generic_maps")
assert host.file("/etc/postfix/generic").exists
assert host.file("/etc/postfix/generic").contains(
"^ossec@{} {}@{}".format(
securedrop_test_vars.monitor_hostname,
securedrop_test_vars.sasl_username,
securedrop_test_vars.sasl_domain,
)
)
assert host.file("/etc/postfix/main.cf").contains("^smtp_generic_maps")
assert host.file("/etc/postfix/main.cf").contains(
"^smtpd_recipient_restrictions = reject_unauth_destination")

Expand Down
7 changes: 6 additions & 1 deletion molecule/testinfra/vars/mon-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ tor_services:
authenticated: yes # value will automatically be coerced to boolean
client: admin

# Disable Postfix in staging, since we don't have valid credentials.
# Postfix is disabled in staging.
postfix_enabled: False

# But it does get configured.
sasl_username: "test"
sasl_domain: "ossec.test"
sasl_password: "password123"

# Log events for OSSEC alerts we suppress
log_events_without_ossec_alerts:
# Check that using an overloaded guard does not produce an OSSEC alert
Expand Down
7 changes: 6 additions & 1 deletion molecule/testinfra/vars/qubes-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,14 @@ allowed_apache_logfiles:
- /var/log/apache2/other_vhosts_access.log
- /var/log/apache2/source-error.log

# Disable Postfix in staging, since we don't have valid credentials.
# Postfix is disabled in staging.
postfix_enabled: False

# But it does get configured.
sasl_username: "test"
sasl_domain: "ossec.test"
sasl_password: "password123"

# Log events for OSSEC alerts we suppress
log_events_without_ossec_alerts:
# Check that using an overloaded guard does not produce an OSSEC alert
Expand Down
7 changes: 6 additions & 1 deletion molecule/testinfra/vars/staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,14 @@ allowed_apache_logfiles:
- /var/log/apache2/other_vhosts_access.log
- /var/log/apache2/source-error.log

# Disable Postfix in staging, since we don't have valid credentials.
# Postfix is disabled in staging.
postfix_enabled: False

# But it does get configured.
sasl_username: "test"
sasl_domain: "ossec.test"
sasl_password: "password123"

# Log events for OSSEC alerts we suppress
log_events_without_ossec_alerts:
# Check that using an overloaded guard does not produce an OSSEC alert
Expand Down

0 comments on commit ee87e05

Please sign in to comment.