Improve services definitions

The services definitions for master.cf were previously defined in
the services.jinja file.

This commit instead moves them into the services.yaml file, as we
should not require any jinja parsing inside the services definitions.

Drive-By: Add a .gitignore file
Drive-By: Set manage_master_config: True for kitchen. We do want to
          verify that the master.cf file generation is actually working.
Drive-By: Add fedora-latest as a kitchen testing target, this helps
          with verifying the os_family map testing that was added in
          PR #79
Drive-By: Link to the kitchen-salt getting started guide in the README
This commit is contained in:
Andreas Thienemann 2018-10-08 11:07:34 +02:00 committed by Andreas Thienemann
parent d2896ea148
commit fb69881dde
7 changed files with 374 additions and 364 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.kitchen/
Gemfile.lock

View File

@ -21,6 +21,10 @@ platforms:
driver_config: driver_config:
provision_command: provision_command:
- yum install udev net-tools -y - yum install udev net-tools -y
- name: fedora-latest
driver_config:
provision_command:
- yum install udev net-tools -y
provisioner: provisioner:
name: salt_solo name: salt_solo
@ -38,7 +42,7 @@ provisioner:
- postfix - postfix
postfix.sls: postfix.sls:
postfix: postfix:
manage_master_config: False manage_master_config: True
verifier: verifier:
name: inspec name: inspec

View File

@ -13,6 +13,7 @@ env:
- INSTANCE: postfix-debian-9 - INSTANCE: postfix-debian-9
- INSTANCE: postfix-ubuntu-1804 - INSTANCE: postfix-ubuntu-1804
- INSTANCE: postfix-centos-7 - INSTANCE: postfix-centos-7
- INSTANCE: postfix-fedora-latest
script: script:
- bundle exec kitchen verify ${INSTANCE} - bundle exec kitchen verify ${INSTANCE}

View File

