\errorcontextlines=99

%\documentclass[colorBG,slideColor,troispoints,pdf]{prosper}
\documentclass[nopagebreak,ps,10pt,a5paper]{ppr-prv}% DO NOT EDIT---WILL BE OVERWRITTEN
\geometry{margin=10mm}% DO NOT EDIT---WILL BE OVERWRITTEN
%\documentclass[12pt,colorBG,total,slideColor,pdf]{ppr-prv-nick}
%\documentclass[colorBG,slideColor,ps]{prosper}
\usepackage{alltt,key,xr,cols,rcs,acro,nick,%
  graphicx,varioref,explanation,booktabs,multicol}
%\RequirePackage[unknownkeysallowed,a4paper,scale=0.93]{geometry}
% \usepackage[nolineno,noindent]{lgrind}

\usepackage[toc,highlight,Tycja]{HA-prosper}
%\usepackage[toc,highlight,vsimple]{HA-prosper}

%\definecolor{green}{rgb}{0,1,0}

% Copyright (c) 2004 by Nick Urbanik <nicku(at)nicku.org>.
% This material may be distributed only subject to the terms and
% conditions set forth in the Open Publication License, v1.0 or later
% (the latest version is presently available at
% http://www.opencontent.org/openpub/).
                                                                                
\RCS $Revision: 1.3 $

\renewcommand*{\bs}{\texttt{\char '134}} % Backslash `\'
%\newcommand*{\labTitle}{LDAP Directories}
\newcommand*{\subject}{Systems and Network Management}
\newcommand*{\emphcolour}[1]{\emph{\red#1}}

\providecommand*{\RPM}{\acro{RPM}\xspace}
\providecommand*{\CD}{\acro{CD}\xspace}
\providecommand*{\IPC}{\acro{IPC}\xspace}
\providecommand*{\UID}{\acro{UID}\xspace}
\providecommand*{\GID}{\acro{GID}\xspace}
\providecommand*{\SMP}{\acro{SMP}\xspace}
\providecommand*{\API}{\acro{API}\xspace}
\providecommand*{\OK}{\acro{OK}\xspace}
\providecommand*{\IETF}{\acro{OK}\xspace}
\providecommand*{\MS}{\acro{MS}\xspace}

\newlength{\lift}
\settoheight{\lift}{$\triangleleft$}
\newcommand*{\generalises}{$\triangleleft$\rule[0.5\lift]{1.7\lift}{.4pt}}

\title{\blue{}Programming LDAP with Perl}
\subtitle{Net::LDAP}
%% \author{Nick Urbanik \texttt{<nicku\at{}nicku.org>}\\
%%   \footnotesize{}Copyright Conditions: Open Publication License (see
%%   \url{http://www.opencontent.org/openpub/})}%
%% \institution{A computing department}
\author{Nick Urbanik \texttt{<nicku\at{}nicku.org>}\\
  \footnotesize{}Copyright Conditions: Open Publication License\\
  \footnotesize{}(see
  \url{http://www.opencontent.org/openpub/})\\
\institution{A computing department}}%
%\footnotesize{}Copyright Conditions: GNU FDL (see
%\url{http://www.gnu.org/licenses/fdl.html})}
\slideCaption{SNM --- LDAP Directories --- ver. \RCSRevision}
%%%%\Logo{\includegraphics[width=15mm]{ict-logo-smaller}}

\DefaultTransition{Wipe}
\TitleSlideNav{FullScreen}
\NormalSlideNav{ShowBookmarks}
\LeftFoot{SNM --- ver. \RCSRevision}
\RightFoot{Network Directories and their Structure}
\begin{document}
\maketitle
%\begin{notes}
%\end{notes}

\tsection{Introduction to Net::LDAP}

\begin{slide}{What is Net::LDAP?}
  \label{sld:what-is-net-ldap}
  \begin{itemize}
  \item Mature and fully-featured Perl library
  \item Pure Perl; very easy to install on any platform
    \begin{itemize}
    \item On Windows, do
\begin{alltt}\footnotesize
D:\bs>\textbf{ppm}
PPM - Programmer's Package Manager version 3.1.
Copyright (c) 2001 ActiveState SRL. All Rights Reserved.
...

ppm> \textbf{install perl-ldap}
\end{alltt}
    \item On other platforms, do:
\begin{alltt}
$ \textbf{sudo perl -MCPAN -e 'install Net::LDAP'}
\end{alltt}%$
    \end{itemize}
  \item Excellent documentation
    \begin{itemize}
    \item Start with
\begin{alltt}
$ \textbf{perldoc Net::LDAP}
\end{alltt}%$
    \end{itemize}
  \item Helpful mailing list
  \end{itemize}
\end{slide}

\tsection{Net::LDAP Operations}

\begin{slide}{Connecting}
  \label{sld:connecting}
  \begin{itemize}
  \item Connect when construct the Net::LDAP object:
\begin{alltt}
my $ldap = Net::LDAP->new( $hostname )
  or die "Unable to connect to $hostname: $!";
\end{alltt}
\item See \texttt{perldoc Net::LDAP} for many other parameters you can
  pass in constructor
  \end{itemize}
\end{slide}

\begin{slide}{Authentication}
  \label{sld:authentication}
  \begin{itemize}
  \item The \emph{bind} operation
  \item Three types: \emphcolour{anonymous}, \emphcolour{simple},
    \emphcolour{SASL}
  \item Anonymous:
\begin{alltt}
my $result = $ldap->bind;
\end{alltt}
  \item Simple:
\begin{alltt}
my $result =
   $ldap->bind( $dn, password => $password );
\end{alltt}
\begin{itemize}
\item Danger!  Password sent in clear text unless use \TLS (see
  slide~\S\ref{sld:start-tls})
\end{itemize}
  \end{itemize}
\end{slide}

\begin{slide}{Return Values}
  \label{sld:return-values}
  \begin{itemize}
  \item Most Net::LDAP methods return an object
    \begin{itemize}
    \item returned object provides method to obtain results of operation
    \end{itemize}
  \item result code returned by \texttt{\$result->code}
  \item error message returned by \texttt{\$result->error}
  \item Example:
\begin{alltt}
warn \$result->error if \$result->code;
\end{alltt}
  \end{itemize}
\end{slide}

\begin{slide}{Searching}
  \label{sld:searching}
  \begin{itemize}
  \item Need three things for a search:
    \begin{itemize}
    \item \emphcolour{search base}, \emphcolour{scope} and
      \emphcolour{filter}
    \end{itemize}
\begin{alltt}
my $result = $ldap->search(
  base => 'dc=tyict,dc=vtc,dc=edu,dc=hk',
  scope => 'sub',
  filter => '(uid=nicku)'
);
die $result->error if $result->code;
\end{alltt}
\item The result also contains the matching entries:
\begin{verbatim}
foreach my $entry ( $result->entries ) {
    $entry->dump;
}
\end{verbatim}%$
  \begin{itemize}
  \item Methods of the object that results from a search documented in
  \texttt{perldoc~Net::LDAP::Search}
  \end{itemize}
\end{itemize}
\end{slide}

\begin{slide}{Entry Object}
  \label{sld:entry-object}
  \begin{itemize}
  \item Entry object is used:
    \begin{itemize}
    \item to create new entries and
    \item is available from a search
    \end{itemize}
  \item Documented in \texttt{perldoc~Net::LDAP::Entry}
  \item Methods:
    \begin{description}
    \item[\texttt{dn}] returns the \DN for the entry:
\begin{verbatim}
my $dn = $entry->dn;
\end{verbatim}
    \item[\texttt{exists}] tests if an attribute exists in the entry:
\begin{verbatim}
do_something() if $entry->exists( 'cn' );
\end{verbatim}%$
    \end{description}
  \end{itemize}
\end{slide}

\begin{slide}{Entry Object --- 2}
  \begin{itemize}
  \item Methods:
    \begin{description}
    \item[\texttt{get\_value}] obtain the value(s) for an attribute in
      the entry
\begin{verbatim}
my $value = $entry->get_value( 'cn' );
\end{verbatim}
    \item[{Multivalued attributes:}] Some attributes have more than
      one value.  For these, \texttt{get\_value} returns the first
      value in a scalar context, and all of them in a list context:
      {\small
\begin{verbatim}
my $first  = $entry->get_value( 'objectClass' );
my @values = $entry->get_value( 'objectClass' );
\end{verbatim}%
%% my $values = $entry->get_value( 'objectClass',
%%                                  asref => 1 );
}%$
\item[\texttt{attributes}] returns a list of attributes the entry
  contains
\begin{verbatim}
my @attrs = $entry->attributes;
\end{verbatim}%$
    \end{description}
  \end{itemize}
\end{slide}

\begin{slide}{Displaying an Entry}
  \label{sld:displating-entries}
  \begin{itemize}
  \item If all attributes can be printed, then this function could
    display an entry:
\par\medskip\par
\begin{verbatim}
sub display_entry {
    my $entry = shift;
    my @attrs = $entry->attributes;

    foreach my $attr ( @attrs ) {
        my @value = $entry->get_value( $attr );

        foreach my $value ( @value ) {
            print "$attr: $value\n";
        }
    }
}
\end{verbatim}
  \end{itemize}
\end{slide}

\begin{slide}[toc=Limit Returns]{Controlling What's Returned}
  \label{sld:controlling-whats-returned}
  \begin{itemize}
  \item By default, \LDAP server returns attributes and their values
    for each entry.
  \item Can ask server for just the types; then value returned for each
    attribute is empty:
\begin{verbatim}
my $r = $ldap->search(
    base   => 'dc=tyict,dc=vtc,dc=edu,dc=hk',
    filter => '(cn=Nick*)',
    typesonly => 1,
);
\end{verbatim}%$
  \item Access control limits what attributes are
    returned; can limit further by specifying a list of required
    attributes:
\begin{verbatim}
my $r = $ldap->search(
    base   => 'dc=tyict,dc=vtc,dc=edu,dc=hk',
    filter => '(cn=Nick*)',
    attrs  => [ qw(uid cn) ],
);
\end{verbatim}%$
  \item Can test for specific attributes by asking for
    \texttt{typesonly} as well as specifying an attribute list.
  \end{itemize}
\end{slide}

\begin{slide}{Adding New Entries}
  \label{sld:adding-new-entries}
\ptsize{14}
  \begin{itemize}
  \item Net::LDAP supports four ways of adding new entries to a
    directory:
    \begin{itemize}
    \item the \texttt{add} method;
    \item the Entry class;
    \item \LDIF: Same as adding with the Entry class, except Entry is
      read from a file via the \LDIF module
    \item \acro{DSML}: Same as adding with the Entry class, except Entry is
      read from a file via the \acro{DSML} module
    \end{itemize}
  \end{itemize}
\end{slide}

\begin{slide}{Adding Entries}
  \label{sld:adding}
  \begin{itemize}
  \item Pass an array reference of attribute and value pairs to the
    \texttt{add} method:
    {\footnotesize%
\begin{verbatim}
my $r = $ldap->add( $dn,
    attrs => [
        cn => 'HP5000-A204e',
        objectClass => [ qw/device ieee802Device/ ],
        description => 'Printer in A204e',
    ],
);
\end{verbatim}%$
    }
  \item \ldots\,or, create an Entry object and call the
    \texttt{update} method:
%% {\small
%% \begin{verbatim}
%% my $dn = 'ou=devices,dc=tyict,dc=vtc,dc=edu,dc=hk';
%% my $e = Net::LDAP::Entry->new( $dn );
%% $e->add( cn => 'HP5000-A204e' );
%% $e->add(
%%     objectClass => 'device',
%%     description => 'Printer in A204e',
%% );
%% $r = $ldap->add( $e );
%% \end{verbatim}
%% }
    {\footnotesize
\begin{verbatim}
my $dn = 'ou=devices,dc=tyict,dc=vtc,dc=edu,dc=hk';
my $entry = Net::LDAP::Entry->new;
$entry->dn( $dn );
$entry->add( cn => 'HP5000-A204e' );
$entry->add(
    objectClass => 'device',
    description => 'Printer in A204e',
);
$mesg = $entry->update( $ldap );
\end{verbatim}
    }
  \end{itemize}
\end{slide}

\begin{slide}{Deleting an Entry}
  \label{sld:deleting-an-entry}
  \begin{itemize}
  \item Can delete an entry by passing a \DN:
\begin{verbatim}
my $dn = 'ou=dev,dc=tyict,dc=vtc,dc=edu,dc=hk';
my $r = $ldap->delete( $dn );
\end{verbatim}
  \item \ldots\,or like many Net::LDAP methods, you can pass an entry
    where a \DN is expected:
\begin{verbatim}
$entry = find_entry_to_delete();
$r = $ldap->delete( $entry );
\end{verbatim}
  \end{itemize}
\end{slide}

\begin{slide}{Modifying an Entry}
  \label{sld:modifying-an-entry}
\ptsize{12}
  \begin{itemize}
  \item \texttt{modify} operation has four sub-operations:
    \begin{description}
    \item[\texttt{add}] \mbox{}
      \begin{itemize}
      \item add new attributes
      \item add values to existing multivalued attributes
      \end{itemize}
    \item[\texttt{delete}] \mbox{}
      \begin{itemize}
      \item delete whole attributes
      \item delete values from within existing attributes
      \end{itemize}
    \item[\texttt{replace}] replace attributes or add if necessary
    \item[\texttt{moddn}] rename an entry under same or different
      parent 
    \end{description}
  \end{itemize}
\end{slide}

\begin{slide}{Modify --- \texttt{add}}
  \label{sld:modify-add}
  \ptsize{12}
  \begin{itemize}
  \item Add a new attribute, or a new value to an existing
  multi-valued attribute:
  \par\medskip\par
\begin{verbatim}
$r = $ldap->modify( $dn,
    add => {
        mail => 'nicku@nicku.org'
    }
);
\end{verbatim}%$
\item An error is returned if:
  \begin{itemize}
  \item the attribute exists and is not multi-valued;
  \item the attribute exists and is multi-valued and the value already
    exists;
  \item the schema does not allow the attribute.
  \end{itemize}
  \end{itemize}
\end{slide}

\begin{slide}{Modify --- \texttt{delete}}
  \label{sld:modify-delete}
  \begin{itemize}
  \item To delete all instances of the attribute in the entry:
\begin{verbatim}
$r = $ldap->modify( $dn,
    delete => [ 'mail' ]
);
\end{verbatim}%$
  \item You can delete specific values:
\begin{verbatim}
$r = $ldap->modify( $dn,
    delete => { 'mail' => [ 'nicku@abc.com' ] }
);
\end{verbatim}%$
  \end{itemize}
\end{slide}

\begin{slide}{Modify --- \texttt{replace}}
  \label{sld:modify-replace}
  \begin{itemize}
  \item Replace whole attributes:
\begin{verbatim}
$r = $ldap->modify( $dn,
    replace => { 'mail' => 'nicku@xyz.com' }
);
\end{verbatim}%$
  \item Multi-valued:
\begin{verbatim}
$r = $ldap->modify( $dn,
    replace => {
        'mail' => [ qw(nicku@xyz.com
                       nick@iohk.com) ]
    }
);
\end{verbatim}%$
  \end{itemize}
\end{slide}

\tsection{Encryption}

\begin{slide}{Using Start TLS}
  \label{sld:start-tls}
  \begin{itemize}
  \item \LDAP{}v3 supports the \emph{Start TLS} extension
  \item Allows a client to request that the server begin encrypting
    traffic with client
  \item Essential when using simple authentication; avoid password
    being sent in clear text over the network
  \item Here is the simplest use, where there is no requirement to
    store local copies of the certificates, but the identity of the
    server is not checked:
\begin{verbatim}
my $r = $ldap->start_tls( verify => 'none' );
\end{verbatim}%$
  \item See \texttt{perldoc~Net::LDAP} and
  \texttt{perldoc~Net::LDAP::Security} for details and examples.
  \end{itemize}
\end{slide}

\begin{slide}{References}
  \label{sld:references}
  \ptsize{8}%
  \begin{itemize}
  \item See the excellent documentation with Net::LDAP:
    \par\smallskip\par
    {\scriptsize\setlength{\extrarowheight}{-1pt}%
    \begin{tabular}{@{}ll@{}}
Net::LDAP                      & Net::LDAP::FAQ \\
Net::LDAP::Constant            & Net::LDAP::Filter \\
Net::LDAP::Control             & Net::LDAPI \\
Net::LDAP::Control::Paged      & Net::LDAP::LDIF \\
Net::LDAP::Control::ProxyAuth  & Net::LDAP::Message \\
Net::LDAP::Control::Sort       & Net::LDAP::Reference \\
Net::LDAP::Control::SortResult & Net::LDAP::RFC \\
Net::LDAP::Control::VLV        & Net::LDAP::RootDSE \\
Net::LDAP::Control::VLVResponse& Net::LDAPS \\
Net::LDAP::DSML                & Net::LDAP::Schema \\
Net::LDAP::Entry               & Net::LDAP::Search \\
{\red{}Net::LDAP::Examples}    & Net::LDAP::Security \\
Net::LDAP::Extra               & Net::LDAP::Util
    \end{tabular}}
\item See the web site for Net::LDAP: \url{http://ldap.perl.org/}
\item Graham Barr wrote slides on which these notes are based:
  \url{http://ldap.perl.org/perl-ldap-oscon2001.pdf}
\item David N. Blank-Edelman, \emph{Perl for System Administration},
  O'Reilly, July 2000, ISBN: 1565926099.
\item Gerald Carter, \emph{LDAP System Administration}, O'Reilly,
  March 2003, ISBN: 1565924916.
\item Clayton Donley, \emph{LDAP Programming, Management and
    Integration}, Manning, 2003, ISBN: 1930110405.
  \end{itemize}
\end{slide}
\end{document}
