debops.postldap default variables¶
Sections
APT packages¶
-
postldap__postfix__dependent_packages
¶
List of additional APT packages needed for the LDAP support.
postldap__postfix__dependent_packages: '{{ [ "postfix-ldap" ]
if postldap__ldap_enabled else [] }}'
DNS / PKI / TLS configuration¶
-
postldap__domain
¶
The DNS domain used to generate a ldap_table(5) pattern for LDAP search queries.
postldap__domain: '{{ ansible_domain }}'
-
postldap__domain_rev_pattern
¶
The search pattern based on the primary DNS domain of the host, with entries
defined in reverse order, for example %3.%2.%1
, depending on the number
of levels in the domain with maximum of 9. See ldap_table(5) manual
page for more details about usage of this pattern.
This pattern may be used in LDAP search queries which look for the host DNS domain or its subdomains. If multiple DNS domains are used in LDAP with different levels (number of domain parts), each level needs to be defined separately in the LDAP search query.
postldap__domain_rev_pattern: |-
{% set reversed = [] %}
{% for element in postldap__domain.split(".") %}
{% set _ = reversed.append("%" + loop.index|string) %}
{% endfor %}
{% if reversed | length == 1 %}
{{ "%d" }}{% else %}
{{ reversed[0:9][::-1] | join(".") }}{% endif %}
-
postldap__tls_ca_cert_dir
¶
Directory containing X509 Certification Authority certificates in PEM format which are to be recognized by the client in SSL/TLS connections. The files each contain one CA certificate.
postldap__tls_ca_cert_dir: '/etc/ssl/certs/'
Secrets¶
-
postldap__no_log
¶
This variable can be used in the Ansible tasks to set the no_log
parameter. Changing it to False
can help with debugging issues with the
roles, but otherwise it should be set to True
to ensure that Ansible
doesn't leak sensitive data in its logs.
postldap__no_log: True
Virtual Mail¶
The settings below help to configure to enable Postfix to host multiple (virtual) domains, and thus provide email to several domains with just one "mail server". Currently the Virtual Mail support works only with LDAP enabled, in the future MariaDB support could be added as well.
-
postldap__vmail_posix_user
¶
Virtual Mail POSIX username For the accesses to the mailbox directories a separate user vmail (Virtual Mail) is created, under which the accesses of Postfix, Dovecot and other components of the mail server should take place. On the one hand this prevents mail server components from accessing sensitive system directories, on the other hand it protects the mailboxes from external access. Only vmail (and root) are allowed to access the mailboxes.
postldap__vmail_posix_user: 'vmail'
-
postldap__vmail_posix_uidnumber
¶
Virtual Mail POSIX uidNumber
postldap__vmail_posix_uidnumber: '{{ ansible_local.postldap.vmail_posix_uidnumber|d(None) }}'
-
postldap__vmail_posix_group
¶
Virtual Mail POSIX group
postldap__vmail_posix_group: 'vmail'
-
postldap__vmail_posix_gidnumber
¶
Virtual Mail POSIX gidNumber
postldap__vmail_posix_gidnumber: '{{ ansible_local.postldap.vmail_posix_gidnumber|d(None) }}'
-
postldap__mailbox_base
¶
All mailboxes are stored directly in the file system of the server.
This setting describes the prefix that the virtual delivery agent prepends to all pathname results from $virtual_mailbox_maps table lookups. The directories under this base contain the users MailDirs. This directory must be created in advance and must be writeable by all potential mail users. To achieve this, either use the same GID across all mail users and set group ownership to that GID, or make the directory world writable.
postldap__mailbox_base: '/var/vmail'
-
postldap__virtual_alias_maps
¶
Optional lookup tables that alias specific mail addresses or domains to other local or remote address. The default option, when using Virtual Mail with LDAP, will first go over the alisaes set by debops.etc_aliases and if no match is found query the LDAP for the email address.
Specify zero or more type:name lookup tables, separated by whitespace or comma. Tables will be searched in the specified order until a match is found. Note: these lookups are recursive.
postldap__virtual_alias_maps:
- '$alias_maps'
- 'ldap:/etc/postfix/ldap_virtual_alias_maps.cf'
Postfix 'main.cf' configuration¶
These variables define the contents of the /etc/postfix/main.cf
configuration file. See Default variable details: postfix__maincf for more details.
-
postldap__postfix__dependent_maincf
¶
List of options needed by postfix for the Virtual Mail configuration
postldap__postfix__dependent_maincf:
# Postfix is final destination for the specified list of domains; mail is delivered
# via the $virtual_transport mail delivery transport
- name: 'virtual_mailbox_domains'
value: 'ldap:/etc/postfix/ldap_virtual_mailbox_domains.cf'
section: 'virtual'
state: '{{ "present"
if (postldap__ldap_enabled|bool and
postfix__version is version_compare("2.0", ">="))
else "absent" }}'
# Optional lookup tables that alias specific mail addresses or domains to other local or remote address.
- name: 'virtual_alias_maps'
value: '{{ postldap__virtual_alias_maps | join(",") }}'
section: 'virtual'
state: '{{ "present"
if (postldap__ldap_enabled|bool and
postfix__version is version_compare("2.0", ">="))
else "absent" }}'
#A prefix that the virtual delivery agent prepends to all pathname results from $virtual_mailbox_maps table lookups.
# This is a safety measure to ensure that an out of control map doesn't litter the file system with mailboxes.
- name: 'virtual_mailbox_base'
value: '{{ postldap__mailbox_base }}'
section: 'virtual'
state: '{{ "present"
if (postldap__ldap_enabled|bool and
postfix__version is version_compare("2.0", ">="))
else "absent" }}'
# Optional lookup tables with all valid addresses in the domains that match $virtual_mailbox_domains.
- name: 'virtual_mailbox_maps'
value: 'ldap:/etc/postfix/ldap_virtual_mailbox_maps.cf'
section: 'virtual'
state: '{{ "present"
if (postldap__ldap_enabled|bool and
postfix__version is version_compare("2.0", ">="))
else "absent" }}'
# Lookup tables with the per-recipient user ID that the virtual delivery agent uses while writing
# to the recipient's mailbox.
- name: 'virtual_uid_maps'
value: 'static:{{ postldap__vmail_posix_uidnumber|mandatory }}'
section: 'virtual'
state: '{{ "present"
if (postldap__ldap_enabled|bool and
postfix__version is version_compare("2.0", ">="))
else "absent" }}'
# Lookup tables with the per-recipient group ID for virtual mailbox delivery.
- name: 'virtual_gid_maps'
value: 'static:{{ postldap__vmail_posix_gidnumber|mandatory }}'
section: 'virtual'
state: '{{ "present"
if (postldap__ldap_enabled|bool and
postfix__version is version_compare("2.0", ">="))
else "absent" }}'
# The minimum user ID value that the virtual delivery agent accepts as a result from $virtual_uid_maps table lookup
# FIXME: problems while parsing number.
- name: 'virtual_minimum_uid'
value: '{{ postldap__vmail_posix_uidnumber|mandatory }}'
section: 'virtual'
state: 'absent'
# Optional lookup table with the SASL login names that own the sender (MAIL FROM) addresses.
- name: 'smtpd_sender_login_maps'
value: [ 'ldap:/etc/postfix/ldap_smtpd_sender_login_maps.cf' ]
section: 'base'
state: '{{ "present"
if (postldap__ldap_enabled|bool)
else "absent" }}'
- name: 'smtpd_sender_restrictions'
value:
- name: 'check_sasl_access ldap:${config_directory}/ldap_known_sender_relays.cf'
copy_id_from: 'permit_mynetworks'
weight: 5
- name: 'check_sender_access ldap:${config_directory}/ldap_unauth_sender_access.cf'
copy_id_from: 'permit_sasl_authenticated'
weight: 10
- name: 'check_sender_access ldap:${config_directory}/ldap_unauth_domain_access.cf'
copy_id_from: 'permit_sasl_authenticated'
weight: 15
state: '{{ "present"
if (postldap__ldap_enabled|bool)
else "ignore" }}'
- name: 'smtpd_relay_restrictions'
value:
- name: 'check_sasl_access ldap:${config_directory}/ldap_known_sender_relays.cf'
copy_id_from: 'permit_mynetworks'
weight: 5
state: '{{ "present"
if (postldap__ldap_enabled|bool)
else "ignore" }}'
- name: 'smtpd_restriction_classes'
value: [ 'smtpd_permit_known_sender_relays' ]
state: '{{ "present"
if (postldap__ldap_enabled|bool)
else "ignore" }}'
- name: 'smtpd_permit_known_sender_relays'
value:
# FIXME: Needs a better check, empty result doesn't block spoofed e-mail
# senders passed through a known relay
- 'reject_unlisted_sender'
- 'permit_sasl_authenticated'
- 'reject'
state: '{{ "present"
if (postldap__ldap_enabled|bool)
else "ignore" }}'
-
postldap__postfix_ldap_connection
¶
The header of the lookup table containing the settings to connect to the LDAP server
postldap__postfix_ldap_connection:
server_host: '{{ postldap__ldap_uri }}'
start_tls: '{{ "yes"
if (postldap__ldap_start_tls|bool)
else "no" }}'
version: '3'
tls_ca_cert_dir: '{{ postldap__tls_ca_cert_dir }}'
bind: 'yes'
bind_dn: '{{ postldap__ldap_binddn }}'
bind_pw: '{{ postldap__ldap_bindpw }}'
scope: 'sub'
-
postldap__postfix__dependent_lookup_tables
¶
The Virtual Mail lookup tables for postfix
postldap__postfix__dependent_lookup_tables:
- name: 'ldap_virtual_alias_maps.cf'
state: 'present'
comment: |
The virtual_alias_maps setting is used to find the target mailbox
(configured in the attribute mail, aka the mailbox or maildrop).
no_log: '{{ postldap__no_log|d(True) }}'
connection: '{{ postldap__postfix_ldap_connection }}'
search_base: '{{ postldap__ldap_people_dn|join(",") }}'
query_filter: '(&
(objectClass=inetOrgPerson)
(|
(mail=%s)
(mailAlias=%s)
)
(|
(authorizedService=all)
(authorizedService=mail:receive)
)
)'
result_attribute: 'mail'
- name: 'ldap_virtual_mailbox_maps.cf'
state: 'present'
comment: |
As we only want to accept mail, where we know the recipients
(and are responsible for them), the virtual_mailbox_maps configuration is used.
no_log: '{{ postldap__no_log|d(True) }}'
connection: '{{ postldap__postfix_ldap_connection }}'
search_base: '{{ postldap__ldap_people_dn|join(",") }}'
query_filter: '(&
(objectClass=inetOrgPerson)
(|
(mail=%s)
(mailAlias=%s)
)
(|
(authorizedService=all)
(authorizedService=mail:receive)
)
)'
result_attribute: 'mail'
result_format: '/%d/%u/Maildir/'
- name: 'ldap_virtual_mailbox_domains.cf'
state: 'present'
comment: |
The virtual_mailbox_domains configurations performs a lookup,
if the postfix is responsible for the given domain.
no_log: '{{ postldap__no_log|d(True) }}'
connection: '{{ postldap__postfix_ldap_connection }}'
search_base: '{{ postldap__ldap_domains_dn|join(",") }}'
query_filter: '(&
(objectClass=dNSDomain)
(dc=%s)
)'
result_attribute: 'dc'
- name: 'ldap_smtpd_sender_login_maps.cf'
state: 'present'
comment: |
The smtpd_sender_login_maps configurations performs a lookup from an incoming
email-sender to a username. Postfix first performs a full lookup
on user@domain, then user and then @domain.
The later one is also used for catchalls where the mailAlias
is set to e.g. @foobar.com
no_log: '{{ postldap__no_log|d(True) }}'
connection: '{{ postldap__postfix_ldap_connection }}'
search_base: '{{ postldap__ldap_base_dn|join(",") }}'
query_filter: '(|
(&
(objectClass=inetOrgPerson)
(|
(mail=%s)
(mailAlias=%s)
)
(|
(authorizedService=all)
(authorizedService=mail:send)
)
)
(&
(objectClass=account)
(uid=%u)
(host=%d)
(|
(authorizedService=all)
(authorizedService=mail:send)
)
)
)'
result_attribute: 'uid, mail, mailAlias'
size_limit: 1
- name: 'ldap_known_sender_relays.cf'
state: 'present'
comment: |
This lookup table checks if a given SASL authenticated login specified as
'user@fqdn' is a service account which can be used to relay e-mails from
other hosts through Postfix. If such service account is found, the lookup
table tells Postfix to use a relaxed sender and relay restrictions which
don't check for sender <-> login mismatch. This is required for accepting
e-mail messages from trusted SMTP services, for example nullmailer, which
can send e-mail messages on behalf of other users but cannot authenticate
as them.
no_log: '{{ postldap__no_log|d(True) }}'
connection: '{{ postldap__postfix_ldap_connection }}'
search_base: '{{ postldap__ldap_base_dn|join(",") }}'
query_filter: '(&
(objectClass=account)
(uid=%u)
(host=%d)
(|
(authorizedService=all)
(authorizedService=mail:send)
)
)'
result_attribute: 'uid'
result_format: 'smtpd_permit_known_sender_relays'
size_limit: 1
- name: 'ldap_unauth_sender_access.cf'
state: 'present'
comment: |
This lookup table is used to check if a sender exists after authenticated
sender has been accepted. If a sender exists, it means that the sender has
not been authenticated properly, or perhaps somebody tries to send e-mail
as one of our own users which is not allowed without authentication. In
such cases, the mail will be rejected with a sensible response indicating
that the sender needs to enable SMTP authentication.
no_log: '{{ postldap__no_log|d(True) }}'
connection: '{{ postldap__postfix_ldap_connection }}'
search_base: '{{ postldap__ldap_base_dn|join(",") }}'
query_filter: '(|
(&
(objectClass=inetOrgPerson)
(|
(mail=%s)
(mailAlias=%s)
)
)
(&
(objectClass=account)
(uid=%u)
(host=%d)
)
)'
result_attribute: 'uid, mail, mailAlias'
result_format: '550 Authentication Required'
- name: 'ldap_unauth_domain_access.cf'
state: 'present'
comment: |
This lookup table is used to check if a sender domain is one of our own
domains. This check is performed after authenticated senders have been
accepted, and if the domain is one of our own domains, it means that
somebody tries to send an e-mail with our own DNS domain which is not
allowed. The e-mail will be rejected with a message suggesting that the
SMTP authentication needs to be enabled.
no_log: '{{ postldap__no_log|d(True) }}'
connection: '{{ postldap__postfix_ldap_connection }}'
search_base: '{{ postldap__ldap_base_dn|join(",") }}'
query_filter: '(|
(&
(objectClass=dNSDomain)
(|
(dc=%d)
(dc={{ postldap__domain_rev_pattern }})
)
)
(&
(objectClass=domainRelatedObject)
(|
(associatedDomain=%d)
(associatedDomain={{ postldap__domain_rev_pattern }})
)
)
)'
result_attribute: 'dc, associatedDomain'
result_format: '550 Domain Authentication Required'
LDAP¶
LDAP authentication¶
-
postldap__ldap_enabled
¶
In order to enable Virtual Mail support LDAP authentication needs to be enabled. When enabled, postfix will configure mail-boxes locally and allow LDAP authenticated users to send email over this instance.
postldap__ldap_enabled: '{{ True
if (ansible_local|d() and ansible_local.ldap|d() and
(ansible_local.ldap.enabled|d())|bool)
else False }}'
-
postldap__ldap_base_dn
¶
The base Distinguished Name which should be used to create Distinguished Names of the LDAP directory objects, defined as a YAML list. If this variable is empty, automated Postfix LDAP configuration will not be performed.
postldap__ldap_base_dn: '{{ ansible_local.ldap.base_dn|d([]) }}'
-
postldap__ldap_device_dn
¶
The Distinguished Name of the current host LDAP object, defined as a YAML list. It will be used as a base for the Postfix service account LDAP object. If the list is empty, the role will not create the account LDAP object automatically.
postldap__ldap_device_dn: '{{ ansible_local.ldap.device_dn|d([]) }}'
-
postldap__ldap_self_rdn
¶
The Relative Distinguished Name of the account LDAP object used by the Postfix service to access the LDAP directory.
postldap__ldap_self_rdn: 'uid=postfix'
-
postldap__ldap_self_object_classes
¶
List of the LDAP object classes which will be used to create the LDAP object used by the postfix service to access the LDAP directory.
postldap__ldap_self_object_classes: [ 'account', 'simpleSecurityObject',
'authorizedServiceObject' ]
-
postldap__ldap_self_attributes
¶
YAML dictionary that defines the attributes of the LDAP object used by the Postfix service to access the LDAP directory.
postldap__ldap_self_attributes:
uid: '{{ postldap__ldap_self_rdn.split("=")[1] }}'
userPassword: '{{ postldap__ldap_bindpw }}'
host: '{{ [ ansible_fqdn, ansible_hostname ] | unique }}'
description: 'Account used by the "Postfix" service to access the LDAP directory'
authorizedService: 'mail:send'
-
postldap__ldap_binddn
¶
The Distinguished Name of the account LDAP object used by the Postfix service to bind to the LDAP directory.
postldap__ldap_binddn: '{{ ([ postldap__ldap_self_rdn ]
+ postldap__ldap_device_dn) | join(",") }}'
-
postldap__ldap_bindpw
¶
The password stored in the account LDAP object used by the Postfix service to bind to the LDAP directory.
postldap__ldap_bindpw: '{{ (lookup("password", secret + "/ldap/credentials/"
+ postldap__ldap_binddn | to_uuid + ".password length=32 "
+ "chars=ascii_letters,digits,!@_#$%^&*"))
if postldap__ldap_enabled|bool
else "" }}'
-
postldap__ldap_people_rdn
¶
The Relative Distinguished Name of the LDAP object which contains the user accounts stored in LDAP.
postldap__ldap_people_rdn: '{{ ansible_local.ldap.people_rdn|d("ou=People") }}'
-
postldap__ldap_people_dn
¶
The Distinguished Name of the LDAP object which contains the user accounts used by Postfix.
postldap__ldap_people_dn: '{{ [ postldap__ldap_people_rdn ]
+ postldap__ldap_base_dn }}'
-
postldap__ldap_uri
¶
List of LDAP URIs that point to the directory servers which should be used by postfix virtual.
postldap__ldap_uri: '{{ ansible_local.ldap.uri|d([""]) }}'
-
postldap__ldap_private_subtree
¶
When this variable is enabled, the debops.ldap role will create
separate LDAP objects that manage the Postfix groups as subtree of the
Postfix service LDAP object. If you set this parameter to False
, the
role will use the global ou=Groups,dc=example,dc=org
subtree instead.
This setting can be used to scale the Postfix server vertically.
postldap__ldap_private_subtree: False
-
postldap__ldap_groups_rdn
¶
The Relative Distinguished Name of the LDAP object which contains the groups stored in LDAP.
postldap__ldap_groups_rdn: '{{ ansible_local.ldap.groups_rdn|d("ou=Groups") }}'
-
postldap__ldap_domains_rdn
¶
The Relative Distinguished Name of the LDAP object which contains the (virtual mail) domains stored in LDAP.
postldap__ldap_domains_rdn: '{{ ansible_local.ldap.domains_rdn|d("ou=Domains") }}'
-
postldap__ldap_groups_dn
¶
The Distinguished Name of the LDAP object which contains the groups used by Postfix. If private groups are enabled, this object will be created automatically.
postldap__ldap_groups_dn: '{{ ([ postldap__ldap_groups_rdn, postldap__ldap_self_rdn ]
+ postldap__ldap_device_dn)
if postldap__ldap_private_subtree|bool
else ([ postldap__ldap_groups_rdn ]
+ postldap__ldap_base_dn) }}'
-
postldap__ldap_domains_dn
¶
The Distinguished Name of the LDAP object which contains the (virtual mail) domains used by Postfix. If private groups are enabled, this object will be created automatically.
postldap__ldap_domains_dn: '{{ ([ postldap__ldap_domains_rdn, postldap__ldap_self_rdn ]
+ postldap__ldap_device_dn)
if postldap__ldap_private_subtree|bool
else ([ postldap__ldap_domains_rdn ]
+ postldap__ldap_base_dn) }}'
-
postldap__ldap_default_virtual_domain_rdn
¶
The rdn of the default virtual mail domain used by Postfix. This is usually the same domain used by the LDAP.
postldap__ldap_default_virtual_domain_rdn: '{{ ansible_domain }}'
-
postldap__ldap_default_virtual_domain_dn
¶
The dn of the default virtual mail domain used by Postfix.
postldap__ldap_default_virtual_domain_dn: '{{ (["dc="
+ postldap__ldap_default_virtual_domain_rdn]
+ postldap__ldap_domains_dn) | join(",") }}'
LDAP connection options¶
-
postldap__ldap_server_uri
¶
The URI address of the LDAP server used by Postfix.
postldap__ldap_server_uri: '{{ ansible_local.ldap.uri|d([""]) | first }}'
-
postldap__ldap_server_port
¶
The TCP port which should be used for connections to the LDAP server.
postldap__ldap_server_port: '{{ ansible_local.ldap.port|d(("389" if postldap__ldap_start_tls|bool else "636")) }}'
-
postldap__ldap_start_tls
¶
If True
, Postfix will use STARTTLS extension to make encrypted
connections to the LDAP server.
postldap__ldap_start_tls: '{{ ansible_local.ldap.start_tls
if (ansible_local|d() and ansible_local.ldap|d() and
(ansible_local.ldap.start_tls|d())|bool)
else True }}'
LDAP settings¶
-
postldap__ldap_default_config
¶
The LDAP configuration options defined by default.
postldap__ldap_default_config: []
-
postldap__ldap_config
¶
List of custom LDAP configuration options defined for all hosts in the Ansible inventory.
postldap__ldap_config: []
-
postldap__group_ldap_config
¶
List of custom LDAP configuration options defined on hosts in a specific Ansible inventory group.
postldap__group_ldap_config: []
-
postldap__host_ldap_config
¶
List of custom LDAP configuration options defined on specific hosts in the Ansible inventory.
postldap__host_ldap_config: []
-
postldap__ldap_combined_config
¶
The variable that combines default and user LDAP configuration and is used in the role tasks and templates.
postldap__ldap_combined_config: '{{ postldap__ldap_default_config
+ postldap__ldap_config
+ postldap__group_ldap_config
+ postldap__host_ldap_config }}'
-
postldap__ldap__dependent_tasks
¶
Configuration for the debops.ldap Ansible role.
postldap__ldap__dependent_tasks:
- name: 'Create Postfix account for {{ postldap__ldap_device_dn | join(",") }}'
dn: '{{ postldap__ldap_binddn }}'
objectClass: '{{ postldap__ldap_self_object_classes }}'
attributes: '{{ postldap__ldap_self_attributes }}'
no_log: '{{ postldap__no_log|d(True) }}'
state: '{{ "present"
if (postldap__ldap_enabled|bool and
postldap__ldap_device_dn|d())
else "ignore" }}'
- name: 'Create Postfix group container for {{ postldap__ldap_device_dn | join(",") }}'
dn: '{{ postldap__ldap_groups_dn }}'
objectClass: 'organizationalUnit'
attributes:
ou: '{{ postldap__ldap_groups_rdn.split("=")[1] }}'
description: 'User groups used in Postfix'
state: '{{ "present"
if (postldap__ldap_enabled|bool and
postldap__ldap_device_dn|d() and
postldap__ldap_private_subtree|bool)
else "ignore" }}'
- name: 'Create Postfix domains container for {{ postldap__ldap_device_dn | join(",") }}'
dn: '{{ postldap__ldap_domains_dn }}'
objectClass: 'organizationalUnit'
attributes:
ou: '{{ postldap__ldap_domains_rdn.split("=")[1] }}'
description: 'Virtual Mail Domains used in Postfix'
state: '{{ "present"
if (postldap__ldap_enabled|bool and
postldap__ldap_device_dn|d() and
postldap__ldap_private_subtree|bool)
else "ignore" }}'
- name: 'Create Postfix Default Virtual Mail Domain for {{ postldap__ldap_default_virtual_domain_dn }}'
dn: '{{ postldap__ldap_default_virtual_domain_dn }}'
objectClass: 'dNSDomain'
state: '{{ "present"
if (postldap__ldap_enabled|bool and
postldap__ldap_device_dn|d() and
postldap__ldap_private_subtree|bool)
else "ignore" }}'