Tivoli Directory Server is an LDAP V3-based directory server used to create directory services. A directory service is an application that stores, retrieves, and modifies information about network resources. LDAP, a lightweight protocol for accessing directory services, is based on entries. An entry is a set of attributes identified by a globally unique distinguished name (DN). Each directory entry attribute has a type and one or more values. In this article, learn how to use the Net::LDAP library to create an LDAP directory service in the Tivoli Directory Server V6.0 directory server. Walk through an example to create a Ruby on Rails application using Tivoli Directory Server V6.0 as a back-end database.
Prerequisites and system requirements
A basic understanding of LDAP and scripting languages is required. This article is primarily for those who know a bit about LDAP and have a need to write a directory service using the Ruby scripting language. To do the examples in this article, the Tivoli Directory Server V6.0 must be installed. Download the example LDAP application for this article.
Ruby on Rails is an open source Web framework for developing Web applications based on a database. Ruby on Rails provides ease of development, support for Ajax, and a Model-View-Controller (MVC) framework. Ruby is an interpreted object-oriented scripting language. Interpretive implies that a Ruby application is run without first compiling the application. Variables in Ruby do not have a type; a Ruby variable may contain data of any type. Variables in Ruby do not require variable declarations. Ruby, being an object-oriented language, has features like classes, methods, and inheritance.
To develop a Ruby on Rails application, a Web server and a database are required. Rails includes a built-in Web server called WEBrick. Rails is configured with the MySQL database by default. Rails is a combination of the following subprojects.
- Model — Active Record
- Models model business objects in an MVC application. In Rails, models are typically based on the Active Record pattern, which provides object-relational mapping (ORM) between business objects and a database.
- View — Action View
- Views are the user interfaces of a Ruby on Rails Web application. A view is rendered using RHTML or RXML. RHTML is Ruby embedded HTML, and RXML is Ruby-generated XML. A view contains links to methods (actions) defined in the controller with which controller actions are invoked.
- Controller — Action Controller
- The controller sets instance variables required by a view and renders a view.
The controller is a class that extends the
ApplicationControllerclass and consists of actions (methods). A controller integrates the model with the view using public methods (actions).
The model provides the data, the controller provides business logic to process the data, and the view presents the data.
An MVC Rails application consists of the following Ruby, RHTML, and configuration files:
- View templates (.rhtml files) in the app/views directory
- Model class in the app/models directory
- Controller class in the app/controllers directory
- Database Configuration file (database.yml) in the config directory
Ruby on Rails provides commands for generating model and controller scripts. Some of the commonly used Ruby on Rails commands are shown below.
Table 1. Common Ruby on Rails commands
| Command (variables in italics) | Description |
|---|---|
rails applicationname | Creates a Rails application of the specified name |
ruby script/server | Starts Ruby Rails Web server WEBrick at http://localhost:3000 |
ruby script/generate model modelname | Generates a model class of specified model name |
ruby script/generate controller controllername ... | Generates a controller class of specified name and generates the controller actions if specified; view templates (.rhtml files) corresponding to controller actions also get generated |
Ruby on Rails provides various Ruby libraries for developing LDAP applications. For example:
- Ruby/ActiveLDAP provides an object-oriented interface to LDAP with LDAP entries mapped to Ruby objects.
- Net::LDAP is an LDAP support Ruby library, and supports LDAP client features.
In this article, you learn to use the Net::LDAP library to create a directory service in the Tivoli Directory Server V6.0 directory server. You will add, modify, search, and delete a directory entry with the Net::LDAP Ruby library.
This section shows how to install Ruby, the Rails framework, and RubyGems. RubyGems is the standard Ruby package manager used with Ruby applications and libraries. You'll also install Net::LDAP, the Ruby class library for LDAP. The example application uses the Windows® platform. The order of installation is to first install Ruby, then Rails, then Net::LDAP.
To install the latest version of Ruby and RubyGems:
- Download the Ruby Windows Installer application. Ruby V1.8.5-21 was used to develop the example directory service application in this article.
- Double-click the ruby185-21.exe application. The Ruby Setup Wizard will start.
- Click Next and accept the license agreement. Select the default components to install, which include the RubyGems package manager, and click Next.
- Specify a directory to install Ruby (default is c:/ruby) and click Next.
- Click Install. Ruby and RubyGems will be installed.
Install Rails:
- Change directory (
Cd) to the c:/ruby directory in which Ruby is installed. - Run the following command to install Rails and dependencies:
c:/ruby>gem install rails --include-dependencies.
Install the ruby-net-ldap gem with:
C:/ruby>gem install ruby-net-ldap |
The Net::LDAP class provides a Ruby implementation of the LDAP client protocol. The Net::LDAP class is used for bind, search, add, modify, delete, and rename operations. The Net::LDAP class methods are described in Table 2.
Table 2. Net::LDAP class methods
| Method | Description |
|---|---|
add(args) | Adds a new directory entry. Arguments are:
|
add_attribute(dn, attribute, value) | Adds a value to an attribute. If the specified attribute is not already defined, creates a new attribute. |
authenticate(username, password) | Specifies the authentication credentials to the LDAP server. |
bind(auth=@auth) | Connects to the LDAP server and requests authentication based on the authentication credentials specified in the open or new method. Returns true if a connection with the LDAP server is established. |
bind_as(args={}) | Binds as a specified user. |
delete(args) | Deletes a directory entry for a specified DN, which is the only supported argument. |
delete_attribute(dn, attribute) | Deletes an attribute and all its values. The dn parameter specifies the directory entry and the attribute specifies the attribute to delete. |
get_operation_result() | Returns an operation result code and message for the bind, search, add, modify, rename, and delete operations. |
modify(args) | Modifies the attribute values for a specified directory entry. Takes the
following arguments as a hash:
|
new(args = {}) | Creates an object of type Net::LDAP, but does not open a connection with the server. The arguments may be:
|
In this section, you create a Rails application to create a directory service with the Net::LDAP Ruby library.
Use the rails command to create a rails application called
netldap:
c:/ruby>rails netldap |
A Rails application with the complete directory structure of the Rails application gets created. You will run the Net::LDAP Ruby on Rails application as a controller script with controller actions for creating a directory entry, modifying a directory entry, searching a directory entry, and deleting a directory entry. You'll also create RHTML view templates corresponding to each of these controller actions to input data for the directory entries.
Create a controller script called directory that consists of controller actions
add_entry, modify_entry,
search_entry, and delete_entry:
C:/ruby/netldap>ruby script/generate controller directory add_entry modify_entry search_entry delete_entry |
A controller script called directory_controller.rb
gets created in the controllers directory. The controller script consists of controller actions add_entry, modify_entry, search_entry, and delete_entry. View templates add_entry.rhtml, modify_entry.rhtml, search_entry.rhtml, and delete_entry.rhtml get created in the views folder.
In the following sections, you modify the controller actions and view templates to add a directory entry, modify a directory entry, search a directory entry, and delete a directory entry.
The next step is to create a directory entry in the Tivoli Directory Server. A
directory entry consists of attributes and attribute values. The DN of a directory entry represents the distinguished name for the
directory entry. A DN consists of the relative
distinguished name and the base DN. For the example, you create a directory
entry in the cn=localhost root/base DN.
Start the Tivoli Directory Server instance if it is not already started.
Each directory entry is identified with a dn attribute. The
objectClass attributes specify the type of data, and
required and optional attributes in an entry. Object classes form a class hierarchy;
some of the commonly used object classes are top, organization, and organizationalPerson.
All object classes are subclasses of the object class top.
You will create a directory service with the top, person, and organizationalPerson object classes:
-
topdoes not have any required attributes. -
personhas the required attributescnandsn. -
organizationalPersondoes not have any required attributes. Some of the attributes that may be specified in a directory entry of object classorganizationalPersonare title and telephoneNumber.
Modify the add_entry.rhtml view template
to input data for the directory entry. Define a form with the form_tag method of the FormTagHelper class. Define a field in the form with the text_field(object_name, method, options = {}) method. Method parameter object represents an object for the form template. The method parameter represents a form field as an attribute of the form object. For example, the following text field:
text_field("directory_entry", "title", "size" => 20)
|
converts to HTML form text field:
<input type="text" id="directory_entry_title" name="directory_entry[title]" size="20"
value="#{@directory_entry.title}" />
|
Add text fields for first name, last name, title, telephone number, department, and fax number to the add_entry.rhtml.
| Text field | Attribute |
|---|---|
| First name | gn |
| Last name | sn |
| Title | title |
| Telephone number | telephoneNumber |
| Department | physicalDeliveryOfficeName |
| FAX number | facsimileTelephoneNumber |
Listing 1 shows the add_entry.rhtml.
Listing 1. add_entry.rhtml
<html>
<body>
<div>
<table border='0' cellspacing='0' cellpadding='5'>
<tr>
<caption>
Add Directory Entry
</caption>
</tr>
<!-- start_form_tag -->
<%= form_tag :action => "add_entry" %>
<tr>
<td>First Name*</td>
<td><%= text_field(:add_entry, :gn) %></td>
</tr><tr>
<td>Last Name*</td>
<td><%= text_field(:add_entry, :sn) %></td>
</tr>
<tr>
<td>Title</td>
<td><%= text_field(:add_entry, :title) %></td>
</tr><tr>
<td>Telephone Number</td>
<td><%= text_field(:add_entry, :telephoneNumber) %></td>
</tr>
<tr>
<td>Department</td>
<td><%= text_field(:add_entry, :physicalDeliveryOfficeName) %></td>
</tr>
<tr>
<td>Fax Number</td>
<td><%= text_field(:add_entry, :facsimileTelephoneNumber) %></td>
</tr>
<tr>
<td><input type="submit" value="Submit"></td>
</tr>
<%= end_form_tag %>
</table>
</div>
* indicates a required field.
</body>
</html>
|
Modify the controller action add_entry and retrieve the parameter values. Retrieve the first name (:gn) and the last name (:sn) and define a variable cn.
values = params[:add_entry]
gn=values[:gn]
sn= values[:sn]
cn=gn+sn
|
Define the distinguished name for the directory entry, dn, which consists of the rdn and the base DN.
dn="cn="+cn+",cn=localhost" |
Retrieve values for the other form fields.
title=values[:title] telephoneNumber=values[:telephoneNumber] physicalDeliveryOfficeName=values[:physicalDeliveryOfficeName] facsimileTelephoneNumber=values[:facsimileTelephoneNumber] |
Define a variable, attr, that consists of the different attributes of the directory entry.
attr = {
:cn => cn,
:objectclass => ['top', 'person', 'organizationalPerson'],
:sn => sn,
:title => title,
:telephoneNumber => telephoneNumber,
:physicalDeliveryOfficeName => physicalDeliveryOfficeName,
:facsimileTelephoneNumber => facsimileTelephoneNumber
}
|
Open a connection to the Tivoli Directory Server and add the directory entry to the server using the add() method.
Net::LDAP.open( :host => 'localhost', :port => 389,:base =>
'cn=localhost', :auth => { :method => :simple, :username => 'cn=root', |
Create a directory entry with the add_entry.rhtml template. Start the WEBrick server with the following command:
C:/ruby/netldap>ruby script/server |
Invoke the add_entry.rhtml view template with the URL http://localhost:3000/directory/add_entry.rhtml. Specify the values for the different attributes and click Submit, as shown below.
Figure 1. Adding a directory entry
A directory entry gets created in the cn=localhost directory
entry in the Tivoli Directory Server instance. Select the cn=localhost directory entry in the Web Administration Tool and
click Expand, as shown below.
Figure 2. Listing directory entries for
cn=localhost
The directory that was added using Ruby on Rails is listed in the directory entries in
the cn=localhost directory entry. To list the attributes of the directory entry, select the directory entry and click Edit attributes.
Figure 3. Listing attributes for the directory entry added
The attributes of the directory entry you added are displayed.
Figure 4. Displaying attributes for the directory entry
In this section, you modify a directory entry. The data to be modified is input in the
modify_entry.rhtml. Similar to adding an entry, you add a form to the
modify_entry.rhtml view template with the form_tag method
of the FormTagHelper class. Add form fields with the text_field method of the FormHelper class.
Listing 2 shows the modify_entry.rhtml view template.
Listing 2. modify_entry.rhtml
<html>
<body>
<div>
<table border='0' cellspacing='0' cellpadding='5'>
<tr>
<caption>
Modify Directory Entry
</caption>
</tr>
<!-- start_form_tag -->
<%= form_tag :action => "modify_entry" %>
<tr>
<td>First Name*</td>
<td><%= text_field(:modify_entry, :gn) %></td>
</tr><tr>
<td>Last Name*</td>
<td><%= text_field(:modify_entry, :sn) %></td>
</tr>
<tr>
<td>Title</td>
<td><%= text_field(:modify_entry, :title) %></td>
</tr><tr>
<td>Telephone Number</td>
<td><%= text_field(:modify_entry, :telephoneNumber) %></td>
</tr>
<tr>
<td>Department</td>
<td><%= text_field(:modify_entry, :physicalDeliveryOfficeName) %></td>
</tr>
<tr>
<td>Fax Number</td>
<td><%= text_field(:modify_entry, :facsimileTelephoneNumber) %></td>
</tr>
<tr>
<td><input type="submit" value="Submit"></td>
</tr>
<%= end_form_tag %>
</table>
</div>
* indicates a required field.
</body>
</html>
|
When the modify_entry.rhtml template is submitted, the modify_entry controller action of the controller directory gets invoked. Modify the modify_entry controller action.
Retrieve the values for the form fields :gn and :sn, and define a variable cn.
values = params[:modify_entry]
gn=values[:gn]
sn= values[:sn]
cn=gn+sn
|
A directory entry is identified with a distinguished name. Define the DN of the directory entry to modify.
dn="cn="+cn+",cn=localhost" |
Retrieve the values of the other form fields.
title=values[:title] telephoneNumber=values[:telephoneNumber] physicalDeliveryOfficeName=values[:physicalDeliveryOfficeName] facsimileTelephoneNumber=values[:facsimileTelephoneNumber] |
Open a connection with the Tivoli Directory Server and replace the attribute values with the replace_attribute method. For example, the :title attribute is replaced as follows:
Net::LDAP.open( :host => 'localhost', :port => 389,:base =>
'cn=localhost', :auth => { :method => :simple, :username => 'cn=root', |
A directory entry is modified from the modify_entry.rhtml view template. Start the WEBrick Web server and invoke the modify_entry.rhtml view template with the URL http://localhost:3000/directory/modify_entry.rhtml. Specify the directory entry to be modified and the modified attributes. Click Submit, as shown below.
Figure 5. Modifying a directory entry
The directory entry gets modified as shown in the Web Administration Tool.
Figure 6. Modified directory entry
This section explores how to search for a directory entry. You will display the result of
the directory search on the same page where the directory entry data is input using the
Ajax Web technique. The Ajax Web technique is implemented by the prototype library.
The prototype library includes the class PrototypeHelper to create a form that may be updated asynchronously using Ajax. Include the prototype library in the search_entry.rhtml view template.
<%= javascript_include_tag "prototype" %> |
Add a form submitted using Ajax with the form_remote_tag method of the PrototypeHelper class. The :update option
of the form_remote_tag specifies the form element to be
updated with the server response. The :url option specifies the URL to which the form is submitted, and the controller action is specified with the :action parameter.
<%=form_remote_tag(:update=>"directory_entry",
:url=>{:action=>:search_entry}) %>
<% end_form_tag %>
|
Specify the directory entry input fields with the text_field_tag of the FormTagHelper class. The form element to be updated is specified as a div.
<div id="directory_entry"></div> |
The search_entry.rhtml view template is shown in Listing 3.
Listing 3. search_entry.rhtml
<html><head>
<title></title>
<%= javascript_include_tag "prototype" %>
</head>
<body>
<caption>
Search Directory Entry
</caption>
<%=form_remote_tag(:update=>"directory_entry",
:url=>{:action=>:search_entry}) %>
<table>
<tr>
<label>First Name*</label>
<%=text_field_tag:firstName %></tr>
<tr><label>Last Name</label>
<%=text_field_tag:lastName %></tr>
<%=submit_tag "Search" %>
</table>
<caption>
<b> Directory Entry Table</b>
</caption>
<div id="directory_entry"></div>
<% end_form_tag %>
* indicates a required field.
</body>
</html>
|
When the search_entry.rhtml form is submitted, the search_entry controller action of the directory controller gets
invoked. Modify the search_entry action. Retrieve the
values of the :gn and :sn fields, and define the base DN of the directory entry to search.
gn=values[:gn] sn= values[:sn] cn=gn+sn treebase= "cn="+cn+",cn=localhost" |
Specify the attributes of the directory entry to retrieve.
attrs = ["cn", "sn","title", "telephoneNumber","physicalDeliveryOfficeName", "facsimileTelephoneNumber"] |
Open a connection with the Tivoli Directory Server and search for the specified directory entry using the search method of the Net::LDAP class.
Net::LDAP.open( :host => 'localhost', :port => 389,:base =>
'cn=localhost', :auth => { :method => :simple, :username =>
'cn=root',
|
The search method returns a result set. Iterate over the
result set and create an HTML table to send as a response to the search_entry.rhtml view template. For example, a row for the cn attribute is added to the
table.
directoryEntry+="<tr>"
directoryEntry+="<td>cn</td>"
directoryEntry+="<td>"+"#{directory.cn}"+"</td>"
directoryEntry+="</tr>"
|
Invoke the search_entry.rhtml view template with the URL http://localhost:3000/directory/search_entry.rhtml to search for a directory entry. Specify the :gn and :sn attributes, which form the rdn of a directory entry, and click Search.
Figure 7. Searching for a directory entry
The directory entry attributes get listed.
Figure 8. Directory entry search result
In this section, you delete a directory entry. A directory entry is identified by a DN,
which is comprised of the rdn and the base DN. The RDN of the directory entry to be
modified is specified in the delete_entry.rhtml view template. The form_tag method is used to create a form, and the text_field tag is used to create a form text field. The
delete_entry.rhtml view template, which consists of input fields for first name and
last name, is shown below.
Listing 4. delete_entry.rhtml
<html>
<body>
<div>
<table border='0' cellspacing='0' cellpadding='5'>
<tr>
<caption>
Delete Entry
</caption>
</tr>
<!-- start_form_tag -->
<%= form_tag :action => "delete_entry" %>
<tr>
<td>First Name*</td>
<td><%= text_field(:delete_entry, :gn) %></td>
</tr><tr>
<td>Last Name*</td>
<td><%= text_field(:delete_entry, :sn) %></td>
</tr><tr>
<td><input type="submit" value="Submit"></td>
</tr>
<%= end_form_tag %>
</table>
</div>
* indicates a required field.
</body>
</html>
|
When the delete_entry.rhtml form is submitted, the delete_entry controller action of the directory controller gets invoked. The delete_entry controller action retrieves the values of the form fields and creates a DN of the directory entry to delete.
values = params[:delete_entry]
gn=values[:gn]
sn= values[:sn]
cn=gn+sn
dn="cn="+cn+",cn=localhost"
|
Open a connection with the directory server and delete the directory entry with the delete method of the Net::LDAP class.
Net::LDAP.open( :host => 'localhost', :port => 389,
:base => 'cn=localhost', :auth => { :method => :simple, :username =>
'cn=root', :password => 'tivoli' } ) do |ldap|
ldap.delete :dn => dn
end
|
To delete a directory entry, invoke the delete_entry.rhtml
view template with the URL http://localhost:3000/directory/delete_entry.rhtml. Specify the :gn (first name) and :sn (last name)
attributes of the directory entry to delete, then click Submit.
Figure 9. Deleting a directory entry
The directory entry gets deleted, as shown in the Web Administration Tool.
Figure 10. Web Administration Tool with the deleted directory entry
The directory_controller.rb controller script is shown below.
Listing 5. directory_controller.rb
require 'net/ldap'
class DirectoryController < ApplicationController
def add_entry
values = params[:add_entry]
gn=values[:gn]
sn= values[:sn]
cn=gn+sn
dn="cn="+cn+",cn=localhost"
title=values[:title]
telephoneNumber=values[:telephoneNumber]
physicalDeliveryOfficeName=values[:physicalDeliveryOfficeName]
facsimileTelephoneNumber=values[:facsimileTelephoneNumber]
attr = {
:cn => cn,
:objectclass => ['top', 'person', 'organizationalPerson'],
:sn => sn,
:title => title,
:telephoneNumber => telephoneNumber,
:physicalDeliveryOfficeName => physicalDeliveryOfficeName,
:facsimileTelephoneNumber => facsimileTelephoneNumber
}
Net::LDAP.open( :host => 'localhost', :port => 389,:base =>
'cn=localhost', :auth => { :method => :simple, :username => 'cn=root',
|
In this article, you installed Ruby on Rails and the Net::LDAP Ruby gem. You learned to create a directory entry in the Tivoli Directory Server V6.0, then modified the directory entry, searched the directory entry, and deleted the directory entry, all with the Ruby scripting language.
Ruby is comparable to PHP, the most commonly used scripting language, in its application to develop LDAP directory services. According to the TIOBE Programming Community Index, Ruby usage has increased in the past year.
| Description | Name | Size | Download method |
|---|---|---|---|
| LDAP application | os-ldap-tivoli-ruby_ldap-app.zip | 29KB | HTTP |
Information about download methods
Learn
-
"Introduction
to LDAP, Part 2: LDAP and WebSphere" explains how LDAP provides an excellent authentication mechanism for your WebSphere Application Server.
-
Get an overview of the
Tivoli Directory Server, and learn about the features, benefits, system requirements,
product support, and more.
-
Learn about and download
Ruby on Rails, the open source Web framework optimized for programmer happiness
and sustainable productivity.
-
"An introduction to Ruby on Rails for DB2 developers" explains how to speed your development of DB2-based Web applications using the Ruby on Rails Web framework.
-
Check out the TIOBE Programming
Community Index to see how Ruby usage has increased in the past year.
-
"Fast-track your Web apps with Ruby on Rails" introduces Ruby on Rails, details the components, and shows you how it works..
-
To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
-
Stay current with developerWorks' Technical events and webcasts.
-
Follow developerWorks on Twitter.
-
Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
-
Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
-
Innovate your next open source development project with IBM trial software, available for download or on DVD.
- Download
IBM product evaluation versions
or explore
the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from
DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
-
Participate in developerWorks blogs and get involved in the developerWorks community.
Comments (Undergoing maintenance)





