FeministWiki:LDAP Schema: Difference between revisions

    From FeministWiki
    No edit summary
     
    (7 intermediate revisions by the same user not shown)
    Line 38: Line 38:
    * The <code>fwRecoveryMail</code> field may hold a mail address that will be used for password reset requests.  It's different from the primary mail address because that one may be the member's FeministWiki address, which they can't access if they've lost their password.
    * The <code>fwRecoveryMail</code> field may hold a mail address that will be used for password reset requests.  It's different from the primary mail address because that one may be the member's FeministWiki address, which they can't access if they've lost their password.
    * The <code>manager</code> contains the DN (distinguished name) of the member who added the member.  It may be empty for special member accounts like "Administrator" or the "Deleted" pseudo-account.
    * The <code>manager</code> contains the DN (distinguished name) of the member who added the member.  It may be empty for special member accounts like "Administrator" or the "Deleted" pseudo-account.
    === Tips on the usage of ldap commands ===
    Commands such as ldapsearch, ldapmodify, etc. require authentication.  The correct method depends on whether you want to interact with the configuration database found in {{C|/etc/ldap/slapd.d}}, or the actual data database found in {{C|/var/lib/ldap}}.
    For configuration, use {{C|-Y external -H ldapi://}} to connect directly with root permissions, so no actual LDAP domain login is needed.
    For data, use {{C|-xy ~/pwd/ldap}} to use the LDAP domain admin password.  The file {{C|~/.ldaprc}} should contain {{C|BINDDN cn=admin,dc=feministwiki,dc=org}} so you don't have to specify the domain admin explicitly every time.


    === Read-only user ===
    === Read-only user ===
    Line 43: Line 51:
    For security purposes, it's a good idea to have a "read-only" user for LDAP read operations, instead of using the admin for everything.
    For security purposes, it's a good idea to have a "read-only" user for LDAP read operations, instead of using the admin for everything.


      # Addition to be made via 'ldapadd'
      # Add read-only user
    ldapadd -xy ~/pwd/ldap <<EOF
      dn: cn=readonly,dc=feministwiki,dc=org
      dn: cn=readonly,dc=feministwiki,dc=org
      objectClass: simpleSecurityObject
      objectClass: simpleSecurityObject
    Line 49: Line 58:
      cn: readonly
      cn: readonly
      description: Read-only user
      description: Read-only user
    userPassword: $(cat ~/pwd/ldap-readonly)
    EOF


    No fiddling with access control is needed, since read-only access is the default.
    No fiddling with access control is needed, since read-only access is the default.
    Line 54: Line 65:
    === Custom objectClass ===
    === Custom objectClass ===


    The following LDIF statement may be passed to <code>ldapadd</code> to create the <code>fwMember</code> object class.
    The following command creates the <code>fwMember</code> object class.


      # Addition to be made via 'ldapadd'
      ldapadd -Y external -H ldapi:// <<EOF
      dn: cn=feministwiki,cn=schema,cn=config
      dn: cn=feministwiki,cn=schema,cn=config
      objectClass: olcSchemaConfig
      objectClass: olcSchemaConfig
    Line 71: Line 82:
         STRUCTURAL
         STRUCTURAL
         MAY ( fwRecoveryMail ) )
         MAY ( fwRecoveryMail ) )
    EOF


    === Attribute permissions ===
    === Attribute permissions ===
    Line 80: Line 92:
    * Members should not be able to see who a member was added by (the <code>manager</code> field).
    * Members should not be able to see who a member was added by (the <code>manager</code> field).


    The following LDIF statement may be passed to 'ldapmodify' to make the necessary access control changes:
    The following command makes the necessary access control changes:


      # Modification to be made via 'ldapmodify'
      ldapmodify -Y external -H ldapi:// <<EOF
      dn: olcDatabase={1}mdb,cn=config
      dn: olcDatabase={1}mdb,cn=config
      changetype: modify
      changetype: modify
    Line 89: Line 101:
      olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact="cn=readonly,dc=feministwiki,dc=org" search
      olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact="cn=readonly,dc=feministwiki,dc=org" search
      olcAccess: {4}to attrs=manager by self read
      olcAccess: {4}to attrs=manager by self read
      -
      EOF


    Note that <code>olcAccess</code> entries are evaluated in order, and the first match takes effect.  This can affect performance.  In the statement above, we start inserting entries from index 2, because indexes 0 and 1 already have some meaningful default entries.
    Note that <code>olcAccess</code> entries are evaluated in order, and the first match takes effect.  This can affect performance.  In the statement above, we start inserting entries from index 2, because indexes 0 and 1 already have some meaningful default entries.


    === Password hashing ===
    === Password policy ===


    To make sure passwords are stored with the <code>{SSHA}</code> scheme rather than plain text, the <code>ppolicy</code> "password policy overlay" is used.  ZYTRAX has a very nice book about LDAP which documents how to enable this: http://www.zytrax.com/books/ldap/ch6/ppolicy.html
    To make sure passwords are stored with the <code>{SSHA}</code> scheme rather than plain text, the <code>ppolicy</code> "password policy overlay" is used.  ZYTRAX has a very nice book about LDAP which documents how to enable this: http://www.zytrax.com/books/ldap/ch6/ppolicy.html
    Line 99: Line 111:
    In short, the steps go as follows (these commands ''should'' work verbatim):
    In short, the steps go as follows (these commands ''should'' work verbatim):


      # Add the ppolicy schema
      # Only needed on old versions of slapd, to add the ppolicy schema
      ldapadd -Y external -H ldapi:// < /etc/ldap/schema/ppolicy.ldif
      #ldapadd -Y external -H ldapi:// < /etc/ldap/schema/ppolicy.ldif
       
       
      # Enable the ppolicy dynamic module
      # Enable the ppolicy dynamic module
    Line 117: Line 129:
      olcPPolicyHashCleartext: TRUE
      olcPPolicyHashCleartext: TRUE
      EOF
      EOF
    Further, <code>ppolicy</code> is used to enable brute-force protection.  For this, we need to add an entry of the object class <code>pwdPolicy</code> to the directory, add attributes related to brute-force protection, and then set it as the default password policy:
    # Add an OU for password policies
    ldapadd -xy ~/pwd/ldap <<EOF
    dn: ou=pwdPolicies,dc=feministwiki,dc=org
    objectClass: organizationalUnit
    ou: pwdPolicies
    EOF
    # Add the pwdPolicy object
    ldapadd -xy ~/pwd/ldap <<EOF
    dn: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org
    objectClass: applicationProcess
    objectClass: pwdPolicy
    cn: default
    pwdAttribute: userPassword
    pwdLockout: TRUE
    pwdLockoutDuration: 3600
    pwdMaxFailure: 10
    pwdFailureCountInterval: 3600
    EOF
    # Set it as the default password policy
    ldapmodify -Y external -H ldapi:// <<EOF
    dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config
    changetype: modify
    add: olcPPolicyDefault
    olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org
    EOF
    With these settings, ten consecutive authentication failures with a username will lock the account for an hour.  Login failures are also cleared after an hour.  This means it's possible to try ten passwords per hour during a brute-force attack, which won't get the attacker very far.


    === Time of last login ===
    === Time of last login ===
    Line 122: Line 166:
    The <code>lastbind</code> module of OpenLDAP keeps track of when a user last logged in.
    The <code>lastbind</code> module of OpenLDAP keeps track of when a user last logged in.


    Load the module:
    # Load the module
     
      ldapmodify -Y external -H ldapi:// <<EOF
      # Modification to be made via 'ldapmodify'
      dn: cn=module{0},cn=config
      dn: cn=module{0},cn=config
      changetype: modify
      changetype: modify
      add: olcModuleLoad
      add: olcModuleLoad
      olcModuleLoad: lastbind
      olcModuleLoad: lastbind
    EOF


    And enable the overlay:
    # Enable the overlay
       
      ldapadd -Y external -H ldapi:// <<EOF
    # Addition to be made via 'ldapadd'
      dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config
      dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config
      objectClass: olcLastBindConfig
      objectClass: olcLastBindConfig
      olcOverlay: lastbind
      olcOverlay: lastbind
      olcLastBindPrecision: 60
      olcLastBindPrecision: 60
    EOF

    Latest revision as of 22:49, 11 January 2024

    The member database of the FeministWiki is stored via LDAP. This page explains some details about the setup.

    Structure

    The basic structure looks like this:

    dc=feministwiki,dc=org
      ou=members
        - cn=username
          objectClass: fwMember
          cn: username
          uid: username
          sn: Display name
          userPassword: {SSHA}saltedhash
          mail: username@feministwiki.org
          fwRecoveryMail: user@example.org
        - cn=username2
          objectClass: fwMembe
          cn: username2
          uid: username2
          sn: Display name
          userPassword: {SSHA}saltedhash2
          mail: username2@feministwiki.org
          manager: cn=username,ou=members,dc=feministwiki,dc=org
        - ...
      ou=groups
        cn=members
        objectClass: groupOfNames
        cn: members
        member: username
        member: username2
        member: ...
    

    Notes:

    • The cn (common name) and uid (user ID) fields both contain the username. This is because some software is preconfigured to look at uid, while most look at cn.
    • The sn (surname) field is used to hold a display name that may be different from the username. The field is filled with the username by default.
    • The mail field holds the primary mail address for communication with the member. It's filled with the FeministWiki mail address of the member by default, but can be changed freely.
    • The fwRecoveryMail field may hold a mail address that will be used for password reset requests. It's different from the primary mail address because that one may be the member's FeministWiki address, which they can't access if they've lost their password.
    • The manager contains the DN (distinguished name) of the member who added the member. It may be empty for special member accounts like "Administrator" or the "Deleted" pseudo-account.

    Tips on the usage of ldap commands

    Commands such as ldapsearch, ldapmodify, etc. require authentication. The correct method depends on whether you want to interact with the configuration database found in /etc/ldap/slapd.d, or the actual data database found in /var/lib/ldap.

    For configuration, use -Y external -H ldapi:// to connect directly with root permissions, so no actual LDAP domain login is needed.

    For data, use -xy ~/pwd/ldap to use the LDAP domain admin password. The file ~/.ldaprc should contain {{{1}}} so you don't have to specify the domain admin explicitly every time.

    Read-only user

    For security purposes, it's a good idea to have a "read-only" user for LDAP read operations, instead of using the admin for everything.

    # Add read-only user
    ldapadd -xy ~/pwd/ldap <<EOF
    dn: cn=readonly,dc=feministwiki,dc=org
    objectClass: simpleSecurityObject
    objectClass: organizationalRole
    cn: readonly
    description: Read-only user
    userPassword: $(cat ~/pwd/ldap-readonly)
    EOF
    

    No fiddling with access control is needed, since read-only access is the default.

    Custom objectClass

    The following command creates the fwMember object class.

    ldapadd -Y external -H ldapi:// <<EOF
    dn: cn=feministwiki,cn=schema,cn=config
    objectClass: olcSchemaConfig
    cn: feministwiki
    olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1
       NAME 'fwRecoveryMail'
       DESC 'FeministWiki password recovery mail'
       EQUALITY caseIgnoreMatch
       SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
    olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1
       NAME 'fwMember'
       DESC 'FeministWiki member'
       SUP inetOrgPerson
       STRUCTURAL
       MAY ( fwRecoveryMail ) )
    EOF
    

    Attribute permissions

    We want to make the following changes to the default LDAP permissions:

    • Members should be able to change their own display name (sn) and e-mail address (mail).
    • The read-only user should be able to find users via the combination of their username and recovery mail address (fwRecoveryMail), but not actually see their recovery mail addresses. (The password reset mechanism uses this.)
    • Members should not be able to see who a member was added by (the manager field).

    The following command makes the necessary access control changes:

    ldapmodify -Y external -H ldapi:// <<EOF
    dn: olcDatabase={1}mdb,cn=config
    changetype: modify
    add: olcAccess
    olcAccess: {2}to attrs=sn,mail by self write
    olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact="cn=readonly,dc=feministwiki,dc=org" search
    olcAccess: {4}to attrs=manager by self read
    EOF
    

    Note that olcAccess entries are evaluated in order, and the first match takes effect. This can affect performance. In the statement above, we start inserting entries from index 2, because indexes 0 and 1 already have some meaningful default entries.

    Password policy

    To make sure passwords are stored with the {SSHA} scheme rather than plain text, the ppolicy "password policy overlay" is used. ZYTRAX has a very nice book about LDAP which documents how to enable this: http://www.zytrax.com/books/ldap/ch6/ppolicy.html

    In short, the steps go as follows (these commands should work verbatim):

    # Only needed on old versions of slapd, to add the ppolicy schema
    #ldapadd -Y external -H ldapi:// < /etc/ldap/schema/ppolicy.ldif
    
    # Enable the ppolicy dynamic module
    ldapmodify -Y external -H ldapi:// <<EOF
    dn: cn=module{0},cn=config
    changetype: modify
    add: olcModuleLoad
    olcModuleLoad: ppolicy
    EOF
    
    # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE
    ldapadd -Y external -H ldapi:// <<EOF
    dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config
    objectClass: olcPPolicyConfig
    olcOverlay: ppolicy
    olcPPolicyHashCleartext: TRUE
    EOF
    

    Further, ppolicy is used to enable brute-force protection. For this, we need to add an entry of the object class pwdPolicy to the directory, add attributes related to brute-force protection, and then set it as the default password policy:

    # Add an OU for password policies
    ldapadd -xy ~/pwd/ldap <<EOF
    dn: ou=pwdPolicies,dc=feministwiki,dc=org
    objectClass: organizationalUnit
    ou: pwdPolicies
    EOF
    
    # Add the pwdPolicy object
    ldapadd -xy ~/pwd/ldap <<EOF
    dn: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org
    objectClass: applicationProcess
    objectClass: pwdPolicy
    cn: default
    pwdAttribute: userPassword
    pwdLockout: TRUE
    pwdLockoutDuration: 3600
    pwdMaxFailure: 10
    pwdFailureCountInterval: 3600
    EOF
    
    # Set it as the default password policy
    ldapmodify -Y external -H ldapi:// <<EOF
    dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config
    changetype: modify
    add: olcPPolicyDefault
    olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org
    EOF
    

    With these settings, ten consecutive authentication failures with a username will lock the account for an hour. Login failures are also cleared after an hour. This means it's possible to try ten passwords per hour during a brute-force attack, which won't get the attacker very far.

    Time of last login

    The lastbind module of OpenLDAP keeps track of when a user last logged in.

    # Load the module
    ldapmodify -Y external -H ldapi:// <<EOF
    dn: cn=module{0},cn=config
    changetype: modify
    add: olcModuleLoad
    olcModuleLoad: lastbind
    EOF
    
    # Enable the overlay
    ldapadd -Y external -H ldapi:// <<EOF
    dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config
    objectClass: olcLastBindConfig
    olcOverlay: lastbind
    olcLastBindPrecision: 60
    EOF