From 3d8b0ac104dee68b47d9a4d2ef622e7f1acdd7a4 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Wed, 27 Nov 2013 01:26:36 +0100 Subject: Reorganization. --- common.yml | 24 +- group_vars/all.yml | 9 + .../common-LDAP/files/etc/ldap/schema/fripost.ldif | 190 ++++++++ .../files/var/lib/ldap/fripost/DB_CONFIG | 5 + roles/common-LDAP/handlers/main.yml | 2 + roles/common-LDAP/tasks/main.yml | 67 +++ .../templates/etc/ldap/database.ldif.j2 | 498 +++++++++++++++++++++ roles/common-SQL/tasks/main.yml | 29 ++ roles/common/files/etc/ldap/schema/fripost.ldif | 190 -------- roles/common/files/var/lib/ldap/fripost/DB_CONFIG | 5 - roles/common/handlers/main.yml | 3 - roles/common/tasks/ldap.yml | 67 --- roles/common/tasks/main.yml | 12 - roles/common/tasks/sql.yml | 29 -- roles/common/templates/etc/ldap/database.ldif.j2 | 498 --------------------- vars.yml | 9 - 16 files changed, 822 insertions(+), 815 deletions(-) create mode 100644 group_vars/all.yml create mode 100644 roles/common-LDAP/files/etc/ldap/schema/fripost.ldif create mode 100644 roles/common-LDAP/files/var/lib/ldap/fripost/DB_CONFIG create mode 100644 roles/common-LDAP/handlers/main.yml create mode 100644 roles/common-LDAP/tasks/main.yml create mode 100644 roles/common-LDAP/templates/etc/ldap/database.ldif.j2 create mode 100644 roles/common-SQL/tasks/main.yml delete mode 100644 roles/common/files/etc/ldap/schema/fripost.ldif delete mode 100644 roles/common/files/var/lib/ldap/fripost/DB_CONFIG delete mode 100644 roles/common/tasks/ldap.yml delete mode 100644 roles/common/tasks/sql.yml delete mode 100644 roles/common/templates/etc/ldap/database.ldif.j2 delete mode 100644 vars.yml diff --git a/common.yml b/common.yml index 2c555f9..cea8611 100644 --- a/common.yml +++ b/common.yml @@ -1,7 +1,27 @@ --- +# XXX: This organization is unfortunate. As of Ansible 1.4, roles are +# applied playbook by playbook and not globally for the whole inventory; +# therefore if two playbooks are given the role 'common', the tasks +# defined in 'common' would be run twice. +# The quickfix to ensure that plays are role-disjoint is to create a +# separate play for each role. Of course the downside is that we loose +# (most of) the advantage of roles... + - name: Common tasks hosts: all - vars_files: - - vars.yml roles: - common + +- name: Common SQL tasks + hosts: MDA:webmail:backup + gather_facts: False + tags: mysql,sql + roles: + - common-SQL + +- name: Common LDAP tasks + hosts: MDA:MSA:lists:LDAP-producer:MX + gather_facts: False + tags: slapd,ldap + roles: + - common-LDAP diff --git a/group_vars/all.yml b/group_vars/all.yml new file mode 100644 index 0000000..2cd3a42 --- /dev/null +++ b/group_vars/all.yml @@ -0,0 +1,9 @@ +--- +postfix_instance: + # The keys are the group names associated with a Postfix role, and the + # values are the name and group (optional) of the instance dedicated + # to that role. + IMAP: { name: mda } + MX: { name: mta-in, group: mta } + MTA-out: { name: mta-out,group: mta } + MSA: { name: msa } diff --git a/roles/common-LDAP/files/etc/ldap/schema/fripost.ldif b/roles/common-LDAP/files/etc/ldap/schema/fripost.ldif new file mode 100644 index 0000000..851988e --- /dev/null +++ b/roles/common-LDAP/files/etc/ldap/schema/fripost.ldif @@ -0,0 +1,190 @@ +# Fripost's LDAP schema +# Copyright © 2013 Guilhem Moulin +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Load this file with +# +# ldapadd -Y EXTERNAL -H ldapi:/// -f fripost.ldif +# +# It will load the schema. To perform modifications, the easiest way is to +# +# * Save the database: slapcat -b 'o=mailHosting,dc=fripost,dc=dev' > /tmp/db.ldif +# * Save the configuration: slapcat -n0 > /tmp/config.ldif +# * Backup slap.d: cp -a /etc/ldap/slapd.d/ /tmp/slap.d_back +# * Edit the schema in /tmp/config.ldif +# * Load the new config: mkdir -m 0700 /tmp/slapd.d_new && slapadd -F /tmp/slapd.d_new -n0 -l /tmp/config.ldif +# * Stop slapd: /etc/init.d/slapd stop +# * Load the new config: rm -rf /etc/ldap/slapd.d/ && mv /tmp/slapd.d_new /etc/ldap/slapd.d && chown -R openldap:openldap /etc/ldap/slapd.d +# * Create indexes: sudo -u openldap slapindex -b 'o=mailHosting,dc=fripost,dc=dev' +# * Start slapd: /etc/init.d/slapd start +# If it fails, remove the existing database and see what's wrong +# rm -rf /var/lib/ldap/dev/* && sudo -u openldap slapadd -b 'o=mailHosting,dc=fripost,dc=org' -l /tmp/db.ldif +# +# +# /!\ WARN: All modification to the ACL should be reflected to the test +# /!\ suite as well! +# +# +# References: +# - http://courier.svn.sourceforge.net/svnroot/courier/trunk/courier-authlib/authldap.schema +# - http://www.qmail-ldap.org/wiki/index.php/Qmail.schema +# - http://www.wanderingbarque.com/howtos/mailserver/mailserver.html + + +# 1.3.6.1.4.1.40011 Fripost's OID +# 1.3.6.1.4.1.40011.1 +# 1.3.6.1.4.1.40011.1.2 fripost LDAP Elements +# 1.3.6.1.4.1.40011.1.2.1 AttributeTypes +# 1.3.6.1.4.1.40011.1.2.2 ObjectClasses +# 1.3.6.1.4.1.40011.1.2.3 Syntax Definitions + +# This schema depends on: +# - core.schema +# - cosine.schema +# - nis.schema + + +dn: cn=fripost-master,cn=schema,cn=config +objectClass: olcSchemaConfig +# +# Attributes: 1.3.6.1.4.1.40011.1.1 +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.1 NAME 'fvd' + DESC 'A virtual mail domain' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.2 NAME 'fvl' + DESC 'The local part of a virtual user, alias, list or list command' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE ) +# +# This is redundant since we always use DNs of the form +# fvl=localpart,fvd=domainpart.tld,... +# (But Postfix doesn't allow the use of '%u' and '%d' from the query in +# its 'result_format'.) +# It is a priori insecure to allow arbitrary values here since users +# will modify this value themselves, however our Postfix will only +# accept well-formed values, enforced by a custom filter: +# query_filter = (&...(fripostLocalAlias=%u#%d)) +# result_attribute = fripostLocalAlias +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.3 NAME 'fripostLocalAlias' + DESC 'A local alias, typically localpart#domainpart.tld' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.4 NAME 'fripostMaildrop' + DESC 'An email address the virtual alias should be mapped to' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) +# +# We are creating a new attribute, optional in virtual domains and +# users, because the presence index should *not* apply to the +# mandatory attribute above. +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.5 NAME 'fripostOptionalMaildrop' + DESC 'An optional email address for catch-all aliases on domains and users' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.6 NAME 'fripostIsStatusActive' + DESC 'When present, a token locking the entry in an inactive state' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.7 NAME 'fripostPendingToken' + DESC 'Is the entry pending?' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{64} SINGLE-VALUE ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.8 NAME 'fripostUserQuota' + DESC 'The quota on a user e.g., "50MB"' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32} SINGLE-VALUE ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.9 NAME 'fripostCanAddDomain' + DESC 'A user/domain that can add domains' + SUP distinguishedName ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.10 NAME 'fripostCanAddAlias' + DESC 'A user/domain that can add aliases under the parent domain' + SUP distinguishedName ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.11 NAME 'fripostCanAddList' + DESC 'A user/domain that can add lists under the parent domain' + SUP distinguishedName ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.12 NAME 'fripostOwner' + DESC 'A user that owns under parent domain' + SUP distinguishedName ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.13 NAME 'fripostPostmaster' + DESC 'A user that is a postmaster of the parent domain' + SUP distinguishedName ) +# +olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.14 NAME 'fripostListManager' + DESC 'The list manager' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{64} SINGLE-VALUE ) +# +# +# Objects: 1.3.6.1.4.1.40011.1.2 +# +olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.1 NAME 'FripostVirtual' + AUXILIARY + DESC 'Virtual mail hosting' + MAY ( fripostCanAddDomain ) ) +# +olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.2 NAME 'FripostVirtualDomain' + SUP top STRUCTURAL + DESC 'Virtual domain' + MUST ( fvd $ fripostIsStatusActive ) + MAY ( fripostCanAddAlias $ fripostCanAddList $ + fripostOwner $ fripostPostmaster $ + fripostOptionalMaildrop $ description ) ) +# +# | TODO: add limits here +olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.3 NAME 'FripostVirtualUser' + SUP top STRUCTURAL + DESC 'Virtual user' + MUST ( fvl $ userPassword $ fripostIsStatusActive ) + MAY ( fripostUserQuota $ fripostOptionalMaildrop $ description) ) +# +olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.4 NAME 'FripostVirtualAlias' + SUP top STRUCTURAL + DESC 'Virtual alias' + MUST ( fvl $ fripostMaildrop $ fripostIsStatusActive ) + MAY ( fripostOwner $ description ) ) +# +olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.5 NAME 'FripostVirtualList' + SUP top STRUCTURAL + DESC 'Virtual list' + MUST ( fvl $ fripostListManager $ fripostIsStatusActive $ fripostLocalAlias ) + MAY ( fripostOwner $ description ) ) +# +olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.6 NAME 'FripostVirtualListCommand' + SUP top STRUCTURAL + DESC 'Virtual list command' + MUST ( fvl $ fripostLocalAlias ) ) +# +olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.7 NAME 'FripostPendingEntry' + SUP top AUXILIARY + DESC 'Virtual pending entry' + MAY ( fripostPendingToken ) ) diff --git a/roles/common-LDAP/files/var/lib/ldap/fripost/DB_CONFIG b/roles/common-LDAP/files/var/lib/ldap/fripost/DB_CONFIG new file mode 100644 index 0000000..0bd4e58 --- /dev/null +++ b/roles/common-LDAP/files/var/lib/ldap/fripost/DB_CONFIG @@ -0,0 +1,5 @@ +set_cachesize 0 5242880 1 +# 5MB cachesize, allow defragmentation +set_lk_max_objects 1500 +set_lk_max_locks 1500 +set_lk_max_lockers 1500 diff --git a/roles/common-LDAP/handlers/main.yml b/roles/common-LDAP/handlers/main.yml new file mode 100644 index 0000000..6972af2 --- /dev/null +++ b/roles/common-LDAP/handlers/main.yml @@ -0,0 +1,2 @@ +- name: Restart slapd + service: name=slapd state=restarted diff --git a/roles/common-LDAP/tasks/main.yml b/roles/common-LDAP/tasks/main.yml new file mode 100644 index 0000000..cb1e835 --- /dev/null +++ b/roles/common-LDAP/tasks/main.yml @@ -0,0 +1,67 @@ +- name: Install OpenLDAP + apt: pkg={{ item }} + with_items: + - slapd + - ldap-utils + - ldapvi + - db-util + - python-ldap + +# Upon install slapd create and populate a database under /var/lib/ldap. +# We clear it up and create a children directory to get finer-grain +# control. +- name: Clear empty /var/lib/ldap + # Don't remove the database (and fail) if it contains something else + # than its suffix or cn=admin,... + openldap: dbdirectory=/var/lib/ldap ignoredn=cn=admin + state=absent + +- name: Create directory /var/lib/ldap/fripost + file: path=/var/lib/ldap/fripost + owner=openldap group=openldap + state=directory + mode=0700 + +- name: Copy /var/lib/ldap/fripost/DB_CONFIG + copy: src=var/lib/ldap/fripost/DB_CONFIG + dest=/var/lib/ldap/fripost/DB_CONFIG + owner=openldap group=openldap + mode=0600 + notify: + # Not sure if required + - Restart slapd + +- name: Create directory /etc/ldap/fripost + file: path=/etc/ldap/fripost + owner=root group=root + state=directory + mode=0755 + +- name: Copy fripost database definition + template: src=etc/ldap/database.ldif.j2 + dest=/etc/ldap/fripost/database.ldif + owner=root group=root + mode=0600 + +- name: Copy fripost schema + copy: src=etc/ldap/schema/fripost.ldif + dest=/etc/ldap/schema/fripost.ldif + owner=root group=root + mode=0644 + +- name: Load fripost's schema and configure the database + openldap: target=/etc/ldap/{{ item }} state=present + with_items: + - schema/fripost.ldif + # TODO load other required schemas *before* loading the database + - fripost/database.ldif + +- name: Load LDAP modules + openldap: module={{ item }}.la state=present + with_items: + # TODO only if provider + - syncprov + # TODO only if writable + - constraint + +# TODO: authz constraint syncprov syncrepl diff --git a/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 b/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 new file mode 100644 index 0000000..19fcdd0 --- /dev/null +++ b/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 @@ -0,0 +1,498 @@ +# Fripost's LDAP database definition +# Copyright © 2013 Guilhem Moulin +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +dn: olcDatabase=hdb,cn=config +objectClass: olcDatabaseConfig +objectClass: olcHdbConfig +olcDbDirectory: /var/lib/ldap/fripost +olcSuffix: o=mailHosting,dc=fripost,dc=org +olcLastMod: TRUE +olcDbCheckpoint: 512 15 +# Require LDAPv3 protocol and authentication prior to directory +# operations. +olcRequires: LDAPv3 authc +# We don't want to give "canAdd{Alias,List}" write access to alias/list +# attributes. +olcAddContentAcl: FALSE +# The root user has all rights on the whole database (when SASL-binding +# on a UNIX socket). +olcRootDN: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth +# +# +######################################################################## +######################################################################## +# Performance considerations +# +# To reindex an existing database, you have to +# * Stop slapd sudo service slapd stop +# * Reindex su openldap -c "slapindex -b 'o=mailHosting,dc=fripost,dc=org'" +# * Restart slapd sudo service slapd start +# +# References +# - https://wiki.zimbra.com/wiki/OpenLDAP_Performance_Tuning_5.0 +# - http://www.openldap.org/doc/admin24/tuning.html +# - http://www.openldap.org/faq/data/cache/42.html +# - http://www.openldap.org/faq/data/cache/136.html +# - http://www.zytrax.com/books/ldap/apa/indeces.html +# +olcDbIndex: objectClass eq +# Let us make Postfix's life easier. TODO: only if MX, lists.f.o, MDA, etc. +olcDbIndex: fripostIsStatusActive,fvd,fvl,fripostLocalAlias eq +olcDbIndex: fripostOptionalMaildrop pres +# SyncProv/SyncRepl specific indexing. TODO: only if SyncProv/SyncRepl +olcDbIndex: entryCSN,entryUUID eq +# +# +# +# 1. On single- and dual-core systems, change the maximum number of +# threads to 8. (The default, 16, is fine for 4- and 8-core systems.) +# +# dn: cn=config +# changetype: modify +# add: olcThreads +# olcThreads: 8 +# +# +# 2. It may be a good idea to modify DB_CONFIG, depending on the output +# of +# +# db_stat -mh /var/lib/ldap/fripost | head -16 +# +# (For optimal performance, the Requested pages found in the cache +# should be above 95%, and the dirty/clean pages forced from the cache +# should be 0.) +# +# and +# +# db_stat -ch /var/lib/ldap/fripost | head -16 +# +# (For optimal performance, usage should be within 85% of the configured +# values.) +# +# +######################################################################## +######################################################################## +# Access control +# /!\ WARN: All modification to the ACL should be reflected to the test +# /!\ suite as well! +# +# References: +# - http://www.openldap.org/doc/admin24/access-control.html +# - http://www.openldap.org/faq/data/cache/189.html +# - http://www.openldap.org/faq/data/cache/1140.html +# - http://www.openldap.org/faq/data/cache/1133.html +# - man 5 slapd.access +# +# +######################################################################## +# Most common services: Postfix, Amavis, SASLauth, Dovecot +# (Most used ACLs are cheaper when written first.) +# +# Postfix have read access to the attribute they need. +olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" + attrs=entry,objectClass,fvd,fvl,fripostMaildrop,fripostOptionalMaildrop,fripostLocalAlias + filter=(&(|(objectClass=FripostVirtualDomain)(objectClass=FripostVirtualUser)(objectClass=FripostVirtualAlias)(objectClass=FripostVirtualList)(objectClass=FripostVirtualListCommand))(!(objectClass=FripostPendingEntry))(!(fripostIsStatusActive=FALSE))) + by dn.exact="cn=Postfix,ou=services,o=mailHosting,dc=fripost,dc=org" =rsd + by users =0 break +# Search lists and domain owners +olcAccess: to dn.exact="ou=virtual,o=mailHosting,dc=fripost,dc=org" + attrs=entry + by dn.exact="cn=Postfix,ou=services,o=mailHosting,dc=fripost,dc=org" =s + by dn.exact="gidNumber=8+uidNumber=8,cn=peercred,cn=external,cn=auth" =s + by users =0 break +# +# Search domain owners / postmasters +olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" + attrs=entry,objectClass,fvd,fvl,fripostPostmaster,fripostOwner + filter=(&(objectClass=FripostVirtualDomain)(!(objectClass=FripostPendingEntry))(!(fripostIsStatusActive=FALSE))) + by dn.exact="gidNumber=8+uidNumber=8,cn=peercred,cn=external,cn=auth" =rsd + by users =0 break +# +# Anonymous can authenticate into the services. (But not read or write the password.) +olcAccess: to dn.one="ou=services,o=mailHosting,dc=fripost,dc=org" + attrs=userPassword + by realanonymous =xd +# +# That's necessary for SASL proxy Authorize the web application. +olcAccess: to dn.exact="cn=AdminWebPanel,ou=services,o=mailHosting,dc=fripost,dc=org" + attrs=entry,objectClass,authzTo + by realanonymous =x +# +# 1. The WebPanel itself cannot bind, read or write passwords. This +# guarantees that, if an attacker gains its priviledge, it will *not* be +# able to change user passwords (which would allow him/her to read every +# emails). This is a trick to tackle the absence of 'realgroup'. +# 2. Anonymous users can bind. +# 3. Users can change their password (but not read it). +# 4. The postmaster of a domain can change (replace) his/her users' password (but not read it). +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualUser) + attrs=userPassword + by realdn.exact="uid=AdminWebPanel@fripost.org,cn=auth" =0 + by realanonymous =xd + by realself =w + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =w + by dn.onelevel="ou=managers,o=mailHosting,dc=fripost,dc=org" =w +# +# A catch-all, to be sure that noone else have access to the passwords. +olcAccess: to dn.subtree="o=mailHosting,dc=fripost,dc=org" + attrs=userPassword + by * =0 +# +# +######################################################################## +# Virtual subtree, pending token and general access +# +# 1. Users need further access. We use a set to deny all access to non-users without +# having a need for an expensive LDAP search (URL) in the AuthzTo. +# /!\ The objectClass "FripostVirtualUser" is case-sensitive in this case! +# 2,3. Services that need particular access on the tree. +# 4. Managers have read/write access to the "virtual" subtree. +olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=org" + by set.exact="user/objectClass & [FripostVirtualUser]" =0 break + by dn.exact="cn=CreateList,ou=services,o=mailHosting,dc=fripost,dc=org" =0 break + by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" =0 break + by dn.onelevel="ou=managers,o=mailHosting,dc=fripost,dc=org" =wrscd +# +# Only the domain Postmasters and Owners can delete the 'pending' status on domains. +olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(&(objectClass=FripostVirtualDomain)(objectClass=FripostPendingEntry)) + attrs=objectClass val=FripostPendingEntry + by dnattr=fripostPostmaster =z break + by dnattr=fripostOwner =z break + by * =0 break +# +# The list creation service can delete the 'pending' status on lists and list commands. +olcAccess: to dn.regex="^fvl=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(&(|(objectClass=FripostVirtualList)(objectClass=FripostVirtualListCommand))(objectClass=FripostPendingEntry)) + attrs=objectClass val=FripostPendingEntry + by dn.exact="cn=CreateList,ou=services,o=mailHosting,dc=fripost,dc=org" =z break + by * +0 break +# +# ObjectClass is a public attribute: everyone can read and search it. +olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=org" + attrs=objectClass + by * +rscd +# +# The pending token is not public, but domain owner and postmasters can check their and +# delete it (if the token matches, but the check is done on the library side). +olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(&(objectClass=FripostVirtualDomain)(objectClass=FripostPendingEntry)) + attrs=fripostPendingToken + by dnattr=fripostPostmaster =zcd break + by dnattr=fripostOwner =zcd break + by * +0 break +# +# The list creation service can delete the 'pending' status on lists and list commands. +olcAccess: to dn.regex="^fvl=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(&(|(objectClass=FripostVirtualList)(objectClass=FripostVirtualListCommand))(objectClass=FripostPendingEntry)) + attrs=fripostPendingToken + by dn.exact="cn=CreateList,ou=services,o=mailHosting,dc=fripost,dc=org" +z + by * +0 +# +# The cleaning service can list the (expired) pending entries and delete them. +olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" + filter=(objectClass=FripostPendingEntry) + attrs=entry + by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" =zrd break + by * =0 break +# +# One can search search everywhere in the virtual tree. +olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=org" + attrs=entry + by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" +s + by * =s break +# +# We're giving away create/delete access on the children attributes, but we will be carefull +# with the 'entry' permissions. +olcAccess: to dn.base="ou=virtual,o=mailHosting,dc=fripost,dc=org" + filter=(objectClass=FripostVirtual) + attrs=children + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" =w + by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" =z +olcAccess: to dn.one="ou=virtual,o=mailHosting,dc=fripost,dc=org" + filter=(objectClass=FripostVirtualDomain) + attrs=children + by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" =z + by * break +olcAccess: to dn.one="ou=virtual,o=mailHosting,dc=fripost,dc=org" + filter=(&(objectClass=FripostVirtualDomain)(!(objectClass=FripostPendingEntry))) + attrs=children + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" =w +# +# The cleaning service needs to know when entries have been created. +olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" + filter=(objectClass=FripostPendingEntry) + attrs=createTimestamp + by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" =s +# +# Users can use these in filters (e.g., to list the entries they have created). +olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" + filter=(|(objectClass=FripostVirtualDomain)(objectClass=FripostVirtualUser)(objectClass=FripostVirtualAlias)(objectClass=FripostVirtualList)) + attrs=fripostOwner,fripostPostmaster,fripostCanAddAlias,fripostCanAddList + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" =s break +# +# +######################################################################## +# Virtual subtree, domains +# +# 1. The postmaster of a domain can give (or take back) people the right to create +# aliases. +# 2,3. People that can create aliases can list the members of the group. +olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(objectClass=FripostVirtualDomain) + attrs=fripostCanAddAlias + by dnattr=fripostPostmaster =wrscd + by dnattr=fripostOwner =rscd + by set.exact="this/fripostCanAddAlias & (user | user/-1)" =rscd +# +# 1. The postmaster of a domain can give (or take back) people the right to create lists. +# 2,3. People that can create lists can list the members of the group. +olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(objectClass=FripostVirtualDomain) + attrs=fripostCanAddList + by dnattr=fripostPostmaster =wrscd + by dnattr=fripostOwner =rscd + by set.exact="this/fripostCanAddList & (user | user/-1)" =rscd +# +# 1-3. Noone (but the managers) can appoint domain Owners or Postmasters. +# But people that can create aliases and lists can list the members of their group. +olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(objectClass=FripostVirtualDomain) + attrs=fripostOwner,fripostPostmaster + by dnattr=fripostOwner =rscd + by dnattr=fripostPostmaster =rscd + by set.exact="(this/fripostCanAddAlias | this/fripostCanAddList) & (user | user/-1)" =rscd + by dn.onelevel,expand="$0" +d + by * +0 +# +# 1. Domain owners can edit their entry's attributes. +# 2. So can domain postmasters. +# 3. Domain users can read the public domain attributes. +# 4. So can users with "canAddAlias" or "canAddList" access. +olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(objectClass=FripostVirtualDomain) + attrs=fvd,fripostIsStatusActive,description + by dnattr=fripostOwner =wrscd + by dnattr=fripostPostmaster =wrscd + by dn.onelevel,expand="$0" =rscd + by set.exact="(this/fripostCanAddAlias | this/fripostCanAddList) & (user | user/-1)" =rscd +# +# 1. Domain owners can edit their entry's attributes. +# 2. So can domain postmasters. +olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(objectClass=FripostVirtualDomain) + attrs=@fripostVirtualDomain + by dnattr=fripostOwner =wrscd + by dnattr=fripostPostmaster =wrscd + by * +0 +# +# Users with "addDomain" access can create new entries, but only if +# there is a pending token. +olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(&(objectClass=FripostVirtualDomain)(objectClass=FripostPendingEntry)(fripostPendingToken=*)) + attrs=entry + by set.exact="this/-1/fripostCanAddDomain & (user | user/-1)" +a break + by * +0 break +# +# 1. Domain owners can delete their domain (and read the entry). +# 2. So can domain postmasters. +# 3. Domain users can read the domain entry (but not delete it). +# 4. So can users with "canAddAlias" or "canAddList" rights. +olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + filter=(objectClass=FripostVirtualDomain) + attrs=entry + by dnattr=fripostOwner +zrd + by dnattr=fripostPostmaster +zrd + by dn.onelevel,expand="$0" +rd + by set.exact="(this/fripostCanAddAlias | this/fripostCanAddList) & (user | user/-1)" +rd + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" +0 +# +# Reserved local parts are reserved. /!\ The case must be insensitive +# - postmaster: RFC 822, appendix C.6 +# - abuse: RFC 2142, section 4 +olcAccess: to dn.regex="^fvl=(postmaster|abuse),fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" + by * =0 +# +# +######################################################################## +# Virtual subtree, users +# +# Users and their postmaster can read the quota (but not change it). +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualUser) + attrs=fripostUserQuota + by self =rscd + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =rscd +# +# 1. Users can modify their own entry. +# 2. So can their postmasters. +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualUser) + attrs=@FripostVirtualUser + by self =wrscd + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =wrscd +# +# 1. Users can read their entry (but not delete it). +# 2. Postmasters can create users (but not delete them). +# (Provided that they have +a access to the parent's "children" attribute.) +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualUser) + attrs=entry + by self +rd + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" +ard +# +# +######################################################################## +# Virtual subtree, aliases +# +# 1. The alias owner can list the ownership of the entry. +# 2. The domain owner can add/delete/change the ownership of the entry. +# 3. So can the domain postmasters. +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualAlias) + attrs=fripostOwner + by dnattr=fripostOwner =rscd continue + by group/FripostVirtualDomain/fripostOwner.expand="$1" =wrscd + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =wrscd + by * +0 +# +# 1. The alias owners can edit the rest of their entry's attributes. +# 2. So can the domain owners. +# 3. So can the domain postmasters. +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualAlias) + attrs=@FripostVirtualAlias + by dnattr=fripostOwner =wrscd + by group/FripostVirtualDomain/fripostOwner.expand="$1" =wrscd + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =wrscd +# +# 1. The alias owners can read and delete the entry. +# 2. So can the domain owner. +# 3. So can the domain postmaster. +# 4. Users with "canAddAlias" access (either explicitely, or as a wildcard) for the domain can create aliases for that domain. +# (But *not* delete them, unless also owner.) +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualAlias) + attrs=entry + by dnattr=fripostOwner +zrd continue + by group/FripostVirtualDomain/fripostOwner.expand="$1" +wrd + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" +wrd + by set.exact="this/-1/fripostCanAddAlias & (user | user/-1)" +a + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" +0 +# +# +######################################################################## +# Virtual subtree, lists +# +# 1. The list owner can list the ownership of the entry. +# 2. The domain owner can add/delete/change the ownership of the entry. +# 3. So can the domain postmasters. +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualList) + attrs=fripostOwner + by dnattr=fripostOwner =rscd continue + by group/FripostVirtualDomain/fripostOwner.expand="$1" =wrscd + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =wrscd + by * +0 +# +# 1. The list owner read (but not edit) the transport-related attributes. +# 2. So can the domain ower. +# 3. So can the domain postmaster. +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualList) + attrs=fripostListManager + by dnattr=fripostOwner =rscd + by group/FripostVirtualDomain/fripostOwner.expand="$1" =rscd + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =rscd +# +# Local aliases are for internal use only. +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualList) + attrs=fripostLocalAlias + by * =0 +# +# 1. The list owners can edit their entry's attributes. +# 2. So can the domain owners. +# 3. So can the domain postmasters. +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualList) + attrs=@FripostVirtualList + by dnattr=fripostOwner =wrscd + by group/FripostVirtualDomain/fripostOwner.expand="$1" =wrscd + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =wrscd +# +# 1. The domain owner can create and delete lists, but only those with a 'pending' status +# 2. So can the domain postmaster. +# 3. The list owner can delete pending lists. +# 4. The entry creator can delete pending lists (needed to be able to rollback). +# 5. People with "canAddList" access can create lists, but only with a 'pending' status. +# 6. The list creation service can search and browse the entry. +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(&(objectClass=FripostVirtualList)(objectClass=FripostPendingEntry)) + attrs=entry + by group/FripostVirtualDomain/fripostOwner.expand="$1" +w break + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" +w break + by dnattr=fripostOwner +z continue + by dnattr=creatorsName +z continue + by set.exact="this/-1/fripostCanAddList & (user | user/-1)" +a break + by dn.exact="cn=CreateList,ou=services,o=mailHosting,dc=fripost,dc=org" +rd + by * +0 break +# +# 1. The domain owner can create and delete list commands, but only those with a 'pending' status +# 2. So can the domain postmaster. +# 3. The entry creator can delete pending list commands (needed to be able to rollback). +# 4. People with "canAddList" access can create list commands, but only with a 'pending' status. +# 5. The list creation service can search and browse the entry. +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(&(objectClass=FripostVirtualListCommand)(objectClass=FripostPendingEntry)) + attrs=entry + by group/FripostVirtualDomain/fripostOwner.expand="$1" +w + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" +w + by dnattr=creatorsName +z continue + by set.exact="this/-1/fripostCanAddList & (user | user/-1)" +a + by dn.exact="cn=CreateList,ou=services,o=mailHosting,dc=fripost,dc=org" +rd + by * +0 +# +# 1. The list owners can read the entry. +# 2. So can the domain's Owner. +# 3. So can the domain's Postmaster. +olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" + filter=(objectClass=FripostVirtualList) + attrs=entry + by dnattr=fripostOwner +rd + by group/FripostVirtualDomain/fripostOwner.expand="$1" +rd + by group/FripostVirtualDomain/fripostPostmaster.expand="$1" +rd + by * +0 +# +# +######################################################################## +# Catchall +# +# Users with "canAddDomain" access can see that they have the right +# to create domains. +olcAccess: to dn.base="ou=virtual,o=mailHosting,dc=fripost,dc=org" + filter=(objectClass=FripostVirtual) + attrs=entry + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" +rd +olcAccess: to dn.base="ou=virtual,o=mailHosting,dc=fripost,dc=org" + filter=(objectClass=FripostVirtual) + attrs=fripostCanAddDomain + by set.exact="this/fripostCanAddDomain & (user | user/-1)" =rscd +# Catch the break above +olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=org" + by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" +0 +# vim: set filetype=ldif : diff --git a/roles/common-SQL/tasks/main.yml b/roles/common-SQL/tasks/main.yml new file mode 100644 index 0000000..e32c863 --- /dev/null +++ b/roles/common-SQL/tasks/main.yml @@ -0,0 +1,29 @@ +- name: Install MySQL + apt: pkg={{ item }} + with_items: + # XXX: In non-interactive mode apt-get doesn't put a password on + # MySQL's root user; we fix that on the next task, but an intruder + # could exploit the race condition and for instance create dummy + # users. + - mysql-common + - mysql-server + - python-mysqldb + +- name: Force root to use UNIX permissions + mysql_user: name=root auth_plugin=auth_socket + state=present + +- name: Disallow anonymous and TCP/IP root login + mysql_user: name={{ item.name|default('') }} host={{ item.host }} + state=absent + with_items: + - { host: '{{ inventory_hostname_short }}' } + - { host: 'localhost' } + - { host: '127.0.0.1'} + - { host: '::1'} + - { name: root, host: '{{ inventory_hostname_short }}' } + - { name: root, host: '127.0.0.1'} + - { name: root, host: '::1'} + +- name: Start MySQL + service: name=mysql state=started diff --git a/roles/common/files/etc/ldap/schema/fripost.ldif b/roles/common/files/etc/ldap/schema/fripost.ldif deleted file mode 100644 index 851988e..0000000 --- a/roles/common/files/etc/ldap/schema/fripost.ldif +++ /dev/null @@ -1,190 +0,0 @@ -# Fripost's LDAP schema -# Copyright © 2013 Guilhem Moulin -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Load this file with -# -# ldapadd -Y EXTERNAL -H ldapi:/// -f fripost.ldif -# -# It will load the schema. To perform modifications, the easiest way is to -# -# * Save the database: slapcat -b 'o=mailHosting,dc=fripost,dc=dev' > /tmp/db.ldif -# * Save the configuration: slapcat -n0 > /tmp/config.ldif -# * Backup slap.d: cp -a /etc/ldap/slapd.d/ /tmp/slap.d_back -# * Edit the schema in /tmp/config.ldif -# * Load the new config: mkdir -m 0700 /tmp/slapd.d_new && slapadd -F /tmp/slapd.d_new -n0 -l /tmp/config.ldif -# * Stop slapd: /etc/init.d/slapd stop -# * Load the new config: rm -rf /etc/ldap/slapd.d/ && mv /tmp/slapd.d_new /etc/ldap/slapd.d && chown -R openldap:openldap /etc/ldap/slapd.d -# * Create indexes: sudo -u openldap slapindex -b 'o=mailHosting,dc=fripost,dc=dev' -# * Start slapd: /etc/init.d/slapd start -# If it fails, remove the existing database and see what's wrong -# rm -rf /var/lib/ldap/dev/* && sudo -u openldap slapadd -b 'o=mailHosting,dc=fripost,dc=org' -l /tmp/db.ldif -# -# -# /!\ WARN: All modification to the ACL should be reflected to the test -# /!\ suite as well! -# -# -# References: -# - http://courier.svn.sourceforge.net/svnroot/courier/trunk/courier-authlib/authldap.schema -# - http://www.qmail-ldap.org/wiki/index.php/Qmail.schema -# - http://www.wanderingbarque.com/howtos/mailserver/mailserver.html - - -# 1.3.6.1.4.1.40011 Fripost's OID -# 1.3.6.1.4.1.40011.1 -# 1.3.6.1.4.1.40011.1.2 fripost LDAP Elements -# 1.3.6.1.4.1.40011.1.2.1 AttributeTypes -# 1.3.6.1.4.1.40011.1.2.2 ObjectClasses -# 1.3.6.1.4.1.40011.1.2.3 Syntax Definitions - -# This schema depends on: -# - core.schema -# - cosine.schema -# - nis.schema - - -dn: cn=fripost-master,cn=schema,cn=config -objectClass: olcSchemaConfig -# -# Attributes: 1.3.6.1.4.1.40011.1.1 -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.1 NAME 'fvd' - DESC 'A virtual mail domain' - EQUALITY caseIgnoreIA5Match - SUBSTR caseIgnoreIA5SubstringsMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.2 NAME 'fvl' - DESC 'The local part of a virtual user, alias, list or list command' - EQUALITY caseIgnoreIA5Match - SUBSTR caseIgnoreIA5SubstringsMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE ) -# -# This is redundant since we always use DNs of the form -# fvl=localpart,fvd=domainpart.tld,... -# (But Postfix doesn't allow the use of '%u' and '%d' from the query in -# its 'result_format'.) -# It is a priori insecure to allow arbitrary values here since users -# will modify this value themselves, however our Postfix will only -# accept well-formed values, enforced by a custom filter: -# query_filter = (&...(fripostLocalAlias=%u#%d)) -# result_attribute = fripostLocalAlias -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.3 NAME 'fripostLocalAlias' - DESC 'A local alias, typically localpart#domainpart.tld' - EQUALITY caseIgnoreIA5Match - SUBSTR caseIgnoreIA5SubstringsMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.4 NAME 'fripostMaildrop' - DESC 'An email address the virtual alias should be mapped to' - EQUALITY caseIgnoreIA5Match - SUBSTR caseIgnoreIA5SubstringsMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) -# -# We are creating a new attribute, optional in virtual domains and -# users, because the presence index should *not* apply to the -# mandatory attribute above. -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.5 NAME 'fripostOptionalMaildrop' - DESC 'An optional email address for catch-all aliases on domains and users' - EQUALITY caseIgnoreIA5Match - SUBSTR caseIgnoreIA5SubstringsMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.6 NAME 'fripostIsStatusActive' - DESC 'When present, a token locking the entry in an inactive state' - EQUALITY booleanMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.7 NAME 'fripostPendingToken' - DESC 'Is the entry pending?' - EQUALITY caseExactMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{64} SINGLE-VALUE ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.8 NAME 'fripostUserQuota' - DESC 'The quota on a user e.g., "50MB"' - EQUALITY caseExactMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32} SINGLE-VALUE ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.9 NAME 'fripostCanAddDomain' - DESC 'A user/domain that can add domains' - SUP distinguishedName ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.10 NAME 'fripostCanAddAlias' - DESC 'A user/domain that can add aliases under the parent domain' - SUP distinguishedName ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.11 NAME 'fripostCanAddList' - DESC 'A user/domain that can add lists under the parent domain' - SUP distinguishedName ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.12 NAME 'fripostOwner' - DESC 'A user that owns under parent domain' - SUP distinguishedName ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.13 NAME 'fripostPostmaster' - DESC 'A user that is a postmaster of the parent domain' - SUP distinguishedName ) -# -olcAttributeTypes: ( 1.3.6.1.4.1.40011.1.2.1.14 NAME 'fripostListManager' - DESC 'The list manager' - EQUALITY caseIgnoreMatch - SUBSTR caseIgnoreSubstringsMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{64} SINGLE-VALUE ) -# -# -# Objects: 1.3.6.1.4.1.40011.1.2 -# -olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.1 NAME 'FripostVirtual' - AUXILIARY - DESC 'Virtual mail hosting' - MAY ( fripostCanAddDomain ) ) -# -olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.2 NAME 'FripostVirtualDomain' - SUP top STRUCTURAL - DESC 'Virtual domain' - MUST ( fvd $ fripostIsStatusActive ) - MAY ( fripostCanAddAlias $ fripostCanAddList $ - fripostOwner $ fripostPostmaster $ - fripostOptionalMaildrop $ description ) ) -# -# | TODO: add limits here -olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.3 NAME 'FripostVirtualUser' - SUP top STRUCTURAL - DESC 'Virtual user' - MUST ( fvl $ userPassword $ fripostIsStatusActive ) - MAY ( fripostUserQuota $ fripostOptionalMaildrop $ description) ) -# -olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.4 NAME 'FripostVirtualAlias' - SUP top STRUCTURAL - DESC 'Virtual alias' - MUST ( fvl $ fripostMaildrop $ fripostIsStatusActive ) - MAY ( fripostOwner $ description ) ) -# -olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.5 NAME 'FripostVirtualList' - SUP top STRUCTURAL - DESC 'Virtual list' - MUST ( fvl $ fripostListManager $ fripostIsStatusActive $ fripostLocalAlias ) - MAY ( fripostOwner $ description ) ) -# -olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.6 NAME 'FripostVirtualListCommand' - SUP top STRUCTURAL - DESC 'Virtual list command' - MUST ( fvl $ fripostLocalAlias ) ) -# -olcObjectClasses: ( 1.3.6.1.4.1.40011.1.2.7 NAME 'FripostPendingEntry' - SUP top AUXILIARY - DESC 'Virtual pending entry' - MAY ( fripostPendingToken ) ) diff --git a/roles/common/files/var/lib/ldap/fripost/DB_CONFIG b/roles/common/files/var/lib/ldap/fripost/DB_CONFIG deleted file mode 100644 index 0bd4e58..0000000 --- a/roles/common/files/var/lib/ldap/fripost/DB_CONFIG +++ /dev/null @@ -1,5 +0,0 @@ -set_cachesize 0 5242880 1 -# 5MB cachesize, allow defragmentation -set_lk_max_objects 1500 -set_lk_max_locks 1500 -set_lk_max_lockers 1500 diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml index 51b19f7..54643ed 100644 --- a/roles/common/handlers/main.yml +++ b/roles/common/handlers/main.yml @@ -35,6 +35,3 @@ - name: Reload Postfix service: name=postfix state=reloaded - -- name: Restart slapd - service: name=slapd state=restarted diff --git a/roles/common/tasks/ldap.yml b/roles/common/tasks/ldap.yml deleted file mode 100644 index cb1e835..0000000 --- a/roles/common/tasks/ldap.yml +++ /dev/null @@ -1,67 +0,0 @@ -- name: Install OpenLDAP - apt: pkg={{ item }} - with_items: - - slapd - - ldap-utils - - ldapvi - - db-util - - python-ldap - -# Upon install slapd create and populate a database under /var/lib/ldap. -# We clear it up and create a children directory to get finer-grain -# control. -- name: Clear empty /var/lib/ldap - # Don't remove the database (and fail) if it contains something else - # than its suffix or cn=admin,... - openldap: dbdirectory=/var/lib/ldap ignoredn=cn=admin - state=absent - -- name: Create directory /var/lib/ldap/fripost - file: path=/var/lib/ldap/fripost - owner=openldap group=openldap - state=directory - mode=0700 - -- name: Copy /var/lib/ldap/fripost/DB_CONFIG - copy: src=var/lib/ldap/fripost/DB_CONFIG - dest=/var/lib/ldap/fripost/DB_CONFIG - owner=openldap group=openldap - mode=0600 - notify: - # Not sure if required - - Restart slapd - -- name: Create directory /etc/ldap/fripost - file: path=/etc/ldap/fripost - owner=root group=root - state=directory - mode=0755 - -- name: Copy fripost database definition - template: src=etc/ldap/database.ldif.j2 - dest=/etc/ldap/fripost/database.ldif - owner=root group=root - mode=0600 - -- name: Copy fripost schema - copy: src=etc/ldap/schema/fripost.ldif - dest=/etc/ldap/schema/fripost.ldif - owner=root group=root - mode=0644 - -- name: Load fripost's schema and configure the database - openldap: target=/etc/ldap/{{ item }} state=present - with_items: - - schema/fripost.ldif - # TODO load other required schemas *before* loading the database - - fripost/database.ldif - -- name: Load LDAP modules - openldap: module={{ item }}.la state=present - with_items: - # TODO only if provider - - syncprov - # TODO only if writable - - constraint - -# TODO: authz constraint syncprov syncrepl diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml index ed84cb5..355b2df 100644 --- a/roles/common/tasks/main.yml +++ b/roles/common/tasks/main.yml @@ -9,15 +9,3 @@ - include: ipsec.yml tags=strongswan,ipsec - include: logging.yml tags=logging - include: mail.yml tags=mail,postfix -- include: sql.yml tags=mysql,sql - # XXX: the conditional here is a bit dirty, because it clutters the - # output with 'skipping' notices. - when: "'MDA' in group_names or - 'webmail' in group_names or - 'backup' in group_names" -- include: ldap.yml tags=slapd,ldap - when: "'MDA' in group_names or - 'MSA' in group_names or - 'lists' in group_names or - 'LDAP-producer' in group_names or - 'MX' in group_names" diff --git a/roles/common/tasks/sql.yml b/roles/common/tasks/sql.yml deleted file mode 100644 index e32c863..0000000 --- a/roles/common/tasks/sql.yml +++ /dev/null @@ -1,29 +0,0 @@ -- name: Install MySQL - apt: pkg={{ item }} - with_items: - # XXX: In non-interactive mode apt-get doesn't put a password on - # MySQL's root user; we fix that on the next task, but an intruder - # could exploit the race condition and for instance create dummy - # users. - - mysql-common - - mysql-server - - python-mysqldb - -- name: Force root to use UNIX permissions - mysql_user: name=root auth_plugin=auth_socket - state=present - -- name: Disallow anonymous and TCP/IP root login - mysql_user: name={{ item.name|default('') }} host={{ item.host }} - state=absent - with_items: - - { host: '{{ inventory_hostname_short }}' } - - { host: 'localhost' } - - { host: '127.0.0.1'} - - { host: '::1'} - - { name: root, host: '{{ inventory_hostname_short }}' } - - { name: root, host: '127.0.0.1'} - - { name: root, host: '::1'} - -- name: Start MySQL - service: name=mysql state=started diff --git a/roles/common/templates/etc/ldap/database.ldif.j2 b/roles/common/templates/etc/ldap/database.ldif.j2 deleted file mode 100644 index 19fcdd0..0000000 --- a/roles/common/templates/etc/ldap/database.ldif.j2 +++ /dev/null @@ -1,498 +0,0 @@ -# Fripost's LDAP database definition -# Copyright © 2013 Guilhem Moulin -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -dn: olcDatabase=hdb,cn=config -objectClass: olcDatabaseConfig -objectClass: olcHdbConfig -olcDbDirectory: /var/lib/ldap/fripost -olcSuffix: o=mailHosting,dc=fripost,dc=org -olcLastMod: TRUE -olcDbCheckpoint: 512 15 -# Require LDAPv3 protocol and authentication prior to directory -# operations. -olcRequires: LDAPv3 authc -# We don't want to give "canAdd{Alias,List}" write access to alias/list -# attributes. -olcAddContentAcl: FALSE -# The root user has all rights on the whole database (when SASL-binding -# on a UNIX socket). -olcRootDN: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth -# -# -######################################################################## -######################################################################## -# Performance considerations -# -# To reindex an existing database, you have to -# * Stop slapd sudo service slapd stop -# * Reindex su openldap -c "slapindex -b 'o=mailHosting,dc=fripost,dc=org'" -# * Restart slapd sudo service slapd start -# -# References -# - https://wiki.zimbra.com/wiki/OpenLDAP_Performance_Tuning_5.0 -# - http://www.openldap.org/doc/admin24/tuning.html -# - http://www.openldap.org/faq/data/cache/42.html -# - http://www.openldap.org/faq/data/cache/136.html -# - http://www.zytrax.com/books/ldap/apa/indeces.html -# -olcDbIndex: objectClass eq -# Let us make Postfix's life easier. TODO: only if MX, lists.f.o, MDA, etc. -olcDbIndex: fripostIsStatusActive,fvd,fvl,fripostLocalAlias eq -olcDbIndex: fripostOptionalMaildrop pres -# SyncProv/SyncRepl specific indexing. TODO: only if SyncProv/SyncRepl -olcDbIndex: entryCSN,entryUUID eq -# -# -# -# 1. On single- and dual-core systems, change the maximum number of -# threads to 8. (The default, 16, is fine for 4- and 8-core systems.) -# -# dn: cn=config -# changetype: modify -# add: olcThreads -# olcThreads: 8 -# -# -# 2. It may be a good idea to modify DB_CONFIG, depending on the output -# of -# -# db_stat -mh /var/lib/ldap/fripost | head -16 -# -# (For optimal performance, the Requested pages found in the cache -# should be above 95%, and the dirty/clean pages forced from the cache -# should be 0.) -# -# and -# -# db_stat -ch /var/lib/ldap/fripost | head -16 -# -# (For optimal performance, usage should be within 85% of the configured -# values.) -# -# -######################################################################## -######################################################################## -# Access control -# /!\ WARN: All modification to the ACL should be reflected to the test -# /!\ suite as well! -# -# References: -# - http://www.openldap.org/doc/admin24/access-control.html -# - http://www.openldap.org/faq/data/cache/189.html -# - http://www.openldap.org/faq/data/cache/1140.html -# - http://www.openldap.org/faq/data/cache/1133.html -# - man 5 slapd.access -# -# -######################################################################## -# Most common services: Postfix, Amavis, SASLauth, Dovecot -# (Most used ACLs are cheaper when written first.) -# -# Postfix have read access to the attribute they need. -olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" - attrs=entry,objectClass,fvd,fvl,fripostMaildrop,fripostOptionalMaildrop,fripostLocalAlias - filter=(&(|(objectClass=FripostVirtualDomain)(objectClass=FripostVirtualUser)(objectClass=FripostVirtualAlias)(objectClass=FripostVirtualList)(objectClass=FripostVirtualListCommand))(!(objectClass=FripostPendingEntry))(!(fripostIsStatusActive=FALSE))) - by dn.exact="cn=Postfix,ou=services,o=mailHosting,dc=fripost,dc=org" =rsd - by users =0 break -# Search lists and domain owners -olcAccess: to dn.exact="ou=virtual,o=mailHosting,dc=fripost,dc=org" - attrs=entry - by dn.exact="cn=Postfix,ou=services,o=mailHosting,dc=fripost,dc=org" =s - by dn.exact="gidNumber=8+uidNumber=8,cn=peercred,cn=external,cn=auth" =s - by users =0 break -# -# Search domain owners / postmasters -olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" - attrs=entry,objectClass,fvd,fvl,fripostPostmaster,fripostOwner - filter=(&(objectClass=FripostVirtualDomain)(!(objectClass=FripostPendingEntry))(!(fripostIsStatusActive=FALSE))) - by dn.exact="gidNumber=8+uidNumber=8,cn=peercred,cn=external,cn=auth" =rsd - by users =0 break -# -# Anonymous can authenticate into the services. (But not read or write the password.) -olcAccess: to dn.one="ou=services,o=mailHosting,dc=fripost,dc=org" - attrs=userPassword - by realanonymous =xd -# -# That's necessary for SASL proxy Authorize the web application. -olcAccess: to dn.exact="cn=AdminWebPanel,ou=services,o=mailHosting,dc=fripost,dc=org" - attrs=entry,objectClass,authzTo - by realanonymous =x -# -# 1. The WebPanel itself cannot bind, read or write passwords. This -# guarantees that, if an attacker gains its priviledge, it will *not* be -# able to change user passwords (which would allow him/her to read every -# emails). This is a trick to tackle the absence of 'realgroup'. -# 2. Anonymous users can bind. -# 3. Users can change their password (but not read it). -# 4. The postmaster of a domain can change (replace) his/her users' password (but not read it). -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualUser) - attrs=userPassword - by realdn.exact="uid=AdminWebPanel@fripost.org,cn=auth" =0 - by realanonymous =xd - by realself =w - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =w - by dn.onelevel="ou=managers,o=mailHosting,dc=fripost,dc=org" =w -# -# A catch-all, to be sure that noone else have access to the passwords. -olcAccess: to dn.subtree="o=mailHosting,dc=fripost,dc=org" - attrs=userPassword - by * =0 -# -# -######################################################################## -# Virtual subtree, pending token and general access -# -# 1. Users need further access. We use a set to deny all access to non-users without -# having a need for an expensive LDAP search (URL) in the AuthzTo. -# /!\ The objectClass "FripostVirtualUser" is case-sensitive in this case! -# 2,3. Services that need particular access on the tree. -# 4. Managers have read/write access to the "virtual" subtree. -olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=org" - by set.exact="user/objectClass & [FripostVirtualUser]" =0 break - by dn.exact="cn=CreateList,ou=services,o=mailHosting,dc=fripost,dc=org" =0 break - by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" =0 break - by dn.onelevel="ou=managers,o=mailHosting,dc=fripost,dc=org" =wrscd -# -# Only the domain Postmasters and Owners can delete the 'pending' status on domains. -olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(&(objectClass=FripostVirtualDomain)(objectClass=FripostPendingEntry)) - attrs=objectClass val=FripostPendingEntry - by dnattr=fripostPostmaster =z break - by dnattr=fripostOwner =z break - by * =0 break -# -# The list creation service can delete the 'pending' status on lists and list commands. -olcAccess: to dn.regex="^fvl=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(&(|(objectClass=FripostVirtualList)(objectClass=FripostVirtualListCommand))(objectClass=FripostPendingEntry)) - attrs=objectClass val=FripostPendingEntry - by dn.exact="cn=CreateList,ou=services,o=mailHosting,dc=fripost,dc=org" =z break - by * +0 break -# -# ObjectClass is a public attribute: everyone can read and search it. -olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=org" - attrs=objectClass - by * +rscd -# -# The pending token is not public, but domain owner and postmasters can check their and -# delete it (if the token matches, but the check is done on the library side). -olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(&(objectClass=FripostVirtualDomain)(objectClass=FripostPendingEntry)) - attrs=fripostPendingToken - by dnattr=fripostPostmaster =zcd break - by dnattr=fripostOwner =zcd break - by * +0 break -# -# The list creation service can delete the 'pending' status on lists and list commands. -olcAccess: to dn.regex="^fvl=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(&(|(objectClass=FripostVirtualList)(objectClass=FripostVirtualListCommand))(objectClass=FripostPendingEntry)) - attrs=fripostPendingToken - by dn.exact="cn=CreateList,ou=services,o=mailHosting,dc=fripost,dc=org" +z - by * +0 -# -# The cleaning service can list the (expired) pending entries and delete them. -olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" - filter=(objectClass=FripostPendingEntry) - attrs=entry - by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" =zrd break - by * =0 break -# -# One can search search everywhere in the virtual tree. -olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=org" - attrs=entry - by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" +s - by * =s break -# -# We're giving away create/delete access on the children attributes, but we will be carefull -# with the 'entry' permissions. -olcAccess: to dn.base="ou=virtual,o=mailHosting,dc=fripost,dc=org" - filter=(objectClass=FripostVirtual) - attrs=children - by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" =w - by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" =z -olcAccess: to dn.one="ou=virtual,o=mailHosting,dc=fripost,dc=org" - filter=(objectClass=FripostVirtualDomain) - attrs=children - by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" =z - by * break -olcAccess: to dn.one="ou=virtual,o=mailHosting,dc=fripost,dc=org" - filter=(&(objectClass=FripostVirtualDomain)(!(objectClass=FripostPendingEntry))) - attrs=children - by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" =w -# -# The cleaning service needs to know when entries have been created. -olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" - filter=(objectClass=FripostPendingEntry) - attrs=createTimestamp - by dn.exact="cn=DeletePendingEntries,ou=services,o=mailHosting,dc=fripost,dc=org" =s -# -# Users can use these in filters (e.g., to list the entries they have created). -olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" - filter=(|(objectClass=FripostVirtualDomain)(objectClass=FripostVirtualUser)(objectClass=FripostVirtualAlias)(objectClass=FripostVirtualList)) - attrs=fripostOwner,fripostPostmaster,fripostCanAddAlias,fripostCanAddList - by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" =s break -# -# -######################################################################## -# Virtual subtree, domains -# -# 1. The postmaster of a domain can give (or take back) people the right to create -# aliases. -# 2,3. People that can create aliases can list the members of the group. -olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(objectClass=FripostVirtualDomain) - attrs=fripostCanAddAlias - by dnattr=fripostPostmaster =wrscd - by dnattr=fripostOwner =rscd - by set.exact="this/fripostCanAddAlias & (user | user/-1)" =rscd -# -# 1. The postmaster of a domain can give (or take back) people the right to create lists. -# 2,3. People that can create lists can list the members of the group. -olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(objectClass=FripostVirtualDomain) - attrs=fripostCanAddList - by dnattr=fripostPostmaster =wrscd - by dnattr=fripostOwner =rscd - by set.exact="this/fripostCanAddList & (user | user/-1)" =rscd -# -# 1-3. Noone (but the managers) can appoint domain Owners or Postmasters. -# But people that can create aliases and lists can list the members of their group. -olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(objectClass=FripostVirtualDomain) - attrs=fripostOwner,fripostPostmaster - by dnattr=fripostOwner =rscd - by dnattr=fripostPostmaster =rscd - by set.exact="(this/fripostCanAddAlias | this/fripostCanAddList) & (user | user/-1)" =rscd - by dn.onelevel,expand="$0" +d - by * +0 -# -# 1. Domain owners can edit their entry's attributes. -# 2. So can domain postmasters. -# 3. Domain users can read the public domain attributes. -# 4. So can users with "canAddAlias" or "canAddList" access. -olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(objectClass=FripostVirtualDomain) - attrs=fvd,fripostIsStatusActive,description - by dnattr=fripostOwner =wrscd - by dnattr=fripostPostmaster =wrscd - by dn.onelevel,expand="$0" =rscd - by set.exact="(this/fripostCanAddAlias | this/fripostCanAddList) & (user | user/-1)" =rscd -# -# 1. Domain owners can edit their entry's attributes. -# 2. So can domain postmasters. -olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(objectClass=FripostVirtualDomain) - attrs=@fripostVirtualDomain - by dnattr=fripostOwner =wrscd - by dnattr=fripostPostmaster =wrscd - by * +0 -# -# Users with "addDomain" access can create new entries, but only if -# there is a pending token. -olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(&(objectClass=FripostVirtualDomain)(objectClass=FripostPendingEntry)(fripostPendingToken=*)) - attrs=entry - by set.exact="this/-1/fripostCanAddDomain & (user | user/-1)" +a break - by * +0 break -# -# 1. Domain owners can delete their domain (and read the entry). -# 2. So can domain postmasters. -# 3. Domain users can read the domain entry (but not delete it). -# 4. So can users with "canAddAlias" or "canAddList" rights. -olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - filter=(objectClass=FripostVirtualDomain) - attrs=entry - by dnattr=fripostOwner +zrd - by dnattr=fripostPostmaster +zrd - by dn.onelevel,expand="$0" +rd - by set.exact="(this/fripostCanAddAlias | this/fripostCanAddList) & (user | user/-1)" +rd - by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" +0 -# -# Reserved local parts are reserved. /!\ The case must be insensitive -# - postmaster: RFC 822, appendix C.6 -# - abuse: RFC 2142, section 4 -olcAccess: to dn.regex="^fvl=(postmaster|abuse),fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" - by * =0 -# -# -######################################################################## -# Virtual subtree, users -# -# Users and their postmaster can read the quota (but not change it). -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualUser) - attrs=fripostUserQuota - by self =rscd - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =rscd -# -# 1. Users can modify their own entry. -# 2. So can their postmasters. -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualUser) - attrs=@FripostVirtualUser - by self =wrscd - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =wrscd -# -# 1. Users can read their entry (but not delete it). -# 2. Postmasters can create users (but not delete them). -# (Provided that they have +a access to the parent's "children" attribute.) -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualUser) - attrs=entry - by self +rd - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" +ard -# -# -######################################################################## -# Virtual subtree, aliases -# -# 1. The alias owner can list the ownership of the entry. -# 2. The domain owner can add/delete/change the ownership of the entry. -# 3. So can the domain postmasters. -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualAlias) - attrs=fripostOwner - by dnattr=fripostOwner =rscd continue - by group/FripostVirtualDomain/fripostOwner.expand="$1" =wrscd - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =wrscd - by * +0 -# -# 1. The alias owners can edit the rest of their entry's attributes. -# 2. So can the domain owners. -# 3. So can the domain postmasters. -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualAlias) - attrs=@FripostVirtualAlias - by dnattr=fripostOwner =wrscd - by group/FripostVirtualDomain/fripostOwner.expand="$1" =wrscd - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =wrscd -# -# 1. The alias owners can read and delete the entry. -# 2. So can the domain owner. -# 3. So can the domain postmaster. -# 4. Users with "canAddAlias" access (either explicitely, or as a wildcard) for the domain can create aliases for that domain. -# (But *not* delete them, unless also owner.) -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualAlias) - attrs=entry - by dnattr=fripostOwner +zrd continue - by group/FripostVirtualDomain/fripostOwner.expand="$1" +wrd - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" +wrd - by set.exact="this/-1/fripostCanAddAlias & (user | user/-1)" +a - by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" +0 -# -# -######################################################################## -# Virtual subtree, lists -# -# 1. The list owner can list the ownership of the entry. -# 2. The domain owner can add/delete/change the ownership of the entry. -# 3. So can the domain postmasters. -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualList) - attrs=fripostOwner - by dnattr=fripostOwner =rscd continue - by group/FripostVirtualDomain/fripostOwner.expand="$1" =wrscd - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =wrscd - by * +0 -# -# 1. The list owner read (but not edit) the transport-related attributes. -# 2. So can the domain ower. -# 3. So can the domain postmaster. -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualList) - attrs=fripostListManager - by dnattr=fripostOwner =rscd - by group/FripostVirtualDomain/fripostOwner.expand="$1" =rscd - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =rscd -# -# Local aliases are for internal use only. -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualList) - attrs=fripostLocalAlias - by * =0 -# -# 1. The list owners can edit their entry's attributes. -# 2. So can the domain owners. -# 3. So can the domain postmasters. -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualList) - attrs=@FripostVirtualList - by dnattr=fripostOwner =wrscd - by group/FripostVirtualDomain/fripostOwner.expand="$1" =wrscd - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" =wrscd -# -# 1. The domain owner can create and delete lists, but only those with a 'pending' status -# 2. So can the domain postmaster. -# 3. The list owner can delete pending lists. -# 4. The entry creator can delete pending lists (needed to be able to rollback). -# 5. People with "canAddList" access can create lists, but only with a 'pending' status. -# 6. The list creation service can search and browse the entry. -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(&(objectClass=FripostVirtualList)(objectClass=FripostPendingEntry)) - attrs=entry - by group/FripostVirtualDomain/fripostOwner.expand="$1" +w break - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" +w break - by dnattr=fripostOwner +z continue - by dnattr=creatorsName +z continue - by set.exact="this/-1/fripostCanAddList & (user | user/-1)" +a break - by dn.exact="cn=CreateList,ou=services,o=mailHosting,dc=fripost,dc=org" +rd - by * +0 break -# -# 1. The domain owner can create and delete list commands, but only those with a 'pending' status -# 2. So can the domain postmaster. -# 3. The entry creator can delete pending list commands (needed to be able to rollback). -# 4. People with "canAddList" access can create list commands, but only with a 'pending' status. -# 5. The list creation service can search and browse the entry. -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(&(objectClass=FripostVirtualListCommand)(objectClass=FripostPendingEntry)) - attrs=entry - by group/FripostVirtualDomain/fripostOwner.expand="$1" +w - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" +w - by dnattr=creatorsName +z continue - by set.exact="this/-1/fripostCanAddList & (user | user/-1)" +a - by dn.exact="cn=CreateList,ou=services,o=mailHosting,dc=fripost,dc=org" +rd - by * +0 -# -# 1. The list owners can read the entry. -# 2. So can the domain's Owner. -# 3. So can the domain's Postmaster. -olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org)$" - filter=(objectClass=FripostVirtualList) - attrs=entry - by dnattr=fripostOwner +rd - by group/FripostVirtualDomain/fripostOwner.expand="$1" +rd - by group/FripostVirtualDomain/fripostPostmaster.expand="$1" +rd - by * +0 -# -# -######################################################################## -# Catchall -# -# Users with "canAddDomain" access can see that they have the right -# to create domains. -olcAccess: to dn.base="ou=virtual,o=mailHosting,dc=fripost,dc=org" - filter=(objectClass=FripostVirtual) - attrs=entry - by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" +rd -olcAccess: to dn.base="ou=virtual,o=mailHosting,dc=fripost,dc=org" - filter=(objectClass=FripostVirtual) - attrs=fripostCanAddDomain - by set.exact="this/fripostCanAddDomain & (user | user/-1)" =rscd -# Catch the break above -olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=org" - by dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" +0 -# vim: set filetype=ldif : diff --git a/vars.yml b/vars.yml deleted file mode 100644 index 2cd3a42..0000000 --- a/vars.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -postfix_instance: - # The keys are the group names associated with a Postfix role, and the - # values are the name and group (optional) of the instance dedicated - # to that role. - IMAP: { name: mda } - MX: { name: mta-in, group: mta } - MTA-out: { name: mta-out,group: mta } - MSA: { name: msa } -- cgit v1.2.3