| 1 | Exercise 4: build an LDAP server |
|---|
| 2 | ================================ |
|---|
| 3 | |
|---|
| 4 | This is by far the hardest part of the operation, due to the cryptic way |
|---|
| 5 | OpenLDAP 2.4 now stores its configs within LDAP instead of in a config file. |
|---|
| 6 | See `man slapd-config` |
|---|
| 7 | |
|---|
| 8 | We are going to build an LDAP server with Base DN |
|---|
| 9 | "dc=realm1,dc=ws,dc=nsrc,dc=org". Change this to match your own realm. |
|---|
| 10 | |
|---|
| 11 | Install the slapd server and ensure everything else needed is present: |
|---|
| 12 | |
|---|
| 13 | # apt-get install slapd ldap-utils libsasl2-modules-gssapi-mit |
|---|
| 14 | |
|---|
| 15 | Set up the service principal with keytab readable by slapd: |
|---|
| 16 | |
|---|
| 17 | # mkdir /etc/ldap/krb5 |
|---|
| 18 | # kadmin -p student/admin |
|---|
| 19 | addprinc -randkey ldap/pc1.ws.nsrc.org |
|---|
| 20 | ktadd -k /etc/ldap/krb5/krb5.keytab ldap/pc1.ws.nsrc.org |
|---|
| 21 | ^D |
|---|
| 22 | # chown -R openldap:openldap /etc/ldap/krb5 |
|---|
| 23 | # chmod 550 /etc/ldap/krb5 |
|---|
| 24 | # chmod 440 /etc/ldap/krb5/krb5.keytab |
|---|
| 25 | # editor /etc/default/slapd |
|---|
| 26 | ... |
|---|
| 27 | export KRB5_KTNAME=/etc/ldap/krb5/krb5.keytab |
|---|
| 28 | |
|---|
| 29 | # service slapd restart |
|---|
| 30 | |
|---|
| 31 | Install the schemas we need: |
|---|
| 32 | |
|---|
| 33 | # ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/cosine.ldif |
|---|
| 34 | # ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/nis.ldif |
|---|
| 35 | # ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif |
|---|
| 36 | # ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/misc.ldif |
|---|
| 37 | |
|---|
| 38 | NOTE: For a real production LDAP server, read the files in |
|---|
| 39 | `/usr/share/doc/slapd` carefully, especially README.Debian.gz |
|---|
| 40 | and README.DB_CONFIG.gz |
|---|
| 41 | |
|---|
| 42 | Now we need to run some scripts - either paste directly to a root shell, |
|---|
| 43 | or create in temporary files and then run them. |
|---|
| 44 | |
|---|
| 45 | BEWARE: in LDIF files, superfluous spaces at the end of lines may cause |
|---|
| 46 | attributes to be rejected as invalid! |
|---|
| 47 | |
|---|
| 48 | First is `create_database.sh` |
|---|
| 49 | |
|---|
| 50 | ldapadd -Y EXTERNAL -H ldapi:/// <<EOS |
|---|
| 51 | # Load hdb backend module |
|---|
| 52 | dn: cn=module{0},cn=config |
|---|
| 53 | objectClass: olcModuleList |
|---|
| 54 | cn: module |
|---|
| 55 | olcModulepath: /usr/lib/ldap |
|---|
| 56 | olcModuleload: {0}back_hdb |
|---|
| 57 | EOS |
|---|
| 58 | |
|---|
| 59 | ldapadd -Y EXTERNAL -H ldapi:/// <<EOS |
|---|
| 60 | # Create the hdb database and place the files under /var/lib/ldap |
|---|
| 61 | dn: olcDatabase={1}hdb,cn=config |
|---|
| 62 | objectClass: olcDatabaseConfig |
|---|
| 63 | objectClass: olcHdbConfig |
|---|
| 64 | olcDatabase: {1}hdb |
|---|
| 65 | olcDbDirectory: /var/lib/ldap |
|---|
| 66 | olcSuffix: dc=realm1,dc=ws,dc=nsrc,dc=org |
|---|
| 67 | olcDbConfig: {0}set_cachesize 0 2097152 0 |
|---|
| 68 | olcDbConfig: {1}set_lk_max_objects 1500 |
|---|
| 69 | olcDbConfig: {2}set_lk_max_locks 1500 |
|---|
| 70 | olcDbConfig: {3}set_lk_max_lockers 1500 |
|---|
| 71 | olcLastMod: TRUE |
|---|
| 72 | olcDbCheckpoint: 512 30 |
|---|
| 73 | olcDbIndex: uid pres,eq |
|---|
| 74 | olcDbIndex: cn,sn,mail pres,eq,approx,sub |
|---|
| 75 | olcDbIndex: objectClass eq |
|---|
| 76 | EOS |
|---|
| 77 | |
|---|
| 78 | (Note: we have no olcRootDN or olcRootPW. This is a pure Kerberos config) |
|---|
| 79 | |
|---|
| 80 | Next is `init_database.sh` |
|---|
| 81 | |
|---|
| 82 | ldapadd -Y EXTERNAL -H ldapi:/// <<EOS |
|---|
| 83 | dn: dc=realm1,dc=ws,dc=nsrc,dc=org |
|---|
| 84 | objectClass: dcObject |
|---|
| 85 | objectclass: organization |
|---|
| 86 | o: ws.nsrc.org |
|---|
| 87 | dc: ws |
|---|
| 88 | description: LDAP root |
|---|
| 89 | |
|---|
| 90 | dn: ou=People,dc=realm1,dc=ws,dc=nsrc,dc=org |
|---|
| 91 | objectClass: top |
|---|
| 92 | objectClass: organizationalUnit |
|---|
| 93 | ou: People |
|---|
| 94 | |
|---|
| 95 | dn: ou=Groups,dc=realm1,dc=ws,dc=nsrc,dc=org |
|---|
| 96 | objectClass: top |
|---|
| 97 | objectClass: organizationalUnit |
|---|
| 98 | ou: Groups |
|---|
| 99 | EOS |
|---|
| 100 | |
|---|
| 101 | And finally `config.sh` |
|---|
| 102 | |
|---|
| 103 | # Because these are 'replace' operations it's safe to modify this script |
|---|
| 104 | # and re-run it |
|---|
| 105 | ldapmodify -Y EXTERNAL -H ldapi:/// <<EOS |
|---|
| 106 | dn: cn=config |
|---|
| 107 | replace: olcSaslSecProps |
|---|
| 108 | olcSaslSecProps: noanonymous,noplain,minssf=56 |
|---|
| 109 | |
|---|
| 110 | dn: olcDatabase={1}hdb,cn=config |
|---|
| 111 | replace: olcAccess |
|---|
| 112 | olcAccess: {0}to * by dn.regex="^uid=([^@,]+)/admin,cn=gssapi,cn=auth$" manage by users read |
|---|
| 113 | - |
|---|
| 114 | replace: olcRequires |
|---|
| 115 | olcRequires: SASL |
|---|
| 116 | EOS |
|---|
| 117 | |
|---|
| 118 | The simple ACL says that full access is permitted to `*/admin` principals in |
|---|
| 119 | our realm, and otherwise read access is granted to any valid user (i.e. |
|---|
| 120 | anyone with a kerberos ticket that we recognize). See OpenLDAP ITS#6757 for |
|---|
| 121 | a note on the format of the auth DN. |
|---|
| 122 | |
|---|
| 123 | We also require SASL, which disables anonymous and simple binds. |
|---|
| 124 | |
|---|
| 125 | Note: minssf enforces encryption. GSSAPI always returns 56 for ssf, |
|---|
| 126 | regardless of the strength of the actual crypto mechanism in use. See |
|---|
| 127 | http://lists.andrew.cmu.edu/pipermail/cyrus-sasl/2006-September/000628.html |
|---|
| 128 | |
|---|
| 129 | The following tweak disables unused sasl mechanisms, and means that |
|---|
| 130 | `-Y GSSAPI` can be omitted form the ldapsearch command line. |
|---|
| 131 | |
|---|
| 132 | # editor /etc/ldap/sasl2/slapd.conf |
|---|
| 133 | mech_list: gssapi external |
|---|
| 134 | |
|---|
| 135 | Test LDAP |
|---|
| 136 | --------- |
|---|
| 137 | |
|---|
| 138 | Update `/etc/ldap/ldap.conf` to point to your own LDAP server and base DN. |
|---|
| 139 | Use ldapsearch to check that you can query it. |
|---|
| 140 | |
|---|
| 141 | $ kinit testuser |
|---|
| 142 | $ ldapsearch [-Y GSSAPI] [-b "dc=realm1,dc=realm1,dc=ws,dc=nsrc,dc=org"] |
|---|
| 143 | |
|---|
| 144 | This should dump back the (mostly empty) LDAP database, as long as you have |
|---|
| 145 | a Kerberos ticket |
|---|
| 146 | |
|---|
| 147 | Create user |
|---|
| 148 | ----------- |
|---|
| 149 | |
|---|
| 150 | We are going to create a user called "newuser" |
|---|
| 151 | |
|---|
| 152 | Firstly in Kerberos: |
|---|
| 153 | |
|---|
| 154 | $ kadmin -p student/admin |
|---|
| 155 | addprinc newuser |
|---|
| 156 | ... choose a password |
|---|
| 157 | ^D |
|---|
| 158 | |
|---|
| 159 | And now in LDAP: |
|---|
| 160 | |
|---|
| 161 | $ kinit student/admin |
|---|
| 162 | $ ldapadd <<EOS |
|---|
| 163 | dn: uid=newuser,ou=People,dc=ws,dc=nsrc,dc=org |
|---|
| 164 | objectClass: account |
|---|
| 165 | objectClass: posixAccount |
|---|
| 166 | cn: newuser |
|---|
| 167 | uid: newuser |
|---|
| 168 | uidNumber: 10000 |
|---|
| 169 | gidNumber: 100 |
|---|
| 170 | homeDirectory: /home/newuser |
|---|
| 171 | loginShell: /bin/bash |
|---|
| 172 | gecos: newuser |
|---|
| 173 | description: User account |
|---|
| 174 | EOS |
|---|
| 175 | $ kdestroy |
|---|
| 176 | |
|---|
| 177 | Test NSS |
|---|
| 178 | -------- |
|---|
| 179 | |
|---|
| 180 | Now update your LDAP nscd/nsswitch configuration (part 2 of exercise 2). |
|---|
| 181 | You will need to edit `/etc/ldap.conf` with your own PC as LDAP server |
|---|
| 182 | and your own Base DN. Restart nscd after doing this. |
|---|
| 183 | |
|---|
| 184 | To verify all is working: |
|---|
| 185 | |
|---|
| 186 | $ id newuser |
|---|
| 187 | |
|---|
| 188 | You should see a result with the uid and gid. Repeated operations should be |
|---|
| 189 | quick as nscd will be caching them. |
|---|
| 190 | |
|---|
| 191 | Troubleshooting: |
|---|
| 192 | |
|---|
| 193 | * Make sure clock is synced |
|---|
| 194 | * Make sure you have a kerberos ticket for root. Re-run |
|---|
| 195 | `/etc/cron.hourly/kerberos` if necessary. |
|---|
| 196 | * Restart nscd |
|---|
| 197 | * If you stop nscd, then 'id <username>' will make an LDAP query as the |
|---|
| 198 | current user. Make sure that the current user has a kerberos ticket. |
|---|
| 199 | |
|---|
| 200 | ldapscripts |
|---|
| 201 | ----------- |
|---|
| 202 | |
|---|
| 203 | There is a package called `ldapscripts` with simple tools for adding |
|---|
| 204 | and managing LDAP users. Unfortunately it doesn't know about GSSAPI |
|---|
| 205 | authentication, so you need to patch it. See ldapscripts-sasl.diff |
|---|
| 206 | |
|---|
| 207 | Then configure it: |
|---|
| 208 | |
|---|
| 209 | # editor /etc/ldapscripts/ldapscripts.conf |
|---|
| 210 | SASLAUTH="GSSAPI" |
|---|
| 211 | ... |
|---|
| 212 | SERVER="ldap://pc1.ws.nsrc.org" |
|---|
| 213 | ... |
|---|
| 214 | SUFFIX="dc=realm1,dc=ws,dc=nsrc,dc=org" |
|---|
| 215 | |
|---|
| 216 | Then adding a new user in LDAP is as simple as: |
|---|
| 217 | |
|---|
| 218 | $ kinit student/admin |
|---|
| 219 | $ ldapadduser someuser users |
|---|
| 220 | $ kdestroy |
|---|
| 221 | |
|---|
| 222 | Adding groups and users into groups: |
|---|
| 223 | |
|---|
| 224 | $ ldapaddgroup noc |
|---|
| 225 | $ ldapaddusertogroup someuser noc |
|---|
| 226 | |
|---|
| 227 | You may need to restart nscd before 'id' shows this information. |
|---|
| 228 | |
|---|
| 229 | Configure backup LDAP |
|---|
| 230 | --------------------- |
|---|
| 231 | |
|---|
| 232 | OpenLDAP replication is left as an exercise to the reader. |
|---|