<?xml version="1.0" encoding="UTF-8"?> <chapter version="5.1" xml:id="ldap" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns="http://docbook.org/ns/transclusion" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:db="http://docbook.org/ns/docbook"> <title><link linkend="glo_LDAP">ldap</link> and <link linkend="glo_JDBC">JDBC</link></title> <section xml:id="ldapIntro"> <title>Getting started with <xref linkend="glo_LDAP"/></title> <para>Resources:</para> <itemizedlist> <listitem> <para><link xlink:href="http://www.zytrax.com/books/ldap/ch3">Schema, objectclasses and attributes</link></para> </listitem> <listitem> <para><link xlink:href="http://www.zytrax.com/books/ldap/apd">LDAP Glossary</link></para> </listitem> </itemizedlist> </section> <section xml:id="ldapSetup"> <title>Setting up an <productname xlink:href="http://www.openldap.org">Openldap</productname> server</title> <para>The MI department provides an <productname xlink:href="http://www.openldap.org">Openldap</productname> server at each workstation (<productname xlink:href="http://www.ubuntu.com/desktop">Ubuntu</productname> / Linux only). The <xref linkend="glo_LDAP"/> manager credentials are:</para> <glosslist> <glossentry> <glossterm>Bind <xref linkend="glo_DN"/>:</glossterm> <glossdef> <para><code>cn=admin,dc=hdm-stuttgart,dc=de</code></para> </glossdef> </glossentry> <glossentry> <glossterm>Bind password:</glossterm> <glossdef> <para><code>XYZ</code></para> </glossdef> </glossentry> </glosslist> <para>In addition <xref linkend="glo_Soft_ApacheDirectoryStudio"/> is in place and may serve as a means to conveniently establish <xref linkend="glo_LDAP"/> communications. Console geeks may use <command xlink:href="http://tldp.org/HOWTO/LDAP-HOWTO/utilities.html">ldapmodify</command> and friends.</para> <task> <title>Set up a connection to your local <xref linkend="glo_LDAP"/> server</title> <procedure> <step> <para>Open <xref linkend="glo_Soft_ApacheDirectoryStudio"/>.</para> </step> <step> <para>Activate the <xref linkend="glo_LDAP"/> perspective.</para> </step> <step> <para>In the <quote>Connections</quote> window right click <quote>New Connection ...</quote> like in <uri xlink:href="https://directory.apache.org/studio/users-guide/ldap_browser/gettingstarted_create_connection.html">http://directory.apache.org/studio/users-guide/ldap_browser/gettingstarted_create_connection.html</uri>.</para> </step> <step> <para>Configure a connection to <parameter xlink:href="http://www.techterms.com/definition/localhost">localhost</parameter> using the above bind parameters.</para> </step> </procedure> </task> </section> <section xml:id="ldapSimpleInserts"> <title>Adding some sample data using <xref linkend="glo_Soft_ApacheDirectoryStudio"/></title> <qandaset defaultlabel="qanda" xml:id="qandaPopulateLdap"> <title>Populating the <xref linkend="glo_DIT"/></title> <qandadiv> <qandaentry> <question> <para>Add two departments <code>billing</code> and <code>research</code>. Then supply corresponding user entries to both departments by using the <link xlink:href="https://directory.apache.org/studio/users-guide/ldap_browser/gettingstarted_browse.html">LDAP browser view</link>. (As being mentioned previously hardcore hackers take <link xlink:href="http://tldp.org/HOWTO/LDAP-HOWTO/utilities.html">this track</link> neglecting time consuming <xref linkend="glo_GUI"/> stuff).</para> <para>Hint: If you do have limited understanding of <xref linkend="glo_LDAP"/> classes an schemata you may want to create entries containing the following <parameter xlink:href="http://www.zytrax.com/books/ldap/apd/index.html#objectclass">objectClass</parameter> values:</para> <glosslist> <glossentry> <glossterm>Departments <code>billing</code> and <code>research</code>:</glossterm> <glossdef> <itemizedlist> <listitem> <para><code xlink:href="http://www.zytrax.com/books/ldap/ape/#organizationalunit">organizationalUnit</code> (structural)</para> </listitem> </itemizedlist> </glossdef> </glossentry> <glossentry> <glossterm>Child user entries below <code>billing</code> and <code>research</code>:</glossterm> <glossdef> <itemizedlist> <listitem> <para><code xlink:href="http://www.zytrax.com/books/ldap/ape/#organizationalperson">organizationalPerson</code> (structural) and <code xlink:href="http://www.zytrax.com/books/ldap/ape/#posixaccount">posixAccount</code> (auxiliary)</para> </listitem> </itemizedlist> </glossdef> </glossentry> </glosslist> <para>Note that required parent <parameter xlink:href="http://www.zytrax.com/books/ldap/apd/index.html#objectclass">objectClass</parameter> definitions like <code>top</code> and <code xlink:href="http://www.zytrax.com/books/ldap/ape/#person">person</code> are being omitted here. <xref linkend="glo_Soft_ApacheDirectoryStudio"/> will gracefully add missing objectClasses on behalf of you automatically. The subsequent <xref linkend="glo_LDIF"/> dump may serve as a hint:</para> <programlisting language="ldif">... <emphasis role="bold">dn: ou=billing,dc=hdm-stuttgart,dc=de</emphasis> objectClass: top objectClass: organizationalUnit ou: billing <emphasis role="bold">dn: ou=research,dc=hdm-stuttgart,dc=de</emphasis> objectClass: top objectClass: organizationalUnit ou: research <emphasis role="bold">dn: uid=lapinski,ou=billing,dc=hdm-stuttgart,dc=de</emphasis> objectClass: posixAccount objectClass: top objectClass: person objectClass: organizationalPerson cn: Mee Lapinski gidNumber: 100 homeDirectory: /home/lapinski sn: Lapinski uid: lapinski uidNumber: 1023 ...</programlisting> <para>Question: What is the ratio behind adding the <code>objectClass</code> value <code>posixAccount</code>? Hint: Try to create a corresponding dataset having two persons with identical names within the same department.</para> </question> <answer> <para>Your result may look like:</para> <figure xml:id="figureLdapTwoDepartments"> <title>Two departments billing and research populated with sample user entries</title> <screenshot> <mediaobject> <imageobject> <imagedata fileref="Ref/Screen/ldapSampleUsers.png"/> </imageobject> </mediaobject> </screenshot> </figure> <para>Without having the <code>objectClass</code> value <code>posixAccount</code> the attribute <code>uid</code> would be disallowed and could thus not be part of our <xref linkend="glo_DN"/> values. This would leave us with solutions like:</para> <programlisting language="ldif"><emphasis role="bold">dn: cn=Mee Lapinski,ou=billing,dc=hdm-stuttgart,dc=de</emphasis></programlisting> <para>This in turn disallows identical common names (e.g. a second <personname>Mee Lapinski</personname>) within the same department. Thus the auxiliary objectClass posixAccount enables us to introduce additional mandatory <code>uid</code> attribute being the unique identifier within a given parent scope.</para> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="ldifImportExport"> <title><xref linkend="glo_LDIF"/> export and import</title> <para>This section is intended to get acquainted with <xref linkend="glo_LDIF"/> representation of <xref linkend="glo_LDAP"/> data and requires successful completion of <xref linkend="qandaPopulateLdap"/> as a prerequisite. You may want to read <uri xlink:href="http://www.zytrax.com/books/ldap/ch8">http://www.zytrax.com/books/ldap/ch8</uri>.</para> <qandaset defaultlabel="qanda" xml:id="qanda_ldifExportImport"> <title>Exporting, modifying and importing <xref linkend="glo_LDAP"/> data using the <xref linkend="glo_LDIF"/> interchange representation.</title> <qandadiv> <qandaentry> <question> <para>Export your current database state being left from <xref linkend="qandaPopulateLdap"/> to an <xref linkend="glo_LDIF"/> text file.</para> <para>Subsequently use this database dump file as a starting point to create a <xref linkend="glo_LDIF"/> import file adding a department <quote>pr</quote> (public relations) containing a user <quote>Paul Simon</quote> with suitable attribute values to the dataset.</para> </question> <answer> <para>Adding the new entries in question requires:</para> <screen>version: 1 dn: ou=pr,dc=hdm-stuttgart,dc=de objectClass: top objectClass: organizationalUnit ou: pr dn: uid=simon,ou=pr,dc=hdm-stuttgart,dc=de objectClass: posixAccount objectClass: top objectClass: person objectClass: organizationalPerson cn: Paul Simon gidNumber: 130 homeDirectory: /home/tauras sn: Svetlana uid: tauras uidNumber: 1028</screen> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="ditSearch"> <title>Searching the <xref linkend="glo_DIT"/></title> <para>Like relational and other database types <xref linkend="glo_LDAP"/> provides a <link xlink:href="http://www.zytrax.com/books/ldap/apa/search.html">query language</link> to filter result entries.</para> <qandaset defaultlabel="qanda" xml:id="qanda_firstLdapQuery"> <title>Filtering child elements</title> <qandadiv> <qandaentry> <question> <para>Create <xref linkend="glo_LDAP"/> queries corresponding to the following descriptions:</para> <orderedlist> <listitem> <para>All users entries within the whole <xref linkend="glo_DIT"/> having a gidNumber value of 100.</para> </listitem> <listitem> <para>All user entries belonging to the billing department having a <code>uid</code> value greater than 1023.</para> </listitem> <listitem> <para>All user entries within the whole <xref linkend="glo_DIT"/> having a common name containing the substring <quote>ei</quote>.</para> </listitem> <listitem> <para>All user entries within the whole <xref linkend="glo_DIT"/> belonging to gidNumber == 100 or having a <code>uid</code> value starting with letter <quote>t</quote>.</para> </listitem> </orderedlist> <para>Hint: <xref linkend="glo_Soft_ApacheDirectoryStudio"/> allows both for <link xlink:href="https://directory.apache.org/studio/users-guide/ldap_browser/tools_filter_editor_dialog.html">filtering</link> and <link xlink:href="https://directory.apache.org/studio/users-guide/ldap_browser/gettingstarted_search.html">searching</link> providing nifty features like attribute name completion and syntax highlighting. For regular searches you may define:</para> <itemizedlist> <listitem> <para>The <xref linkend="glo_DIT"/> entry to start from being identified by its <xref linkend="glo_DN"/>.</para> </listitem> <listitem> <para>The search scope being either of object, one level or subtree.</para> </listitem> <listitem> <para>Boolean expressions based on attribute values.</para> </listitem> </itemizedlist> <para>But yes, I forgot to mention <link xlink:href="http://tldp.org/HOWTO/LDAP-HOWTO/utilities.html">something</link>.</para> </question> <answer> <orderedlist> <listitem> <para><emphasis role="bold">All users entries within the whole </emphasis><xref linkend="glo_DIT"/><emphasis role="bold"> having a gidNumber value of 100.</emphasis></para> <para>Solution: <code>(gidNumber=100)</code>, starting from top of <xref linkend="glo_DIT"/> having subtree scope.</para> </listitem> <listitem> <para><emphasis role="bold">All user entries belonging to the billing department having a <code>uid</code> value greater than 1023.</emphasis></para> <para>Solution: <code>(uidNumber>=1024)</code> starting from <xref linkend="glo_DN"/> <code>ou=billing,dc=hdm-stuttgart,dc=de</code> and scope <code>one level</code>.</para> <para>Notice the expression <code>(uidNumber>=1024)</code> in favour of the seemingly equivalent but syntactically illegal counterpart <code>(uidNumber>1023)</code>.</para> </listitem> <listitem> <para><emphasis role="bold">All user entries within the whole </emphasis><xref linkend="glo_DIT"/><emphasis role="bold"> having a common name containing the substring <quote>ei</quote>.</emphasis></para> <para>Solution: <code>(cn=*ei*)</code>, starting from top of <xref linkend="glo_DIT"/> having subtree scope.</para> </listitem> <listitem> <para><emphasis role="bold">All user entries within the whole </emphasis><xref linkend="glo_DIT"/><emphasis role="bold"> belonging to gidNumber == 100 or having a <code>uid</code> value starting with letter <quote>t</quote>.</emphasis></para> <para>Solution: <code>(|(gidNumber=100)(uid=t*))</code>, starting from top of <xref linkend="glo_DIT"/> having subtree scope.</para> </listitem> </orderedlist> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="unix2sql2ldap"> <title><xref linkend="glo_UNIX"/> to <xref linkend="glo_SQL"/> to <xref linkend="glo_LDAP"/></title> <para><xref linkend="glo_UNIX"/> type operating systems manage users, groups and their respective relationships in three different text files:</para> <glosslist> <glossentry> <glossterm><filename>/etc/passwd</filename></glossterm> <glossdef> <para>Users being defined on the system:</para> <literallayout>root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync ...</literallayout> <para>We illustrate the meaning of this <xref linkend="glo_CSV"/> (actually **character** separated) by examining the first row:</para> <glosslist> <glossentry> <glossterm>Column 1, <code>root</code>:</glossterm> <glossdef> <para>The user's unique system name as being entered at login.</para> </glossdef> </glossentry> <glossentry> <glossterm>Column 2, x<code>:</code></glossterm> <glossdef> <para>This field is not being used on current <xref linkend="glo_UNIX"/> implementations. Historically either the user's clear text password or its hash value was present here. For security reasons this attribute has been moved to a third file <filename>/etc/shadow</filename> being read access protected to non-administrator users.</para> </glossdef> </glossentry> <glossentry> <glossterm>Column 3, <code>0</code>:</glossterm> <glossdef> <para>The user's unique integer numerical <parameter>uid</parameter> number value.</para> </glossdef> </glossentry> <glossentry> <glossterm>Column 4, <code>0</code>:</glossterm> <glossdef> <para>The user's unique primary group integer numerical <parameter>gid</parameter> number value. The value <quote>0</quote> here refers to a group root of identical name being defined in <filename>/etc/group</filename>, see next section.</para> </glossdef> </glossentry> <glossentry> <glossterm>Column 5, <code>root</code>:</glossterm> <glossdef> <para>The user's common name. For a regular user account this might be <quote>Jim Beam</quote> for example.</para> </glossdef> </glossentry> <glossentry> <glossterm>Column 6, <filename>/root</filename>:</glossterm> <glossdef> <para>The user's home directory. Might be /home/beam for a user <quote>Jim Beam</quote>.</para> </glossdef> </glossentry> <glossentry> <glossterm>Column 7, <command>/bin/bash</command>:</glossterm> <glossdef> <para>The user's login shell (command interpreter. This attribute contains a reference to a command interpreter like <command>/bin/(t)csh</command>, <command>/bin/ksh</command> and so on.</para> </glossdef> </glossentry> </glosslist> </glossdef> </glossentry> <glossentry> <glossterm><filename>/etc/group</filename></glossterm> <glossdef> <para>This file contains all groups being defined on the system:</para> <literallayout>root:x:0: daemon:x:1: bin:x:2: sys:x:3: adm:x:4:syslog,mi <co xml:id="secondaryGroupmembership"/> tty:x:5: ...</literallayout> <glosslist> <glossentry> <glossterm>Column1,root:</glossterm> <glossdef> <para>The group's name</para> </glossdef> </glossentry> <glossentry> <glossterm>Column 2, x:</glossterm> <glossdef> <para>Not used</para> </glossdef> </glossentry> <glossentry> <glossterm>Column 3, 4:</glossterm> <glossdef> <para>The group's unique <parameter>gid</parameter> number</para> </glossdef> </glossentry> <glossentry> <glossterm>Column 4, <code>syslog,mi</code>:</glossterm> <glossdef> <para>The set <code>{syslog,mi}</code> <coref linkend="secondaryGroupmembership"/> defines secondary group memberships: These two users will belong to the group <code>adm</code> in addition to their respective primary group definition.</para> </glossdef> </glossentry> </glosslist> </glossdef> </glossentry> </glosslist> <qandaset defaultlabel="qanda" xml:id="qandUnixToSqlToLdap"> <title>Exporting and importing data</title> <qandadiv> <qandaentry> <question> <para>Write two applications being able to perform the following tasks:</para> <orderedlist> <listitem> <para>Import the previously described UNIX user and group data ton an RDBMS using <xref linkend="glo_JDBC"/>. You will have to define a suitable SQL schema first.</para> </listitem> <listitem> <para>Transfer RDBMS data to your local <xref linkend="glo_LDAP"/> server using <link xlink:href="https://docs.oracle.com/javase/jndi/tutorial/ldap/misc/url.html">JNDI</link>.</para> </listitem> </orderedlist> </question> <answer> <annotation role="make"> <para role="eclipse">Sda2/UnixSqlLdap/Jndi/Unix2Rdbms</para> </annotation> <annotation role="make"> <para role="eclipse">Sda2/UnixSqlLdap/Jndi/Rdbms2Ldap</para> </annotation> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="transactionsInJdbc"> <title>Transactions in <xref linkend="glo_JDBC"/></title> <para>You may review some remarks on SQL standard isolation level definitions:</para> <itemizedlist> <listitem> <para><xref linkend="glo_Javadoc"/>:</para> <itemizedlist> <listitem> <para><link xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html#TRANSACTION_READ_UNCOMMITTED">TRANSACTION_READ_UNCOMMITTED</link></para> </listitem> <listitem> <para><link xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html#TRANSACTION_READ_COMMITTED">TRANSACTION_READ_COMMITTED</link></para> </listitem> <listitem> <para><link xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html#TRANSACTION_REPEATABLE_READ">TRANSACTION_READ_REPEATABLE_READ</link></para> </listitem> <listitem> <para><link xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html#TRANSACTION_SERIALIZABLE">TRANSACTION_READ_SERIALIZABLE</link></para> </listitem> </itemizedlist> </listitem> <listitem> <para><link xlink:href="http://www.oracle.com/technetwork/issue-archive/2005/05-nov/o65asktom-082389.html">On Transaction Isolation Levels (Oracle)</link></para> </listitem> <listitem> <para><link xlink:href="https://technet.microsoft.com/en-us/library/ms378149(v=sql.110).aspx">Understanding Isolation Levels (Microsoft)</link></para> </listitem> </itemizedlist> <section xml:id="accountTransferPessimistic"> <title>Account Transfer using pessimistic concurrency control</title> <qandaset defaultlabel="qanda" xml:id="qandaJdbcIsolation"> <title>Accounts and balances</title> <qandadiv> <qandaentry> <question> <para>Consider the following simple schema of accounts keeping customer balances:</para> <programlisting language="sql">CREATE TABLE Account ( number INT NOT NULL PRIMARY KEY ,balance INT NOT NULL )</programlisting> <para>Write two GUI applications to:</para> <itemizedlist> <listitem> <para>Transfer amounts from one account to another</para> </listitem> <listitem> <para>Get the sum of all balances</para> </listitem> </itemizedlist> <informalfigure> <mediaobject> <imageobject> <imagedata fileref="Ref/Screen/accountTransferSum.png"/> </imageobject> </mediaobject> </informalfigure> </question> <answer> <annotation role="make"> <para role="eclipse">Sda2/account</para> </annotation> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="accountTransferOptimistic"> <title>Account Transfer using optimistic concurrency control</title> <figure xml:id="fig_optimisticConcurrencyControl"> <title>Optimistic concurrency control</title> <mediaobject> <imageobject> <imagedata fileref="Ref/Fig/concurrentOptimistic.svg"/> </imageobject> </mediaobject> </figure> <para>An interfering transaction obeying the protocol causes a transaction failure:</para> <figure xml:id="concurrentObtimisticFail"> <title>Failure with optimistic transactions</title> <mediaobject> <imageobject> <imagedata fileref="Ref/Fig/concurrentOptimisticFail.svg"/> </imageobject> </mediaobject> </figure> <para>Considerations:</para> <itemizedlist> <listitem> <para>Race conditions, time of check to time of use</para> </listitem> </itemizedlist> <qandaset defaultlabel="qanda" xml:id="qandaTransferOptimistic"> <title>Optimistic account transfer</title> <qandadiv> <qandaentry> <question> <para>Implement your (pessimistic) account transfer application <xref linkend="qandaJdbcIsolation"/> in an optimistic manner:</para> <itemizedlist> <listitem> <para>Make sure both source and destination accounts get protected against interfering transactions.</para> </listitem> <listitem> <para>Provide a means to definitely avoid deadlocks during the second transaction section of a balance transfer operation.</para> </listitem> <listitem> <para>Supply a suitable message in case of an interfering second balance transfer</para> </listitem> </itemizedlist> </question> </qandaentry> </qandadiv> </qandaset> </section> </section> </chapter>