diff options
-rw-r--r-- | lib/modules/openldap | 2 | ||||
-rw-r--r-- | roles/LDAP-provider/files/etc/ldap/syncprov.ldif | 2 | ||||
-rw-r--r-- | roles/LDAP-provider/tasks/main.yml | 1 | ||||
-rw-r--r-- | roles/common-LDAP/files/var/lib/ldap/DB_CONFIG | 20 | ||||
-rw-r--r-- | roles/common-LDAP/tasks/main.yml | 6 | ||||
-rw-r--r-- | roles/common-LDAP/templates/etc/ldap/database.ldif.j2 | 19 |
6 files changed, 11 insertions, 39 deletions
diff --git a/lib/modules/openldap b/lib/modules/openldap index 69ee4df..91e6a3c 100644 --- a/lib/modules/openldap +++ b/lib/modules/openldap @@ -33,41 +33,41 @@ import tempfile, atexit indexedAttributes = frozenset([ 'olcAttributeTypes', 'olcObjectClasses', 'olcAccess', 'olcSyncrepl', 'olcOverlay', 'olcLimits', 'olcAuthzRegexp', 'olcDbConfig', ]) # Another hack. Configuration entries sometimes pollutes the DNs with # indices, thus it's not possible to directly use them as base. # Instead, we use their parent as a pase, and search for the *unique* # match with the same ObjectClass and the matching extra attributes. # ('%s' in the attribute value is replaced with the value of the source # entry.) indexedDN = { 'olcSchemaConfig': [('cn', '{*}%s')], - 'olcHdbConfig': [('olcDbDirectory', '%s' )], + 'olcMdbConfig': [('olcDbDirectory', '%s' )], 'olcOverlayConfig': [('olcOverlay', '%s' )], } # Allow for flexible ACLs for user using SASL's EXTERNAL mechanism. # "username=postfix,cn=peercred,cn=external,cn=auth" is replaced by # "gidNumber=106+uidNumber=102,cn=peercred,cn=external,cn=auth" where # 102 is postfix's UID and 106 its primary GID. # (Regular expressions are not allowed.) sasl_ext_re = re.compile( r"""(?P<start>\sby\s+dn(?:\.exact)?)= (?P<quote>['\"]?)username=(?P<user>[a-z][-a-z0-9_]*), (?P<end>cn=peercred,cn=external,cn=auth) (?P=quote)\s""" , re.VERBOSE ) multispaces = re.compile( r"\s+" ) pwd_dict = {} def acl_sasl_ext(m): u = m.group('user') if u not in pwd_dict.keys(): pwd_dict[u] = pwd.getpwnam(u) diff --git a/roles/LDAP-provider/files/etc/ldap/syncprov.ldif b/roles/LDAP-provider/files/etc/ldap/syncprov.ldif index 42f06a0..edb19c1 100644 --- a/roles/LDAP-provider/files/etc/ldap/syncprov.ldif +++ b/roles/LDAP-provider/files/etc/ldap/syncprov.ldif @@ -1,13 +1,13 @@ # References: # - http://www.openldap.org/doc/admin24/replication.html#Syncrepl # - http://www.zytrax.com/books/ldap/ch7/#ol-syncrepl-rap # - man 5 slapo-syncprov -dn: olcOverlay=syncprov,olcDatabase={*}hdb,cn=config +dn: olcOverlay=syncprov,olcDatabase={*}mdb,cn=config objectClass: olcOverlayConfig objectClass: olcSyncProvConfig olcOverlay: syncprov # contextCSN saved to database every 50 updates or 5 # minutes olcSpCheckpoint: 50 5 olcSpReloadHint: TRUE diff --git a/roles/LDAP-provider/tasks/main.yml b/roles/LDAP-provider/tasks/main.yml index fa212a0..3f7f29f 100644 --- a/roles/LDAP-provider/tasks/main.yml +++ b/roles/LDAP-provider/tasks/main.yml @@ -1,14 +1,15 @@ - 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 # TODO: authz constraint diff --git a/roles/common-LDAP/files/var/lib/ldap/DB_CONFIG b/roles/common-LDAP/files/var/lib/ldap/DB_CONFIG deleted file mode 100644 index 07738c2..0000000 --- a/roles/common-LDAP/files/var/lib/ldap/DB_CONFIG +++ /dev/null @@ -1,20 +0,0 @@ -# It may be a good idea to modify this file, depending on the output of -# -# db_stat -mh /var/lib/ldap | 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 | head -16 -# -# (For optimal performance, usage should be within 85% of the configured -# values.) -# -# 5MB cachesize -set_cachesize 0 5242880 0 -set_lk_max_objects 1500 -set_lk_max_locks 1500 -set_lk_max_lockers 1500 diff --git a/roles/common-LDAP/tasks/main.yml b/roles/common-LDAP/tasks/main.yml index 60ccc76..5c15cc8 100644 --- a/roles/common-LDAP/tasks/main.yml +++ b/roles/common-LDAP/tasks/main.yml @@ -1,46 +1,40 @@ # XXX If #742056 gets fixed, we should preseed slapd to use peercreds as # RootDN once the fix enters stable. - name: Install OpenLDAP apt: pkg={{ item }} with_items: - slapd - ldap-utils - ldapvi - db-util - python-ldap - name: Configure slapd template: src=etc/default/slapd.j2 dest=/etc/default/slapd owner=root group=root mode=0644 register: r1 notify: - Restart slapd -- name: Copy DB_CONFIG - copy: src=var/lib/ldap/DB_CONFIG - dest=/var/lib/ldap/DB_CONFIG - owner=openldap group=openldap - mode=0644 - - name: Create directory /etc/ldap/ssl file: path=/etc/ldap/ssl state=directory owner=root group=root mode=0755 tags: - genkey # XXX: It's ugly to list all roles here, and to prunes them with a # conditional... - name: Generate a private key and a X.509 certificate for slapd # XXX: GnuTLS (libgnutls26 2.12.20-8+deb7u2, found in Wheezy) doesn't # support ECDSA; and slapd doesn't seem to support DHE (!?) so # we're stuck with "plain RSA" Key-Exchange. Also, there is a bug with # SHA-512. command: genkeypair.sh x509 --pubkey=/etc/ldap/ssl/{{ item.name }}.pem --privkey=/etc/ldap/ssl/{{ item.name }}.key --ou=LDAP {{ item.ou }} --cn={{ item.name }} --usage=digitalSignature,keyEncipherment,keyCertSign diff --git a/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 b/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 index e19d182..48758be 100644 --- a/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 +++ b/roles/common-LDAP/templates/etc/ldap/database.ldif.j2 @@ -24,70 +24,63 @@ olcArgsFile: /var/run/slapd/slapd.args olcPidFile: /var/run/slapd/slapd.pid olcLogLevel: none olcToolThreads: 1 {% if ansible_processor_vcpus > 4 %} olcThreads: {{ 2 * ansible_processor_vcpus }} {% else %} olcThreads: 8 {% endif %} {% if 'LDAP-provider' in group_names %} olcTLSCertificateFile: /etc/ldap/ssl/ldap.fripost.org.pem olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap.fripost.org.key # If we are being offered a client cert, it has to be trusted (in which # case we map the X.509 subject to a DN in our namespace), or we # terminate the connection. Not providing a certificate is fine for # TLS-protected simple binds, though. olcTLSVerifyClient: try olcTLSCACertificateFile: /etc/ldap/ssl/clients.pem olcAuthzRegexp: "^(cn=[^,]+,ou=syncRepl),ou=LDAP,ou=SSLcerts,o=Fripost$" "$1,dc=fripost,dc=org" olcSaslSecProps: minssf=128,noanonymous,noplain,nodict -# XXX We would like to say 'PFS' here, but Wheezy'z GnuTLS (libgnutls26 -# 2.12.20-8+deb7u2) is too old :-( (Also, DHE/ECDHE are not supported.) -olcTLSCipherSuite: SECURE128:!CIPHER-ALL:+AES-128-CBC:+AES-256-CBC:!MD5 +olcTLSCipherSuite: PFS:%LATEST_RECORD_VERSION:!VERS-SSL3.0:!VERS-TLS1.0:!VERS-TLS1.1:!CIPHER-ALL:+AES-128-GCM:+AES-256-GCM {% endif %} olcLocalSSF: 128 # /!\ This is not portable! But we only use glibc's crypt(3), which # supports (salted, streched) SHA512 olcPasswordHash: {CRYPT} olcPasswordCryptSaltFormat: $6$%s -dn: olcDatabase=hdb,cn=config +dn: olcDatabase=mdb,cn=config objectClass: olcDatabaseConfig -objectClass: olcHdbConfig +objectClass: olcMdbConfig olcDbDirectory: /var/lib/ldap olcSuffix: dc=fripost,dc=org {% if 'LDAP-provider' not in group_names and ('MX' in group_names or 'lists' in group_names) %} olcReadOnly: TRUE {% endif %} {% if 'LDAP-provider' in group_names %} olcLastMod: TRUE olcDbCheckpoint: 512 15 {% else %} olcLastMod: FALSE {% endif %} -# See DB_CONFIG -olcDbConfig: set_cachesize 0 5242880 0 -olcDbConfig: set_lk_max_objects 1500 -olcDbConfig: set_lk_max_locks 1500 -olcDbConfig: set_lk_max_lockers 1500 # 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 # Ensure that all DIT access is made according to the LDAPv3 protocol, # and must use 1/ authentication, and 2/ SASL or TLS. (Local clients # should use ldapi:// and SASL/EXERNAL, while remote clients should use # TLS.) # XXX: olcRequires: none LDAPv3 authc strong olcRequires: none LDAPv3 authc olcSecurity: simple_bind=128 ssf=128 update_ssf=128 # # ######################################################################## # Performance considerations # # 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 # @@ -216,76 +209,80 @@ olcAddContentAcl: TRUE # connections. # * Anonymous users are allowed to simple bind when connecting to a # 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 dn.exact="username=guilhem,cn=peercred,cn=external,cn=auth" sockurl.regex="^ldapi://" =w + by group.exact="cn=admin,ou=groups,dc=fripost,dc=org" =w # # XXX # * Anonymous users are allowed to simple bind as Postfix, but only when # using a local ldapi:// listener from one of the Postfix instance # (which should be accessible by the 'postfix' UNIX user only). olcAccess: to dn.exact="cn=postfix,ou=services,dc=fripost,dc=org" attrs=userPassword by realanonymous sockurl.regex="^ldapi://%2Fvar%2Fspool%2Fpostfix-[-[:alnum:]]+%2Fprivate%2F" =xd # # TODO: are there other services which need to be able to simple bind? # # * 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 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. 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 -%} by dn.exact="cn=postfix,ou=services,dc=fripost,dc=org" sockurl.regex="^ldapi://%2Fvar%2Fspool%2Fpostfix-[-[:alnum:]]+%2Fprivate%2F" =sd {% endif -%} by users =0 break # |