diff options
Diffstat (limited to 'roles/common-LDAP/templates')
-rw-r--r-- | roles/common-LDAP/templates/etc/ldap/database.ldif.j2 | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 b/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 index 3752f9f..b4c2c4f 100644 --- a/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 +++ b/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 @@ -62,126 +62,158 @@ olcDbIndex: fripostIsStatusActive,fvd,fvl eq olcDbIndex: fripostOptionalMaildrop pres # SyncProv/SyncRepl specific indexing. olcDbIndex: entryCSN,entryUUID eq # # ######################################################################## ######################################################################## # Sync Replication # TODO: replace the simple bind by Kerberos/GSSAPI # # References: # - http://www.openldap.org/doc/admin24/replication.html#Syncrepl # - http://www.zytrax.com/books/ldap/ch7/#ol-syncrepl-rap # {% if 'LDAP-provider' in group_names %} olcLimits: dn.exact="cn=MX-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited +olcLimits: dn.exact="cn=lists-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" + time.soft=unlimited + time.hard=unlimited + size.soft=unlimited + size.hard=unlimited {% elif 'MX' in group_names %} olcSyncrepl: rid=000 provider=ldap://{{ LDAP_provider }} type=refreshAndPersist retry="5 5 300 +" searchbase="ou=virtual,o=mailHosting,dc=fripost,dc=org" attrs=objectClass,fvd,fvl,fripostMaildrop,fripostOptionalMaildrop,fripostPostmaster,fripostOwner scope=sub schemachecking=off bindmethod=simple binddn="cn=MX-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" credentials=mx +{% elif 'lists' in group_names %} +olcSyncrepl: rid=001 + provider=ldap://{{ LDAP_provider }} + type=refreshAndPersist + retry="5 5 300 +" + searchbase="ou=virtual,o=mailHosting,dc=fripost,dc=org" + attrs=objectClass,fvd,fvl,fripostListManager,fripostOwner + scope=sub + schemachecking=off + bindmethod=simple + binddn="cn=lists-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" + credentials=lists {% endif %} # # ######################################################################## ######################################################################## # 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, Dovecot # (Most used ACLs are cheaper when written first.) # # Postfix have read access to the attribute it needs when eg, doing # alias resolution. olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" attrs=entry,objectClass,fvd,fvl,fripostMaildrop,fripostOptionalMaildrop - filter=(&(|(objectClass=FripostVirtualDomain)(objectClass=FripostVirtualUser)(objectClass=FripostVirtualAlias)(objectClass=FripostVirtualList)(objectClass=FripostVirtualListCommand))(!(objectClass=FripostPendingEntry))(!(fripostIsStatusActive=FALSE))) + filter=(&(|(objectClass=FripostVirtualDomain)(objectClass=FripostVirtualUser)(objectClass=FripostVirtualAlias)(objectClass=FripostVirtualList))(!(objectClass=FripostPendingEntry))(!(fripostIsStatusActive=FALSE))) by dn.exact="cn=MX-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" =rsd by realanonymous =rsd by users =0 break # # Search domain owners / postmasters (used by reserved-alias.pl). 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="cn=MX-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" =rsd - by dn.exact="username=postfix,cn=peercred,cn=external,cn=auth" =rsd + by dn.exact="username=nobody,cn=peercred,cn=external,cn=auth" =rsd + by users =0 break +# +# List replicates +olcAccess: to dn.children="ou=virtual,o=mailHosting,dc=fripost,dc=org" + attrs=entry,objectClass,fvd,fvl,fripostListManager,fripostOwner + filter=(&(|(objectClass=FripostVirtualDomain)(objectClass=FripostVirtualList))(!(objectClass=FripostPendingEntry))(!(fripostIsStatusActive=FALSE))) + by dn.exact="cn=lists-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" =rsd + by realanonymous =rsd by users =0 break # # The following is required for the content filter {% if 'MDA' in group_names %} olcAccess: to dn.regex="^fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" attrs=entry - filter=(&(objectClass=FripostVirtualDomain)(fripostIsStatusActive=TRUE)) + filter=(&(objectClass=FripostVirtualDomain)(!(fripostIsStatusActive=FALSE))) by dn.exact="username=amavis,cn=peercred,cn=external,cn=auth" =s by users =0 break olcAccess: to dn.regex="^fvl=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" attrs=entry,objectClass,fvl,@AmavisAccount filter=(&(objectClass=FripostVirtualUser)(objectClass=AmavisAccount)(fripostIsStatusActive=TRUE)) by dn.exact="username=amavis,cn=peercred,cn=external,cn=auth" =rsd by users =0 break # # The following is required for the userdb olcAccess: to dn.regex="^fvl=[^,]+,fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripost,dc=org$" attrs=entry,objectClass filter=(objectClass=FripostVirtualUser) by dn.exact="username=dovecot,cn=peercred,cn=external,cn=auth" =rsd by users =0 break {% endif %} # # 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 # # The following is required 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 # # The following is required for Sync Replication. {% if 'LDAP-provider' in group_names %} +olcAccess: to dn.exact="ou=virtual,o=mailHosting,dc=fripost,dc=org" + attrs=entry,objectClass + filter=(objectClass=FripostVirtual) + by dn.exact="cn=MX-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" =rsd + by dn.exact="cn=lists-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" =rsd + by users =0 break olcAccess: to dn.subtree="ou=virtual,o=mailHosting,dc=fripost,dc=org" - attrs=entry,objectClass,structuralObjectClass,createTimestamp,creatorsName,entryDN,entryUUID,modifiersName,modifyTimestamp,hasSubordinates,subschemaSubentry + attrs=structuralObjectClass,createTimestamp,creatorsName,entryDN,entryUUID,modifiersName,modifyTimestamp,hasSubordinates,subschemaSubentry by dn.exact="cn=MX-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" =rsd + by dn.exact="cn=lists-replicate,ou=services,o=mailHosting,dc=fripost,dc=org" =rsd by users =0 break {% endif %} # # 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. @@ -197,62 +229,62 @@ olcAccess: to dn.subtree="o=mailHosting,dc=fripost,dc=org" # 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)) + filter=(&(objectClass=FripostVirtualList)(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)) + filter=(&(objectClass=FripostVirtualList)(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" @@ -466,55 +498,40 @@ olcAccess: to dn.regex="^fvl=[^,]+,(fvd=[^,]+,ou=virtual,o=mailHosting,dc=fripos 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 |