summaryrefslogtreecommitdiff
path: root/puppet/modules/site_postfix
diff options
context:
space:
mode:
Diffstat (limited to 'puppet/modules/site_postfix')
-rw-r--r--puppet/modules/site_postfix/files/checks/received_anon2
-rw-r--r--puppet/modules/site_postfix/manifests/mx.pp123
-rw-r--r--puppet/modules/site_postfix/manifests/mx/checks.pp18
-rw-r--r--puppet/modules/site_postfix/manifests/mx/received_anon.pp13
-rw-r--r--puppet/modules/site_postfix/manifests/mx/reserved_aliases.pp15
-rw-r--r--puppet/modules/site_postfix/manifests/mx/rewrite_openpgp_header.pp11
-rw-r--r--puppet/modules/site_postfix/manifests/mx/smtp_tls.pp17
-rw-r--r--puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp19
-rw-r--r--puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp16
-rw-r--r--puppet/modules/site_postfix/manifests/mx/static_aliases.pp88
-rw-r--r--puppet/modules/site_postfix/templates/checks/helo_access.erb2
-rw-r--r--puppet/modules/site_postfix/templates/checks/rewrite_openpgp_headers.erb13
-rw-r--r--puppet/modules/site_postfix/templates/virtual-aliases.erb21
13 files changed, 287 insertions, 71 deletions
diff --git a/puppet/modules/site_postfix/files/checks/received_anon b/puppet/modules/site_postfix/files/checks/received_anon
index 2822973e..9de25e63 100644
--- a/puppet/modules/site_postfix/files/checks/received_anon
+++ b/puppet/modules/site_postfix/files/checks/received_anon
@@ -1,2 +1,2 @@
-/^Received: from (.* \([-._[:alnum:]]+ \[[.[:digit:]]{7,15}\]\))([[:space:]]+).*(\(using [.[:alnum:]]+ with cipher [-A-Z0-9]+ \([0-9]+\/[0-9]+ bits\)\))[[:space:]]+\(Client CN "([[:alnum:]]+)", Issuer "[[:print:]]+" \(verified OK\)\)[[:space:]]+by ([.[:alnum:]]+) \(([^)]+)\) with (E?SMTPS?A?) id ([A-F[:digit:]]+).*/
+/^Received: from (.* \([-._[:alnum:]]+ \[[.[:digit:]]{7,15}\]\))([[:space:]]+).*(\(using [.[:alnum:]]+ with cipher [-A-Z0-9]+ \([0-9]+\/[0-9]+ bits\)\))[[:space:]]+\(Client CN "([-._@[:alnum:]]+)", Issuer "[[:print:]]+" \(verified OK\)\)[[:space:]]+by ([.[:alnum:]]+) \(([^)]+)\) with (E?SMTPS?A?) id ([A-F[:digit:]]+).*/
REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1])${2}${3}${2}(Authenticated sender: $4)${2}with $7 id $8
diff --git a/puppet/modules/site_postfix/manifests/mx.pp b/puppet/modules/site_postfix/manifests/mx.pp
index 49692d24..c269946b 100644
--- a/puppet/modules/site_postfix/manifests/mx.pp
+++ b/puppet/modules/site_postfix/manifests/mx.pp
@@ -7,10 +7,12 @@ class site_postfix::mx {
$domain = $domain_hash['full_suffix']
$host_domain = $domain_hash['full']
$cert_name = hiera('name')
- $mynetworks = join(hiera('mynetworks'), ' ')
+ $mynetworks = join(hiera('mynetworks', ''), ' ')
+ $rbls = suffix(prefix(hiera('rbls', []), 'reject_rbl_client '), ',')
- $root_mail_recipient = hiera('contacts')
- $postfix_smtp_listen = 'all'
+ $root_mail_recipient = hiera('contacts')
+ $postfix_smtp_listen = 'all'
+ $postfix_use_postscreen = 'yes'
include site_config::x509::cert
include site_config::x509::key
@@ -20,20 +22,41 @@ class site_postfix::mx {
postfix::config {
'mynetworks':
value => "127.0.0.0/8 [::1]/128 [fe80::]/64 ${mynetworks}";
+ # Note: mydestination should not include @domain, because this is
+ # used in virtual alias maps.
'mydestination':
- value => "\$myorigin, localhost, localhost.\$mydomain, ${domain}";
+ value => "\$myorigin, localhost, localhost.\$mydomain";
'myhostname':
value => $host_domain;
'mailbox_size_limit':
value => '0';
'home_mailbox':
- value => 'Maildir/';
+ value => '';
+ 'virtual_mailbox_domains':
+ value => 'deliver.local';
+ 'virtual_mailbox_base':
+ value => '/var/mail/leap-mx';
+ 'virtual_mailbox_maps':
+ value => 'static:Maildir/';
+ # Note: virtual-aliases map will take precedence over leap-mx
+ # lookup (tcp:localhost)
'virtual_alias_maps':
- value => 'tcp:localhost:4242';
+ value => 'hash:/etc/postfix/virtual-aliases tcp:localhost:4242';
'luser_relay':
- value => 'vmail';
- 'smtpd_tls_received_header':
- value => 'yes';
+ value => '';
+ # uid and gid are set to an arbitrary hard-coded value here, this
+ # must match the 'leap-mx' user/group
+ 'virtual_uid_maps':
+ value => 'static:42424';
+ 'virtual_gid_maps':
+ value => 'static:42424';
+ # the two following configs are needed for matching user's client cert
+ # fingerprints to enable relaying (#3634). Satellites do not have
+ # these configured.
+ 'smtpd_tls_fingerprint_digest':
+ value => 'sha1';
+ 'relay_clientcerts':
+ value => 'tcp:localhost:2424';
# Note: we are setting this here, instead of in site_postfix::mx::smtp_tls
# because the satellites need to have a different value
'smtp_tls_security_level':
@@ -44,40 +67,86 @@ class site_postfix::mx {
# alias map
'local_recipient_maps':
value => '$alias_maps';
+ # setup clamav and opendkim on smtpd
+ 'smtpd_milters':
+ value => 'unix:/run/clamav/milter.ctl,inet:localhost:8891';
+ # setup opendkim for smtp (non-smtpd) outgoing mail
+ 'non_smtpd_milters':
+ value => 'inet:localhost:8891';
+ 'milter_default_action':
+ value => 'accept';
+ # Make sure that the right values are set, these could be set to different
+ # things on install, depending on preseed or debconf options
+ # selected (see #7478)
+ 'relay_transport':
+ value => 'relay';
+ 'default_transport':
+ value => 'smtp';
+ 'mailbox_command':
+ value => '';
+ 'header_checks':
+ value => '';
+ 'postscreen_access_list':
+ value => 'permit_mynetworks';
+ 'postscreen_greet_action':
+ value => 'enforce';
}
- include site_postfix::mx::smtpd_checks
- include site_postfix::mx::checks
- include site_postfix::mx::smtp_tls
- include site_postfix::mx::smtpd_tls
- include site_postfix::mx::reserved_aliases
+ # Make sure that the cleanup serivce is not chrooted, otherwise it cannot
+ # access the opendkim milter socket (#8020)
+ exec { 'unset_cleanup_chroot':
+ command => '/usr/sbin/postconf -F "cleanup/unix/chroot=n"',
+ onlyif => '/usr/sbin/postconf -h -F "cleanup/unix/chroot" | egrep -q ^n',
+ notify => Service['postfix'],
+ require => File['/etc/postfix/master.cf']
+ }
+
+ include ::site_postfix::mx::smtpd_checks
+ include ::site_postfix::mx::checks
+ include ::site_postfix::mx::smtp_tls
+ include ::site_postfix::mx::smtpd_tls
+ include ::site_postfix::mx::static_aliases
+ include ::site_postfix::mx::rewrite_openpgp_header
+ include ::site_postfix::mx::received_anon
+ include ::clamav
+ include ::opendkim
+ include ::postfwd
# greater verbosity for debugging, take out for production
#include site_postfix::debug
- user { 'vmail':
- ensure => present,
- comment => 'Leap Mailspool',
- home => '/var/mail/vmail',
- shell => '/bin/false',
- managehome => true,
+ case $::operatingsystemrelease {
+ /^7.*/: {
+ $smtpd_relay_restrictions=''
+ }
+ default: {
+ $smtpd_relay_restrictions=" -o smtpd_relay_restrictions=\$smtps_relay_restrictions\n"
+ }
}
+ $mastercf_tail = "
+smtps inet n - - - - smtpd
+ -o smtpd_tls_wrappermode=yes
+ -o smtpd_tls_security_level=encrypt
+ -o tls_preempt_cipherlist=yes
+${smtpd_relay_restrictions} -o smtpd_recipient_restrictions=\$smtps_recipient_restrictions
+ -o smtpd_helo_restrictions=\$smtps_helo_restrictions
+ -o smtpd_client_restrictions=
+ -o cleanup_service_name=clean_smtps
+clean_smtps unix n - n - 0 cleanup
+ -o header_checks=pcre:/etc/postfix/checks/rewrite_openpgp_headers,pcre:/etc/postfix/checks/received_anon"
+
class { 'postfix':
preseed => true,
root_mail_recipient => $root_mail_recipient,
smtp_listen => 'all',
- mastercf_tail =>
- "smtps inet n - - - - smtpd
- -o smtpd_tls_wrappermode=yes
- -o smtpd_tls_security_level=encrypt
- -o smtpd_recipient_restrictions=\$smtps_recipient_restrictions
- -o smtpd_helo_restrictions=\$smtps_helo_restrictions",
+ mastercf_tail => $mastercf_tail,
+ use_postscreen => 'yes',
require => [
Class['Site_config::X509::Key'],
Class['Site_config::X509::Cert'],
Class['Site_config::X509::Client_ca::Key'],
Class['Site_config::X509::Client_ca::Ca'],
- User['vmail'] ]
+ User['leap-mx'] ]
}
}
diff --git a/puppet/modules/site_postfix/manifests/mx/checks.pp b/puppet/modules/site_postfix/manifests/mx/checks.pp
index 5d75a5e5..f406ad34 100644
--- a/puppet/modules/site_postfix/manifests/mx/checks.pp
+++ b/puppet/modules/site_postfix/manifests/mx/checks.pp
@@ -20,22 +20,4 @@ class site_postfix::mx::checks {
refreshonly => true,
subscribe => File['/etc/postfix/checks/helo_checks'];
}
-
- # Anonymize the user's home IP from the email headers (Feature #3866)
- package { 'postfix-pcre': ensure => installed, require => Package['postfix'] }
-
- file { '/etc/postfix/checks/received_anon':
- source => 'puppet:///modules/site_postfix/checks/received_anon',
- mode => '0644',
- owner => root,
- group => root,
- notify => Service['postfix']
- }
-
- postfix::config {
- 'header_checks':
- value => 'pcre:/etc/postfix/checks/received_anon',
- require => File['/etc/postfix/checks/received_anon'];
- }
-
}
diff --git a/puppet/modules/site_postfix/manifests/mx/received_anon.pp b/puppet/modules/site_postfix/manifests/mx/received_anon.pp
new file mode 100644
index 00000000..51ba3faa
--- /dev/null
+++ b/puppet/modules/site_postfix/manifests/mx/received_anon.pp
@@ -0,0 +1,13 @@
+# Anonymize the user's home IP from the email headers (Feature #3866)
+class site_postfix::mx::received_anon {
+
+ package { 'postfix-pcre': ensure => installed, require => Package['postfix'] }
+
+ file { '/etc/postfix/checks/received_anon':
+ source => 'puppet:///modules/site_postfix/checks/received_anon',
+ mode => '0644',
+ owner => root,
+ group => root,
+ notify => Service['postfix']
+ }
+}
diff --git a/puppet/modules/site_postfix/manifests/mx/reserved_aliases.pp b/puppet/modules/site_postfix/manifests/mx/reserved_aliases.pp
deleted file mode 100644
index 83e27376..00000000
--- a/puppet/modules/site_postfix/manifests/mx/reserved_aliases.pp
+++ /dev/null
@@ -1,15 +0,0 @@
-# Defines which mail addresses shouldn't be available and where they should fwd
-class site_postfix::mx::reserved_aliases {
-
- postfix::mailalias {
- [ 'abuse', 'admin', 'arin-admin', 'administrator', 'bin', 'cron',
- 'certmaster', 'domainadmin', 'games', 'ftp', 'hostmaster', 'lp',
- 'maildrop', 'mysql', 'news', 'nobody', 'noc', 'postmaster', 'postgresql',
- 'security', 'ssladmin', 'sys', 'usenet', 'uucp', 'webmaster', 'www',
- 'www-data',
- ]:
- ensure => present,
- recipient => 'root'
- }
-
-}
diff --git a/puppet/modules/site_postfix/manifests/mx/rewrite_openpgp_header.pp b/puppet/modules/site_postfix/manifests/mx/rewrite_openpgp_header.pp
new file mode 100644
index 00000000..71f945b8
--- /dev/null
+++ b/puppet/modules/site_postfix/manifests/mx/rewrite_openpgp_header.pp
@@ -0,0 +1,11 @@
+class site_postfix::mx::rewrite_openpgp_header {
+ $mx = hiera('mx')
+ $correct_domain = $mx['key_lookup_domain']
+
+ file { '/etc/postfix/checks/rewrite_openpgp_headers':
+ content => template('site_postfix/checks/rewrite_openpgp_headers.erb'),
+ mode => '0644',
+ owner => root,
+ group => root;
+ }
+}
diff --git a/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp b/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp
index d56f6b54..c93c3ba2 100644
--- a/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp
+++ b/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp
@@ -1,11 +1,16 @@
+# configure smtp tls
class site_postfix::mx::smtp_tls {
include site_config::x509::ca
include x509::variables
+ $cert_name = hiera('name')
$ca_path = "${x509::variables::local_CAs}/${site_config::params::ca_name}.crt"
$cert_path = "${x509::variables::certs}/${site_config::params::cert_name}.crt"
$key_path = "${x509::variables::keys}/${site_config::params::cert_name}.key"
+ include site_config::x509::cert
+ include site_config::x509::key
+
# smtp TLS
postfix::config {
'smtp_use_tls': value => 'yes';
@@ -20,9 +25,19 @@ class site_postfix::mx::smtp_tls {
'smtp_tls_fingerprint_digest':
value => 'sha1';
'smtp_tls_session_cache_database':
- value => 'btree:${data_directory}/smtp_cache';
+ value => "btree:\${data_directory}/smtp_cache";
# see issue #4011
'smtp_tls_protocols':
value => '!SSLv2, !SSLv3';
+ 'smtp_tls_mandatory_protocols':
+ value => '!SSLv2, !SSLv3';
+ 'tls_ssl_options':
+ value => 'NO_COMPRESSION';
+ # We can switch between the different postfix internal list of ciphers by
+ # using smtpd_tls_ciphers. For server-to-server connections we leave this
+ # at its default because of opportunistic encryption combined with many mail
+ # servers only support outdated protocols and ciphers and if we are too
+ # strict with required ciphers, then connections *will* fall-back to
+ # plain-text. Bad ciphers are still better than plain text transmission.
}
}
diff --git a/puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp b/puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp
index 0ec40277..291d7ee4 100644
--- a/puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp
+++ b/puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp
@@ -1,3 +1,5 @@
+# smtpd checks for incoming mail on smtp port 25 and
+# mail sent via the bitmask client using smtps port 465
class site_postfix::mx::smtpd_checks {
postfix::config {
@@ -6,7 +8,7 @@ class site_postfix::mx::smtpd_checks {
'checks_dir':
value => '$config_directory/checks';
'smtpd_client_restrictions':
- value => 'permit_mynetworks,permit';
+ value => "permit_mynetworks,${site_postfix::mx::rbls},permit";
'smtpd_data_restrictions':
value => 'permit_mynetworks, reject_unauth_pipelining, permit';
'smtpd_delay_reject':
@@ -15,13 +17,16 @@ class site_postfix::mx::smtpd_checks {
value => 'permit_mynetworks, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, check_helo_access hash:$checks_dir/helo_checks, permit';
'smtpd_recipient_restrictions':
value => 'reject_unknown_recipient_domain, permit_mynetworks, check_recipient_access tcp:localhost:2244, reject_unauth_destination, permit';
- # We should change from permit_tls_all_clientcerts to permit_tls_clientcerts
- # with a lookup on $relay_clientcerts! Right now we are listing the only
- # valid CA that client certificates can use in the $smtp_tls_CAfile parameter
- # but we cannot cut off a certificate that should no longer be used unless
- # we use permit_tls_clientcerts with the $relay_clientcerts lookup
+
+ # permit_tls_clientcerts will lookup client cert fingerprints from the tcp
+ # lookup on port 2424 (based on what is configured in relay_clientcerts
+ # paramter, see site_postfix::mx postfix::config resource) to determine
+ # if a client is allowed to relay mail through us. This enables us to
+ # disable a user by removing their valid client cert (#3634)
'smtps_recipient_restrictions':
- value => 'permit_tls_all_clientcerts, check_recipient_access tcp:localhost:2244, reject_unauth_destination, permit';
+ value => 'permit_tls_clientcerts, check_recipient_access tcp:localhost:2244, reject_unauth_destination, permit';
+ 'smtps_relay_restrictions':
+ value => 'permit_mynetworks, permit_tls_clientcerts, defer_unauth_destination';
'smtps_helo_restrictions':
value => 'permit_mynetworks, check_helo_access hash:$checks_dir/helo_checks, permit';
'smtpd_sender_restrictions':
diff --git a/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp b/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp
index 0809c75f..66297f55 100644
--- a/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp
+++ b/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp
@@ -1,3 +1,4 @@
+# configure smtpd tls
class site_postfix::mx::smtpd_tls {
include x509::variables
@@ -12,12 +13,25 @@ class site_postfix::mx::smtpd_tls {
'smtpd_tls_cert_file': value => $cert_path;
'smtpd_tls_key_file': value => $key_path;
'smtpd_tls_ask_ccert': value => 'yes';
+ 'smtpd_tls_received_header':
+ value => 'yes';
'smtpd_tls_security_level':
value => 'may';
'smtpd_tls_eecdh_grade':
value => 'ultra';
'smtpd_tls_session_cache_database':
- value => 'btree:${data_directory}/smtpd_scache';
+ value => "btree:\${data_directory}/smtpd_scache";
+ # see issue #4011
+ 'smtpd_tls_mandatory_protocols':
+ value => '!SSLv2, !SSLv3';
+ 'smtpd_tls_protocols':
+ value => '!SSLv2, !SSLv3';
+ # For connections to MUAs, TLS is mandatory and the ciphersuite is modified.
+ # MX and SMTP client configuration
+ 'smtpd_tls_mandatory_ciphers':
+ value => 'high';
+ 'tls_high_cipherlist':
+ value => 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!RC4:!MD5:!PSK!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
}
# Setup DH parameters
diff --git a/puppet/modules/site_postfix/manifests/mx/static_aliases.pp b/puppet/modules/site_postfix/manifests/mx/static_aliases.pp
new file mode 100644
index 00000000..9cd7ca02
--- /dev/null
+++ b/puppet/modules/site_postfix/manifests/mx/static_aliases.pp
@@ -0,0 +1,88 @@
+#
+# Defines static, hard coded aliases that are not in the database.
+# These aliases take precedence over the database aliases.
+#
+# There are three classes of reserved names:
+#
+# (1) forbidden_usernames:
+# Some usernames are forbidden and cannot be registered.
+# this is defined in node property webapp.forbidden_usernames
+# This is enforced by the webapp.
+#
+# (2) public aliases:
+# Some aliases for root, and are publicly exposed so that anyone
+# can deliver mail to them. For example, postmaster.
+# These are implemented in the virtual alias map, which takes
+# precedence over the local alias map.
+#
+# (3) local aliases:
+# Some aliases are only available locally: mail can be delivered
+# to the alias if the mail originates from the local host, or is
+# hostname qualified, but otherwise it will be rejected.
+# These are implemented in the local alias map.
+#
+# The alias for local 'root' is defined elsewhere. In this file, we
+# define the virtual 'root@domain' (which can be overwritten by
+# defining an entry for root in node property mx.aliases).
+#
+
+class site_postfix::mx::static_aliases {
+
+ $mx = hiera('mx')
+ $root_recipients = hiera('contacts')
+
+ #
+ # LOCAL ALIASES
+ #
+
+ # NOTE: if you remove one of these, they will still appear in the
+ # /etc/aliases file
+ $local_aliases = [
+ 'admin', 'administrator', 'bin', 'cron', 'games', 'ftp', 'lp', 'maildrop',
+ 'mysql', 'news', 'nobody', 'noc', 'postgresql', 'ssladmin', 'sys',
+ 'usenet', 'uucp', 'www', 'www-data', 'leap-mx'
+ ]
+
+ postfix::mailalias {
+ $local_aliases:
+ ensure => present,
+ recipient => 'root'
+ }
+
+ #
+ # PUBLIC ALIASES
+ #
+
+ $public_aliases = $mx['aliases']
+
+ $default_public_aliases = {
+ 'root' => $root_recipients,
+ 'abuse' => 'postmaster',
+ 'arin-admin' => 'root',
+ 'certmaster' => 'hostmaster',
+ 'domainadmin' => 'hostmaster',
+ 'hostmaster' => 'root',
+ 'mailer-daemon' => 'postmaster',
+ 'postmaster' => 'root',
+ 'security' => 'root',
+ 'webmaster' => 'hostmaster',
+ }
+
+ $aliases = merge($default_public_aliases, $public_aliases)
+
+ exec { 'postmap_virtual_aliases':
+ command => '/usr/sbin/postmap /etc/postfix/virtual-aliases',
+ refreshonly => true,
+ user => root,
+ group => root,
+ require => Package['postfix'],
+ subscribe => File['/etc/postfix/virtual-aliases']
+ }
+ file { '/etc/postfix/virtual-aliases':
+ content => template('site_postfix/virtual-aliases.erb'),
+ owner => root,
+ group => root,
+ mode => '0600',
+ require => Package['postfix']
+ }
+}
diff --git a/puppet/modules/site_postfix/templates/checks/helo_access.erb b/puppet/modules/site_postfix/templates/checks/helo_access.erb
index bef3c11d..bac2c45a 100644
--- a/puppet/modules/site_postfix/templates/checks/helo_access.erb
+++ b/puppet/modules/site_postfix/templates/checks/helo_access.erb
@@ -18,4 +18,4 @@
# Reject anybody that HELO's as being in our own domain(s)
# anyone who identifies themselves as us is a virus/spammer
-<%= domain %> 554 You are not in domain <%= domain %>
+<%= @domain %> 554 You are not in domain <%= @domain %>
diff --git a/puppet/modules/site_postfix/templates/checks/rewrite_openpgp_headers.erb b/puppet/modules/site_postfix/templates/checks/rewrite_openpgp_headers.erb
new file mode 100644
index 00000000..7af14f7d
--- /dev/null
+++ b/puppet/modules/site_postfix/templates/checks/rewrite_openpgp_headers.erb
@@ -0,0 +1,13 @@
+# THIS FILE IS MANAGED BY PUPPET
+#
+# This will replace the OpenPGP header that the client adds, because it is
+# sometimes incorrect (due to the client not always knowing what the proper URL
+# is for the webapp).
+# e.g. This will rewrite this header:
+# OpenPGP: id=4C0E01CD50E2F653; url="https://leap.se/key/elijah"; preference="signencrypt
+# with this replacement:
+# OpenPGP: id=4C0E01CD50E2F653; url="https://user.leap.se/key/elijah"; preference="signencrypt
+#
+# Note: whitespace in the pattern is represented by [[:space:]] to avoid these warnings from postmap:
+# "record is in "key: value" format; is this an alias file?" and "duplicate entry"
+/^(OpenPGP:[[:space:]]id=[[:alnum:]]+;[[:space:]]url="https:\/\/)<%= @domain %>(\/key\/[[:alpha:]]+";.*)/i REPLACE ${1}<%= @correct_domain %>${2}
diff --git a/puppet/modules/site_postfix/templates/virtual-aliases.erb b/puppet/modules/site_postfix/templates/virtual-aliases.erb
new file mode 100644
index 00000000..8373de97
--- /dev/null
+++ b/puppet/modules/site_postfix/templates/virtual-aliases.erb
@@ -0,0 +1,21 @@
+#
+# This file is managed by puppet.
+#
+# These virtual aliases take precedence over all other aliases.
+#
+
+#
+# enable these virtual domains:
+#
+<%= @domain %> enabled
+<%- @aliases.keys.map {|addr| addr.split('@')[1] }.compact.sort.uniq.each do |virt_domain| -%>
+<%= virt_domain %> enabled
+<%- end %>
+
+#
+# virtual aliases:
+#
+<%- @aliases.keys.sort.each do |from| -%>
+<%- full_address = from =~ /@/ ? from : from + "@" + @domain -%>
+<%= full_address %> <%= [@aliases[from]].flatten.map{|a| a =~ /@/ ? a : a + "@" + @domain}.join(', ') %>
+<%- end -%>