\documentclass{ictlab} \RCS $Revision: 1.6 $ \usepackage{verbatim,key,alltt,amstext,answer2} \usepackage[hang,bf,nooneline]{caption2} \usepackage[pdfpagemode=None,pdfauthor={Nick Urbanik}]{hyperref} \newcommand*{\labTitle}{LDAP Schemas} \renewcommand*{\floatpagefraction}{0.75} % default is .5, to increase % density. \renewcommand*{\bottomfraction}{0.6} % default is 0.3 \renewcommand*{\topfraction}{0.85} % default is 0.7 \renewcommand*{\textfraction}{0.1} % default is 0.2 \begin{document} \section{Background} The \LDAP protocol is a standard for network directories. Some proprietary directory servers have been based on \LDAP, for example, Novell Directory Services (\NDS) or Microsoft Active Directory (M?\acro{AD}). Open\LDAP is a standard \LDAP server project begun many years ago at the University of Michegan\e. The \URL is \url{http://www.openldap.org/}. The \LDAP protocol provides a \emph{standard method for query} over the network (unlike \acro{SQL}, which has many proprietary extensions), and is designed for \emph{rapid read access} over the network. It also \emph{supports encryption} using \TLS with the start \TLS protocol. It supports security functions that allow it to be used for authentication and for storing system information. An \LDAP directory is not designed for storing large ``chunks'' of data, and has a slower write operation than many relational databases. It also does not support transactional integrity in the same way as a relational database. \LDAP directories can be used for storing computer account information, for email information, for corporate address books, for network management information, and for many other applications. \section{Overview} \label{sec:overview} Here you will create an \LDAP directory that provides network authentication. You will create some accounts on your computer, then migrate them to your \LDAP directory. You will then configure your machine to use these network accounts. \section{Procedure} \label{sec:procedure} \subsection{Setting up your directory server} \label{sec:setting-up-server} \begin{enumerate} \item Ensure that the \texttt{openldap-servers} package is installed on your computer: \begin{verbatim} $ rpm -qa | grep openldap- openldap-clients-2.0.27-2.8.0 openldap-servers-2.0.27-2.8.0 openldap-2.0.27-2.8.0 openldap-devel-2.0.27-2.8.0 \end{verbatim}%$ If not, then install the updates (this will replace any that are missing): \begin{alltt} $ \textbf{sudo rpm -Uhv /home/nfs/rh-8.0-updated/RedHat/RPMS/openldap-*} \end{alltt}%$ \end{enumerate} \subsection{Configuring the \LDAP server} \label{sec:configuration} \begin{enumerate} \item Edit the configuration file for your \LDAP server and create a proper secure hashed password for the manager. The password you choose should be different from your other passwords. It will be used to administer your directory. \begin{alltt} $ \textbf{xhost +localhost} $ \textbf{sudo -v} $ \textbf{sudo emacs /etc/openldap/slapd.conf &} $ \textbf{slappasswd} New password: Re-enter new password: \{SSHA\}PTPNHoKcjUjKAKHb/yyCV/C6N4rBK31v \end{alltt} Now copy and paste this password into \texttt{/etc/openldap/slapd.conf} so that exactly one uncommented line begins with \texttt{rootpw} and looks like this (but copy and paste \emph{your} password, not this silly example): \begin{verbatim} rootpw {SSHA}PTPNHoKcjUjKAKHb/yyCV/C6N4rBK31v \end{verbatim} \item Select a domain name for your system. Here I use the domain \texttt{abc.com}. If you stick with \texttt{my-domain.com}, you can skip the next step. \item Specify the \emph{base} of your directory. Change all cases of ``\texttt{dc=my-domain,dc=com}'' to match your domain. For example if your domain is \texttt{abc.com}, then change all cases of ``\texttt{dc=my-domain,dc=com}'' to ``\texttt{dc=abc,dc=com}''. Another example: the domain \texttt{tyict.vtc.edu.hk} would give you a distinguished name for your base of ``\texttt{dc=tyict,dc=vtc,dc=edu,dc=hk}''. \item Add the following to the section on access control to restrict access to the password fields: \begin{verbatim} access to attr=userPassword by self write by anonymous auth by * none access to attr=loginShell by self write by * read access to * by * read \end{verbatim} \begin{explanation} This provides access control to three sets of attributes: the attribute \texttt{userPassword}, the attribute \texttt{loginShell}, and all other attributes. The rules to access the \texttt{userPassword} attribute are: \begin{itemize} \item If you are logged in, you can read and write your own password (in other words, you can change your own password) \item If you are connected anonymously to the directory server, you are allowed to authenticate, but you may not read or write any passwords. \item No other access to the \texttt{userPassword} attribute is permitted. \end{itemize} The rules to access the attribute \texttt{loginShell} are: \begin{itemize} \item If you are logged in, you can read and write the attribute \texttt{loginShell} --- in other words, you can change your own shell. \item Other users have read access to all \texttt{loginShell} attributes. \end{itemize} The last rule controls access to all other attributes that are not covered earlier; it means that all other attributes can be read by anyone. \end{explanation} \item Replace the line in \texttt{/etc/openldap/slapd.conf} that loads the \texttt{rfc822-MailMember.schema} and load the \texttt{misc.schema} instead. The change to your \texttt{slapd.conf} will look like this: \begin{verbatim} # include /etc/openldap/schema/redhat/rfc822-MailMember.schema include /etc/openldap/schema/misc.schema \end{verbatim} \item Make sure you save \texttt{slapd.conf} before you move to the following steps. \item The configuration file \emph{must} be owned by the user \texttt{ldap}: \begin{alltt} $ \textbf{sudo chown ldap.ldap /etc/openldap/slapd.conf} \end{alltt}%$ \item Start the ldap service, and ensure it starts when you boot your computer: \begin{alltt} $ \textbf{sudo service ldap start} $ \textbf{sudo chkconfig --level 345 ldap on} \end{alltt} \item Make sure it's running: \begin{alltt} $ \textbf{sudo service ldap status} slapd (pid 19150 19077 19076) is running... \end{alltt}%$ \end{enumerate} \subsection{Set up the Migration Tools} \label{sec:setup-migration-tools} \begin{enumerate} \item The following patch to the migration tools restricts what is put into the directory to non-system users and groups. It is available from \url{http://nicku.org/snm/lab/ldap-schemas/migration-tools-rh-nick.patch}. Apply it to the migration tools that come with OpenLDAP like this: \begin{alltt} $ \textbf{cd /usr/share/openldap/migration} $ \textbf{sudo patch -b < \(\sim\)/migration-tools-rh-nick.patch} \end{alltt} {\small% \begin{verbatim} --- migrate_common.ph.orig 2002-12-14 04:42:40.000000000 +0800 +++ migrate_common.ph 2003-04-22 14:05:06.000000000 +0800 @@ -67,6 +67,13 @@ $NAMINGCONTEXT{'services'} = "ou=Services"; } +# Nick: reduce directory to what we need: +my @wanted_namingcontexts = ( 'passwd', 'group' ); +for my $context ( keys %NAMINGCONTEXT ) { + delete $NAMINGCONTEXT{$context} + unless grep { /$context/ } @wanted_namingcontexts; +} + # Default DNS domain $DEFAULT_MAIL_DOMAIN = "padl.com"; --- migrate_group.pl.orig 2002-12-14 04:42:40.000000000 +0800 +++ migrate_group.pl 2003-04-22 14:05:06.000000000 +0800 @@ -41,6 +41,10 @@ $PROGRAM = "migrate_group.pl"; $NAMINGCONTEXT = &getsuffix($PROGRAM); +# Nick Urbanik +# It's a lousy idea to create groups for system groups, which depend +# on the locally installed software. +my $min_gidNumber = 100; &parse_args(); &open_files(); @@ -52,6 +56,7 @@ local($group, $pwd, $gid, $users) = split(/:/); + next unless $gid >= $min_gidNumber; if ($use_stdout) { &dump_group(STDOUT, $group, $pwd, $gid, $users); } else { --- migrate_passwd.pl.orig 2002-12-14 04:42:40.000000000 +0800 +++ migrate_passwd.pl 2003-04-26 16:27:29.000000000 +0800 @@ -42,6 +42,10 @@ $PROGRAM = "migrate_passwd.pl"; $NAMINGCONTEXT = &getsuffix($PROGRAM); +# Nick Urbanik +# It's a lousy idea to create accounts for system user accounts, which depend +# on the locally installed software. +my $min_uidNumber = 500; &parse_args(); &read_shadow_file(); &open_files(); @@ -73,6 +77,7 @@ s/å/ae/g; local($user, $pwd, $uid, $gid, $gecos, $homedir, $shell) = split(/:/); + next unless $uid >= $min_uidNumber; if ($use_stdout) { &dump_user(STDOUT, $user, $pwd, $uid, $gid, $gecos, $homedir, $shell); @@ -122,7 +127,7 @@ if ($DEFAULT_MAIL_HOST) { print $HANDLE "mailRoutingAddress: $user\@$DEFAULT_MAIL_HOST\n"; print $HANDLE "mailHost: $DEFAULT_MAIL_HOST\n"; - print $HANDLE "objectClass: mailRecipient\n"; + print $HANDLE "objectClass: inetLocalMailRecipient\n"; } print $HANDLE "objectClass: person\n"; print $HANDLE "objectClass: organizationalPerson\n"; \end{verbatim}%$ } \item Create a little shell file to set up your environment that looks something like this (available from\\ \url{http://nicku.org/snm/lab/ldap-schemas/migrate-environment.sh}). It \emph{must} match the base and domain name you selected earlier. \begin{verbatim} # Should source into current environment LDAP_BASEDN="dc=abc,dc=com" # Kerberos realm: LDAP_DEFAULT_MAIL_DOMAIN="abc.com" LDAP_DEFAULT_MAIL_HOST="abc.com" LDAP_BINDDN= LDAP_EXTENDED_SCHEMA=1 export LDAP_BASEDN LDAP_DEFAULT_MAIL_DOMAIN LDAP_DEFAULT_MAIL_HOST \ LDAP_BINDD LDAP_EXTENDED_SCHEMA \end{verbatim} \item \emph{Source} this file into the current shell process: \begin{alltt} $ \textbf{. \(\sim\)/migrate-environment.sh} \end{alltt}%$ Note that you need to do this before running any of the migration tools. Check the environment is set correctly with the command: \begin{alltt} $ \textbf{set | grep LDAP} \end{alltt}%$ \end{enumerate} \subsection{Generating the Base Entries for your Directory} \label{sec:generating-the-base-entries} The directory will have a tree structure. Before you can add user accounts to it, you need to create the top-level entries for your directory. We create them here. \begin{enumerate} \item Now change to the migrate directory and generate some \LDIF: \begin{alltt} $ \textbf{cd /usr/share/openldap/migration} $ \textbf{./migrate_base.pl | tee \(\sim\)/base.ldif} \end{alltt} \item Carefully examine the resulting \LDIF. \item Add your \LDIF to the the \LDAP database: \begin{alltt} $ \textbf{ldapadd -x -h localhost -D "cn=Manager,dc=abc,dc=com" -W -f \(\sim\)/base.ldif} \end{alltt}%$ \item When prompted, enter the directory administrator password you created earlier. \item If you see any error messages, correct the errors in either the \texttt{slapd.conf} file or your \LDIF input. \item Verify that your directory has the base entries: \begin{alltt} $ \textbf{ldapsearch -x -h 'localhost' -b 'dc=abc,dc=com'} \end{alltt}%$ \end{enumerate} \subsection{Migrating User Accounts and Groups } \label{sec:migrating-accounts} \begin{enumerate} \item Now migrate the accounts from your password and group files: \begin{alltt} $ \textbf{sudo ./migrate_passwd.pl /etc/passwd | tee \(\sim\)/accounts.ldif} $ \textbf{./migrate_group.pl /etc/group | tee -a \(\sim\)/accounts.ldif} \end{alltt} \item Carefully examine the resulting \LDIF. \item Add your \LDIF to the the \LDAP server: \begin{alltt} $ \textbf{ldapadd -x -h localhost -D "cn=Manager,dc=abc,dc=com" -W -f \(\sim\)/accounts.ldif} \end{alltt}%$ \item If you see any error messages, correct the errors in either the \texttt{slapd.conf} file or your \LDIF input. \item Verify that your directory has entries for all the users and groups in your \LDIF file: \begin{alltt} $ \textbf{ldapsearch -x -h 'localhost' -b 'dc=abc,dc=com'} \end{alltt}%$ You should see all the data from your \LDIF file (except for the passwords) displayed on the output %% \item Download the \LDIF file from this location: %% \url{http://nicku.org/snm/lab/ldap-schemas/base.ldif} %% and examine its contents. %% \item Add this \LDIF to your directory: %% \begin{verbatim} %% ldapadd -x -h localhost -D "cn=Manager,dc=my-domain,dc=com" -W -f base.ldif %% \end{verbatim} %% and type the password \texttt{secret} when prompted. %% \item Now search your directory to see the content: %% \begin{verbatim} %% ldapsearch -x -h localhost -b 'dc=my-domain,dc=com' %% \end{verbatim} %% If that shows a successful search, your directory server is now %% functioning. We can now add more entries to it and experiment with %% schemas. \end{enumerate} \subsection{Suppose I Make a Big Mistake?} \label{sec:how-delete-directory} Suppose you find that you forgot to set the \texttt{LDAP\_\ldots} environment variables by doing \texttt{source \(\sim\)/migrate-environment}, and the base is wrong? Or suppose you reversed the patch to the migration tools, and now your directory is filled with system accounts? How to undo all this? You could delete the entries online with the \texttt{ldapdelete} tool, but it will be simpler to just delete the directory and recreate it. Here is how you could do that: \begin{alltt} $ \textbf{sudo service ldap stop} $ \textbf{sudo rm -rf /var/lib/ldap} $ \textbf{sudo mkdir /var/lib/ldap} $ \textbf{sudo chmod 700 /var/lib/ldap} $ \textbf{sudo chown ldap.ldap /var/lib/ldap} \end{alltt}%$ Then just run the migration tools again. You may also find the \texttt{-c} option to \texttt{slapadd} useful. \subsection{Adding Entries Offline with slapadd} \label{sec:using-slapadd} For a large number of entries (more than 2,000), \texttt{ldapadd} can be a bit slow. You may wish to use the offline tool, \texttt{slapadd}. It is quite easy to use, although the error messages are sometimes a little harder to understand than when using \texttt{ldapadd}. \texttt{ldapadd} also performs more thorough schema checking, since the checking is done by the directory server itself. Here we add the accounts offline, using \texttt{slapadd}: \begin{enumerate} \item Stop the directory server. \begin{alltt} $ \textbf{sudo service ldap stop} \end{alltt}%$ \item Add your \LDIF to the the \LDAP database: \begin{alltt} \textbf{sudo -u ldap slapadd -v -l \(\sim\)/accounts.ldif} \end{alltt} \item If you see any error messages, correct the errors in either the \texttt{slapd.conf} file or your \LDIF input. \item Restart the server: \begin{alltt} $ \textbf{service ldap start} \end{alltt}%$ \end{enumerate} %% \subsection{Migrating Online With \texttt{ldapadd}} %% \label{sec:ldapadd} %% The error messages from \texttt{slapadd} are sometimes not very %% helpful. It is sometimes better to have the \LDAP server running, and %% then add the directory entries online with the tool \texttt{ldapadd}. %% Here is how to use it to add the entries in %% $\sim$\texttt{/accounts.ldif}: %% \begin{alltt} %% $ \textbf{ldapadd -x -h localhost -D "cn=Manager,dc=abc,dc=com" -W -f \(\sim\)/accounts.ldif} %% \end{alltt}%$ %% Then when prompted, type the password you added to for the directory %% administrator. In fact, this is better than using \texttt{slapadd}, %% since the directory can do proper schema checking. \section{Adding support for Automounting Home Directories} \label{sec:autofs} \begin{enumerate} \item Select a machine to serve home directories via \NFS (and \texttt{samba}) \item Create the required home directories for all users who will have their home directories on the network \item Create two files to migrate into the directory: \texttt{auto.master} and \texttt{auto.home} \begin{alltt} $ \textbf{cat /etc/auto.master} # Sample auto.master file # Format of this file: # mountpoint map options # For details of the format look at autofs(8). # /misc /etc/auto.misc --timeout=60 /.auto /etc/auto.auto --timeout=60 /home ldap:nicksbox.tyict.vtc.edu.hk:/etc/auto.home --timeout=60 $ \textbf{cat /etc/auto.home} nicku -rw,hard,intr nicksbox.tyict.vtc.edu.hk:/home/nicku pam -rw,hard,intr nicksbox.tyict.vtc.edu.hk:/home/pam linus -rw,hard,intr nicksbox.tyict.vtc.edu.hk:/home/linus nfs -ro,soft,intr nicksbox.tyict.vtc.edu.hk:/var/ftp/pub mp3 -ro,soft,intr nicksbox.tyict.vtc.edu.hk:/mp3 \end{alltt} Note that it is better to have only one space between each field, otherwise the data will be a little bit harder to read in your directory, as it would be \acro{MIME} encoded. %% $ ldapsearch -x -b 'ou=auto.master,dc=tyict,dc=vtc,dc=edu,dc=hk' %% version: 2 %% # %% # filter: (objectclass=*) %% # requesting: ALL %% # %% # auto.master, tyict, vtc, edu, hk %% dn: ou=auto.master,dc=tyict,dc=vtc,dc=edu,dc=hk %% ou: auto.master %% objectClass: top %% objectClass: automountMap %% # /home, auto.master, tyict, vtc, edu, hk %% dn: cn=/home,ou=auto.master,dc=tyict,dc=vtc,dc=edu,dc=hk %% objectClass: automount %% cn: /home %% automountInformation: ldap:nicku.org:ou=auto.home,dc=tyict,dc=vt %% c,dc=edu,dc=hk --timeout 60 %% # /usr/remote, auto.master, tyict, vtc, edu, hk %% dn: cn=/usr/remote,ou=auto.master,dc=tyict,dc=vtc,dc=edu,dc=hk %% objectClass: automount %% automountInformation: ldap:nicku.org:ou=auto.practical,dc=tyict, %% dc=vtc,dc=edu,dc=hk --timeout 60 %% cn: /usr/remote % Can use a wildcard autofs entry. Need check this. Read the autofs % source code, mailing lists. Implement and check. % Apr 23 16:06:15 ictlab slapd[16910]: conn=25266 op=2 SRCH base="ou=auto.home,dc=tyict,dc=vtc,dc=edu,dc=hk" scope=2 filter="(&(objectClass=automount)(cn=/))" \item Migrate them into another \LDIF file: \begin{alltt} $ \textbf{./migrate_automount.pl /etc/auto.master | tee \(\sim\)/automount.ldif} $ \textbf{./migrate_automount.pl /etc/auto.home | tee -a \(\sim\)/automount.ldif} \end{alltt} \item Export the \texttt{/home} directory to the machines that are authorised to access them by adding the appropriate line to the \texttt{/etc/exports} file: \begin{verbatim} /var/ftp/pub 192.168.0.0/24(ro) /mp3 192.168.0.0/24(ro) /home 192.168.0.0/24(rw) \end{verbatim} \item Use \texttt{ldapadd} to add the entries in your new \LDIF file, and check that you can read the entries with \texttt{ldapsearch -x}, then verify that clients can get their home directory. \end{enumerate} \begin{thebibliography}{HSG99} \bibitem[HSG99]{bib:HSG99} Timothy Howes and Mark C. Smith and Gordon S. Good, \emph{Understanding and Deploying LDAP Directory Services}, Macmillan, 1999, ISBN: 1-57870-070-1 (Tsing Yi Library call number: TK 5105.595.H69 1999 ) \bibitem[Car03]{bib:Car03} Gerald Carter, \emph{LDAP System Administration}, O'Reilly, March 2003, ISBN: 1-56592-491-6 \bibitem[Don03]{bib:Don03} Clayton Donley, \emph{LDAP Programming, Management and Integration}, Manning, 2003, ISBN: 1-930110-40-5 \bibitem[HSG03]{bib:HSG03} Tim Howes, Timothy A. Howes, Mark C. Smith, Gordon S. Good, \emph{Understanding and Deploying LDAP Directory Services (2nd Edition)} ISBN: 0672323168, Addison Wesley Professional, May 2, 2003 \end{thebibliography} \end{document}