@ -8,6 +8,7 @@ Formulas to set up and configure the Postfix mail transfer agent.
See the full `Salt Formulas installation and usage instructions See the full `Salt Formulas installation and usage instructions
<http://docs.saltstack.com/en/latest/topics/development/conventions/formulas.html>`_. <http://docs.saltstack.com/en/latest/topics/development/conventions/formulas.html>`_.
Available states Available states
================ ================
@ -50,3 +51,12 @@ Installs postfix pcre package ( Debian only)
------------------ ------------------
Installs postfix postsrsd package Installs postfix postsrsd package
Integration testing
===================
A rudimentary test-suite exists to verify basic functionality of the postfix-formula.
Testing is done using the [Kitchen CI Framework](https://kitchen.ci/). Pull-Requests are verified using [Travis CI](https://travis-ci.org/).
A general getting started guide for kitchen-salt can be found at <https://github.com/saltstack/kitchen-salt/blob/master/docs/gettingstarted.md>.

View File

@ -1,7 +1,6 @@
{%- from "postfix/map.jinja" import postfix with context -%} {%- from "postfix/map.jinja" import postfix with context -%}
{%- set master_config = salt['pillar.get']('postfix:master_config', {}) -%} {%- set master_config = salt['pillar.get']('postfix:master_config', {}) -%}
{%- from "postfix/services.jinja" import postfix_master_services_defaults, {% import_yaml "postfix/services.yaml" as postfix_master_services %}
postfix_master_services_order -%}
{#- {#-
# Handle the case that the pillar data does not provide any service # Handle the case that the pillar data does not provide any service
@ -49,7 +48,7 @@
{#- Fetch the value from the passed service dictionary or fall back to the {#- Fetch the value from the passed service dictionary or fall back to the
# service defaults by chaining .get() commands. #} # service defaults by chaining .get() commands. #}
{%- set value = service.get(parameter_name, {%- set value = service.get(parameter_name,
postfix_master_services_defaults[service_name].get( postfix_master_services.defaults[service_name].get(
parameter_name, default)) -%} parameter_name, default)) -%}
{%- if value is sameas false -%} {%- if value is sameas false -%}
n n
@ -76,7 +75,7 @@ y
# service type private unpriv chroot wakeup maxproc command + args # service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (no) (never) (100) # (yes) (yes) (no) (never) (100)
# ========================================================================== # ==========================================================================
{%- for service_name in postfix_master_services_order %} {%- for service_name in postfix_master_services.order %}
{#- Try to get the service configuration from the pillar if present. {#- Try to get the service configuration from the pillar if present.
# Next try if the service has been dynamically configured and is present in # Next try if the service has been dynamically configured and is present in
# the additional_services dictionary. # the additional_services dictionary.
@ -84,7 +83,7 @@ y
{%- set service = salt['pillar.get']('postfix:master_config:services:%s' % ( {%- set service = salt['pillar.get']('postfix:master_config:services:%s' % (
service_name,), service_name,),
additional_services.get(service_name, additional_services.get(service_name,
postfix_master_services_defaults[service_name])) -%} postfix_master_services.defaults[service_name])) -%}
{%- if service.get('enable', True) -%} {%- if service.get('enable', True) -%}
{%- set comment = '' -%} {%- set comment = '' -%}
{%- else -%} {%- else -%}
@ -100,7 +99,7 @@ y
service_param(service, service_name, 'maxproc'), service_param(service, service_name, 'maxproc'),
service_param(service, service_name, 'command', service_name)) -}} service_param(service, service_name, 'command', service_name)) -}}
{%- if service.args is not none -%} {%- if service.args is not none -%}
{%- for option in service.get('args', postfix_master_services_defaults[ {%- for option in service.get('args', postfix_master_services.defaults[
service_name].get('args', [])) -%} service_name].get('args', [])) -%}
{%- if option.startswith('#') %} {%- if option.startswith('#') %}
{{ option }} {{ option }}
@ -116,7 +115,7 @@ y
{%- do handled_extra_services.append(service_name) -%} {%- do handled_extra_services.append(service_name) -%}
{%- set service = salt['pillar.get']('postfix:master_config:services:%s' % ( {%- set service = salt['pillar.get']('postfix:master_config:services:%s' % (
service_name,), service_name,),
postfix_master_services_defaults[service_name]) -%} postfix_master_services.defaults[service_name]) -%}
{%- if service.get('enable', True) -%} {%- if service.get('enable', True) -%}
{%- set comment = '' -%} {%- set comment = '' -%}
{%- else -%} {%- else -%}
@ -131,7 +130,7 @@ y
service_param(service, service_name, 'wakeup'), service_param(service, service_name, 'wakeup'),
service_param(service, service_name, 'maxproc'), service_param(service, service_name, 'maxproc'),
service_param(service, service_name, 'command', service_name)) }} service_param(service, service_name, 'command', service_name)) }}
{%- if 'flags' in service or 'flags' in postfix_master_services_defaults[service_name] -%} {%- if 'flags' in service or 'flags' in postfix_master_services.defaults[service_name] -%}
{%- set parameter_str = "%s flags=%s user=%s argv=%s %s" | format(comment, {%- set parameter_str = "%s flags=%s user=%s argv=%s %s" | format(comment,
service_param(service, service_name, 'flags'), service_param(service, service_name, 'flags'),
service_param(service, service_name, 'user'), service_param(service, service_name, 'user'),
@ -153,7 +152,7 @@ y
{#- Handle legacy configuration of services for backwards compatibility {#- Handle legacy configuration of services for backwards compatibility
by extending the services dictionary accordingly #} by extending the services dictionary accordingly #}
{%- if salt['pillar.get']('postfix:policyd-spf:enabled', False) %} {%- if salt['pillar.get']('postfix:policyd-spf:enabled', False) %}
{%- do postfix_master_services_defaults.update({'policy-spf': { {%- do postfix_master_services.defaults.update({'policy-spf': {
'command': 'spawn', 'command': 'spawn',
'chroot': False, 'chroot': False,
'enable': True, 'enable': True,
@ -164,7 +163,7 @@ y
{%- endif %} {%- endif %}
{%- if master_config.get('enable_dovecot', False) -%} {%- if master_config.get('enable_dovecot', False) -%}
{%- set dovecot = master_config.get('dovecot', {} )%} {%- set dovecot = master_config.get('dovecot', {} )%}
{%- do postfix_master_services_defaults.update({'dovecot': { {%- do postfix_master_services.defaults.update({'dovecot': {
'command': 'pipe', 'command': 'pipe',
'chroot': False, 'chroot': False,
'enable': True, 'enable': True,
@ -234,11 +233,11 @@ y
dictionary for all defined services that have not been otherwise be dictionary for all defined services that have not been otherwise be
handled yet. -#} handled yet. -#}
{%- for service in salt['pillar.get']('postfix:master_config:services', []) if not service in handled_extra_services -%} {%- for service in salt['pillar.get']('postfix:master_config:services', []) if not service in handled_extra_services -%}
{%- do postfix_master_services_defaults.update({service: salt['pillar.get']('postfix:master_config:services:%s' % (service,))}) -%} {%- do postfix_master_services.defaults.update({service: salt['pillar.get']('postfix:master_config:services:%s' % (service,))}) -%}
{%- endfor -%} {%- endfor -%}
{%- for service in postfix_master_services_defaults if not service in handled_extra_services and not service in postfix_master_services_order %} {%- for service in postfix_master_services.defaults if not service in handled_extra_services and not service in postfix_master_services.order %}
# #
{%- if postfix_master_services_defaults[service].get('wrap', False) %} {%- if postfix_master_services.defaults[service].get('wrap', False) %}
{{ extra_service(service, 78) }} {{ extra_service(service, 78) }}
{%- else %} {%- else %}
{{ extra_service(service) }} {{ extra_service(service) }}

View File

@ -1,350 +0,0 @@
{#-
# Default Postfix master processes as defined by postfix
#
# The dictionary is keyed off the service name ("smtp", "smtpd", etc.) except
# for the few cases the service name is repeated to illustrate alternative
# options in the file.
# In such a case the second entry has a unique identifier appended, e.g.
# "smtp-unix". The 'service' attribute is used to provide the service name
# that will be rendered by jinja thus overriding the usual key to prevent
# clashes.
-#}
{% set postfix_master_services_defaults = {
'smtp': {
'type': 'inet',
'private': False,
'chroot': False,
'command': 'smtpd'
},
'smtp-postscreen': {
'service': 'smtp',
'enable': False,
'type': 'inet',
'maxproc': 1,
'private': False,
'chroot': False,
'command': 'postscreen'
},
'smtpd': {
'enable': False,
'type': 'pass',
'chroot': False
},
'dnsblog': {
'maxproc': 0,
'enable': False,
'type': 'unix',
'chroot': False
},
'tlsproxy': {
'maxproc': 0,
'enable': False,
'type': 'unix',
'chroot': False
},
'submission': {
'chroot': False,
'command': 'smtpd',
'enable': False,
'args': [
'-o syslog_name=postfix/submission',
'-o smtpd_tls_security_level=encrypt',
'-o smtpd_sasl_auth_enable=yes',
'-o smtpd_reject_unlisted_recipient=no',
'-o smtpd_client_restrictions=$mua_client_restrictions',
'-o smtpd_helo_restrictions=$mua_helo_restrictions',
'-o smtpd_sender_restrictions=$mua_sender_restrictions',
'-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject',
'-o milter_macro_daemon_name=ORIGINATING'
],
'type': 'inet',
'private': False
},
'smtps': {
'chroot': False,
'command': 'smtpd',
'enable': False,
'args': [
'-o syslog_name=postfix/smtps',
'-o smtpd_tls_wrappermode=yes',
'-o smtpd_sasl_auth_enable=yes',
'-o smtpd_reject_unlisted_recipient=no',
'-o smtpd_client_restrictions=$mua_client_restrictions',
'-o smtpd_helo_restrictions=$mua_helo_restrictions',
'-o smtpd_sender_restrictions=$mua_sender_restrictions',
'-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject',
'-o milter_macro_daemon_name=ORIGINATING'
],
'type': 'inet',
'private': False
},
'628': {
'enable': False,
'command': 'qmqpd',
'type': 'inet',
'chroot': False,
'private': False
},
'pickup': {
'maxproc': 1,
'chroot': False,
'wakeup': 60,
'type': 'unix',
'private': False,
},
'cleanup': {
'maxproc': 0,
'chroot': False,
'type': 'unix',
'private': False
},
'qmgr': {
'chroot': False,
'private': False,
'maxproc': 1,
'wakeup': 300,
'type': 'unix'
},
'qmgr-oqmgr': {
'service': 'qmgr',
'chroot': False,
'private': False,
'maxproc': 1,
'enable': False,
'command': 'oqmgr',
'wakeup': 300,
'type': 'unix'
},
'tlsmgr': {
'wakeup': '1000?',
'chroot': False,
'type': 'unix',
'maxproc': 1
},
'rewrite': {
'type': 'unix',
'chroot': False,
'command': 'trivial-rewrite'
},
'bounce': {
'maxproc': 0,
'chroot': False,
'type': 'unix'
},
'defer': {
'maxproc': 0,
'chroot': False,
'type': 'unix',
'command': 'bounce'
},
'trace': {
'maxproc': 0,
'chroot': False,
'type': 'unix',
'command': 'bounce'
},
'smtp-unix': {
'service': 'smtp',
'chroot': False,
'type': 'unix',
'command': 'smtp'
},
'verify': {
'maxproc': 1,
'chroot': False,
'type': 'unix'
},
'flush': {
'maxproc': 0,
'chroot': False,
'wakeup': '1000?',
'type': 'unix',
'private': False
},
'proxymap': {
'chroot': False,
'type': 'unix'
},
'proxywrite': {
'maxproc': 1,
'chroot': False,
'type': 'unix',
'command': 'proxymap'
},
'relay': {
'type': 'unix',
'chroot': False,
'args': [
'# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5'
],
'command': 'smtp'
},
'showq': {
'chroot': False,
'type': 'unix',
'private': False
},
'error': {
'chroot': False,
'type': 'unix'
},
'retry': {
'type': 'unix',
'chroot': False,
'command': 'error'
},
'discard': {
'chroot': False,
'type': 'unix'
},
'local': {
'unpriv': False,
'chroot': False,
'type': 'unix'
},
'virtual': {
'unpriv': False,
'chroot': False,
'type': 'unix'
},
'lmtp': {
'chroot': False,
'type': 'unix'
},
'anvil': {
'maxproc': 1,
'chroot': False,
'type': 'unix'
},
'scache': {
'maxproc': 1,
'chroot': False,
'type': 'unix'
},
'maildrop': {
'command': 'pipe',
'chroot': False,
'enable': False,
'extras': '-d ${recipient}',
'flags': 'DRhu',
'type': 'unix',
'unpriv': False,
'user': 'vmail',
'argv': '/usr/local/bin/maildrop',
},
'cyrus': {
'command': 'pipe',
'chroot': False,
'enable': False,
'extras': '-e -r ${sender} -m ${extension} ${user}',
'type': 'unix',
'unpriv': False,
'user': 'cyrus',
'argv': '/cyrus/bin/deliver',
},
'old-cyrus': {
'command': 'pipe',
'chroot': False,
'enable': False,
'extras': '-e -m ${extension} ${user}',
'flags': 'R',
'type': 'unix',
'unpriv': False,
'user': 'cyrus',
'argv': '/cyrus/bin/deliver',
},
'uucp': {
'command': 'pipe',
'chroot': False,
'enable': False,
'extras': '-r -n -z -a$sender - $nexthop!rmail ($recipient)',
'flags': 'Fqhu',
'type': 'unix',
'unpriv': False,
'user': 'uucp',
'argv': 'uux',
},
'ifmail': {
'command': 'pipe',
'chroot': False,
'enable': False,
'extras': '-r $nexthop ($recipient)',
'flags': 'F',
'type': 'unix',
'unpriv': False,
'user': 'ftn',
'argv': '/usr/lib/ifmail/ifmail',
},
'bsmtp': {
'command': 'pipe',
'chroot': False,
'enable': False,
'extras': '-f $sender $nexthop $recipient',
'flags': 'Fq.',
'type': 'unix',
'unpriv': False,
'user': 'bsmtp',
'argv': '/usr/local/sbin/bsmtp',
},
'scalemail-backend': {
'command': 'pipe',
'chroot': False,
'enable': False,
'extras': '${nexthop} ${user} ${extension}',
'flags': 'R',
'maxproc': 2,
'type': 'unix',
'unpriv': False,
'user': 'scalemail',
'argv': '/usr/lib/scalemail/bin/scalemail-store',
},
'mailman': {
'command': 'pipe',
'chroot': False,
'enable': False,
'extras': '${nexthop} ${user}',
'flags': 'FR',
'type': 'unix',
'unpriv': False,
'user': 'list',
'argv': '/usr/lib/mailman/bin/postfix-to-mailman.py',
},
} %}
{# Service order inside the master.cf file #}
{% set postfix_master_services_order = [
'smtp',
'smtp-postscreen',
'smtpd',
'dnsblog',
'tlsproxy',
'submission',
'smtps',
'628',
'pickup',
'cleanup',
'qmgr',
'qmgr-oqmgr',
'tlsmgr',
'rewrite',
'bounce',
'defer',
'trace',
'verify',
'flush',
'proxymap',
'proxywrite',
'smtp-unix',
'relay',
'showq',
'error',
'retry',
'discard',
'local',
'virtual',
'lmtp',
'anvil',
'scache'
] %}

344
postfix/services.yaml Normal file
View File

@ -0,0 +1,344 @@
# Default Postfix master processes as defined by postfix
#
# The dictionary is keyed off the service name ("smtp", "smtpd", etc.) except
# for the few cases the service name is repeated to illustrate alternative
# options in the file.
# In such a case the second entry has a unique identifier appended, e.g.
# "smtp-unix". The 'service' attribute is used to provide the service name
# that will be rendered thus overriding the usual key to prevent clashes.
#
defaults:
# Postfix internal services/processes defaults
smtp:
chroot: false
command: smtpd
private: false
type: inet
smtp-postscreen:
chroot: false
command: postscreen
enable: false
maxproc: 1
private: false
service: smtp
type: inet
smtpd:
chroot: false
enable: false
type: pass
dnsblog:
chroot: false
enable: false
maxproc: 0
type: unix
tlsproxy:
chroot: false
enable: false
maxproc: 0
type: unix
submission:
args:
- '-o syslog_name=postfix/submission'
- '-o smtpd_tls_security_level=encrypt'
- '-o smtpd_sasl_auth_enable=yes'
- '-o smtpd_reject_unlisted_recipient=no'
- '-o smtpd_client_restrictions=$mua_client_restrictions'
- '-o smtpd_helo_restrictions=$mua_helo_restrictions'
- '-o smtpd_sender_restrictions=$mua_sender_restrictions'
- '-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject'
- '-o milter_macro_daemon_name=ORIGINATING'
chroot: false
command: smtpd
enable: false
private: false
type: inet
smtps:
args:
- '-o syslog_name=postfix/smtps'
- '-o smtpd_tls_wrappermode=yes'
- '-o smtpd_sasl_auth_enable=yes'
- '-o smtpd_reject_unlisted_recipient=no'
- '-o smtpd_client_restrictions=$mua_client_restrictions'
- '-o smtpd_helo_restrictions=$mua_helo_restrictions'
- '-o smtpd_sender_restrictions=$mua_sender_restrictions'
- '-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject'
- '-o milter_macro_daemon_name=ORIGINATING'
chroot: false
command: smtpd
enable: false
private: false
type: inet
'628':
chroot: false
command: qmqpd
enable: false
private: false
type: inet
pickup:
chroot: false
maxproc: 1
private: false
type: unix
wakeup: 60
cleanup:
chroot: false
maxproc: 0
private: false
type: unix
qmgr:
chroot: false
maxproc: 1
private: false
type: unix
wakeup: 300
qmgr-oqmgr:
chroot: false
command: oqmgr
enable: false
maxproc: 1
private: false
service: qmgr
type: unix
wakeup: 300
tlsmgr:
chroot: false
maxproc: 1
type: unix
wakeup: '1000?'
rewrite:
chroot: false
command: trivial-rewrite
type: unix
bounce:
chroot: false
maxproc: 0
type: unix
defer:
chroot: false
command: bounce
maxproc: 0
type: unix
trace:
chroot: false
command: bounce
maxproc: 0
type: unix
smtp-unix:
chroot: false
command: smtp
service: smtp
type: unix
verify:
chroot: false
maxproc: 1
type: unix
flush:
chroot: false
maxproc: 0
private: false
type: unix
wakeup: '1000?'
proxymap:
chroot: false
type: unix
proxywrite:
chroot: false
command: proxymap
maxproc: 1
type: unix
relay:
args:
- '# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5'
chroot: false
command: smtp
type: unix
showq:
chroot: false
private: false
type: unix
error:
chroot: false
type: unix
retry:
chroot: false
command: error
type: unix
discard:
chroot: false
type: unix
local:
chroot: false
type: unix
unpriv: false
virtual:
chroot: false
type: unix
unpriv: false
lmtp:
chroot: false
type: unix
anvil:
chroot: false
maxproc: 1
type: unix
scache:
chroot: false
maxproc: 1
type: unix
# Postfix MDA definitions, these are optional and commented out by default
maildrop:
argv: /usr/local/bin/maildrop
chroot: false
command: pipe
enable: false
extras: '-d ${recipient}'
flags: DRhu
type: unix
unpriv: false
user: vmail
cyrus:
argv: /cyrus/bin/deliver
chroot: false
command: pipe
enable: false
extras: "-e -r ${sender} -m ${extension} ${user}"
type: unix
unpriv: false
user: cyrus
old-cyrus:
argv: /cyrus/bin/deliver
chroot: false
command: pipe
enable: false
extras: '-e -m ${extension} ${user}'
flags: R
type: unix
unpriv: false
user: cyrus
uucp:
argv: uux
chroot: false
command: pipe
enable: false
extras: '-r -n -z -a$sender - $nexthop!rmail ($recipient)'
flags: Fqhu
type: unix
unpriv: false
user: uucp
ifmail:
argv: /usr/lib/ifmail/ifmail
chroot: false
command: pipe
enable: false
extras: '-r $nexthop ($recipient)'
flags: F
type: unix
unpriv: false
user: ftn
bsmtp:
argv: /usr/local/sbin/bsmtp
chroot: false
command: pipe
enable: false
extras: '-f $sender $nexthop $recipient'
flags: Fq.
type: unix
unpriv: false
user: bsmtp
scalemail-backend:
argv: /usr/lib/scalemail/bin/scalemail-store
chroot: false
command: pipe
enable: false
extras: '${nexthop} ${user} ${extension}'
flags: R
maxproc: 2
type: unix
unpriv: false
user: scalemail
mailman:
argv: /usr/lib/mailman/bin/postfix-to-mailman.py
chroot: false
command: pipe
enable: false
extras: '${nexthop} ${user}'
flags: FR
type: unix
unpriv: false
user: list
# Service order inside the master.cf file
order:
- smtp
- smtp-postscreen
- smtpd
- dnsblog
- tlsproxy
- submission
- smtps
- '628'
- pickup
- cleanup
- qmgr
- qmgr-oqmgr
- tlsmgr
- rewrite
- bounce
- defer
- trace
- verify
- flush
- proxymap
- proxywrite
- smtp-unix
- relay
- showq
- error
- retry
- discard
- local
- virtual
- lmtp
- anvil
- scache