diff --git a/hieradata/common.yaml b/hieradata/common.yaml index 3863f91..7ca2200 100644 --- a/hieradata/common.yaml +++ b/hieradata/common.yaml @@ -158,6 +158,15 @@ lookup_options: rke2::config_hash: merge: strategy: deep + postfix::configs: + merge: + strategy: deep + postfix::maps: + merge: + strategy: deep + postfix::virtuals: + merge: + strategy: deep facts_path: '/opt/puppetlabs/facter/facts.d' diff --git a/hieradata/roles/infra/mail/gateway.yaml b/hieradata/roles/infra/mail/gateway.yaml index f3069bd..458b528 100644 --- a/hieradata/roles/infra/mail/gateway.yaml +++ b/hieradata/roles/infra/mail/gateway.yaml @@ -3,3 +3,50 @@ # additional altnames profiles::pki::vault::alt_names: - in-mta.main.unkin.net + +# base postfix configuration (passed to postfix class) +postfix::relayhost: 'direct' +postfix::myorigin: 'main.unkin.net' +postfix::mydestination: 'blank' +postfix::mynetworks: '127.0.0.0/8 [::1]/128' +postfix::mta: true +postfix::manage_aliases: true + +# profile parameters for customization +profiles::postfix::gateway::myhostname: 'in-mta.main.unkin.net' + +# postfix map content (templates) +profiles::postfix::gateway::relay_recipients_maps: + '@main.unkin.net': 'OK' + +profiles::postfix::gateway::relay_domains_maps: + 'main.unkin.net': 'OK' + +profiles::postfix::gateway::postscreen_access_maps: + '127.0.0.1/32': 'permit' + '10.10.12.200/32': 'permit' + +profiles::postfix::gateway::helo_access_maps: + '.dynamic.': 'REJECT' + '.dialup.': 'REJECT' + 'unknown': 'REJECT' + 'localhost': 'REJECT You are not localhost' + +# postfix transports +postfix::transports: + 'main.unkin.net': + ensure: present + destination: 'relay' + nexthop: 'ausyd1nxvm2120.main.unkin.net:25' + +# postfix virtuals +postfix::virtuals: + 'root': + ensure: present + destination: 'ben@main.unkin.net' + 'postmaster': + ensure: present + destination: 'ben@main.unkin.net' + 'abuse': + ensure: present + destination: 'ben@main.unkin.net' diff --git a/site/profiles/files/postfix/gateway/helo_access b/site/profiles/files/postfix/gateway/helo_access deleted file mode 100644 index 7ece2c6..0000000 --- a/site/profiles/files/postfix/gateway/helo_access +++ /dev/null @@ -1,11 +0,0 @@ -# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED - -# HELO/EHLO access controls -# Format: pattern action -# Actions: REJECT, OK, WARN, etc. - -# Block common spam patterns -.dynamic. REJECT -.dialup. REJECT -unknown REJECT -localhost REJECT You are not localhost \ No newline at end of file diff --git a/site/profiles/files/postfix/gateway/postscreen_access b/site/profiles/files/postfix/gateway/postscreen_access deleted file mode 100644 index 2e0743c..0000000 --- a/site/profiles/files/postfix/gateway/postscreen_access +++ /dev/null @@ -1,4 +0,0 @@ -# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED - -127.0.0.1/32 permit -10.10.12.200/32 permit diff --git a/site/profiles/files/postfix/gateway/recipient_access b/site/profiles/files/postfix/gateway/recipient_access deleted file mode 100644 index 9a09e9f..0000000 --- a/site/profiles/files/postfix/gateway/recipient_access +++ /dev/null @@ -1,9 +0,0 @@ -# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED - -# Recipient access controls -# Format: recipient_pattern action -# Actions: REJECT, OK, WARN, DISCARD, etc. - -# Protected recipients that require special handling -# Example entries: -# @main.unkin.net OK \ No newline at end of file diff --git a/site/profiles/files/postfix/gateway/recipient_canonical b/site/profiles/files/postfix/gateway/recipient_canonical deleted file mode 100644 index 63fe6d7..0000000 --- a/site/profiles/files/postfix/gateway/recipient_canonical +++ /dev/null @@ -1,8 +0,0 @@ -# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED - -# Recipient canonical address mapping -# Format: original_address canonical_address -# Used to rewrite recipient addresses - -# Example mappings: -# user@olddomain.com user@main.unkin.net \ No newline at end of file diff --git a/site/profiles/files/postfix/gateway/relay_domains b/site/profiles/files/postfix/gateway/relay_domains deleted file mode 100644 index c779905..0000000 --- a/site/profiles/files/postfix/gateway/relay_domains +++ /dev/null @@ -1,3 +0,0 @@ -# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED - -main.unkin.net OK diff --git a/site/profiles/files/postfix/gateway/relay_recipients b/site/profiles/files/postfix/gateway/relay_recipients deleted file mode 100644 index 209fc19..0000000 --- a/site/profiles/files/postfix/gateway/relay_recipients +++ /dev/null @@ -1,3 +0,0 @@ -# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED - -@main.unkin.net OK diff --git a/site/profiles/files/postfix/gateway/sender_access b/site/profiles/files/postfix/gateway/sender_access deleted file mode 100644 index ba803bd..0000000 --- a/site/profiles/files/postfix/gateway/sender_access +++ /dev/null @@ -1,10 +0,0 @@ -# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED - -# Sender access controls -# Format: sender_pattern action -# Actions: REJECT, OK, WARN, DISCARD, etc. - -# Block known spam domains -# Example entries: -# spammer@example.com REJECT -# @badspammer.com REJECT \ No newline at end of file diff --git a/site/profiles/files/postfix/gateway/sender_canonical b/site/profiles/files/postfix/gateway/sender_canonical deleted file mode 100644 index d470b0a..0000000 --- a/site/profiles/files/postfix/gateway/sender_canonical +++ /dev/null @@ -1,8 +0,0 @@ -# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED - -# Sender canonical address mapping -# Format: original_address canonical_address -# Used to rewrite sender addresses - -# Example mappings: -# user@internal.local user@main.unkin.net \ No newline at end of file diff --git a/site/profiles/manifests/postfix/gateway.pp b/site/profiles/manifests/postfix/gateway.pp index 8b78be2..d86cbff 100644 --- a/site/profiles/manifests/postfix/gateway.pp +++ b/site/profiles/manifests/postfix/gateway.pp @@ -1,250 +1,349 @@ class profiles::postfix::gateway ( - $tls_cert_file = '/etc/pki/tls/vault/certificate.pem', - $tls_key_file = '/etc/pki/tls/vault/certificate.pem', - $tls_ca_file = '/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem', + Stdlib::Absolutepath $tls_cert_file = '/etc/pki/tls/vault/certificate.pem', + Stdlib::Absolutepath $tls_key_file = '/etc/pki/tls/vault/certificate.pem', + Stdlib::Absolutepath $tls_ca_file = '/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem', + String $myhostname = $trusted['certname'], + String $message_size_limit = '133169152', + String $mailbox_size_limit = '133169152', + String $local_transport = 'error:No local mail delivery', + Boolean $enable_postscreen = true, + Array[String] $alias_maps = [ + 'hash:/etc/aliases', + 'hash:/etc/postfix/aliases', + ], + Array[String] $postscreen_dnsbl_sites = [ + 'zen.spamhaus.org*3', + 'b.barracudacentral.org=127.0.0.[2..11]*2', + 'bl.spameatingmonkey.net*2', + 'bl.spamcop.net', + 'dnsbl.sorbs.net', + 'swl.spamhaus.org*-4', + 'list.dnswl.org=127.[0..255].[0..255].0*-2', + 'list.dnswl.org=127.[0..255].[0..255].1*-4', + 'list.dnswl.org=127.[0..255].[0..255].[2..3]*-6', + ], + Array[String] $smtpd_client_restrictions = [ + 'permit_sasl_authenticated', + 'permit_mynetworks', + 'reject_rbl_client zen.spamhaus.org', + ], + Array[String] $smtpd_sender_restrictions = [ + 'permit_sasl_authenticated', + 'check_sender_access hash:/etc/postfix/sender_access', + 'reject_non_fqdn_sender', + 'reject_unknown_sender_domain', + ], + Array[String] $smtpd_recipient_restrictions = [ + 'permit_sasl_authenticated', + 'permit_mynetworks', + 'reject_unauth_destination', + 'reject_non_fqdn_recipient', + 'reject_unknown_recipient_domain', + 'check_recipient_access hash:/etc/postfix/recipient_access', + 'reject_unverified_recipient', + ], + Array[String] $smtpd_relay_restrictions = [ + 'permit_sasl_authenticated', + 'permit_mynetworks', + 'reject_unauth_destination', + ], + Hash[String, String] $smtp_tls_policy_maps = {}, + Hash[String, String] $sender_canonical_maps = {}, + Hash[String, String] $sender_access_maps = {}, + Hash[String, String] $relay_recipients_maps = {}, + Hash[String, String] $relay_domains_maps = {}, + Hash[String, String] $recipient_canonical_maps = {}, + Hash[String, String] $recipient_access_maps = {}, + Hash[String, String] $postscreen_access_maps = {}, + Hash[String, String] $helo_access_maps = {}, ) { - $alias_maps = 'hash:/etc/aliases, hash:/etc/postfix/aliases' + $alias_maps_string = join($alias_maps, ', ') - class { 'postfix': - relayhost => 'direct', - myorigin => 'main.unkin.net', - mydestination => 'blank', - mynetworks => '127.0.0.0/8 [::1]/128', - alias_maps => $alias_maps, - mta => true, - manage_aliases => true, - master_smtp => 'smtp inet n - n - 1 postscreen', - master_entries => [ - # Postscreen backend services + # Set master.cf configuration based on postscreen setting + if $enable_postscreen { + $master_smtp = 'smtp inet n - n - 1 postscreen' + $master_entries = [ 'smtpd pass - - n - - smtpd', 'dnsblog unix - - n - 0 dnsblog', 'tlsproxy unix - - n - 0 tlsproxy', - ], + ] + $postscreen_configs = { + 'postscreen_access_list' => { + 'value' => 'permit_mynetworks, cidr:/etc/postfix/postscreen_access' + }, + 'postscreen_blacklist_action' => { + 'value' => 'enforce' + }, + 'postscreen_cache_map' => { + 'value' => 'btree:$data_directory/postscreen_cache' + }, + 'postscreen_dnsbl_action' => { + 'value' => 'enforce' + }, + 'postscreen_dnsbl_sites' => { + 'value' => join($postscreen_dnsbl_sites, ', ') + }, + 'postscreen_dnsbl_threshold' => { + 'value' => '2' + }, + 'postscreen_greet_action' => { + 'value' => 'enforce' + }, + 'postscreen_greet_banner' => { + 'value' => '$smtpd_banner' + }, + 'postscreen_greet_wait' => { + 'value' => "\${stress?2}\${stress:6}s" + }, + } + } else { + $master_smtp = undef + $master_entries = [] + $postscreen_configs = {} } - postfix::config { - 'alias_database': - value => $alias_maps; - 'default_destination_recipient_limit': - value => '1'; - 'disable_vrfy_command': - value => 'yes'; - 'enable_long_queue_ids': - value => 'yes'; - 'error_notice_recipient': - value => 'root'; - 'header_checks': - value => 'regexp:/etc/postfix/header_checks'; - 'local_recipient_maps': - ensure => 'blank'; # no local mailboxes - 'local_transport': - value => 'error:No local mail delivery'; - 'mailbox_size_limit': - value => '133169152'; # ~127MB - 'message_size_limit': - value => '133169152'; # ~127MB - 'myhostname': - value => 'in-mta.main.unkin.net'; - 'non_smtpd_milters': - ensure => 'blank'; - 'postscreen_access_list': - value => 'permit_mynetworks, cidr:/etc/postfix/postscreen_access'; - 'postscreen_blacklist_action': - value => 'enforce'; - 'postscreen_cache_map': - value => 'btree:$data_directory/postscreen_cache'; - 'postscreen_dnsbl_action': - value => 'enforce'; - 'postscreen_dnsbl_sites': - value => join([ - 'zen.spamhaus.org*3', - 'b.barracudacentral.org=127.0.0.[2..11]*2', - 'bl.spameatingmonkey.net*2', - 'bl.spamcop.net', - 'dnsbl.sorbs.net', - 'swl.spamhaus.org*-4', - 'list.dnswl.org=127.[0..255].[0..255].0*-2', - 'list.dnswl.org=127.[0..255].[0..255].1*-4', - 'list.dnswl.org=127.[0..255].[0..255].[2..3]*-6' - ], ', '); - 'postscreen_dnsbl_threshold': - value => '2'; - 'postscreen_greet_action': - value => 'enforce'; - 'postscreen_greet_banner': - value => '$smtpd_banner'; - 'postscreen_greet_wait': - value => "\${stress?2}\${stress:6}s"; - 'qmqpd_authorized_clients': - value => '127.0.0.1 [::1]'; - 'recipient_canonical_maps': - value => 'hash:/etc/postfix/recipient_canonical'; - 'recipient_delimiter': - value => '+'; - 'relay_domains': - value => 'hash:/etc/postfix/relay_domains'; - 'relay_recipient_maps': - value => 'hash:/etc/postfix/relay_recipients'; - 'sender_canonical_maps': - value => 'hash:/etc/postfix/sender_canonical'; - 'smtp_tls_CAfile': - value => $tls_ca_file; - 'smtp_tls_mandatory_protocols': - value => '!SSLv2,!SSLv3'; - 'smtp_tls_note_starttls_offer': - value => 'yes'; - 'smtp_tls_protocols': - value => '!SSLv2,!SSLv3'; - 'smtp_tls_security_level': - value => 'may'; - 'smtp_tls_session_cache_database': - value => 'btree:/var/lib/postfix/smtp_tls_session_cache'; - 'smtp_use_tls': - value => 'yes'; - 'smtpd_banner': - value => '$myhostname ESMTP $mail_name'; - 'smtpd_client_restrictions': - value => 'permit_sasl_authenticated, permit_mynetworks, reject_rbl_client zen.spamhaus.org'; - 'smtpd_data_restrictions': - value => 'reject_unauth_pipelining'; - 'smtpd_delay_reject': - value => 'yes'; - 'smtpd_discard_ehlo_keywords': - value => 'chunking, silent-discard'; - 'smtpd_forbid_bare_newline': - value => 'yes'; - 'smtpd_forbid_bare_newline_exclusions': - value => '$mynetworks'; - 'smtpd_forbid_unauth_pipelining': - value => 'yes'; - 'smtpd_helo_required': - value => 'yes'; - 'smtpd_helo_restrictions': - value => 'check_helo_access hash:/etc/postfix/helo_access, reject_invalid_hostname'; - 'smtpd_milters': - value => 'inet:127.0.0.1:33333'; - 'smtpd_recipient_restrictions': - value => join([ - 'permit_sasl_authenticated', - 'permit_mynetworks', - 'reject_unauth_destination', - 'reject_non_fqdn_recipient', - 'reject_unknown_recipient_domain', - 'check_recipient_access hash:/etc/postfix/recipient_access', - 'check_policy_service inet:127.0.0.1:2501', - 'reject_unverified_recipient' - ], ', '); - 'smtpd_relay_restrictions': - value => 'permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination'; - 'smtpd_sender_restrictions': - value => join([ - 'permit_sasl_authenticated', - 'check_sender_access hash:/etc/postfix/sender_access', - 'reject_non_fqdn_sender', - 'reject_unknown_sender_domain' - ], ', '); - 'smtpd_tls_CAfile': - value => $tls_ca_file; - 'smtpd_tls_cert_file': - value => $tls_cert_file; - 'smtpd_tls_ciphers': - value => 'medium'; - 'smtpd_tls_key_file': - value => $tls_key_file; - 'smtpd_tls_loglevel': - value => '1'; - 'smtpd_tls_mandatory_protocols': - value => '!SSLv2,!SSLv3'; - 'smtpd_tls_protocols': - value => '!SSLv2,!SSLv3'; - 'smtpd_tls_received_header': - value => 'yes'; - 'smtpd_tls_security_level': - value => 'may'; - 'smtpd_tls_session_cache_database': - value => 'btree:/var/lib/postfix/smtpd_tls_session_cache'; - 'smtpd_tls_session_cache_timeout': - value => '3600s'; - 'smtpd_use_tls': - value => 'yes'; - 'tls_medium_cipherlist': - value => join([ + # Base postfix configuration + $base_configs = { + 'alias_database' => { + 'value' => $alias_maps_string + }, + 'default_destination_recipient_limit' => { + 'value' => '1' + }, + 'disable_vrfy_command' => { + 'value' => 'yes' + }, + 'enable_long_queue_ids' => { + 'value' => 'yes' + }, + 'error_notice_recipient' => { + 'value' => 'root' + }, + 'header_checks' => { + 'value' => 'regexp:/etc/postfix/header_checks' + }, + 'local_recipient_maps' => { + 'ensure' => 'blank' + }, + 'local_transport' => { + 'value' => $local_transport + }, + 'mailbox_size_limit' => { + 'value' => $mailbox_size_limit + }, + 'message_size_limit' => { + 'value' => $message_size_limit + }, + 'myhostname' => { + 'value' => $myhostname + }, + 'non_smtpd_milters' => { + 'ensure' => 'blank' + }, + 'qmqpd_authorized_clients' => { + 'value' => '127.0.0.1 [::1]' + }, + 'recipient_canonical_maps' => { + 'value' => 'hash:/etc/postfix/recipient_canonical' + }, + 'recipient_delimiter' => { + 'value' => '+' + }, + 'relay_domains' => { + 'value' => 'hash:/etc/postfix/relay_domains' + }, + 'relay_recipient_maps' => { + 'value' => 'hash:/etc/postfix/relay_recipients' + }, + 'sender_canonical_maps' => { + 'value' => 'hash:/etc/postfix/sender_canonical' + }, + 'smtp_tls_CAfile' => { + 'value' => $tls_ca_file + }, + 'smtp_tls_mandatory_protocols' => { + 'value' => '!SSLv2,!SSLv3' + }, + 'smtp_tls_note_starttls_offer' => { + 'value' => 'yes' + }, + 'smtp_tls_protocols' => { + 'value' => '!SSLv2,!SSLv3' + }, + 'smtp_tls_security_level' => { + 'value' => 'may' + }, + 'smtp_tls_session_cache_database' => { + 'value' => 'btree:/var/lib/postfix/smtp_tls_session_cache' + }, + 'smtp_use_tls' => { + 'value' => 'yes' + }, + 'smtpd_banner' => { + 'value' => '$myhostname ESMTP $mail_name' + }, + 'smtpd_client_restrictions' => { + 'value' => join($smtpd_client_restrictions, ', ') + }, + 'smtpd_data_restrictions' => { + 'value' => 'reject_unauth_pipelining' + }, + 'smtpd_delay_reject' => { + 'value' => 'yes' + }, + 'smtpd_discard_ehlo_keywords' => { + 'value' => 'chunking, silent-discard' + }, + 'smtpd_forbid_bare_newline' => { + 'value' => 'yes' + }, + 'smtpd_forbid_bare_newline_exclusions' => { + 'value' => '$mynetworks' + }, + 'smtpd_forbid_unauth_pipelining' => { + 'value' => 'yes' + }, + 'smtpd_helo_required' => { + 'value' => 'yes' + }, + 'smtpd_helo_restrictions' => { + 'value' => 'check_helo_access hash:/etc/postfix/helo_access, reject_invalid_hostname' + }, + 'smtpd_milters' => { + 'value' => 'inet:127.0.0.1:33333' + }, + 'smtpd_recipient_restrictions' => { + 'value' => join($smtpd_recipient_restrictions, ', ') + }, + 'smtpd_relay_restrictions' => { + 'value' => join($smtpd_relay_restrictions, ', ') + }, + 'smtpd_sender_restrictions' => { + 'value' => join($smtpd_sender_restrictions, ', ') + }, + 'smtpd_tls_CAfile' => { + 'value' => $tls_ca_file + }, + 'smtpd_tls_cert_file' => { + 'value' => $tls_cert_file + }, + 'smtpd_tls_ciphers' => { + 'value' => 'medium' + }, + 'smtpd_tls_key_file' => { + 'value' => $tls_key_file + }, + 'smtpd_tls_loglevel' => { + 'value' => '1' + }, + 'smtpd_tls_mandatory_protocols' => { + 'value' => '!SSLv2,!SSLv3' + }, + 'smtpd_tls_protocols' => { + 'value' => '!SSLv2,!SSLv3' + }, + 'smtpd_tls_received_header' => { + 'value' => 'yes' + }, + 'smtpd_tls_security_level' => { + 'value' => 'may' + }, + 'smtpd_tls_session_cache_database' => { + 'value' => 'btree:/var/lib/postfix/smtpd_tls_session_cache' + }, + 'smtpd_tls_session_cache_timeout' => { + 'value' => '3600s' + }, + 'smtpd_use_tls' => { + 'value' => 'yes' + }, + 'tls_medium_cipherlist' => { + 'value' => join([ 'ECDSA+AESGCM:ECDH+AESGCM:DH+AESGCM:ECDSA+AES:ECDH+AES:DH+AES', 'ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS' - ], ':'); - 'tls_preempt_cipherlist': - value => 'yes'; - 'tls_random_source': - value => 'dev:/dev/urandom'; - 'unverified_recipient_reject_code': - value => '550'; - 'unverified_recipient_reject_reason': - value => 'No user at this address'; + ], ':') + }, + 'tls_preempt_cipherlist' => { + 'value' => 'yes' + }, + 'tls_random_source' => { + 'value' => 'dev:/dev/urandom' + }, + 'unverified_recipient_reject_code' => { + 'value' => '550' + }, + 'unverified_recipient_reject_reason' => { + 'value' => 'No user at this address' + }, + 'smtp_tls_policy_maps' => { + 'value' => 'hash:/etc/postfix/smtp_tls_policy_maps' + }, } - postfix::map { 'postscreen_access': - ensure => present, - type => 'cidr', - source => 'puppet:///modules/profiles/postfix/gateway/postscreen_access' - } - postfix::map { 'relay_recipients': - ensure => present, - type => 'hash', - source => 'puppet:///modules/profiles/postfix/gateway/relay_recipients' - } - postfix::map { 'relay_domains': - ensure => present, - type => 'hash', - source => 'puppet:///modules/profiles/postfix/gateway/relay_domains' - } - postfix::map { 'aliases': - ensure => present, - type => 'hash', - source => 'puppet:///modules/profiles/postfix/gateway/aliases' - } - postfix::map { 'helo_access': - ensure => present, - type => 'hash', - source => 'puppet:///modules/profiles/postfix/gateway/helo_access' - } - postfix::map { 'sender_access': - ensure => present, - type => 'hash', - source => 'puppet:///modules/profiles/postfix/gateway/sender_access' - } - postfix::map { 'recipient_access': - ensure => present, - type => 'hash', - source => 'puppet:///modules/profiles/postfix/gateway/recipient_access' - } - postfix::map { 'recipient_canonical': - ensure => present, - type => 'hash', - source => 'puppet:///modules/profiles/postfix/gateway/recipient_canonical' - } - postfix::map { 'sender_canonical': - ensure => present, - type => 'hash', - source => 'puppet:///modules/profiles/postfix/gateway/sender_canonical' + # Postfix maps (all using templates now) + $postfix_maps = { + 'postscreen_access' => { + 'ensure' => 'present', + 'type' => 'cidr', + 'content' => template('profiles/postfix/gateway/postscreen_access.erb') + }, + 'relay_recipients' => { + 'ensure' => 'present', + 'type' => 'hash', + 'content' => template('profiles/postfix/gateway/relay_recipients.erb') + }, + 'relay_domains' => { + 'ensure' => 'present', + 'type' => 'hash', + 'content' => template('profiles/postfix/gateway/relay_domains.erb') + }, + 'aliases' => { + 'ensure' => 'present', + 'type' => 'hash', + 'source' => 'puppet:///modules/profiles/postfix/gateway/aliases' + }, + 'helo_access' => { + 'ensure' => 'present', + 'type' => 'hash', + 'content' => template('profiles/postfix/gateway/helo_access.erb') + }, + 'sender_access' => { + 'ensure' => 'present', + 'type' => 'hash', + 'content' => template('profiles/postfix/gateway/sender_access.erb') + }, + 'recipient_access' => { + 'ensure' => 'present', + 'type' => 'hash', + 'content' => template('profiles/postfix/gateway/recipient_access.erb') + }, + 'recipient_canonical' => { + 'ensure' => 'present', + 'type' => 'hash', + 'content' => template('profiles/postfix/gateway/recipient_canonical.erb') + }, + 'sender_canonical' => { + 'ensure' => 'present', + 'type' => 'hash', + 'content' => template('profiles/postfix/gateway/sender_canonical.erb') + }, + 'smtp_tls_policy_maps' => { + 'ensure' => 'present', + 'type' => 'hash', + 'content' => template('profiles/postfix/gateway/smtp_tls_policy_maps.erb') + }, } - postfix::transport { - 'main.unkin.net': - ensure => present, - destination => 'relay', - nexthop => 'ausyd1nxvm2120.main.unkin.net:25'; - } - postfix::virtual { - 'root': - ensure => present, - destination => 'ben@main.unkin.net'; - 'postmaster': - ensure => present, - destination => 'ben@main.unkin.net'; - 'abuse': - ensure => present, - destination => 'ben@main.unkin.net'; + # Merge base configs with postscreen configs + $all_configs = $base_configs + $postscreen_configs + + class { 'postfix': + master_smtp => $master_smtp, + master_entries => $master_entries, + alias_maps => $alias_maps_string, + configs => $all_configs, + maps => $postfix_maps, } } diff --git a/site/profiles/templates/postfix/gateway/helo_access.erb b/site/profiles/templates/postfix/gateway/helo_access.erb new file mode 100644 index 0000000..24148e2 --- /dev/null +++ b/site/profiles/templates/postfix/gateway/helo_access.erb @@ -0,0 +1,11 @@ +# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED +# +# Controls access based on HELO/EHLO hostnames to block spam patterns +# HELO/EHLO access controls +# Format: pattern action +# Example: .dynamic.example.com REJECT +# Example: localhost REJECT You are not localhost + +<% @helo_access_maps.each do |pattern, action| -%> +<%= pattern %> <%= action %> +<% end -%> \ No newline at end of file diff --git a/site/profiles/templates/postfix/gateway/postscreen_access.erb b/site/profiles/templates/postfix/gateway/postscreen_access.erb new file mode 100644 index 0000000..4ef63a1 --- /dev/null +++ b/site/profiles/templates/postfix/gateway/postscreen_access.erb @@ -0,0 +1,10 @@ +# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED +# +# Controls which IP addresses/networks are allowed through postscreen +# Postscreen access controls (CIDR format) +# Format: network/mask action +# Example: 192.168.1.0/24 permit + +<% @postscreen_access_maps.each do |network, action| -%> +<%= network %> <%= action %> +<% end -%> \ No newline at end of file diff --git a/site/profiles/templates/postfix/gateway/recipient_access.erb b/site/profiles/templates/postfix/gateway/recipient_access.erb new file mode 100644 index 0000000..57c7981 --- /dev/null +++ b/site/profiles/templates/postfix/gateway/recipient_access.erb @@ -0,0 +1,11 @@ +# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED +# +# Controls access based on recipient email addresses or domains +# Recipient access controls +# Format: recipient_pattern action +# Example: @example.com OK +# Example: admin@foo.net REJECT + +<% @recipient_access_maps.each do |recipient, action| -%> +<%= recipient %> <%= action %> +<% end -%> \ No newline at end of file diff --git a/site/profiles/templates/postfix/gateway/recipient_canonical.erb b/site/profiles/templates/postfix/gateway/recipient_canonical.erb new file mode 100644 index 0000000..026caf3 --- /dev/null +++ b/site/profiles/templates/postfix/gateway/recipient_canonical.erb @@ -0,0 +1,10 @@ +# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED +# +# Rewrites recipient addresses before delivery (address normalization) +# Recipient canonical address mapping +# Format: original_address canonical_address +# Example: user@olddomain.com user@example.com + +<% @recipient_canonical_maps.each do |original, canonical| -%> +<%= original %> <%= canonical %> +<% end -%> \ No newline at end of file diff --git a/site/profiles/templates/postfix/gateway/relay_domains.erb b/site/profiles/templates/postfix/gateway/relay_domains.erb new file mode 100644 index 0000000..68c8d68 --- /dev/null +++ b/site/profiles/templates/postfix/gateway/relay_domains.erb @@ -0,0 +1,10 @@ +# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED +# +# Defines which domains are allowed for mail relaying +# Relay domains control +# Format: domain action +# Example: example.com OK + +<% @relay_domains_maps.each do |domain, action| -%> +<%= domain %> <%= action %> +<% end -%> \ No newline at end of file diff --git a/site/profiles/templates/postfix/gateway/relay_recipients.erb b/site/profiles/templates/postfix/gateway/relay_recipients.erb new file mode 100644 index 0000000..e664715 --- /dev/null +++ b/site/profiles/templates/postfix/gateway/relay_recipients.erb @@ -0,0 +1,10 @@ +# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED +# +# Defines which recipient addresses are allowed for mail relaying +# Relay recipients control +# Format: recipient_pattern action +# Example: @example.com OK + +<% @relay_recipients_maps.each do |recipient, action| -%> +<%= recipient %> <%= action %> +<% end -%> \ No newline at end of file diff --git a/site/profiles/templates/postfix/gateway/sender_access.erb b/site/profiles/templates/postfix/gateway/sender_access.erb new file mode 100644 index 0000000..31d2ecf --- /dev/null +++ b/site/profiles/templates/postfix/gateway/sender_access.erb @@ -0,0 +1,11 @@ +# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED +# +# Controls access based on sender email addresses or domains +# Sender access controls +# Format: sender_pattern action +# Example: spammer@foo.net REJECT +# Example: @badspammer.com REJECT + +<% @sender_access_maps.each do |sender, action| -%> +<%= sender %> <%= action %> +<% end -%> \ No newline at end of file diff --git a/site/profiles/templates/postfix/gateway/sender_canonical.erb b/site/profiles/templates/postfix/gateway/sender_canonical.erb new file mode 100644 index 0000000..2cffab1 --- /dev/null +++ b/site/profiles/templates/postfix/gateway/sender_canonical.erb @@ -0,0 +1,10 @@ +# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED +# +# Rewrites sender addresses before sending (address masquerading) +# Sender canonical address mapping +# Format: original_address canonical_address +# Example: user@internal.local user@example.com + +<% @sender_canonical_maps.each do |original, canonical| -%> +<%= original %> <%= canonical %> +<% end -%> \ No newline at end of file diff --git a/site/profiles/templates/postfix/gateway/smtp_tls_policy_maps.erb b/site/profiles/templates/postfix/gateway/smtp_tls_policy_maps.erb new file mode 100644 index 0000000..a16ad83 --- /dev/null +++ b/site/profiles/templates/postfix/gateway/smtp_tls_policy_maps.erb @@ -0,0 +1,11 @@ +# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED +# +# Enforces TLS security policies for outbound mail per destination domain +# SMTP TLS policy map for outbound connections +# Format: destination policy +# Example: gmail.com encrypt +# Example: secure-bank.example.com secure + +<% @smtp_tls_policy_maps.each do |destination, policy| -%> +<%= destination %> <%= policy %> +<% end -%> \ No newline at end of file