diff options
-rw-r--r-- | roles/LDAP-provider/tasks/main.yml | 3 | ||||
-rw-r--r-- | roles/common-LDAP/templates/etc/ldap/database.ldif.j2 | 35 |
2 files changed, 36 insertions, 2 deletions
diff --git a/roles/LDAP-provider/tasks/main.yml b/roles/LDAP-provider/tasks/main.yml index ad6e7bb..af46c51 100644 --- a/roles/LDAP-provider/tasks/main.yml +++ b/roles/LDAP-provider/tasks/main.yml @@ -1,15 +1,18 @@ - name: Load and configure the syncprov overlay openldap: module=syncprov suffix=dc=fripost,dc=org target=etc/ldap/syncprov.ldif local=file - name: Enable the EXTERNAL SASL mechanism lineinfile: dest=/usr/lib/sasl2/slapd.conf regexp='^mech_list{{':'}}' line='mech_list{{':'}} EXTERNAL' create=yes owner=root group=root mode=0644 +#- name: Load dyngroup schema +# openldap: target=/etc/ldap/schema/dyngroup.ldif + # TODO: authz constraint diff --git a/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 b/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 index 494888e..7372304 100644 --- a/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 +++ b/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 @@ -87,40 +87,41 @@ olcSecurity: simple_bind=128 ssf=128 update_ssf=128 # To reindex an existing database, you have to # * Stop slapd sudo service slapd stop # * Reindex sudo -u openldap slapindex -b 'dc=fripost,dc=org' # * Restart slapd sudo service slapd start # olcDbIndex: objectClass eq # Let us make Postfix's life easier. {% if 'LDAP-provider' in group_names %} olcDbIndex: fvd,fvl eq,sub olcDbIndex: fripostIsStatusActive eq {% elif 'MX' in group_names or 'MDA' in group_names %} olcDbIndex: fripostIsStatusActive,fvd,fvl eq {% endif %} {% if 'LDAP-provider' in group_names %} olcDbIndex: fripostOptionalMaildrop,fripostMaildrop eq,sub olcDbIndex: fripostCanAddDomain,fripostCanAddAlias,fripostCanAddList,fripostOwner,fripostPostmaster,fripostListManager eq {% elif 'MX' in group_names %} olcDbIndex: fripostOptionalMaildrop pres {% endif %} {% if 'LDAP-provider' in group_names %} +olcDbIndex: member,cn eq {% endif %} {% if ('LDAP-provider' not in group_names and 'MX' in group_names) or ('LDAP-provider' in group_names and groups.MX | difference([inventory_hostname])) %} # SyncProv/SyncRepl specific indexing. olcDbIndex: entryCSN,entryUUID eq {% endif%} # # # 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 # # ######################################################################## # Sync Replication # # References: @@ -196,88 +197,98 @@ olcAddContentAcl: TRUE # local ldapi:// socket (when using auth_binds, Dovecot delegates # authentication to the LDAP server). # * Authenticated users are allowed to change (ie replace) their # password through TLS-protected connections, but read access is not # granted. # * Domain postmasters are allowed to change (ie replace) their users' # password through TLS-protected connections, but read access is not # granted. # * The same goes for general admins. # * The same goes for local admins. olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,dc=fripost,dc=org)$" filter=(objectClass=FripostVirtualUser) attrs=userPassword by realanonymous tls_ssf=128 =xd by realanonymous sockurl.regex="^ldapi://" =xd by realself tls_ssf=128 =w by group/FripostVirtualDomain/fripostPostmaster.expand="$1" tls_ssf=128 =w by dn.onelevel="ou=admins,dc=fripost,dc=org" tls_ssf=128 =w by group.exact="cn=admin,ou=groups,dc=fripost,dc=org" =w # -# TODO: are there other services which need to be able to simple bind? +# * Services can authenticate +{% if 'LDAP-provider' in group_names -%} +olcAccess: to dn.onelevel="ou=services,dc=fripost,dc=org" + filter=(objectClass=simpleSecurityObject) + attrs=userPassword + by realanonymous tls_ssf=128 =xd +{% endif -%} # # * Catch-all: no one else may access the passwords (including for # simple bind). olcAccess: to dn.subtree="dc=fripost,dc=org" attrs=userPassword by * =0 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Base # # * Only SyncRepl replicates may access operational attributes in the # subtree, when using a TLS-protected connection. {% if 'LDAP-provider' in group_names -%} olcAccess: to dn.subtree="ou=virtual,dc=fripost,dc=org" - attrs=entryDN,entryCSN,entryUUID,structuralObjectClass,hasSubordinates,subschemaSubentry + attrs=entryCSN,structuralObjectClass,hasSubordinates,subschemaSubentry by dn.onelevel="ou=syncRepl,dc=fripost,dc=org" tls_ssf=128 =rsd by * =0 # # * They may also read entries (ie, the attributes they have access to # as per the ACL below) in that subtree, when using a TLS-protected # connection. Listing entries (their DN) is required to replicate # deletions properly. olcAccess: to dn.subtree="ou=virtual,dc=fripost,dc=org" attrs=entry,objectClass by dn.onelevel="ou=syncRepl,dc=fripost,dc=org" tls_ssf=128 =rsd by group.exact="cn=admin,ou=groups,dc=fripost,dc=org" =wrsd by users =0 break olcAccess: to dn.children="ou=virtual,dc=fripost,dc=org" by group.exact="cn=admin,ou=groups,dc=fripost,dc=org" =wrsd by users =0 break {% endif -%} # # * Postfix may use the base as a searchBase on the MX:es, when # connecting a local ldapi:// socket from the 'private' directory in # one of the non-default instance's chroot. # * So may Dovecot on the MDA (needed for the iterate filter), when # SASL-binding using the EXTERNAL mechanism and connecting to a local # ldapi:// socket. +# * So may Nextcloud on the LDAP provider olcAccess: to dn.exact="ou=virtual,dc=fripost,dc=org" attrs=entry,objectClass filter=(objectClass=FripostVirtual) {% if 'MDA' in group_names -%} by dn.exact="username=dovecot,cn=peercred,cn=external,cn=auth" sockurl.regex="^ldapi://" =sd {% endif -%} {% if 'MX' in group_names or 'MSA' in group_names -%} by dn.exact="username=postfix,cn=peercred,cn=external,cn=auth" sockurl.regex="^ldapi://%2Fvar%2Fspool%2Fpostfix-[-[:alnum:]]+%2Fprivate%2F" =sd {% endif -%} + {% if 'LDAP-provider' in group_names -%} + by dn.exact="cn=nextcloud,ou=services,dc=fripost,dc=org" tls_ssf=128 =sd + {% endif -%} by users =0 break # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Domain entries # # * The SyncRepl replicates have read access to the entry itself, when # using a TLS-protected connection. # * So has Postfix, when connecting a local ldapi:// socket from the # 'private' directory in one of the non-default instance's chroot. # * So has Dovecot on the MDA (for the iterate filter), when # SASL-binding using the EXTERNAL mechanism and connecting to a local # ldapi:// socket. # * Amavis may use the entry as searchBase (required to look for the # per-user preferences) but doesn't have read access to the entry. # * The 'nobody' UNIX user has read access on the MX:es, when using # SASL-binding using the EXTERNAL mechanism and connecting to a local # ldapi:// socket. This is required for the 'reserved-alias.pl' # script. olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,dc=fripost,dc=org$" attrs=entry,objectClass,fvd @@ -477,34 +488,54 @@ olcAccess: to dn.regex="^fvl=[^,]+,fvd=[^,]+,ou=virtual,dc=fripost,dc=org$" by users =0 break {% endif %} # # * The MSA's postfix user can read entry ownership to dermine the SASL # login name(s) owning a given sender address {% if 'MSA' in group_names %} olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,dc=fripost,dc=org$" attrs=fripostOwner,fripostPostmaster filter=(|(objectClass=FripostVirtualAliasDomain)(objectClass=FripostVirtualDomain)) by dn.exact="username=postfix,cn=peercred,cn=external,cn=auth" sockurl.regex="^ldapi://%2Fvar%2Fspool%2Fpostfix-[-[:alnum:]]+%2Fprivate%2F" =rsd by users =0 break olcAccess: to dn.regex="^fvl=[^,]+,fvd=[^,]+,ou=virtual,dc=fripost,dc=org$" attrs=entry,objectClass,fvl,fripostOwner filter=(|(objectClass=FripostVirtualAlias)(objectClass=FripostVirtualList)(objectClass=FripostVirtualUser)) by dn.exact="username=postfix,cn=peercred,cn=external,cn=auth" sockurl.regex="^ldapi://%2Fvar%2Fspool%2Fpostfix-[-[:alnum:]]+%2Fprivate%2F" =rsd by users =0 break {% endif %} {% if 'LDAP-provider' in group_names %} # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# +# Export Fripost members to Nextcloud +olcAccess: to dn.exact="fvd=fripost.org,ou=virtual,dc=fripost,dc=org" + attrs=entry,objectClass,fvd + filter=(&(objectClass=FripostVirtualDomain)(!(objectClass=FripostPendingEntry))) + by dn.exact="cn=nextcloud,ou=services,dc=fripost,dc=org" tls_ssf=128 =rsd + by users =0 break +olcAccess: to dn.regex="^fvl=[^,]+,fvd=fripost.org,ou=virtual,dc=fripost,dc=org$" + attrs=entry,entryDN,entryUUID,objectClass,fvl,fripostIsStatusActive + filter=(&(objectClass=FripostVirtualUser)(!(objectClass=FripostPendingEntry))(fripostIsStatusActive=TRUE)) + by dn.exact="cn=nextcloud,ou=services,dc=fripost,dc=org" tls_ssf=128 =rsd + by users =0 break +olcAccess: to dn.exact="ou=groups,dc=fripost,dc=org" + attrs=entry,objectClass + by dn.exact="cn=nextcloud,ou=services,dc=fripost,dc=org" tls_ssf=128 =rsd + by users =0 break +olcAccess: to dn.exact="cn=medlemmar,ou=groups,dc=fripost,dc=org" + by dn.exact="cn=nextcloud,ou=services,dc=fripost,dc=org" tls_ssf=128 =rsd + by users =0 break +# # TODO: allow users to edit their entry, etc # {% endif %} # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Catch-all # # * Catch all the breaks above. # * Deny any access to everyone else. olcAccess: to dn.subtree="dc=fripost,dc=org" by dn.children="ou=virtual,dc=fripost,dc=org" +0 by * =0 # vim: set filetype=ldif : |