<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Red Hat Magazine &#187; technical</title>
	<atom:link href="http://magazine.redhat.com/category/technical/feed/" rel="self" type="application/rss+xml" />
	<link>http://magazine.redhat.com</link>
	<description>Just another WordPress.com weblog</description>
	<lastBuildDate>Tue, 15 Sep 2009 20:14:47 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='magazine.redhat.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/43e95982d87da9fb7c7b9a74b524335f?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Red Hat Magazine &#187; technical</title>
		<link>http://magazine.redhat.com</link>
	</image>
			<item>
		<title>Red Hat and Intel:  Smart processors, virtualization boost efficiency and performance</title>
		<link>http://magazine.redhat.com/2009/04/14/red-hat-and-intel-smart-processors-virtualization-boost-efficiency-and-performance/</link>
		<comments>http://magazine.redhat.com/2009/04/14/red-hat-and-intel-smart-processors-virtualization-boost-efficiency-and-performance/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 20:52:17 +0000</pubDate>
		<dc:creator>The editorial team</dc:creator>
				<category><![CDATA[Red Hat Enterprise Linux]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://magazine.redhat.com/?p=1400</guid>
		<description><![CDATA[On Monday March 30, Intel announced the availability of their much anticipated new line of processors, the Intel&#174; Xeon&#174; Processor 5500 series&#8211;nicknamed Nehalem. 
Red Hat, a long-time partner of the market-leading chip maker , collaborated on the chip&#8217;s debut, testing and optimizing the recently released Red Hat&#174; Enterprise Linux&#174; 5.3 on the new processor.  [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1400&subd=rhredhatmagazine&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>On Monday March 30, Intel announced the availability of their much anticipated new line of processors, the Intel&reg; Xeon&reg; Processor 5500 series&#8211;nicknamed Nehalem. </p>
<p>Red Hat, a long-time partner of the market-leading chip maker , collaborated on the chip&#8217;s debut, testing and optimizing the recently released Red Hat&reg; Enterprise Linux&reg; 5.3 on the new processor.  </p>
<p>Changes include a new processor architecture, platform architecture, memory subsystem, I/O subsystem, and options (including SSD and 10GbE).</p>
<p>So what&#8217;s the big deal?  Why all the fuss?  Here&#8217;s just a few of the improvements wrought by the combination of Intel&#8217;s processing power and Red Hat advancements in performance and efficiency.<span id="more-1400"></span></p>
<h2>Improved performance</h2>
<p>According to Stream performance data, the new Intel Xeon 5500 series processor delivers a 2.25 times performance improvement, when compared to the performance of the preceding processor series (the Intel Xeon 5400).  This allows the new processor to handle datacenter workloads at nearly twice the efficiency.</p>
<h2>Intelligent performance</h2>
<p>The processor can dynamically adapt throughput to the workload. Intel Hyper-Threading Technology lets system administrators increase workloads and add capabilities without slowing the system down—there&#8217;s plenty of reserve for usage peaks.  Expanded physical server limits in Enterprise Linux 5.3 (255 CPUs and 1 TB main memory)  improve system scalability dramatically.</p>
<h2>Virtualization</h2>
<p>Red Hat Enterprise Linux and Intel Virtualization Technology (Intel VT) deliver high consolidation ratios. These virtualization enhancements provide greater scalability and performance, and allow for the virtualization of a wide range of workloads, even those that are I/O intensive. </p>
<h2>Automated energy efficiency</h2>
<p>The combination of technologies supports low-latency changes between power states.  This can help lower power consumption during off-peak hours . Integrated power gates and memory controllers deliver energy efficiency from the hardware side, while enhanced power management and CPU clock frequency scaling help conserve power from the Red Hat Enterprise Linux side.</p>
<p>Red Hat and Intel have a long history of working together to take open source technology to its full potential. Whether it&#8217;s combined open source contributions or corporate partnerships, the x86 platform and the open source software revolution have changed the face of  computing.  Integrated virtualization—and continued rapid improvements in processor technology—keeps the changes coming.  </p>
<h2>More information</h2>
<ul>
<li><a href="http://www.press.redhat.com/2009/03/30/red-hat-and-intel-industry-leaders-redefine-datacenter-price-performance/">Red Hat and Intel: Industry Leaders Redefine Datacenter Price-Performance</a> (Red Hat Press)</li>
<li>What you <a href="http://arstechnica.com/hardware/news/2008/04/what-you-need-to-know-about-nehalem.ars">need to know about Intel&#8217;s Nehalem CPU</a> (ars technica)</li>
<li>Internet: <a href="http://www.intel.com/pressroom/archive/releases/20090330corp_sm.htm">Meet your new processor</a> (Intel.com)</li>
</ul>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rhredhatmagazine.wordpress.com/1400/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rhredhatmagazine.wordpress.com/1400/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rhredhatmagazine.wordpress.com/1400/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rhredhatmagazine.wordpress.com/1400/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rhredhatmagazine.wordpress.com/1400/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rhredhatmagazine.wordpress.com/1400/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rhredhatmagazine.wordpress.com/1400/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rhredhatmagazine.wordpress.com/1400/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rhredhatmagazine.wordpress.com/1400/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rhredhatmagazine.wordpress.com/1400/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1400&subd=rhredhatmagazine&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://magazine.redhat.com/2009/04/14/red-hat-and-intel-smart-processors-virtualization-boost-efficiency-and-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">The editorial team</media:title>
		</media:content>
	</item>
		<item>
		<title>Writing simple python setup commands</title>
		<link>http://magazine.redhat.com/2009/04/09/writing-simple-python-setup-commands/</link>
		<comments>http://magazine.redhat.com/2009/04/09/writing-simple-python-setup-commands/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 18:54:19 +0000</pubDate>
		<dc:creator>Steve &#39;Ashcrow&#39; Milner</dc:creator>
				<category><![CDATA[technical]]></category>
		<category><![CDATA[tips and tricks]]></category>

		<guid isPermaLink="false">http://magazine.redhat.com/?p=1386</guid>
		<description><![CDATA[Building software in most languages is a pain. Remember ant build.xml, maven2 pom files, and multi-level makefiles?
Python has a simple solution for building modules, applications, and extensions called distutils. Disutils comes as part of the Python distribution so there are no other packages required.
Pull down just about any python source code and you&#8217;re more than [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1386&subd=rhredhatmagazine&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Building software in most languages is a pain. Remember ant build.xml, maven2 pom files, and multi-level makefiles?</p>
<p>Python has a simple solution for building modules, applications, and extensions called <a href="http://docs.python.org/library/distutils.html">distutils</a>. Disutils comes as part of the Python distribution so there are no other packages required.</p>
<p>Pull down just about any python source code and you&#8217;re more than likely going to find a setup.py script that helps make building and installing a snap. Most engineers don&#8217;t add functionality when using distutils, instead opting to use the default commands. </p>
<p>In some cases, developers might provide secondary scripts to do other tasks for building and testing outside of the setup script, but I believe that can lead to unnecessary complication of common tasks.<span id="more-1386"></span></p>
<p>For those who are not familiar with setup scripts, Figure 1 shows a simple example.</p>
<pre>
#!/usr/bin/env python
"""
Setup script.
"""

from distutils.core import setup

setup(name = "myapp",
    version = "1.0.0",
    description = "My simple application",
    long_description = "My simple application that doesn't do anything.",
    author = "Me",
    author_email = 'me@example.dom',
    url = "http://example.dom/myapp/",
    download_url = "http://example.dom/myapp/download/",
    platforms = ['any'],

    license = "GPLv3+",

    package_dir = {'myapp': 'src/myapp'},
    packages = ['myapp'],

    classifiers = [
        'License :: OSI Approved :: GNU General Public License (GPL)',
        'Development Status :: 5 - Production/Stable',
        'Topic :: Software Development :: Libraries :: Python Modules',
        'Programming Language :: Python'],
)
</pre>
<div class="caption">Figure 1.</div>
<p>This setup script lists the metadata, maps to a package directory, and provides the general commands expected from distutils setup. This is great, but as I&#8217;ve said, it may not do everything you need it to. </p>
<p>What if, for example, we want to be able to see all the TODO tags in the codebase on any platform? In other words, grep won&#8217;t cut it. </p>
<p>Let&#8217;s start by writing a function that searches for TODO tags in files and prints them back to the screen in a nice format like:</p>
<p><code>src/myapp/__init__.py (11): TODO: remove me</code></p>
<pre>
def report_todo():
    """
    Prints out TODO's in the code.
    """
    import os
    import re

    # The format of the string to print: file_path (line_no): %s line_str
    format_str = "%s (%i): %s"
    # regex to remove whitespace in front of TODO's
    remove_front_whitespace = re.compile("^[ ]*(.*)$")

    # Look at all non pyc files from current directory down
    for rootdir in ['src/', 'bin/']:
        # walk down each root directory
        for root, dirs, files in os.walk(rootdir):
            # for each single file in the files
            for afile in files:
                # if the file doesn't end with .pyc
                if not afile.endswith('.pyc'):
                    full_path = os.path.join(root, afile)
                    fobj = open(full_path, 'r')
                    line_no = 0
                    # look at each line for TODO's
                    for line in fobj.readlines():
                        if 'todo' in line.lower():
                            nice_line = remove_front_whitespace.match(
                                line).group(1)
                            # print the info if we have a TODO
                            print(format_str % (
                                full_path, line_no, nice_line))
                        line_no += 1
</pre>
<div class="caption">Figure 2.</div>
<p>The report_todo function is self-contained and quite simple, if  a bit clunky by itself. Who wants to install and use a &#8216;report-todo&#8217; command on machines just to look for TODO tags?</p>
<p>We want to turn this into a setup command so that we can ship it with our application &#8216;myapp&#8217; to be used by developers via setup.py. We will probably add more setup commands in the future, so let&#8217;s create a class to subclass our commands from. We do this because most of our commands will probably be simple and won&#8217;t need to override the *_option methods (though they can if they need to).</p>
<pre>
import os

from distutils.core import setup, Command

class SetupBuildCommand(Command):
    """
    Master setup build command to subclass from.
    """

    user_options = []

    def initialize_options(self):
        """
        Setup the current dir.
        """
        self._dir = os.getcwd()

    def finalize_options(self):
        """
        Set final values for all the options that this command supports.
        """
        pass
</pre>
<div class="caption">Figure 3.</div>
<p>The SetupBuildCommand defines a few methods that are required for all setup commands. As I stated before, most of our commands will probably not deviate from these defaults, so defining them higher in the object hierarchy means simpler code in the commands themselves. If we do want to add arguments to to any of our commands, we can override initialize_options() and finalize_options() to handle the arguments properly.</p>
<p>Now that we have the SetupBuildCommand to subclass from we can merge our report_todo function into a SetupBuildCommand class. To do this, we create a class that subclasses SetupBuildCommand, and then add a description variable and a run method (which is what is executed when the command runs).</p>
<pre>
class TODOCommand(SetupBuildCommand):
    """
    Quick command to show code TODO's.
    """

    description = "prints out TODO's in the code"

    def run(self):
        """
        Prints out TODO's in the code.
        """
        import re

        # The format of the string to print: file_path (line_no): %s line_str
        format_str = "%s (%i): %s"
        # regex to remove whitespace in front of TODO's
        remove_front_whitespace = re.compile("^[ ]*(.*)$")

        # Look at all non pyc files in src/ and bin/
        for rootdir in ['src/', 'bin/']:
            # walk down each root directory
            for root, dirs, files in os.walk(rootdir):
                # for each single file in the files
                for afile in files:
                    # if the file doesn't end with .pyc
                    if not afile.endswith('.pyc'):
                        full_path = os.path.join(root, afile)
                        fobj = open(full_path, 'r')
                        line_no = 0
                        # look at each line for TODO's
                        for line in fobj.readlines():
                            if 'todo' in line.lower():
                                nice_line = remove_front_whitespace.match(
                                    line).group(1)
                                # print the info if we have a TODO
                                print(format_str % (
                                    full_path, line_no, nice_line))
                            line_no += 1
</pre>
<div class="caption">Figure 4.</div>
<p>The run method in this example is the same as report_todo but in a method format (with self) and renamed to run. </p>
<p>Now it&#8217;s time to bring all this together. If we add Figure 1 and Figure 2 to the setup script (Figure 1), then all that is left is to map the setup command with a command name. Do this via the cmdclass argument, and in the form:</p>
<p><code>cmdclass = {'name': CommandClass} </code></p>
<p>Figure 5 shows it all together in an abbreviated form.</p>
<pre>
#!/usr/bin/env python
"""
Setup script.
"""

import os

from distutils.core import setup, Command

class SetupBuildCommand(Command):
    """
    Master setup build command to subclass from.
    """
    # See Figure 3

class TODOCommand(SetupBuildCommand):
    """
    Quick command to show code TODO's.
    """
    # See Figure 4

setup(name = "myapp",
    version = "1.0.0",
    description = "My simple application",
    long_description = "My simple application that doesn't do anything.",
    author = "Me",
    author_email = 'me@example.dom',
    url = "http://example.dom/myapp/",
    download_url = "http://example.dom/myapp/download/",
    platforms = ['any'],

    license = "GPLv3+",

    package_dir = {'myapp': 'src/myapp'},
    packages = ['myapp'],

    classifiers = [
        'License :: OSI Approved :: GNU General Public License (GPL)',
        'Development Status :: 5 - Production/Stable',
        'Topic :: Software Development :: Libraries :: Python Modules',
        'Programming Language :: Python'],

    cmdclass = {'todo': TODOCommand},
)
</pre>
<div class="caption">Figure 5.</div>
<p>You&#8217;ll notice that `python setup.py &#8211;help-commands` now shows &#8216;Extra commands&#8217; with our TODO command listed. </p>
<p>Give it a go and see what you have left to do in your code!</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rhredhatmagazine.wordpress.com/1386/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rhredhatmagazine.wordpress.com/1386/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rhredhatmagazine.wordpress.com/1386/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rhredhatmagazine.wordpress.com/1386/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rhredhatmagazine.wordpress.com/1386/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rhredhatmagazine.wordpress.com/1386/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rhredhatmagazine.wordpress.com/1386/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rhredhatmagazine.wordpress.com/1386/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rhredhatmagazine.wordpress.com/1386/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rhredhatmagazine.wordpress.com/1386/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1386&subd=rhredhatmagazine&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://magazine.redhat.com/2009/04/09/writing-simple-python-setup-commands/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Steve &#39;Ashcrow&#39; Milner</media:title>
		</media:content>
	</item>
		<item>
		<title>Risk report: Four years of Red Hat Enterprise Linux 4</title>
		<link>http://magazine.redhat.com/2009/03/10/risk-report-four-years-of-red-hat-enterprise-linux-4/</link>
		<comments>http://magazine.redhat.com/2009/03/10/risk-report-four-years-of-red-hat-enterprise-linux-4/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 22:06:47 +0000</pubDate>
		<dc:creator>Mark Cox</dc:creator>
				<category><![CDATA[Red Hat Enterprise Linux]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[truth]]></category>

		<guid isPermaLink="false">http://magazine.redhat.com/?p=1162</guid>
		<description><![CDATA[Red Hat&#174; Enterprise Linux&#174; 4 was released on February 15th, 2005. This report takes a look at the state of security for the first four years from release.  We look at key metrics, specific vulnerabilities, and the most common ways users were affected by security issues.  We will show some best practices that [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1162&subd=rhredhatmagazine&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Red Hat&reg; Enterprise Linux&reg; 4 was released on February 15th, 2005. This report takes a look at the state of security for the first four years from release.  We look at key metrics, specific vulnerabilities, and the most common ways users were affected by security issues.  We will show some best practices that could have been used to minimise the impact of the issues, and also take a look at how the included security innovations helped. <a id="more-98"></a></p>
<p>This report is an update to the three-year risk report <a href="http://magazine.redhat.com/2008/02/26/risk-report-three-years-of-red-hat-enterprise-linux-4/">published in Red Hat Magazine in February 2007</a>.  </p>
<p><span id="more-1162"></span></p>
<dl>
<dt><span class="sect1"><a href="#intro">1. Introduction</a></span></dt>
<dt><span class="sect1"><a href="#sect1-vulnerabilities">2. Vulnerabilities</a></span></dt>
<dd>
<dl>
<dt><span class="sect2"><a href="#id1548191">2.1. Vulnerability Counts</a></span></dt>
<dt><span class="sect2"><a href="#id1548192">2.2. Critical Flaws</a></span></dt>
<dt><span class="sect2"><a href="#id1548193">2.3. Expanding &#8220;days of risk&#8221;</a></span></dt>
<dt><span class="sect2"><a href="#id1548900">2.4. Riskiest packages</a></span></dt>
<dt><span class="sect2"><a href="#id1548901">2.5. Advisory Workload</a></span></dt>
</dl>
</dd>
<dt><span class="sect1"><a href="#sect1-threats">3. Threats</a></span></dt>
<dd>
<dl>
<dt><span class="sect2"><a href="#id1549636">3.1. Exploits</a></span></dt>
<dd>
<dl>
<dt><span class="sect3"><a href="#id1549994">3.1.1. Kernel exploits</a></span></dt>
<dt><span class="sect3"><a href="#id1549680">3.1.2. Browser exploits</a></span></dt>
<dt><span class="sect3"><a href="#id1550129">3.1.3. Other user-complicit exploits</a></span></dt>
<dt><span class="sect3"><a href="#id1550273">3.1.4. PHP exploits</a></span></dt>
<dt><span class="sect3"><a href="#id1550274">3.1.4. Servers and services exploits</a></span></dt>
</dl>
</dd>
<dt><span class="sect2"><a href="#id1550537">3.2. Worms</a></span></dt>
</dl>
</dd>
<dt><span class="sect1"><a href="#sect1-conclusion">4. Conclusion</a></span></dt>
<dt><span class="sect1"><a href="#sect1-furtherreading">5. Further Reading</a></span></dt>
<dt><span class="sect1"><a href="#sect1-author">6. About the Author</a></span></dt>
</dl>
<p><a name="intro"></a></p>
<h2>1. Introduction</h2>
<p>We measure the overall risk of running Enterprise Linux 4 as a function of two factors; the vulnerabilities and the threats.  Our first section covers the security vulnerabilities found in packages that are part of Enterprise Linux 4 and the advisories that address them.  Our second section covers the threats by examining actual exploitation of those vulnerabilities through exploits and worms.</p>
<p>All the data used to generate this report, tables, and graphs, apply to Red Hat Enterprise Linux 4 AS from release day, 15 February 2005 to 14 February 2009 unless otherwise stated.</p>
<p><a name="sect1-vulnerabilities"></a></p>
<h2>2. Vulnerabilities</h2>
<p>At first sight it may appear that Red Hat have released a lot of updates for Enterprise Linux 4; in the last twelve months publishing a total of 107 <a href="http://rhn.redhat.com/errata/rhel4as-errata-security.html">security advisories</a> to address 251 individual vulnerabilities.  But in reality this is by far a worst-case metric, as it treats all vulnerabilities as equal, regardless of their severity and assumes a system that has installed every available package &#8211; which is not a default or even a likely installation.</p>
<p>With the release of Enterprise Linux 4, we started publishing severity levels with package errata to help users determine which advisories were the ones that mattered the most.  Providing a prioritised risk assessment helps customers to understand and better schedule upgrades to their systems, being able to make a more informed decision on the risk that each issue places on their unique environment.  Red Hat rates the impact of individual vulnerabilities on a <a href="http://www.redhat.com/security/updates/classification/">four-point scale</a> designed to be an at-a-glance guide to how worried Red Hat is about each security issue. </p>
<p><a name="id1548191"></a></p>
<h3>2.1. Vulnerability Counts</h3>
<p>There are four variants of Red Hat Enterprise Linux 4; two targeted at server solutions with Enterprise Linux AS and ES, and two targeted at client solutions with Enterprise Linux WS and Red Hat Desktop. The package set available in Enterprise Linux WS and Red Hat Desktop is a subset of that available in Enterprise Linux AS.</p>
<p>During Enterprise Linux 4 installation, the user <a href="http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/x8664-multi-install-guide/s1-pkgselection.html">gets a choice</a> of installing either the default selection of packages, or making a custom selection.  Table 2 shows the vulnerability counts, normalised by CVE name, for some selected configurations.</p>
<p><a name="tb-vulncount"></a></p>
<table summary="Number of vulnerabilities for each severity" border="1">
<thead>
<tr>
<th>Severity</th>
<th>Enterprise Linux 4 AS<br />default install</th>
<th>Enterprise Linux 4 WS<br />default install</th>
<th>Enterprise&nbsp;Linux&nbsp;4&nbsp;AS<br />all possible packages</th>
</tr>
</thead>
<tbody>
<tr>
<td>Critical</td>
<td>10</td>
<td>126</td>
<td>130</td>
</tr>
<tr>
<td>Important</td>
<td>267</td>
<td>320</td>
<td>360</td>
</tr>
<tr>
<td>Moderate</td>
<td>211</td>
<td>350</td>
<td>484</td>
</tr>
<tr>
<td>Low</td>
<td>151</td>
<td>184</td>
<td>295</td>
</tr>
<tr>
<td>Total</td>
<td>639</td>
<td>980</td>
<td>1269</td>
</tr>
</tbody>
</table>
<div class="caption">Table 2. Vulnerabilities by severity, 4 years</div>
<p>A default install of Enterprise Linux 4 AS was only vulnerable to ten critical flaws in the whole four years.  This is because most of the critical flaws have been in web browsers and their plug-ins: Firefox and Mozilla/SeaMonkey packages are not installed by default on distributions intended for server systems.</p>
<p>Client systems (Enterprise Linux WS and Red Hat Desktop) do include Firefox, Mozilla, and Helixplayer by default, leading to 126 critical vulnerabilities.  A custom installation of AS, selecting every available package, would yield a system affected by the maximum possible number of critical vulnerabilities for the four years, 130.</p>
<p>For the purposes of this study we consider the worst-case scenario, a version of Red Hat Enterprise Linux 4 obtained on the day of release.  During the first four years, six Update releases were made (Update 1 in June 2005, Update 2 in October 2005, Update 3 in March 2006, Update 4 in August 2006, Update 5 in May 2007, Update 6 in November 2007, Update 7 in July 2008).  The Update releases are similar to a &#8220;service pack&#8221; and contain a roll-up of all security advisories. So, for example, a user who installed Enterprise Linux 4 in August 2008 would use Update 7 and be affected by only a subset of the issues. We&#8217;ve also counted vulnerabilities not advisories; it&#8217;s usual for a single security update of a package to fix a number of vulnerabilities at the same time, so the number of advisories and updates needed to be installed is far lower.</p>
<dl class="adtip">
<dt>Tip</dt>
<dd>You can cut down the number of security issues you need to deal with by carefully choosing the right Enterprise Linux variant and package set when deploying a new system, and ensuring you install the latest<br />
available Update release.</dd>
</dl>
<p><a name="id1548192"></a></p>
<h3>2.2. Critical Flaws</h3>
<p>Vulnerabilities rated critical severity are the ones that can pose the most risk to an organisation.  By definition, a critical vulnerability is one that could potentially be exploited remotely and automatically by a worm.  However we also stretch the definition to include those flaws that affect web browsers or plug-ins where a user only needs to visit a malicious (or compromised) web site in order to be exploited.  Since the vast majority of critical severity issues occurred due to web browsers or plugins, this is why there is such a difference between the number of critical issues that affects a default install of Enterprise Linux 4 AS and WS.</p>
<p>For the purposes of the severity classification we ignore what privileges the attacker would be able to gain: a remote root compromise via something like Samba would be of a much higher risk than a user-complicit Firefox flaw that results in running code as an unprivileged user, but both would be rated as critical on this scale.</p>
<p>To help qualify the risk we&#8217;ve split up the critical vulnerabilities into those that require some minimal user interaction to be exploitable (such as if a user visits malicious web page), and those that require no user interaction at all (and therefore could potentially be exploited by a worm).</p>
<p>For Enterprise Linux 4 AS with every package installed,  Table 3 summarises all critical issues, and Table 4 breaks out the critical, non-browser flaws.</p>
<p><a name="tb-critical3"></a></p>
<table summary="All critical flaws" border="1">
<thead>
<tr>
<th>Type</th>
<th>Number of flaws</th>
<th>&#8220;Days of Risk&#8221;</th>
<th>Fix within one day</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mozilla products (Firefox, Mozilla, SeaMonkey, Thunderbird)</td>
<td>102</td>
<td>1.7</td>
<td>88%</td>
</tr>
<tr>
<td>Media Player Plugin (HelixPlayer)</td>
<td>7</td>
<td>1.4</td>
<td>85%</td>
</tr>
<tr>
<td>Other browsers (Lynx, Links, KDE, QT)</td>
<td>5</td>
<td>1.2</td>
<td>80%</td>
</tr>
<tr>
<td>Non-Browser (see Table 4)</td>
<td>16</td>
<td>0.6</td>
<td>94%</td>
</tr>
<tr>
<td>Total</td>
<td>130</td>
<td>1.6</td>
<td>87%</td>
</tr>
</tbody>
</table>
<div class="caption">Table 3. All critical flaws</div>
<p><a name="tb-critical2"></a></p>
<table summary="Non-browser critical flaws" border="1">
<thead>
<tr>
<th>Package affected</th>
<th>Default Installed?</th>
<th>References</th>
<th>Description</th>
<th>&#8220;Days of Risk&#8221;</th>
</tr>
</thead>
<tbody>
<tr>
<td>openssh</td>
<td>Yes</td>
<td>
<a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-3844">CVE-2008-3844</a></p>
<p><a href="http://rhn.redhat.com/errata/RHSA-2008-0855.html">RHSA-2008:0855</a>
</td>
<td>
Mitigate an intrusion into certain Red Hat computers where a small number of signed tampered packages were created but not distributed on Red Hat Network. Classified critical to ensure any tampered packages would be<br />
replaced with official ones.
</td>
<td>0</td>
</tr>
<tr>
<td>samba</td>
<td>Yes</td>
<td>
<a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-1105">CVE-2008-1105</a></p>
<p><a href="http://rhn.redhat.com/errata/RHSA-2008-0288.html">RHSA-2008:0288</a>
</td>
<td>
Heap-based buffer overflow handling over-sized packets.
</td>
<td>0</td>
</tr>
<tr>
<td>krb5</td>
<td>Yes</td>
<td>
<a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-0062">CVE-2008-0062</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2008-0180.html">RHSA-2008:0180</a></td>
<td>
Use of an uninitialized pointer.
</td>
<td>0</td>
</tr>
<tr>
<td>samba</td>
<td>Yes</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-6015">CVE-2007-6015</a></p>
<p><a href="http://rhn.redhat.com/errata/RHSA-2007-1114.html">RHSA-2007:1114</a></td>
<td>Stack-based buffer overflow if the &#8220;domain logons&#8221; option is enabled.</td>
<td>0</td>
</tr>
<tr>
<td>samba</td>
<td>Yes</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-5398">CVE-2007-5398</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2007-1016.html">RHSA-2007:1016</a></td>
<td>Stack-based buffer overflow if operating as a WINS server.</td>
<td>0</td>
</tr>
<tr>
<td>samba</td>
<td>Yes</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-2446">CVE-2007-2446</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2007-0354.html">RHSA-2007:0354 </a></td>
<td>Heap-based buffer overflows.</td>
<td>0</td>
</tr>
<tr>
<td>krb5</td>
<td>Yes</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-0956">CVE-2007-0956</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2007-0095.html">RHSA-2007:0095 </a></td>
<td>Authentication bypass is the krb5 telnet daemon is enabled</td>
<td>0</td>
</tr>
<tr>
<td>sendmail</td>
<td>Yes</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-0058">CVE-2006-0058</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2006-0264.html">RHSA-2006:0264</a></td>
<td>Race condition in the handling of asynchronous signals.</td>
<td>0</td>
</tr>
<tr>
<td>kopete</td>
<td>Yes</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-1852">CVE-2005-1852</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2005-639.html">RHSA-2005:639</a></td>
<td>Integer overflow triggered by a malicious message on the Gadu-Gadu network</td>
<td>1</td>
</tr>
<tr>
<td>evolution</td>
<td>No</td>
<td>
<a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-1108">CVE-2008-1108</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2008-0516.html">RHSA-2008:0516</a>
</td>
<td>
Stack-based buffer overflow handling iCalendar attachments if the Itip formatter plugin is disabled.</p>
</td>
<td>0</td>
</tr>
<tr>
<td>evolution</td>
<td>No</td>
<td>
<a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-0072">CVE-2008-0072</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2008-0177.html">RHSA-2008:0177</a>
</td>
<td>
Format string vulnerability in Evolution triggered by receiving a malicious message
</td>
<td>0</td>
</tr>
<tr>
<td>tog-pegasus</td>
<td>No</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-0003">CVE-2008-0003</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2008-0002.html">RHSA-2008:0002 </a></td>
<td>Stack-based buffer overflow in the OpenPegasus CIM management server.</td>
<td>0</td>
</tr>
<tr>
<td>gnomemeeting</td>
<td>No</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-1007">CVE-2007-1007</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2007-0086.html">RHSA-2007:0086 </a></td>
<td>Format string vulnerability</td>
<td>7</td>
</tr>
<tr>
<td>mod_auth_pgsql</td>
<td>No</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-3656">CVE-2005-3656</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2006-0164.html">RHSA-2006:0164</a></td>
<td>Several format string vulnerability if mod_auth_pgsql is used for user authentication.</td>
<td>0</td>
</tr>
<tr>
<td>gaim</td>
<td>No</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-2103">CVE-2005-2103</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2005-627.html">RHSA-2005:627</a></td>
<td>Buffer overflow triggered by a malicious away message on the AIM or ICQ networks.</td>
<td>2</td>
</tr>
<tr>
<td>gaim</td>
<td>No</td>
<td><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-1261">CVE-2005-1261</a><br />
<a href="http://rhn.redhat.com/errata/RHSA-2005-429.html">RHSA-2005:429</a></td>
<td>
Buffer overflow triggered by a malicious URL</td>
<td>0</td>
</tr>
</tbody>
</table>
<div class="caption">Table 4. Non-browser critical flaws</div>
<p><a name="tb-critical"></a></p>
<p>We&#8217;ve included in these tables the &#8220;days of risk&#8221; metric.  This is commonly defined as the number of calendar days it takes for a vendor to produce updates that correct a flaw after the flaw is first known to the public.</p>
<p>Fixes for 87% of critical flaws were available from Red Hat Network the same day or next calendar day after public disclosure of the flaw.  This fast response time is a deliberate goal of the Red Hat Security Response Team and forms an essential part of reducing customer risk from critical flaws.</p>
<p><a name="id1548193"></a></p>
<h3>2.3. Expanding &#8220;days of risk&#8221;</h3>
<p>The &#8220;days of risk&#8221; metric has it&#8217;s limitations and so it isn&#8217;t particularly useful for comparing different software vendors against each other.  The software that makes up the Enterprise Linux 4 distribution is open source, so we&#8217;re not the only vendor shipping each particular application.  Unlike companies shipping proprietary software, Red Hat is not in sole control over the date each flaw is made public.  This is actually a good thing and leads to much shorter response times between flaws being first reported to being made public.  It also keeps us honest; Red Hat can&#8217;t play games to artificially reduce our #8220;days of risk&#8221; statistics by using tactics such as holding off public disclosure of important flaws for a long period, or until some regularly scheduled patch day.</p>
<p>A more useful metric to help assess risk would also take into account the amount of time that each issue was known to the vendor in advance.  As part of our security measurement work since Enterprise Linux 4 we&#8217;ve been tracking how the Red Hat Security Response Team first found out about each vulnerability we fix. This information is interesting as it can also show us which relationships matter the most to us, and identify trends in vulnerability disclosure.</p>
<p>For each of the 1269 total vulnerabilities, across every package in Enterprise Linux in the 4 years, we determined if the flaw was something we knew about a day or more in advance of it being publicly disclosed, and how we found out <sup>[<a name="id1548910" href="#ftn.id1548910">1</a>]</sup> about the flaw.  The results are summarised in Figure 2 and Figure 3.</p>
<p><a name="fig-infoadvance"></a><br />
<a href="info-advance.gif" title="Photo Sharing"><img src="http://www.awe.com/mark/talks/20090310-info-advance.gif" width="460" height="191" alt="A graph showing the information sources"></a></p>
<div class="caption">Figure 2. Source of vulnerabilities known in advance</div>
<p><a name="fig-infopublic"></a><br />
<a href="info-public.gif" title="Photo Sharing"><img src="http://www.awe.com/mark/talks/20090310-info-public.gif" width="454" height="224" alt="A graph showing the information sources"></a></p>
<div class="caption">Figure 3. Source of vulnerabilities already public</div>
<p>Red Hat knew about 51% of the security vulnerabilities that we fixed at least a day in advance of them being publicly disclosed.  For those issues, the average notice was 21 calendar days, although the median was much lower, with half the private issues having advance notice of 9 days or less.  Figure 4 shows the distribution of notice periods in more detail.</p>
<p><a name="fig-infonotice"></a><br />
<a href="advance-notice.gif" title="Photo Sharing"><img src="http://www.awe.com/mark/talks/20090310-advance-notice.gif" width="488" height="240" alt="A graph showing the time Red Hat knew about issues in advance"></a></p>
<div class="caption">Figure 4. How much time in advance Red Hat knew about issues before they were publicly disclosed</div>
<p><a name="id1548900"></a></p>
<h3>2.4. Riskiest packages</h3>
<p>In our work tracking and fixing vulnerabilities it sometimes seems like we produce a security advisory for the same packages every month.  We therefore analysed Enterprise Linux 4 to find out which packages were<br />
responsible for the most vulnerabilities, weighting them <sup>[<a name="id1548911" href="#ftn.id1548911">2</a>]</sup> to take into account their severity.  The results are shown in Table 5, which lists the top 10, ranked across all four years.</p>
<p><a name="tb-worstpackages"></a></p>
<table summary="Top 10 packages with the worst Enterprise Linux 4 security history" border="1">
<thead>
<tr>
<th>Rank</th>
<th>Package</th>
<th>Critical</th>
<th>Important</th>
<th>Moderate</th>
<th>Low</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>mozilla/seamonkey</td>
<td>100</td>
<td>22</td>
<td>86</td>
<td>18</td>
</tr>
<tr>
<td>2</td>
<td>firefox</td>
<td>94</td>
<td>31</td>
<td>87</td>
<td>22</td>
</tr>
<tr>
<td>3</td>
<td>thunderbird</td>
<td>46</td>
<td>22</td>
<td>106</td>
<td>12</td>
</tr>
<tr>
<td>4</td>
<td>kernel</td>
<td>0</td>
<td>115</td>
<td>59</td>
<td>34</td>
</tr>
<tr>
<td>5</td>
<td>HelixPlayer</td>
<td>7</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>6</td>
<td>cups</td>
<td>0</td>
<td>23</td>
<td>9</td>
<td>1</td>
</tr>
<tr>
<td>7</td>
<td>samba</td>
<td>4</td>
<td>2</td>
<td>3</td>
<td>0</td>
</tr>
<tr>
<td>8</td>
<td>krb5</td>
<td>2</td>
<td>10</td>
<td>3</td>
<td>2</td>
</tr>
<tr>
<td>9</td>
<td>php</td>
<td>0</td>
<td>14</td>
<td>22</td>
<td>25</td>
</tr>
<tr>
<td>10</td>
<td>evolution</td>
<td>3</td>
<td>3</td>
<td>8</td>
<td>4</td>
</tr>
</tbody>
</table>
<div class="caption">Table 5. Top 10 packages with the worst security history, 4 years</div>
<p>These top 10 packages together totaled 79% of all the weighted vulnerabilities.  The kernel, cups, php, krb5, and samba packages are part of the default installation of Enterprise Linux 4 AS.</p>
<dl class="adtip">
<dt>Tip</dt>
<dd>You can reduce the number of vulnerabilities that will affect your systems by removing packages that you don&#8217;t need or don&#8217;t use, particularly those that have the worst security history.  For example, if you don&#8217;t use thunderbird on a machine you could just remove the package.</dd>
</dl>
<p><a name="id1548901"></a></p>
<h3>2.5. Advisory Workload</h3>
<p>In previous reports we&#8217;ve graphed the vulnerability workload, a measure of the number of vulnerabilities that security operations staff would need to worry about every day, weighted by severity. But the actual effort in maintaining an Enterprise Linux system is more related to the number of advisories we released, rather than the number of vulnerabilities:  A single Firefox advisory may fix ten different issues of critical severity, but takes far less total effort to manage than ten separate advisories each fixing one critical Samba vulnerability.</p>
<p>Our Advisory Workload index gives a measure of the number of important advisories that users would need to worry about every day. The higher the number, the greater the workload, and the greater the general risk represented by the vulnerabilities addressed.  This workload index is calculated in a similar way to the <a href="http://nvd.nist.gov/home.cfm?workloadindex">NIST workload index</a>.</p>
<p>For a given month, Advisory Workload = weighted number of advisories <sup>[<a name="id151" href="#ftn.1">3</a>]</sup> / days in the month.   A workload of 1.0 would mean one important advisory a day.</p>
<p><a name="fig-vulnworkload"></a><br />
<a href="workflow-metrics.gif" title="Photo Sharing"><img src="http://www.awe.com/mark/talks/20090310-workflow-metrics.gif" width="533" height="200" alt="A graph showing the workload index decrease from an initial high to a low average over the 4 years"></a></p>
<div class="caption">Figure 5. Advisory Workload</div>
<p>Figure 5 shows the advisory workload index for a installation of Enterprise Linux 4 including every package.  The initial peak during the first month looks surprising, but is easily explained, as the packages for Enterprise Linux 4 had a code freeze a few months prior to release.  This led to a backlog of security issues that were fixed with updates on the date of release.  The small peak in August 2005 aligns with the release of Update 1, and the other peaks align with Update releases or months during which there were several Firefox and SeaMonkey<br />
updates.</p>
<dl class="adtip">
<dt>Tip</dt>
<dd>Cut down on the number of alerts you receive.  Register your systems with the Red Hat Network to get customised notifications for security updates for the packages your systems have installed.  If you want to see all security updates for every Enterprise Linux version and package, subscribe to  <a href="http://www.redhat.com/security/updates/advisory/">enterprise-watch-list mailing list</a> as well.</dd>
</dl>
<p><a name="sect1-threats"></a></p>
<h2>3. Threats</h2>
<p>The first part of this report analysed the total vulnerabilities found affecting Enterprise Linux 4.  But to get a better evaluation of platform risk we also need to take into account the threat.  This part therefore looks at<br />
exploits and worms written to take advantage of the vulnerabilities.</p>
<p>Red Hat is continually developing technologies to help reduce the risk of security threats, and a number of these were consolidated into Red Hat Enterprise Linux 4.  The most significant technologies were SELinux and<br />
Exec-Shield.  Exec-Shield is a project which includes support for the No eXecute (NX) memory permission, simulating NX via segment limits, Position Independent Executables (PIE), gcc, and glibc hardening.  For more details, a <a href="http://www.awe.com/mark/blog/200801070918.html">table of the major security technology innovations in Enterprise 4</a> is available.</p>
<p><a name="id1549636"></a></p>
<h3>3.1. Exploits</h3>
<p>An exploit is the way that an attacker makes use of a vulnerability.  The Red Hat Security Response Team monitor numerous sources to track which vulnerabilities are being exploited.  For this report we compiled a list of the publicly available exploits for the vulnerabilities that affected the first four years of Enterprise Linux 4.</p>
<p>We are interested in those exploits that have the potential to cause remote damage to the confidentiality or integrity of a system and we therefore don&#8217;t include exploits for vulnerabilities that are limited to a denial of service (affecting availability).  We do, however, include exploits which are labeled &#8220;proof of concept&#8221;.  A proof of concept exploit may only cause a crash or not quite work properly without modification, but in theory the vulnerability could be exploited properly leading to greater consequences. These proof of concept exploits often show techniques that a skilled attacker can turn into a full exploit.</p>
<p>We found exploits for 59 vulnerabilities for the first four years.  24 (40%) of these exploits are for buffer overflow vulnerabilities where in most cases the Exec-Shield technology should help prevent remote exploitation due to protections such as ASLR and enforcement of a non-executable stack.</p>
<p><a name="id1549994"></a></p>
<h4>3.1.1. Kernel exploits</h4>
<p>The public exploits for the Linux kernel lead to one of two consequences: either a local unprivileged user can cause the machine to crash, or a local user can gain privileges.</p>
<p>We found exploits for nine vulnerabilities that had the potential to allow an unprivileged user to gain privileges on an unpatched Enterprise Linux 4 system.  Of the nine, one required the target system to be using bluetooth drivers (CVE-2005-0750), another was exploitable only on systems with more than one CPU (CVE-2005-0001), one affected only x86_64 architectures (CVE-2007-4573), and one required a writable sgid directory (CVE-2008-4210).</p>
<p>The remainder (CVE-2006-3626, CVE-2006-2451, CVE-2005-0736, CVE-2004-1235, and CVE-2005-0531) could work on any default, unpatched system.  Some of those exploits need unpublished source code adjustments in order to work against an Enterprise Linux 4 kernel.</p>
<p><a name="id1549680"></a></p>
<h4>3.1.2. Browser exploits</h4>
<p>Around of quarter of the public exploits we found were for flaws in web browsers; and all but three targeted the Mozilla suite (Mozilla, Firefox, Thunderbird). These are detailed in Table 6.  For each exploit, any resultant code execution would be limited to being run with the same rights as the user that is running the vulnerable browser.  It is best practice to never use a web browser or email client as root.  Some of these exploits are also blocked if JavaScript is disabled.</p>
<p><a name="tb-browser"></a></p>
<table summary="Exploits for browser flaws" border="1">
<thead>
<tr>
<th>Vulnerabilities</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>CVE-2005-0399</td>
<td>An exploit for a flaw where a malicious GIF image could cause an overflow. This issue is more serious in Thunderbird, where opening a malicious email could trigger this flaw.</td>
</tr>
<tr>
<td>CVE-2006-0295, CVE-2005-2871</td>
<td>Exploits for flaws where a malicious web page could run arbitrary code.  The public exploit for CVE-2005-2871 was designed for Windows platforms, exploiting this flaw on Linux would require different techniques.</td>
</tr>
<tr>
<td>CVE-2005-1476, CVE-2005-1531, CVE-2005-2264, CVE-2005-1160, CVE-2005-1155, CVE-2005-1157</td>
<td>Exploits for flaws where a malicious web page could run arbitrary JavaScript, doing things like changing home pages, stealing cookies, cross-site scripting, or creating files on the system.</td>
</tr>
<tr>
<td>CVE-2005-2262, CVE-2005-2269</td>
<td>Exploits for two user-complicit overflow flaws that require the victim to use the &#8217;set as wallpaper&#8217; option on a malicious image.</td>
</tr>
<tr>
<td>CVE-2006-3677</td>
<td>An exploit for a JavaScript code flaw.  This could result in the execution of arbitrary code if a victim visits a malicious website.</td>
</tr>
<tr>
<td>CVE-2007-0981</td>
<td>An exploit that can bypass the same-origin policy, allowing cookie or cross-domain attacks.</td>
</tr>
<tr>
<td>CVE-2005-2710</td>
<td>An exploit for a format-string vulnerability in HelixPlayer.  HelixPlayer can run as a web browser applet potentially allowing code execution.</td>
</tr>
<tr>
<td>CVE-2005-3120</td>
<td>An exploit in the Lynx optional text-based browser.  The public exploit is a proof of concept only.</td>
</tr>
<tr>
<td>CVE-2006-5925</td>
<td>An exploit in the Links text web browser which could allow arbitrary commands to be executed if a victim visits a malicious web site.</td>
</tr>
</tbody>
</table>
<div class="caption">Table 6. Exploits for browser flaws</div>
<p><a name="id1550129"></a></p>
<h4>3.1.3. Other user-complicit exploits</h4>
<p>The next class of exploits are those we term &#8216;user-complicit&#8217;, in that they need some involvement from the victim to be exploited.  Some examples of user involvement would be opening a malicious file with a vulnerable application, or viewing an instant message from an unknown user.  Table 7 lists the exploits we discovered that require some user involvement.</p>
<p><a name="tb-complicit"></a></p>
<table summary="Exploits for user-complicit flaws" border="1">
<thead>
<tr>
<th>Vulnerabilities</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>CVE-2008-2383</td>
<td>An exploit for a flaw in xterm.  An attacker could create a malicious text file (or log entry, if unfiltered) that could run arbitrary commands if read by a victim inside an xterm window.</td>
</tr>
<tr>
<td>CVE-2008-2292</td>
<td>Proof of concept DoS exploit for a buffer overflow in the Perl bindings for Net-SNMP. This could be triggered if an attacker could convince an application using the Net-SNMP Perl module to connect to a malicious SNMP agent.</td>
</tr>
<tr>
<td>CVE-2008-1801</td>
<td>Proof of concept DoS exploit for an integer underflow flaw in rdesktop. If an attacker can convince a victim to connect to a malicious RDP server, the attacker could cause the victim&#8217;s rdesktop to crash or possibly execute arbitrary code</td>
</tr>
<tr>
<td>CVE-2008-1105</td>
<td>Proof of concept DoS exploit for a heap overflow in Samba.  If an attacker can convince a victim to connect to a malicious server, the attacker could cause the client to crash or possible execute arbitrary code</td>
</tr>
<tr>
<td>CVE-2007-3103</td>
<td>An exploit for a flaw in X.Org font server.  If a local attacker can get the xfs service to be restarted by root they could gain privileges.</td>
</tr>
<tr>
<td>CVE-2007-2356</td>
<td>An exploit for a stack buffer flaw in the Gimp image editor.  If an attacker can force a victim to run the Gimp on a malicious image they could execute arbitrary code as the victim.</td>
</tr>
<tr>
<td>CVE-2006-2656</td>
<td>An exploit for a flaw in libtiff.  If an attacker can force a victim to run the &#8216;tiffsplit&#8217; executable with a malicious filename they could cause code to run as that user.  This is low severity as nothing we ship<br />
runs &#8216;tiffsplit&#8217; with an arbitrary filename.</td>
</tr>
<tr>
<td>CVE-2006-1542</td>
<td>An exploit for a flaw in Python.  This is a low severity issue as the user would need to be tricked into running python with a very long script name, an unlikely scenario.</td>
</tr>
<tr>
<td>CVE-2005-3243, CVE-2005-2367, CVE-2005-1461, CVE-2005-0699</td>
<td>Exploits for several vulnerabilities in Ethereal/Wireshark.  In order to be exploited a victim with privileges would have to be analysing network packets using Wireshark from a network into which an attacker could inject carefully crafted malicious packets.  The protocols affected by the vulnerabilities (SLIMP3, AFP, SIP, and RADIUS) are unlikely to be allowed through a border firewall, so the ability to exploit this flaw remotely is restricted.</td>
</tr>
<tr>
<td>CVE-2005-1704</td>
<td>An integer overflow could allow a malicious executable to execute arbitrary code.  This is low severity as the attacker needs to convince the victim to run the malicious binary (and a malicious binary could perform arbitrary actions anyway).</td>
</tr>
<tr>
<td>CVE-2005-1261</td>
<td>Proof of concept DoS exploit for a flaw in the Gaim instant-messaging client.  For some protocols, an attacker could send a carefully crafted message which could trigger the flaw and cause code execution.</td>
</tr>
<tr>
<td>CVE-2005-0156</td>
<td>An exploit for a flaw in the setuid Perl package.  Where perl-setuid is installed, an unprivileged local user could gain root privileges.  The exploit as published needs minor changes to work on unpatched Enterprise Linux 4 systems.</td>
</tr>
</tbody>
</table>
<div class="caption">Table 7. Exploits for user-complicit flaws</div>
<p><a name="id1550273"></a></p>
<h4>3.1.4. PHP exploits</h4>
<p>During March 2007 the &#8220;Month of PHP bugs&#8221; uncovered a number of issues, some of which affected the PHP packages as distributed with Enterprise Linux 4. The PHP interpreter does not offer a reliable sand-boxed security layer (as found in, say, a JVM) in which untrusted scripts can be run, so any script run by the PHP interpreter must be trusted with the privileges of the interpreter itself.  Therefore, in analysis of these issues, exploits which relied on an &#8220;untrusted local attacker&#8221; were not classified as security-sensitive since no trust boundary was crossed.</p>
<p>This leaves us with the exploits shown in Table 8.  These exploits rely on the victim having PHP scripts installed that use the vulnerable PHP functions in a particular way or with untrusted data.  In each case the default SELinux targeted policy for Apache would restrict what a successful exploit is able to do.</p>
<p><a name="tb-php"></a></p>
<table summary="Exploits for PHP flaws" border="1">
<thead>
<tr>
<th>Vulnerabilities</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>CVE-2007-1286</td>
<td><!--http://www.php-security.org/MOPB/MOPB-04-2007.html--></p>
<p>Exploit for a flaw in the unserialize function. Although unserialize is used by some PHP scripts with untrusted data, the input string required to exploit this issue must exceed ~512K in length, so default Apache line length limits will prevent this from being  remotely exploited via input data carried in the HTTP request headers or URI.  </td>
</tr>
<tr>
<td>CVE-2007-1287</td>
<td><!--http://www.php-security.org/MOPB/MOPB-08-2007.html--><br />
Exploit for a cross-site-scripting issue in the phpinfo function. Generally, the phpinfo function should never be used in publicly-accessible PHP scripts.
</td>
</tr>
<tr>
<td>CVE-2007-1701</td>
<td><!--http://www.php-security.org/MOPB/MOPB-31-2007.html--><br />
Exploit for a flaw in the session extension which allows super-globals to be over-ridden by an attacker, exploitable if session data is taken from an untrusted source.</td>
</tr>
<tr>
<td>CVE-2007-1718</td>
<td><!--http://www.php-security.org/MOPB/MOPB-34-2007.html--></p>
<p>Exploit for a flaw in the mail function which could allow a remote attacker to inject arbitrary headers into PHP generated mail if the mail Subject comprises of user-supplied data.
<td> </tr>
<tr>
<td>CVE-2007-1885</td>
<td><!--http://www.php-security.org/MOPB/MOPB-39-2007.html--><br />
Exploit for an integer overflow in the str_replace function, which can be triggered remotely if a script passes large untrusted strings to particular arguments of this function.</td>
</tr>
<tr>
<td>CVE-2007-0906</td>
<td><!--http://www.php-security.org/MOPB/MOPB-40-2007.html--> Exploit for a heap overflow in the imap_mail_compose function, which can be triggered if a script uses the function to create a new MIME message based on an input body from an untrusted source.</td>
</tr>
<tr>
<td>CVE-2006-4020</td>
<td>Exploits for a flaw in the sscanf function.  If a PHP script passed data under an attackers control to sscanf it could result in a buffer overflow.</td>
</tr>
<tr>
<td>CVE-2005-1921, CVE-2005-2498</td>
<td>Exploits for flaws in the PEAR XML-RPC code.  These exploits require a server to be running a third-party PHP application that exports an XML-RPC interface. </td>
</tr>
</tbody>
</table>
<div class="caption">Table 8. Exploits for PHP flaws</div>
<p><a name="id1550274"></a></p>
<h4>3.1.5. Servers and services exploits</h4>
<p>Our final class of exploits are those that affect server applications and services, in Table 9.  These are the most serious threats.</p>
<p><a name="tb-services"></a></p>
<table summary="Exploits for flaws in servers and services" border="1">
<thead>
<tr>
<th>Vulnerabilities</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>CVE-2008-2936</td>
<td>An exploit for a flaw in Postfix.  A local attacker could gain root privileges in the unlikely event they have write access to a mail spool directory with no root mailbox.</td>
</tr>
<tr>
<td>CVE-2008-1891</td>
<td>An exploit for a Ruby WEBrick flaw.  A remote attacker could read arbitrary CGI files, but only if the files were being served from a NTFS or FAT filesystem.</td>
</tr>
<tr>
<td>CVE-2008-0960</td>
<td>An exploit to bypass authentication in Net-SNMP.  A remote attacker could cause the execution of arbitrary commands if they can connect to a system using Net-SNMP.</td>
</tr>
<tr>
<td>CVE-2008-1447, CVE-2007-2926</td>
<td>Problems with BIND not having sufficient randomisation. Exploits were released to use these flaws to poison the DNS cache.</td>
</tr>
<tr>
<td>CVE-2007-0957</td>
<td>An exploit for a buffer overflow in the Kerberos administration daemon.  A remote authenticated user could execute arbitrary code as root on the Kerberos server.</td>
</tr>
<tr>
<td>CVE-2007-6015</td>
<td>An exploit for a buffer overflow in Samba.  In order to exploit this flaw, the &#8220;domain logons&#8221; option would need to be enabled.</td>
</tr>
<tr>
<td>CVE-2005-0022</td>
<td>A remote exploit for a buffer overflow in the non-default Exim mail server which could lead to arbitrary code execution as the &#8216;exim&#8217; unprivileged user.  In order to exploit this vulnerability, Exim needs to be installed and SPA authentication specifically enabled, which is not a usual configuration. </td>
</tr>
<tr>
<td>CVE-2005-0710, CVE-2005-0709</td>
<td>Exploits for flaws in the MySQL server.  A remote authenticated user with privileges to insert or delete from a database table could execute arbitrary code on the MySQL server as the unprivileged &#8216;mysql&#8217; user. The default SELinux targeted policy for MySQL would restrict what a successful exploit is able to do.</td>
</tr>
</tbody>
</table>
<div class="caption">Table 9. Exploits for flaws in servers and services</div>
<dl class="adtip">
<dt>Tip</dt>
<dd>The way to reduce your risk from exploits is to make sure your systems have all applicable security updates installed.  The Red Hat Network can help keep track of this.</dd>
</dl>
<p><a name="id1550537"></a></p>
<h3>3.2. Worms</h3>
<p>Worms take advantage of vulnerabilities in order to compromise systems, then use the compromised system to seek out other systems to infect.  By our definition, any vulnerability that could be exploited in this way would be classed as severity critical.  In the first section of this report we listed every vulnerability that was rated as critical severity and showed that only a subset of those vulnerabilities could be actually used by worms.  This is because we also class as critical some browser vulnerabilities where a victim has to take action (for example visiting a malicious web page) and therefore are not exploitable by a worm.</p>
<p>Worms affecting Linux platforms have been quite scarce in the last few years, and the anti-virus vendors who track malware recorded only two (although some variants of each exist) during the four year period of this study:</p>
<ul>
<li>Linux/MARE was discovered in November 2005 and was a worm that spread by exploiting a flaw in PHP-Nuke.  PHP-Nuke is not shipped as part of Red Hat Enterprise Linux.</li>
<li>Linux/Lupper was also discovered in November 2005 and was a worm designed to exploit <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-1921">CVE-2005-1921</a>, a flaw in the PHP PEAR XML-RPC server package exploitable through a number of third party PHP applications.  None of the affected third-party applications were shipped as part of Red Hat Enterprise Linux.  Additionally, a PHP update in July 2005 fixed the underlying flaw in PHP.  Even users that had not patched were also protected from this worm by the default SELinux configuration.</li>
</ul>
<p>Without critical vulnerabilities to allow attackers to remotely exploit machines, we saw attackers instead try to focus on exploiting weak configurations.  During the period of this study we tracked attempts by attackers to exploit machines with stolen passwords and brute-force password tools.  The tools simply looked for internet-accessible SSH services they could connect to, then tried to log in with lots of combinations of common usernames and passwords.  Restricting access to SSH remotely, moving the SSH daemon to a different port, and making sure all your users have strong passwords or use key authentication are all useful defenses against this particular attack.</p>
<p><a name="sect1-conclusion"></a></p>
<h2>4. Conclusion</h2>
<p>The aim of this report was to get a measure of the security risk to users of Red Hat Enterprise Linux 4 during the first four years since release.  We&#8217;ve shown that although on the surface it looks like Red Hat released a large number of security advisories, many of them do not apply to usual or default installations, and only a very small subset are a high risk.  We&#8217;ve shown:</p>
<ul>
<li>A default installation of Enterprise Linux 4 AS was vulnerable to ten critical security issues over the first four years</li>
<li>A customised installation of Enterprise Linux 4, selecting every package, would have been vulnerable to 114 critical browser security issues, and 16 in non-browser packages in the four years.  87% of those vulnerabilities had fixes to correct them available from the Red Hat Network within one  calendar day of them being known to the public</li>
<li>Red Hat knew about 51% of security issues affecting the first four years of Enterprise Linux 4 in advance.  The average time between Red Hat knowing about an issue and it being made public was 21 days (median 9<br />
days)</li>
<li>We found public exploits for 59 vulnerabilities that could have affected a customised full installation, although the majority relied on user interaction or non-default settings. Attempts to use many of the exploits would be caught by standard Enterprise Linux 4 security innovations</li>
<li>The most likely successful exploits allowed a local unprivileged user to gain root privileges on an unpatched Enterprise Linux 4 machine</li>
<li>Two worms targeting Linux systems were found during the four years, but both affected third party PHP applications not shipped in Red Hat Enterprise Linux 4.  In addition, an update to PHP released over three months before one of the worms was released protected systems that had installed the third party applications</li>
</ul>
<p>It would be foolish to draw conclusions about the future state of security in Red Hat Enterprise Linux 4 solely on the basis of this analysis of the past, however what we&#8217;ve tried to do is to enumerate the level of vulnerability and threat and hence overall platform risk. Red Hat treats vulnerabilities in our products and services seriously and the policies of the Red Hat Security Response Team are specifically designed to reduce the risk from security vulnerabilities:</p>
<ul>
<li>We place an emphasis on providing the fastest possible, highest quality, turnaround for critical vulnerabilities. We have a Security Response Team distributed globally which can draw on significant Engineering and Quality resources to get the things that matter the most fixed quickly</li>
<li>We release updates for critical and important security issues as soon as possible rather than batching them into monthly or quarterly updates</li>
<li>We provide transparency in the handling of vulnerabilities, our methods, and our metrics</li>
</ul>
<p>All of the raw data used to generate the statistics in this report along with some tools to analyse them <a href="https://www.redhat.com/security/data/metrics/">are available</a> from the Red Hat Security Response Team. We also provide other tools and data that can help security measurement including CVE mappings for all our advisories and OVAL definitions.</p>
<p><a name="sect1-furtherreading"></a></p>
<h2>5. Further Reading</h2>
<ul>
<li><a href="http://www.redhat.com/magazine/006apr05/features/security/" target="_top">What&#8217;s new in security for Red Hat Enterprise Linux 4</a></li>
<li><a href="http://www.awe.com/mark/blog/200610241300.html" target="_top">Vulnerability Types for Enterprise Linux 4</a></li>
<li><a href="http://www.awe.com/mark/blog/200801070918.html" target="_top">Security Features in Red Hat Enterprise Linux and Fedora Core</a></li>
<li><a href="https://www.redhat.com/apps/webform.html?event_type=whitepaper&amp;eid=315" target="_top">SELinux: A New Approach to Secure Systems</a></li>
<li><a href="http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/security-guide/" target="_top">Red Hat Enterprise Linux 4 Security Guide</a></li>
<li><a href="http://www.redhat.com/security/data/metrics/" target="_top">Statistics and data from the Security Response Team</a></li>
</ul>
<p><a name="sect1-author"></a></p>
<h2>6. About the author</h2>
<p>
<img src="http://www.awe.com/mark/talks/20090310-markcox5.jpg" width="140" height="93" align="left"><br />
Mark J Cox lives in Scotland and is Director of Red Hat Security Response. Over the last 14 years, Mark has developed software and worked on the security teams of some of the most popular open source projects including Apache, mod_ssl, and OpenSSL. Mark is a founding member of the Apache Software Foundation and the OpenSSL project, and a board member of the Mitre CVE project.  In his spare time he <a href="http://www.geocaching.com/">finds geocaches</a> with his family and occasionally <a href="http://www.sonik.co.uk/">plays music</a>.</p>
<p></p>
<hr width="100" align="left">
<div class="footnote">
<p><sup>[<a name="ftn.id1548910" href="#id1548910">1</a>] </sup> We count the first place that the security team heard about a security issue. &#8216;Peer vendors&#8217; are other distributors of open source software who are part of vendor-sec. &#8216;Upstream relationship&#8217; covers issues told to us because we work on the upstream<br />
projects or they contacted us to tell us about an issue.  &#8216;Red Hat discovered&#8217; are issues Red Hat employees discovered.  &#8216;Red Hat notified&#8217; are where some customer, researcher, or other third party told us about an issue through email, bugzilla, or other means. &#8216;Security Lists&#8217; includes public lists like Bugtraq and Full-Disclosure,<br />
&#8216;CVE feed&#8217; is a Mitre feed of newly allocated CVE names for public issues.</p>
<p><sup>[<a name="ftn.id1548911" href="#id1548911">2</a>] </sup> To rank the riskiest packages we use a weighting of &#8220;Critical + Important/5 + Moderate/25 + Low/100&#8243;</a></p>
<p><sup>[<a name="ftn.1" href="#id151">3</a>] </sup> To weight the effort of dealing with advisories, Critical and Important advisories are scored as 1.00, Moderate advisories as 0.20, and Low advisories as 0.05.  This is designed to be similar to the way that NIST calculate their workload metrics.</p>
</div>
<p><!-- footnote --></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rhredhatmagazine.wordpress.com/1162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rhredhatmagazine.wordpress.com/1162/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rhredhatmagazine.wordpress.com/1162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rhredhatmagazine.wordpress.com/1162/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rhredhatmagazine.wordpress.com/1162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rhredhatmagazine.wordpress.com/1162/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rhredhatmagazine.wordpress.com/1162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rhredhatmagazine.wordpress.com/1162/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rhredhatmagazine.wordpress.com/1162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rhredhatmagazine.wordpress.com/1162/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1162&subd=rhredhatmagazine&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://magazine.redhat.com/2009/03/10/risk-report-four-years-of-red-hat-enterprise-linux-4/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Mark Cox</media:title>
		</media:content>

		<media:content url="http://www.awe.com/mark/talks/20090310-info-advance.gif" medium="image">
			<media:title type="html">A graph showing the information sources</media:title>
		</media:content>

		<media:content url="http://www.awe.com/mark/talks/20090310-info-public.gif" medium="image">
			<media:title type="html">A graph showing the information sources</media:title>
		</media:content>

		<media:content url="http://www.awe.com/mark/talks/20090310-advance-notice.gif" medium="image">
			<media:title type="html">A graph showing the time Red Hat knew about issues in advance</media:title>
		</media:content>

		<media:content url="http://www.awe.com/mark/talks/20090310-workflow-metrics.gif" medium="image">
			<media:title type="html">A graph showing the workload index decrease from an initial high to a low average over the 4 years</media:title>
		</media:content>

		<media:content url="http://www.awe.com/mark/talks/20090310-markcox5.jpg" medium="image" />
	</item>
		<item>
		<title>Introducing Pylons:  A hacker&#8217;s web framework</title>
		<link>http://magazine.redhat.com/2008/11/05/introducing-pylons-a-hackers-web-framework/</link>
		<comments>http://magazine.redhat.com/2008/11/05/introducing-pylons-a-hackers-web-framework/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 20:22:20 +0000</pubDate>
		<dc:creator>Noah Gift</dc:creator>
				<category><![CDATA[Fedora]]></category>
		<category><![CDATA[Red Hat Enterprise Linux]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2008/11/05/introducing-pylons-a-hackers-web-framework/</guid>
		<description><![CDATA[Python has a good reputation for tasks like systems programming, network programming, and scripting, but Python for the web is becoming red hot.  Part of this has to do with the very popular web framework Django, that was developed at a newspaper to help quickly create Content Management Sites.  . Another reason is [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1063&subd=rhredhatmagazine&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Python has a good reputation for tasks like systems programming, network programming, and scripting, but Python for the web is becoming red hot.  Part of this has to do with the very popular web framework Django, that was developed at a newspaper to help quickly create Content Management Sites.  . Another reason is that Google App Engine&#8211;Google&#8217;s Cloud Computing offering for developers&#8211;only exposes a Python API.</p>
<p>If you are new to Python Web Development, then I&#8217;d recommend Django, as it is ideal for building CMS-type applications, social networking websites, and blogs. On the other hand, If you want a hacker&#8217;s framework, you might want to give Pylons a look.</p>
<p>Please note: By hacker, I am referring to the kind of hacker Eric Raymond refers to when he writes, &#8220;Becoming a hacker will take intelligence, practice, dedication, and hard work.  Therefore, you have to learn to distrust attitude and respect competence of every kind. Hackers won&#8217;t let posers waste their time, but they worship competence — especially competence at hacking, but competence at anything is valued.&#8221;</p>
<p>Ok, so what problem does a hacker&#8217;s framework solve that a framework like Django doesn&#8217;t?  According to some of the Pylons developers, their framework is geared to solve 80/20 problems. Most people—80% of people&#8211;want to build blogs, and CMS-type applications. And for that 80%, Django works just great. Of course, the other 20% is where Pylons comes in to play as a &#8220;hacker&#8217;s framework.&#8221;<span id="more-1063"></span></p>
<p>Philosophically, Pylons is quite different. Pylons abstracts third-party libraries, such as WebOb, Mako, SQLAlchemy, Routes, and Beaker, to make a &#8220;hacker&#8217;s brew.&#8221;  These libraries are loosely coupled&#8211;not in a internet marketing sense, but in a computer science sense. This means that it is quite easy to swap out the ORM, or templates, or URL routing, and create some alternate development stack.  Note, that another hacker&#8217;s framework, Werkzeug, also follows a similar philosophy (See the references for more details).</p>
<p>What does a hacker&#8217;s framework buy you?  Well, it allows you to change your web development paradigm.  You no longer need to think in terms of what you can do with the choices defined by a framework. It allows the experienced developer to transcend this potential trap, and think about the actual problem at hand. For example, it may be more productive to start by using SQLAlchemy (the object-relational mapper) by itself.</p>
<p>Once the data model is working as expected, then it could turn into a command line tool, then potentially a WXPython application instead of a web application.  Hacker&#8217;s frameworks let the developer decide what is best for them at any given situation.  Additionally, by focusing on loosely coupling the “best of breed” components, it allows the user of a “hacker” framework, to use literally, the best component for the job.  This extra power can come in handy with more complex problems.</p>
<h2>Setup</h2>
<p>In this article we dive into building an AJAX blog using Pylons.  We cheat by using the bookmark tagging site, Del.icio.us  as an admin interface that we don&#8217;t have to write.  When a user creates content on Delicious, the Google AJAX feed API allows that content to be displayed locally on the web page. This is one of the most efficient type of blog that someone can create, as it reuses existing code, APIs, and services.</p>
<h2>Building a Pylons AJAX blog</h2>
<p>To get started you can download the whole example and run it, or you can follow the steps below.  Note that in version control, each step is a separate Pylons project.</p>
<p><strong>[ Step 1] <a href="http://code.google.com/p/pyatl-pylons/source/browse/#svn/trunk/1">http://code.google.com/p/pyatl-pylons/source/browse/#svn/trunk/1</a></strong></p>
<p>1:  Download <a href="http://www.pylonshq.com/download/0.9.7/go-pylons.py">http://www.pylonshq.com/download/0.9.7/go-pylons.py</a></p>
<pre>
ngift@noah][H:10471][J:0]# python gopylons.py --no-site-packages pylonsblog
New python executable in pylonsblog/bin/python
Installing setuptools..........................done.
Searching for Pylons
[snip]
</pre>
<p><strong>Note:</strong> You will need to meet all requirements of the package.</p>
<p> 2:</p>
<pre>
cd pylonsblog
</pre>
<p> 3:  Active environ</p>
<pre>
source bin/activate
</pre>
<p> 4:  Make project</p>
<pre>
mkdir -p src
paster create --template=pylons ajaxblog
</pre>
<p> 5:  Get Pylons running</p>
<pre>
cd ajaxblog

paster serve development.ini
</pre>
<p> 6:  Make a controller</p>
<pre>
paster controller blog

cd ajaxblog/controller to verify

go to page:

http://localhost:5000/blog

See Hello World, change it.

"Hello Red Hat Magazine"
</pre>
<p><strong>[Step 2] <a href="http://code.google.com/p/pyatl-pylons/source/browse/#svn/trunk/step2">http://code.google.com/p/pyatl-pylons/source/browse/#svn/trunk/step2</a></strong></p>
<p> 7:  Change front page</p>
<p>  Add your own content to public/index.html</p>
<p> 8:  Add a couple of templates, and hook up to blog controller</p>
<p>Create base.html<br />
Create blog.html</p>
<p>Add this line to blog.html:</p>
<pre>
Hello from blog.html template: Red Hat Magazine
</pre>
<p> 9:  Change controller to render template</p>
<p>Edit controller/blog.py to this:</p>
<pre>
class BlogController(BaseController):

    def index(self):
        # Return a rendered template
        #   return render('/some/template.mako')
        # or, Return a response
        return render('/blog.html')
</pre>
<p><strong>[Step 3] http://code.google.com/p/pyatl-pylons/source/browse/#svn/trunk/step3</strong></p>
<p>10:  Get Buzzword compliant:  Adding AJAX, RSS, Mashup and Google</p>
<p>A.  Sign up for AJAX RSS Developer Key:</p>
<p><a href="http://code.google.com/apis/ajaxfeeds/">http://code.google.com/apis/ajaxfeeds/</a></p>
<p>B.  Add javascript Code to base.html<br />
C.  Call feed div in blog.html</p>
<p>11:  See RSS Feed appear</p>
<p>If you go to localhost:5000/blog you will see my last RSS feeds</p>
<p><strong>[Step 4] <a href="http://code.google.com/p/pyatl-pylons/source/browse/#svn/trunk/step4">http://code.google.com/p/pyatl-pylons/source/browse/#svn/trunk/step4</a></strong></p>
<p>Bonus Points:  Try to add persistent comments using the SQLAlchemy ORM on your own!</p>
<h2>Summary</h2>
<p>In this article we explored some of the ideas behind Pylons, a hacker&#8217;s framework, and how it differs from a philosophy framework, like Django or Ruby on Rails. Note by philosophy framework, I am referring to how a developer must abide by the opinions of the developer of the framework, such as in the case of Django templates where a developer is handcuffed against running code in the template. For example, their idea of perfection might be different then yours. Some people refer to this as being an &#8220;opinionated&#8221; framework. Each one has its purpose, and place. If you just want to make a Content Management website MS website for your American Literature class project, then maybe a hacker&#8217;s framework isn&#8217;t suited for you or the project, as it is overkill. On the other hand, if you want maximum flexibility, power, (and, of course, &#8220;street cred&#8221;) you might give a hacker&#8217;s framework a try.</p>
<p>Finally, we got into making an actual Pylons AJAX blog that used Delicious to suck in feeds. This was accomplished by reusing code via the Google AJAX Feed API. Ok, enough talk, get to hacking&#8230;.</p>
<p>Extra Credit:  If you are interested diving into a more complex Pylons project template on your own take a look at this <a href="http://code.google.com/p/pyatl-pylons/source/browse/#svn/trunk/bonus_project_form_validation_jonathan_ellis">source code url</a>. Jonathan Ellis, a Python hacker known for his work with SQLAlchemy, has donated a do-it-yourself tutorial on using FormAlchemy to create a simple blog in Pylons.  I have included a link to his original article on the topic in the reference section.</p>
<h2>References</h2>
<p>Pylons Book:  <a href="http://pylonsbook.com/alpha1/toc">http://pylonsbook.com/alpha1/toc</a><br />
Google AJAX Feed API:  <a href="http://code.google.com/apis/ajaxfeeds/">http://code.google.com/apis/ajaxfeeds/</a><br />
SQLAlchemy: <a href="http://www.sqlalchemy.org/">http://www.sqlalchemy.org/</a><br />
Using SQLAlchemy:  <a href="http://www.ibm.com/developerworks/aix/library/au-sqlalchemy/">http://www.ibm.com/developerworks/aix/library/au-sqlalchemy/</a><br />
How To Become a Hacker:  <a href="http://www.catb.org/~esr/faqs/hacker-howto.html">http://www.catb.org/~esr/faqs/hacker-howto.html</a><br />
Google App Engine:  <a href="http://code.google.com/appengine/">http://code.google.com/appengine/</a><br />
WebOb: <a href="http://pythonpaste.org/webob/">http://pythonpaste.org/webob/</a><br />
Source Code For Example:  <a href="http://pyatl-pylons.googlecode.com/svn/trunk/">http://pyatl-pylons.googlecode.com/svn/trunk/</a><br />
Werkzeug (An alternate hacker&#8217;s framework):  <a href="http://werkzeug.pocoo.org">http://werkzeug.pocoo.org</a><br />
Loose Coupling Computer Science Definition:  <a href="http://en.wikipedia.org/wiki/Loose_coupling#Definition">http://en.wikipedia.org/wiki/Loose_coupling#Definition</a><br />
Pylons FormAlchemy How To: <a href="http://http://spyced.blogspot.com/2008/10/formalchemy-10.html">http://spyced.blogspot.com/2008/10/formalchemy-10.html</a><br />
Extra Credit Project: <a href="http://code.google.com/p/pyatl-pylons/source/browse/#svn/trunk/bonus_project_form_validation_jonathan_ellis">http://code.google.com/p/pyatl-pylons/source/browse/#svn/trunk/bonus_project_form_validation_jonathan_ellis</a></p>
<h2>About the author</h2>
<p>Noah Gift is the co-author of &#8220;Python For Unix and Linux&#8221; by O&#8217;Reilly, and &#8220;Google App Engine in Action&#8221; by Manning. He is an author, speaker, consultant, and community leader, writing for publications such as IBM Developerworks, Red Hat Magazine, O&#8217;Reilly, Manning and MacTech.   He has a Master&#8217;s degree in CIS from Cal State Los Angeles, B.S. in Nutritional Science from Cal Poly San Luis Obispo, is an Apple and LPI certified sysadmin, and has worked at companies such as, Caltech, Disney Feature Animation, Sony Imageworks, Turner Studios, and&#8211;most recently&#8211;WetaDigital.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rhredhatmagazine.wordpress.com/1063/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rhredhatmagazine.wordpress.com/1063/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rhredhatmagazine.wordpress.com/1063/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rhredhatmagazine.wordpress.com/1063/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rhredhatmagazine.wordpress.com/1063/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rhredhatmagazine.wordpress.com/1063/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rhredhatmagazine.wordpress.com/1063/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rhredhatmagazine.wordpress.com/1063/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rhredhatmagazine.wordpress.com/1063/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rhredhatmagazine.wordpress.com/1063/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1063&subd=rhredhatmagazine&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://magazine.redhat.com/2008/11/05/introducing-pylons-a-hackers-web-framework/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Noah Gift</media:title>
		</media:content>
	</item>
		<item>
		<title>Video: Spotlight on PackageKit</title>
		<link>http://magazine.redhat.com/2008/10/29/video-spotlight-on-packagekit/</link>
		<comments>http://magazine.redhat.com/2008/10/29/video-spotlight-on-packagekit/#comments</comments>
		<pubDate>Wed, 29 Oct 2008 22:48:55 +0000</pubDate>
		<dc:creator>The editorial team</dc:creator>
				<category><![CDATA[multimedia]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2008/10/29/video-spotlight-on-packagekit/</guid>
		<description><![CDATA[
Download this video: [Ogg Theora]



In the second installment of the Spotlight On series, we feature Red Hat engineer Richard Hughes on the fantastic new abstraction layer called PackageKit. PackageKit allows users to manage packages in a secure way using a cross-distro, cross-architecture API. This maintains a common set of GUI features, enabling the user to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1068&subd=rhredhatmagazine&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><div class="alignLeft">
<object id="http://www.redhat.com/v/swf/redbox/redbox-player.swf?oid=http://www.redhat.com/v/magazine/swf/HughesRHM.flv" width="320" height="260" data="http://www.redhat.com/v/swf/redbox/redbox-player.swf?oid=http://www.redhat.com/v/magazine/swf/HughesRHM.flv" type="application/x-shockwave-flash">
<param name="movie" value="http://www.redhat.com/v/swf/redbox/redbox-player.swf?oid=http://www.redhat.com/v/magazine/swf/HughesRHM.flv" />
<param name="bgcolor" value="#000000" />
<param name="quality" value="high" />
<param name="flashvars" value="file=http://www.redhat.com/v/magazine/swf/HughesRHM.flv&amp;vid_skin=http://www.redhat.com/v/swf/redbox/redbox-gui.swf&amp;autoStart=false&amp;image=http://www.redhat.com/g/magazine/packagekit2.png&amp;omniEnv=redhatcom" />
</object></p>
<div class="caption">Download this video: [<a href="http://www.redhat.com/v/magazine/ogg/HughesRHM.ogg">Ogg Theora</a>]
</div>
<p><!-- caption --></div>
<p><!-- alignLeft --></p>
<p>In the second installment of the Spotlight On series, we feature Red Hat engineer Richard Hughes on the fantastic new abstraction layer called PackageKit. PackageKit allows users to manage packages in a secure way using a cross-distro, cross-architecture API. This maintains a common set of GUI features, enabling the user to have a better session experience overall. For more information, visit <a href="http://www.packagekit.org">www.packagekit.org</a>.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rhredhatmagazine.wordpress.com/1068/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rhredhatmagazine.wordpress.com/1068/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rhredhatmagazine.wordpress.com/1068/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rhredhatmagazine.wordpress.com/1068/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rhredhatmagazine.wordpress.com/1068/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rhredhatmagazine.wordpress.com/1068/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rhredhatmagazine.wordpress.com/1068/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rhredhatmagazine.wordpress.com/1068/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rhredhatmagazine.wordpress.com/1068/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rhredhatmagazine.wordpress.com/1068/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1068&subd=rhredhatmagazine&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://magazine.redhat.com/2008/10/29/video-spotlight-on-packagekit/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
<enclosure url="http://www.redhat.com/v/magazine/swf/HughesRHM.flv" length="22519799" type="video/x-flv" />
	
		<media:content url="" medium="image">
			<media:title type="html">The editorial team</media:title>
		</media:content>
	</item>
		<item>
		<title>This isn&#8217;t your grandpappy&#8217;s dd command</title>
		<link>http://magazine.redhat.com/2008/10/02/this-isnt-your-grandpappys-dd-command/</link>
		<comments>http://magazine.redhat.com/2008/10/02/this-isnt-your-grandpappys-dd-command/#comments</comments>
		<pubDate>Thu, 02 Oct 2008 15:03:10 +0000</pubDate>
		<dc:creator>Noah Gift</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2008/10/02/this-isnt-your-grandpappys-dd-command/</guid>
		<description><![CDATA[co-authored with Grig Gheorghiu
Background
The dd command is one of those ancient UNIX tools that is extremely powerful, yet at the same time, the syntax can make it feel slightly archaic. A lot of seasoned sysadmins and developers still remember the first time they saw the dd command used by a bearded wizard. He might have [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1058&subd=rhredhatmagazine&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><em>co-authored with Grig Gheorghiu</em></p>
<h2>Background</h2>
<p>The dd command is one of those ancient UNIX tools that is extremely powerful, yet at the same time, the syntax can make it feel slightly archaic. A lot of seasoned sysadmins and developers still remember the first time they saw the dd command used by a bearded wizard. He might have used it to test the disk I/O, capture a disk image, or restore it.</p>
<p>In some ways, dd can seem like Old Spice&#8211;only the guys over 60 use it.  But the younger generation should know that dd still has some tricks up its sleeve. In this article, we&#8217;re going to put a new twist on this old favorite and show how grandpappy really does know best sometimes. The new twist is to mix dd with Python and the Google Chart API to make a UNIX 2.0 mashup tool. (&#8220;UNIX 2.0&#8243; is a play on words for what happens when you change the original behavior of a tool like dd to make it do something a bit different.)  <span id="more-1058"></span></p>
<h2>Setup</h2>
<p>For this article, we assume you&#8217;re running Fedora Core 8. We&#8217;re actually just renting some time from Amazon in all of these examples. To do that we allocated a 1 GB Elastic Block Storage volume from Amazon and attached it as the device /dev/sdd to an Amazon Machine Instance (AMI) running Fedora Core 8.  <a href="http://www.redhat.com/solutions/cloud/">Learn more about using Amazon Cloud Computing with Red Hat.</a></p>
<h2>Using dd for disk benchmarking with Google Charts API and Python</h2>
<p>We benchmarked the throughput of the disk by running the dd command with various block sizes from 128 KB to 1 MB. (Note: If you want to run the script on your own machine, make sure that the volume you use doesn&#8217;t contain any valuable data, because the data will be erased by the dd command. Remember, data loss makes grandpappy mad!)</p>
<p>For the benchmark, we wrote a Python script that uses the commands module to run and capture the output of the dd command. The script also uses the csv module to generate a comma-separated values file so that we can graph the results later. For this example, we chose to graph the results using the Google Chart API.</p>
<pre class="screen">
#!/usr/bin/env python
import commands
import re
import csv
</pre>
<p>Next we define the main function, which takes a device name and a block size as parameters, and returns the throughput measured with dd and the unit of measure (e.g. MB/s). We use the regular expression module (re) to isolate the throughput value and unit of measure from the output of the dd command.</p>
<p><em>Editor&#8217;s note: In the code below,  <code>unit = ""</code> has been added since the article was posted.</em></p>
<pre class="screen">
def get_disk_throughput(device, blocksize):

    blocksize = str(blocksize) + 'k'

    cmd = "dd if=/dev/zero of=%s bs=%s" % (device, blocksize)

    output = commands.getoutput(cmd)

    throughput = 0

    unit = ""

    for line in output.split('\n'):

        s = re.search(' copied,.*, (\S+) (\S+)$', line)

        if s:

            throughput = s.group(1)

            unit = s.group(2)

            break

    return (throughput, unit)
</pre>
<p>Here is the portion of the script that is executed when it&#8217;s run from the command line. We open a csv file and associate it with a csv writer. We then use the writerow method of the writer to append the header and each data row. We iterate over the list of block sizes and call the get_disk_throughput function for each block size.</p>
<p>We also compose the Google Chart URL by filling in the exact data values, represented by the throughput numbers that we obtain from the get_disk_throughput function. Then we print the URL to stdout. If you <a href="http://chart.apis.google.com/chart?cht=bvs&amp;chtt=Disk%20throughput&amp;chs=400x250&amp;chd=t:62.6,63.6,63.0,63.7&amp;chl=128k%7C256k%7C512k%7C1024k&amp;chxt=x,y&amp;chxr=1,0,73.7&amp;chds=0,73.7">check the URL</a>, you&#8217;ll see the chart generated with our data.</p>
<p>For details on the Google Chart API and what each parameter to the URL represents, see the  <a href="http://code.google.com/apis/chart">Developer&#8217;s Guide</a>.</p>
<p><em>Editor&#8217;s note: This is an updated version of the code that originally appeared with this article. It has command-line argument processing, and it composes the Google Chart URL in a better, more self-explanatory fashion. See the end of the article for the original.</em></p>
<pre class="screen">
f = open('disk_throughput.csv', 'w')
        writer = csv.writer(f)
        writer.writerow( ('Block size (KB)', 'Throughput') )
        blocksizes = [128, 256, 512, 1024]
        gchart_url = "http://chart.apis.google.com/chart?"
        gchart_type = "cht=bvs"
        gchart_title = "&amp;chtt=Disk%20throughput"
        gchart_size = "&amp;chs=400x250"
        gchart_axis_labels = "&amp;chxt=x,y"
        gchart_data = "&amp;chd=t:"
        gchart_labels = "&amp;chl="
        max_t = 0.0
        for blocksize in blocksizes:
            (t, u) = get_disk_throughput(device, blocksize)
            if float(t) &gt; max_t:
                max_t = float(t)
            writer.writerow( (blocksize, t) )
            print 'Block Size: %sk Throughput: %s %s' % (blocksize, t, u)
            gchart_data += t + ","
            gchart_labels += str(blocksize) + "k" + "|"
        gchart_data = gchart_data.rstrip(',')
        gchart_labels = gchart_labels.rstrip('|')
        gchart_axis_range = "&amp;chxr=1,0," + str(max_t+10.0)
        gchart_scaling = "&amp;chds=0," + str(max_t+10.0)
        gchart_url += gchart_type + gchart_title + gchart_size + gchart_data + gchart_labels
        gchart_url += gchart_axis_labels + gchart_axis_range + gchart_scaling
        print "Google Chart URL (just paste in a browser):", gchart_url
    finally:
        f.close()</pre>
<p>Here is the output of the script in one of our runs:</p>
<pre class="screen">
Block Size: 128 Throughput: 62.8 MB/s

Block Size: 256 Throughput: 61.8 MB/s

Block Size: 512 Throughput: 57.1 MB/s

Block Size: 1024 Throughput: 56.5 MB/s
</pre>
<p>Now here is the actual image that gets created:<br />
<a href="http://www.flickr.com/photos/redhatmagazine/2907593650/"><img src="http://farm4.static.flickr.com/3151/2907593650_32339224ba_o.png"></a></p>
<h2>Full script</h2>
<pre class="screen">
#!/usr/bin/env python

import sys
import commands
import re
import csv
from optparse import OptionParser

def get_disk_throughput(device, blocksize):
    blocksize = str(blocksize) + 'k'
    cmd = "dd if=/dev/zero of=%s bs=%s" % (device, blocksize)
    output = commands.getoutput(cmd)
    throughput = 0
    unit = ""
    for line in output.split('\n'):
        s = re.search(' copied,.*, (\S+) (\S+)$', line)
        if s:
            throughput = s.group(1)
            unit = s.group(2)
            break
    return (throughput, unit)

if __name__ == "__main__":

    usage = "usage: %prog options"
    parser = OptionParser(usage=usage)
    parser.add_option("-d", "--device", dest="device",
            help="Disk device to operate on (NOTE: any data on that device will be lost)")
    (options, args) = parser.parse_args()
    device = options.device
    if not device:
        parser.print_help()
        sys.exit(1)

    try:
        f = open('disk_throughput.csv', 'w')
        writer = csv.writer(f)
        writer.writerow( ('Block size (KB)', 'Throughput') )
        blocksizes = [128, 256, 512, 1024]
        gchart_url = "http://chart.apis.google.com/chart?"
        gchart_type = "cht=bvs"
        gchart_title = "&amp;chtt=Disk%20throughput"
        gchart_size = "&amp;chs=400x250"
        gchart_axis_labels = "&amp;chxt=x,y"
        gchart_data = "&amp;chd=t:"
        gchart_labels = "&amp;chl="
        max_t = 0.0
        for blocksize in blocksizes:
            (t, u) = get_disk_throughput(device, blocksize)
            if float(t) &gt; max_t:
                max_t = float(t)
            writer.writerow( (blocksize, t) )
            print 'Block Size: %sk Throughput: %s %s' % (blocksize, t, u)
            gchart_data += t + ","
            gchart_labels += str(blocksize) + "k" + "|"
        gchart_data = gchart_data.rstrip(',')
        gchart_labels = gchart_labels.rstrip('|')
        gchart_axis_range = "&amp;chxr=1,0," + str(max_t+10.0)
        gchart_scaling = "&amp;chds=0," + str(max_t+10.0)
        gchart_url += gchart_type + gchart_title + gchart_size + gchart_data + gchart_labels
        gchart_url += gchart_axis_labels + gchart_axis_range + gchart_scaling
        print "Google Chart URL (just paste in a browser):", gchart_url
    finally:
        f.close()</pre>
<h2>Summary</h2>
<p>In this article we shattered the myth that you must be 60, have a massive grey beard, and have worked at Bell Labs to use the dd command. Even for a newer generation, dd can be used in some inventive ways. We combined Python, the Google Chart API, and Red Hat on Amazon&#8217;s cloud computing infrastructure to create a novel way to measure and chart disk I/O and performance. Go celebrate by buying yourself a bottle of Old Spice.</p>
<h2>References</h2>
<p>Python: <a href="http://www.python.org/">http://www.python.org/</a><br />
dd example scripts:  <a href="http://tldp.org/LDP/abs/html/extmisc.html">http://tldp.org/LDP/abs/html/extmisc.html</a><br />
Google Chart API:  <a href="http://code.google.com/apis/chart/">http://code.google.com/apis/chart/</a></p>
<h2>Original code</h2>
<pre class="screen">
if __name__ == "__main__":

    try:

        f = open('disk_throughput.csv', 'w')

        writer = csv.writer(f)

        writer.writerow( ('Block size (KB)', 'Throughput') )

        device = '/dev/sdd'

        blocksizes = [128, 256, 512, 1024]

        google_chart_url = "http://chart.apis.google.com/chart?cht=bvs&amp;chd=t:"

        google_chart_data = ""

        google_chart_labels = ""

        max_t = 0.0

        for blocksize in blocksizes:

            (t, u) = get_disk_throughput(device, blocksize)

            if float(t) &gt; max_t:

                max_t = float(t)

            writer.writerow( (blocksize, t) )

            print 'Block Size: %s Throughput: %s %s' % (blocksize, t, u)

            google_chart_data += t + ","

            google_chart_labels += str(blocksize) + "k" + "|"

        google_chart_data = google_chart_data.rstrip(',')

        google_chart_labels = google_chart_labels.rstrip('|')

        google_chart_url += google_chart_data +"&amp;chl=" + google_chart_labels

        google_chart_url += "&amp;chtt=Disk%20throughput" +"&amp;chs=400x250&amp;chxt=x,y"

        google_chart_url += "&amp;chxr=1,0,%s&amp;chds=0,%s" % (str(max_t+10.0), str(max_t+10.0))

        print google_chart_url

    finally:

        f.close()
</pre>
<h2>Authors</h2>
<p><b>Noah Gift</b> is the co-author of <em>Python For Unix and Linux</em> by O&#8217;Reilly, and <em>Google App Engine in Action</em> by Manning. He is an author, speaker, consultant, and community leader, writing for publications such as IBM Developerworks, Red Hat Magazine, O&#8217;Reilly, Manning, and MacTech. He has a master&#8217;s degree in CIS from Cal State Los Angeles, a B.S. in nutritional science from Cal Poly San Luis Obispo, and is an Apple and LPI certified sys admin. He&#8217;s worked at companies that include Caltech, Disney Feature Animation, Sony Imageworks, Turner Studios, and most recently, WetaDigital.</p>
<p><strong>Grig Gheorghiu</strong> is the director of technology for RIS Technology, a web hosting company based in Los Angeles. Grig has 15 years industry experience, during which time he has worked as a programmer, research lab manager, system/network/security architect, IT consultant, and lead test engineer.</p>
<p>Grig is an active member of the Python and agile testing communities. He maintains a <a href="http://agiletesting.blogspot.com">blog</a> dedicated to agile testing, Python programming, and automated testing tools and techniques.  Grig is the founder of the Southern California Python Interest Group, aka <a href="http://socal-piggies.org">“the SoCal Piggies”</a>. He lives in Los Angeles with his wife and two children.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rhredhatmagazine.wordpress.com/1058/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rhredhatmagazine.wordpress.com/1058/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rhredhatmagazine.wordpress.com/1058/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rhredhatmagazine.wordpress.com/1058/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rhredhatmagazine.wordpress.com/1058/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rhredhatmagazine.wordpress.com/1058/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rhredhatmagazine.wordpress.com/1058/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rhredhatmagazine.wordpress.com/1058/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rhredhatmagazine.wordpress.com/1058/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rhredhatmagazine.wordpress.com/1058/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1058&subd=rhredhatmagazine&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://magazine.redhat.com/2008/10/02/this-isnt-your-grandpappys-dd-command/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Noah Gift</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3151/2907593650_32339224ba_o.png" medium="image" />
	</item>
		<item>
		<title>JBoss Drools how-to: Tuning Guvnor, part 2</title>
		<link>http://magazine.redhat.com/2008/08/14/jboss-drools-how-to-tuning-guvnor-part-2/</link>
		<comments>http://magazine.redhat.com/2008/08/14/jboss-drools-how-to-tuning-guvnor-part-2/#comments</comments>
		<pubDate>Thu, 14 Aug 2008 22:34:10 +0000</pubDate>
		<dc:creator>kijanowski</dc:creator>
				<category><![CDATA[JBoss]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2008/08/14/jboss-drools-how-to-tuning-guvnor-part-2/</guid>
		<description><![CDATA[Guvnor is the business rules management system in Drools 5. When you deploy it out of the box, you get an unsecured web application that stores data in Jackrabbit&#8217;s embedded Derby database.
This two-part article explains how to tune Guvnor deployed on JBoss Application Server 4.2.3. (If you missed the first half of the series, catch [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1021&subd=rhredhatmagazine&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Guvnor is the business rules management system in Drools 5. When you deploy it out of the box, you get an unsecured web application that stores data in Jackrabbit&#8217;s embedded Derby database.</p>
<p>This two-part article explains how to tune Guvnor deployed on JBoss Application Server 4.2.3. (If you missed the first half of the series, <a href="http://www.redhatmagazine.com/2008/08/12/jboss-drools-how-to-tuning-guvnor-part-1/">catch up</a> in our archives.)This means that we will use the container&#8217;s configuration files and security infrastructure. This installment covers enabling password validation based on an OpenLDAP server, moving from the default data repository, and enabling SSL for better security.<span id="more-1021"></span></p>
<ol>
<li><a href="#ldap">Use OpenLDAP as a user repository</a></li>
<li><a href="#mysql">Use MySQL as a data repository</a></li>
<li><a href="#ssl">Enable SSL</a></li>
<li><a href="#secured">How to use a secured Guvnor package</a></li>
<li><a href="#summary">Summary</a></li>
</ol>
<p><a name="ldap"></a></p>
<h2>Use OpenLDAP as a user repository</h2>
<p>There are several reasons why you would want to use an LDAP directory instead of a clear text file &#8212; security, provisioning,  and reuseability are just a few. First of all, we need a directory. OpenLDAP will do for this example. Download and extract the bits from the OpenLDAP <a href="http://www.openldap.org/">home page</a>. In this example, I&#8217;ve used <a href="ftp://ftp.openldap.org/pub/OpenLDAP/openldap-stable/openldap-stable-20071118.tgz">openldap-2.3.39.tgz</a>. Next, go to the directory where you&#8217;ve extracted the installation files and perform following steps:</p>
<pre>
$ mkdir -p /data/openldap-2.3.39
$ ./configure --prefix=/data/openldap-2.3.39
$ make depend
$ make
$ make install
</pre>
<p>For more detailed instructions, look at the INSTALL file or the <a href="http://www.openldap.org/doc/admin23/">OpenLDAP Administrator&#8217;s Guide</a>.</p>
<p>The next instructions will configure our directory and create a tree which looks like this:</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2744228157/" title="Fig 2.1  tree by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3093/2744228157_6ccd75dac5.jpg" width="500" height="334" alt="Fig 2.1  tree" /></a></p>
<div class="caption">Fig 2.1 tree</div>
<p>We need to initialize the LDAP server and provide data like the root suffix, directory manager, and password. We also want to enable SSL like so:</p>
<pre>
$ mkdir /data/openldap-2.3.39/ssl
$ openssl req -newkey rsa:1024 -x509 -nodes -out /data/openldap-2.3.39/ssl/server.pem -keyout /data/openldap-2.3.39/ssl/server.pem -days 365
Generating a 1024 bit RSA private key
....++++++
................++++++
writing new private key to 'server.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:EU
State or Province Name (full name) [Berkshire]:Mazovia
Locality Name (eg, city) [Newbury]:Warsaw
Organization Name (eg, company) [My Company Ltd]:Kijanowski
Organizational Unit Name (eg, section) []:Guvnor
Common Name (eg, your name or your server's hostname) []:localhost
Email Address []:a@a.a
</pre>
<p>Since this is a self-signed certificate we will need to add it to the client&#8217;s (JBoss AS) truststore.</p>
<pre>
$ openssl
OpenSSL&gt; x509 -inform PEM -outform DER -in /data/openldap-2.3.39/ssl/server.pem -out /data/openldap-2.3.39/ssl/server.der
OpenSSL&gt; exit

$ keytool -import -file /data/openldap-2.3.39/ssl/server.der -keystore $JBOSS_SERVER/conf/ldap.truststore

Enter keystore password:  qwerty
Owner: EMAILADDRESS=a@a.a, CN=localhost, OU=Guvnor, O=Kijanowski, L=Warsaw, ST=Mazovia, C=EU
Issuer: EMAILADDRESS=a@a.a, CN=localhost, OU=Guvnor, O=Kijanowski, L=Warsaw, ST=Mazovia, C=EU
Serial number: d8537a079c5eed59
Valid from: Wed Jul 16 18:35:50 CEST 2008 until: Thu Jul 16 18:35:50 CEST 2009
Certificate fingerprints:
         MD5:  25:C5:88:7B:D4:88:02:46:F1:EF:0D:6B:D6:EE:1F:A7
         SHA1: 57:B8:F4:25:77:F0:12:BD:B2:2E:DD:7D:CE:09:D2:D4:96:56:BC:26
Trust this certificate? [no]:  yes
Certificate was added to keystore
</pre>
<p>To enable the new truststore, edit <code>$JBOSS_SERVER/deploy/properties-service.xml</code> and add following lines:</p>
<pre>

    javax.net.ssl.trustStore=/data/jboss-4.2.3.GA/server//conf/ldap.truststore
    javax.net.ssl.trustStorePassword=qwerty
</pre>
<p>Now edit the file <code>/data/openldap-2.3.39/etc/openldap/slapd.conf</code>:</p>
<pre>
include         /data/openldap-2.3.39/etc/openldap/schema/core.schema
include         /data/openldap-2.3.39/etc/openldap/schema/cosine.schema
include         /data/openldap-2.3.39/etc/openldap/schema/inetorgperson.schema

pidfile         /data/openldap-2.3.39/var/run/slapd.pid
argsfile        /data/openldap-2.3.39/var/run/slapd.args

database        bdb
suffix          "dc=kijanowski,dc=eu"
rootdn          "cn=DirManager,dc=kijanowski,dc=eu"
rootpw          secret
directory       /data/openldap-2.3.39/var/openldap-data
index   objectClass     eq

TLSCipherSuite HIGH:MEDIUM:-SSLv2
TLSCACertificateFile /data/openldap-2.3.39/ssl/server.pem
TLSCertificateFile /data/openldap-2.3.39/ssl/server.pem
TLSCertificateKeyFile /data/openldap-2.3.39/ssl/server.pem
TLSVerifyClient never
</pre>
<p>The rootpw attribute should be changed from &#8217;secret&#8217; to:</p>
<pre>
$ /data/openldap-2.3.39/sbin/slappasswd -s admin123
</pre>
<p>where &#8216;admin123&#8242; is the new directory manager&#8217;s password. For better performance, you can create a config file for the backend database or copy the sample configuration file like so:</p>
<pre>
$ cp /data/openldap-2.3.39/var/openldap-data/DB_CONFIG.example /data/openldap-2.3.39/var/openldap-data/DB_CONFIG
</pre>
<p>To start the server with a customized listener, run:</p>
<pre>
$ /data/openldap-2.3.39/libexec/slapd -h ldaps://localhost:16636
</pre>
<p>You can make sure your LDAP server is up and running (listening) by running:</p>
<pre>
$ netstat -an|grep 16636
tcp        0      0 127.0.0.1:16636             0.0.0.0:*                   LISTEN
</pre>
<p>To create tree like the one shown above, we need to add the following myorg.ldif file:</p>
<pre>
dn: dc=kijanowski,dc=eu
objectclass: top
objectclass: dcObject
objectclass: organization
dc: kijanowski
o: kijanowski

dn: o=guvnor,dc=kijanowski,dc=eu
objectclass: top
objectclass: organization
o: guvnor

dn: ou=People,o=guvnor,dc=kijanowski,dc=eu
objectclass: top
objectclass: organizationalUnit
ou: People

dn: uid=admin,ou=People,o=guvnor,dc=kijanowski,dc=eu
objectclass: top
objectclass: uidObject
objectclass: person
objectClass: inetOrgPerson
uid: admin
cn: Guvnor Admin
sn: Administrator
userPassword: {SSHA}ZGUjbzh0wN0JoWxIAcZfFXpV5MIu/gZw

dn: uid=user1,ou=People,o=guvnor,dc=kijanowski,dc=eu
objectclass: top
objectclass: uidObject
objectclass: person
objectClass: inetOrgPerson
uid: user1
cn: Regular User
sn: Regular
userPassword: {SSHA}Gcif1SlGPu2vHrtoLGYlKXbKBytJiVVF

dn: ou=Roles,o=guvnor,dc=kijanowski,dc=eu
objectClass: top
objectClass: organizationalUnit
ou: Roles

dn: cn=admin,ou=Roles,o=guvnor,dc=kijanowski,dc=eu
objectClass: top
objectClass: groupOfNames
cn: admin
description: the GuvnorAdmin group
member: uid=admin,ou=People,o=guvnor,dc=kijanowski,dc=eu

dn: cn=regular,ou=Roles,o=guvnor,dc=kijanowski,dc=eu
objectClass: top
objectClass: groupOfNames
cn: regular
description: the Guvnor Regular group
member: uid=user1,ou=People,o=guvnor,dc=kijanowski,dc=eu
</pre>
<p>The passwords for admin and user1 are &#8216;9uvn04&#8242; and &#8216;user1&#8242; (respectively) and were generated with slappasswd. To add this ldif to our directory, we will use an ldap client application called ldapadd. First we need to update its configuration to be able to talk over SSL. Edit the file <code>/data/openldap-2.3.39/etc/openldap/ldap.conf</code> and add following line:</p>
<pre>
TLS_REQCERT allow
</pre>
<p>This will prevent us from getting errors like these:</p>
<pre>
client side:
ldap_initialize( ldaps://localhost:16636 )
ldap_bind: Can't contact LDAP server (-1)
        additional info: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

server side:
TLS trace: SSL3 alert read:fatal:unknown CA
TLS trace: SSL_accept:failed in SSLv3 read client certificate A
TLS: can't accept.
TLS: error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca s3_pkt.c:1057
connection_read(11): TLS accept failure error=-1 id=4, closing
connection_closing: readying conn=4 sd=11 for close
connection_close: conn=4 sd=11
</pre>
<p>Now we can add the ldif file to our directory:</p>
<pre>
$ /data/openldap-2.3.39/bin/ldapadd -x -D "cn=DirManager,dc=kijanowski,dc=eu" -H ldaps://localhost:16636 -w admin123 -f myorg.ldif

adding new entry "dc=kijanowski,dc=eu"
adding new entry "o=guvnor,dc=kijanowski,dc=eu"
adding new entry "ou=People,o=guvnor,dc=kijanowski,dc=eu"
adding new entry "uid=admin,ou=People,o=guvnor,dc=kijanowski,dc=eu"
adding new entry "uid=user1,ou=People,o=guvnor,dc=kijanowski,dc=eu"
adding new entry "ou=Roles,o=guvnor,dc=kijanowski,dc=eu"
adding new entry "cn=admin,ou=Roles,o=guvnor,dc=kijanowski,dc=eu"
adding new entry "cn=regular,ou=Roles,o=guvnor,dc=kijanowski,dc=eu"
</pre>
<p>The last step is to configure JAAS in <code>$JBOSS_SERVER/conf/login-config.xml</code>. Replace the previous file based login module with this one:</p>
<pre>

            ldaps://localhost:16636
            ssl
            cn=DirManager,dc=kijanowski,dc=eu
            admin123

            ou=People,o=guvnor,dc=kijanowski,dc=eu
            (uid={0})

            ou=Roles,o=guvnor,dc=kijanowski,dc=eu
            (member={1})
            cn

            -1
            ONELEVEL_SCOPE
</pre>
<p>Now restart JBoss AS and try to login as admin with password 9uvn04. The application server will talk with the OpenLDAP server over SSL. If you want to shutdown the OpenLDAP server you need to determine its PID and interrupt it by sending the process a SIGINT signal:</p>
<pre>
$ kill -INT `cat /data/openldap-2.3.39/var/run/slapd.pid`
</pre>
<p><a name="mysql"></a></p>
<h2>Use MySQL as a data repository</h2>
<p>Jackrabbit has been chosen as a Java Content Repository (JCR) implementation. By default, it uses the Derby database as a backend. You may want to switch to a database you are more familiar with, and can regularly back up and properly tune. If you have already used the file-based repository and don&#8217;t want to loose all your assets, export them. After MySQL is up and running, import them back. To export your current repository, go to the &#8216;Administration&#8217; menu on the left side, expand &#8216;Admin,&#8217; choose &#8216;Import/Export,&#8217; and click on &#8216;Export&#8217;:</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2745062730/" title="Fig 2.2  export by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3255/2745062730_9186be390d.jpg" width="500" height="188" alt="Fig 2.2  export" /></a></p>
<div class="caption">Fig 2.2 export</div>
<p>Shut down the server and set up MySQL as your new repository. First, download <a href="http://dev.mysql.com/">MySQL</a> and extract it. I will use the <a href="http://dev.mysql.com/get/Downloads/MySQL-5.0/mysql-5.0.51a-linux-i686.tar.gz/from/http://mysql.linux.cz/">community server 5.0.51a standard</a>,  extracted to /data/mysql-5.0.51. As root, perform the following steps. (For more details, have a look at the INSTALL-BINARY file):</p>
<pre>
$ /usr/sbin/groupadd mysql5
$ /usr/sbin/useradd -g mysql5 mysql5
$ cd /data/mysql-5.0.51
$ chown -R mysql5 .
$ chgrp -R mysql5 .
$ /data/mysql-5.0.51/scripts/mysql_install_db --user=mysql5

$ chown -R root .
$ chown -R mysql5 data

# now start MySQL
$ /data/mysql-5.0.51/bin/mysqld_safe --user=mysql5 &amp;

# and create a password for root
$ /data/mysql-5.0.51/bin/mysqladmin -u root password mysqladminpwd
To shutdown the MySQL server run:
$ /data/mysql-5.0.51/bin/mysqladmin -u root shutdown -p
Logout as root and log in to MySQL to create a user and database for Guvnor:
$ /data/mysql-5.0.51/bin/mysql -u root -p
mysql&gt; create database guvnor;
Query OK, 1 row affected (0.00 sec)

mysql&gt; grant all privileges on guvnor.* to 'guvnor-user'@'localhost' identified by 'guvnor-pwd';
Query OK, 0 rows affected (0.00 sec)

mysql&gt; flush privileges;
Query OK, 0 rows affected (0.00 sec)
</pre>
<p>Now the DB side is complete.</p>
<p>Edit the <code>$GUVNOR/WEB-INF/components.xml</code> file and provide a path to where you would like to keep the repository configuration files. You can leave the default value&#8211;which is the JBoss Application Server&#8217;s bin directory&#8211;however it is recommended to provide a location that is regularly backed up. Under the &#8216;repositoryConfiguration&#8217; component add:</p>
<pre>
/data/GuvnorRepo/
</pre>
<p>This last step creates a repository.xml file. It is created by default when running Guvnor the first time and is placed into the AS bin directory. This file configures the data repository. We would like to use MySQL, so we will create <code>/data/GuvnorRepo/repository.xml</code>:</p>
<pre>

        <!-- Define where to store global data -->

                        <!-- param name="externalBLOBs" value="false" /-->
</pre>
<p>As you see we&#8217;re using the com.mysql.jdbc.Driver, so we need to provide it. Download the mysql java connector from <a href="http://dev.mysql.com/">MySQL</a>, unzip it, and copy the JAR file to $JBOSS_SERVER/lib. (I&#8217;m using <a href="http://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.6.zip/from/http://mysql.linux.cz/">mysql-connector-java-5.1.6</a>.)</p>
<p>Now you can start the app server. If you have exported your assets, just go to the &#8216;Administration&#8217; menu, expand &#8216;Admin,&#8217; choose &#8216;Import/Export,&#8217; and import your xml file. Please note that you have to unzip your exported xml file before you can upload it.</p>
<p><a name="ssl"></a></p>
<h2>Enable SSL</h2>
<p>The last tweak is enabling SSL. It not only provides security, but also ensures the transmitted data hasn&#8217;t been modified. This is strictly a server-side task.</p>
<p>First, we need a certificate. Please note that as the &#8220;first and last name&#8221; you have to provide the <strong>fully qualified domain name</strong> of the host. For testing purposes you can use localhost like so:</p>
<pre>
$ keytool -genkey -alias guvnor -keyalg RSA -keystore $JBOSS_SERVER/conf/guvnor.keystore -validity 365

Enter keystore password:  guvnorkspwd
What is your first and last name?
  [Unknown]:  localhost
What is the name of your organizational unit?
  [Unknown]:  My Department
What is the name of your organization?
  [Unknown]:  My Company
What is the name of your City or Locality?
  [Unknown]:  My City
What is the name of your State or Province?
  [Unknown]:  My State
What is the two-letter country code for this unit?
  [Unknown]:  US
Is CN=My Name, OU=My Department, O=My Company, L=My City, ST=My State, C=US correct?
  [no]:  yes

Enter key password for
        (RETURN if same as keystore password):
</pre>
<p>Now we can enable an SSL connector. Edit the file $JBOSS_SERVER/deploy/jboss-web.deployer/server.xml like so:</p>
<pre>
</pre>
<p>Restart your JBoss Application Server. Guvnor should be available at <a href="https://localhost:8443/drools-guvnor">https://localhost:8443/drools-guvnor</a>.</p>
<p><a name="secured"></a></p>
<h2>How to use a secured Guvnor package</h2>
<p>The last part of this article shows how you can access a drools package from Guvnor in a secure way. This is very straight forward if you use certificates signed by trusted authorities. In our test environment, it&#8217;s a little bit more complicated since we use self-signed certificates.</p>
<p>First create a package and deploy it. I&#8217;ll use the package we made during the quick introduction. This package is available under <a href="https://localhost:8443/drools-guvnor/org.drools.guvnor.Guvnor/package/myNewPackage/LATEST">https://localhost:8443/drools-guvnor/org.drools.guvnor.Guvnor/package/myNewPackage/LATEST</a>. Replace the url attribute with the new value in Guvnor.properties:</p>
<pre>
url=https://localhost:8443/drools-guvnor/org.drools.guvnor.Guvnor/package/myNewPackage/LATEST
</pre>
<p>One would expect that running the Drools application should end successfully, however this is not the case:</p>
<pre>
RuleAgent(default) INFO (Wed Jul 23 20:38:03 CEST 2008): Configuring with newInstance=false, secondsToRefresh=-1
RuleAgent(default) INFO (Wed Jul 23 20:38:03 CEST 2008): Configuring package provider : URLScanner monitoring URLs:  https://localhost:8443/drools-guvnor/org.drools.guvnor.Guvnor/package/myNewPackage/LATEST
RuleAgent(default) WARNING (Wed Jul 23 20:38:04 CEST 2008): Was an error contacting https://localhost:8443/drools-guvnor/org.drools.guvnor.Guvnor/package/myNewPackage/LATEST. Reponse header: {}
RuleAgent(default) EXCEPTION (Wed Jul 23 20:38:04 CEST 2008): Was unable to reach server.. Stack trace should follow.
java.io.IOException: Was unable to reach server.
        at org.drools.agent.URLScanner.hasChanged(URLScanner.java:149)
        at org.drools.agent.URLScanner.getChangeSet(URLScanner.java:113)
        at org.drools.agent.URLScanner.loadPackageChanges(URLScanner.java:90)
        at org.drools.agent.RuleAgent.checkForChanges(RuleAgent.java:341)
        at org.drools.agent.RuleAgent.refreshRuleBase(RuleAgent.java:300)
        at org.drools.agent.RuleAgent.configure(RuleAgent.java:285)
        at org.drools.agent.RuleAgent.init(RuleAgent.java:209)
        at org.drools.agent.RuleAgent.newRuleAgent(RuleAgent.java:177)
        at org.drools.agent.RuleAgent.newRuleAgent(RuleAgent.java:149)
        at org.drools.agent.RuleAgent.newRuleAgent(RuleAgent.java:217)
        at kijanowski.eu.GuvnorTest.main(GuvnorTest.java:12)
Exception in thread "main" java.lang.NullPointerException
        at org.drools.agent.RuleAgent.refreshRuleBase(RuleAgent.java:301)
        at org.drools.agent.RuleAgent.configure(RuleAgent.java:285)
        at org.drools.agent.RuleAgent.init(RuleAgent.java:209)
        at org.drools.agent.RuleAgent.newRuleAgent(RuleAgent.java:177)
        at org.drools.agent.RuleAgent.newRuleAgent(RuleAgent.java:149)
        at org.drools.agent.RuleAgent.newRuleAgent(RuleAgent.java:217)
        at kijanowski.eu.GuvnorTest.main(GuvnorTest.java:12)
</pre>
<p>If you navigate with your browser to this URL, you will be asked to accept the non-signed certificate. In case of our test application, we need to trust the server by importing its public key to our (temporary) local keystore:</p>
<pre>
$ mkdir /data/ssl

# export the public key
$ keytool -export -alias guvnor -keystore $JBOSS_SERVER/conf/guvnor.keystore -file /data/ssl/out.cert

# you don't have to provide a password
Enter keystore password:

*****************  WARNING WARNING WARNING  *****************
* The integrity of the information stored in your keystore  *
* has NOT been verified!  In order to verify its integrity, *
* you must provide your keystore password.                  *
*****************  WARNING WARNING WARNING  *****************

Certificate stored in file 

# import this key to a local truststore
$ keytool -import -alias guvnor -file /data/ssl/out.cert -keystore /data/ssl/myKS

Enter keystore password:  qwerty
Owner: CN=localhost, OU=My Department, O=My Company, L=My City, ST=My State, C=US
Issuer: CN=localhost, OU=My Department, O=My Company, L=My City, ST=My State, C=US
Serial number: 48862cb6
Valid from: Tue Jul 22 20:53:42 CEST 2008 until: Wed Jul 22 20:53:42 CEST 2009
Certificate fingerprints:
         MD5:  81:FD:97:97:12:E7:2B:94:DA:62:35:11:2C:2B:4E:2B
         SHA1: 7E:B1:36:F4:C9:F9:45:5A:98:F2:F1:46:F6:58:E6:0D:81:46:EC:B5
Trust this certificate? [no]:  yes
Certificate was added to keystore
</pre>
<p>Now we have a keystore with a server&#8217;s key that we trust. To use this keystore, just start the drools application with the following property:</p>
<pre>
-Djavax.net.ssl.trustStore=/data/ssl/myKS
</pre>
<p>In Eclipse, click on GuvnorTest.java. From the menu Run -&gt; Open Run Dialog and then add this property to the VM arguments:</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2745062728/" title="Fig 2.3  eclipse by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3075/2745062728_7bac4326aa.jpg" width="500" height="443" alt="Fig 2.3  eclipse" /></a></p>
<div class="caption">Fig 2.3 eclipse</div>
<p>Now your Drools application runs in a secure environment.</p>
<p><a name="summary"></a></p>
<h2>Summary</h2>
<p>This article has shown how you can upgrade your BRMS, which should only be deployed out-of-the-box for testing purposes. For a multiuser environment with mission-critical applications, Guvnor should be tuned. Have a look at this <a href="http://blogs.sun.com/andreas/entry/no_more_unable_to_find">blog post</a>, the <a href="http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html">JSSE Reference Guide</a> or the <a href="http://java.sun.com/javase/6/docs/technotes/tools/solaris/keytool.html">key tool docs page</a> for more details about the tools we used. For LDAP browsing I recommend this <a href="http://www-unix.mcs.anl.gov/~gawor/ldap/index.html">user-friendly and light-weight tool</a>.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/rhredhatmagazine.wordpress.com/1021/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/rhredhatmagazine.wordpress.com/1021/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rhredhatmagazine.wordpress.com/1021/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rhredhatmagazine.wordpress.com/1021/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rhredhatmagazine.wordpress.com/1021/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rhredhatmagazine.wordpress.com/1021/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rhredhatmagazine.wordpress.com/1021/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rhredhatmagazine.wordpress.com/1021/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rhredhatmagazine.wordpress.com/1021/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rhredhatmagazine.wordpress.com/1021/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rhredhatmagazine.wordpress.com/1021/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rhredhatmagazine.wordpress.com/1021/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=1021&subd=rhredhatmagazine&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://magazine.redhat.com/2008/08/14/jboss-drools-how-to-tuning-guvnor-part-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">kijanowski</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3093/2744228157_6ccd75dac5.jpg" medium="image">
			<media:title type="html">Fig 2.1  tree</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3255/2745062730_9186be390d.jpg" medium="image">
			<media:title type="html">Fig 2.2  export</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3075/2745062728_7bac4326aa.jpg" medium="image">
			<media:title type="html">Fig 2.3  eclipse</media:title>
		</media:content>
	</item>
		<item>
		<title>Open source telephony: a Fedora-based VoIP server with Asterisk</title>
		<link>http://magazine.redhat.com/2008/07/24/open-source-telephony-a-fedora-based-voip-server-with-asterisk/</link>
		<comments>http://magazine.redhat.com/2008/07/24/open-source-telephony-a-fedora-based-voip-server-with-asterisk/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 22:37:47 +0000</pubDate>
		<dc:creator>The editorial team</dc:creator>
				<category><![CDATA[Fedora]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2008/07/24/open-source-telephony-a-fedora-based-voip-server-with-asterisk/</guid>
		<description><![CDATA[Voice over Internet Protocol (VoIP) has emerged as a popular technology for modern voice communications. Many organizations have replaced their analog or proprietary digital telephone systems with VoIP-based solutions. This allows the consolidation of telephone services into an existing IP infrastructure. In addition, using IP to host voice services lets the organization leverage existing expertise&#8211;while [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=986&subd=rhredhatmagazine&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Voice over Internet Protocol (VoIP) has emerged as a popular technology for modern voice communications. Many organizations have replaced their analog or proprietary digital telephone systems with VoIP-based solutions. This allows the consolidation of telephone services into an existing IP infrastructure. In addition, using IP to host voice services lets the organization leverage existing expertise&#8211;while retaining all of the network&#8217;s management advantages. Though not without its disadvantages, VoIP provides a compelling option to those looking for a telephone solution.</p>
<p>This article will present a simple VoIP solution using Asterisk, an open source private branch exchange (PBX) product. It will show you how to install Asterisk, configure it using its LDAP backend, and connect to it using the Ekiga software VoIP client and a Cisco 7900 Series VoIP telephone to make calls.<span id="more-986"></span></p>
<h2>Prerequisites</h2>
<dl class="adnote">
<dt>Important note about Asterisk:</dt>
<dd>Asterisk 1.6 Beta 10 has not yet been released. This version will fix a bug in Asterisk&#8217;s realtime LDAP code that causes the server to crash. In the meantime, one may compile the upcoming realtime LDAP module and install it for use with Fedora&#8217;s packages. In order to do this, follow the following instructions after installing the Fedora Asterisk packages:</p>
<ol>
<li>Execute &#8220;yum install openldap-devel&#8221;</li>
<li>Download the Asterisk 1.6 Beta 9 source from http://www.asterisk.org/ and extract it.</li>
<li>Enter the resulting asterisk-1.6.0-beta9 directory.</li>
<li>Apply the patch available at http://www.flyn.org/patches/asterisk-1.6.0-beta9-crashfix/asterisk-1.6.0-beta9-crashfix.patch.gz by downloading it and executing &#8220;gunzip -c PATH-TO-PATCH.gz | patch -p1&#8243; from within the asterisk-1.6.0-beta9 directory.</li>
<li>Execute &#8220;./configure &#8211;prefix=/usr &#8211;sysconf=/etc&#8221;</li>
<li>Execute &#8220;make res&#8221;</li>
<li>Execute &#8220;cp res/res_config_ldap.so /usr/lib/asterisk/modules/&#8221;</li>
</ol>
</dd>
</dl>
<p>There are a few prerequisites to discuss before covering the configuration of Asterisk. First, my instructions assume that you have already installed Fedora 9. Second, you must have an existing LDAP server. The LDAP schema I use in this article is compatible with Fedora Directory Server. I recommend using the <a href="http://www.freeipa.org/">FreeIPA</a> system to manage FDS. Fedora 9 provides packages for both FDS (fedora-ds-base) and FreeIPA (ipa-server). Finally, the machine hosting Asterisk must allow incoming UDP connections to ports 5060 (Session Initiation Protocol) and 69 (TFTP) to pass through its firewall.</p>
<dl class="adnote">
<dt>Note:</dt>
<dd>In general, the LDAP database is optional. All configurations may be stored in flat files on the Asterisk server&#8217;s disk. However, I have chosen to store my Asterisk users and extensions in an LDAP database. This is beneficial for organizations that wish to consolidate user information in LDAP. In addition, Asterisk&#8217;s realtime LDAP backend is new to 1.6. I hope to help fill the gap in existing documentation with this article.</dd>
</dl>
<p>Install the Asterisk components by executing the command <code>yum install asterisk asterisk-ldap asterisk-alsa asterisk-voicemail asterisk-voicemail-plain</code>. In order to configure a Cisco 7900 Series VoIP telephone, you will also need to execute <code>yum install tftp-server</code>, have an existing DHCP server (the one on an inexpensive wireless router will work fine) and a copy of Cisco&#8217;s Session Initiation Protocol (SIP) software for the phone.</p>
<dl class="adnote">
<dt>Note:</dt>
<dd>Depending on how you buy a Cisco telephone, you may need to purchase the rights to Cisco&#8217;s SIP software. Cisco telephones are typically sold with support for the proprietary SCCP protocol. In order to use the telephone with SIP, one must load a SIP flash image onto the telephone. This image may not have been included in the original telephone purchase. One way to obtain a license for the software is to purchase a Cisco SmartNet support package. Support for a 7900 Series telephone costs less than $10 and should be available from the vendor that sold you the telephone. I will cover installing the SIP software later in the article.</dd>
</dl>
<p>The Fedora project does not yet package Asterisk&#8217;s audio files because their copyright holder has not yet assigned a license to them (see Red Hat <a href="https://bugzilla.redhat.com/show_bug.cgi?id=428832">Bugzilla bug #428832</a>). These audio files are required to implement features like an echo test and voicemail. Fortunately, it is quite simple to install them. Visit the <a href="http://www.asterisk.org/">Asterisk website</a> and download the latest Asterisk 1.6 series release. Inside the Asterisk archive is another, <code>sounds/asterisk-core-sounds-en-gsm-1.4.11.tar.gz</code>. Extract this archive file into <code>/usr/share/asterisk/sounds</code>.</p>
<h2>Configuring the Asterisk PBX</h2>
<p>The Asterisk PBX has many features and is very flexible. In this section, I will focus on configuring four things: the SIP module, the extensions module, the external configuration engine, and the realtime LDAP backend. Once Asterisk is configured, I will demonstrate how to add SIP users and extensions to your LDAP database.</p>
<p>Asterisk provides a module to support the SIP protocol. SIP is used to set up and tear down a VoIP phone call. Though individual SIP users will be stored in an LDAP database, some global parameters will exist in the following configuration file. Save this configuration as <code>/etc/asterisk/sip.conf</code>:</p>
<pre>
[general]
videosupport=yes
allow=all
bindaddr=0.0.0.0
realm=example.com
</pre>
<dl>
<dt>videosupport</dt>
<dd>Enable support for video streaming.</dd>
<dt>allow</dt>
<dd>List of CODEC&#8217;s to allow.</dd>
<dt>bindaddr</dt>
<dd>IP address of the device to bind to. 0.0.0.0 ensures that Asterisk will listen on all available network devices.</dd>
<dt>realm</dt>
<dd>The authentication realm.</dd>
</dl>
<p>We will now move on to define extensions. In many cases, an extension is simply a telephone number that will be associated with a SIP user. Individual extensions, like SIP users, will be stored in an<br />
LDAP database. However, as with the SIP configuration, global parameters will be configured in a file,<br />
<code>/etc/asterisk/extensions.conf</code>. The following example supports the LDAP entries I will use in this article:</p>
<pre>
[users]
switch =&gt; Realtime/@

[demo]
switch =&gt; Realtime/@

[default]
include =&gt; users
include =&gt; demo
</pre>
<p>This example defines three contexts: default, users, and demo. The line <code>switch =&gt; Realtime/@</code> states that the extensions in a context will be defined using one of Asterisk&#8217;s realtime back-ends (in our case, LDAP). Each individual extension will be assigned to one of these contexts. As a collection of available extensions, contexts determine what happens when a user dials a phone number.</p>
<p>Asterisk&#8217;s external configuration engines are activated in <code>/etc/asterisk/extconfig.conf</code>.  The following example configures Asterisk to pull SIP and extension information using its real-time LDAP back-end:</p>
<pre>
[settings]
sipusers =&gt; ldap,"dc=example,dc=com",sip
sippeers =&gt; ldap,"dc=example,dc=com",sip
extensions =&gt; ldap,"dc=example,dc=com",extensions
 </pre>
<p>This example causes Asterisk to activate its real-time LDAP back-end look for SIP users, SIP peers, and extensions in the LDAP database. In addition, the base DN used for queries is specified.</p>
<dl class="adnote">
<dt>Note:</dt>
<dd>All of the examples in this article will use <em>dc=example,dc=com</em> as the LDAP database&#8217;s base DN. This should be replaced with your organization&#8217;s base DN.</dd>
</dl>
<p>The final configuration file we will write configures Asterisk&#8217;s real-time LDAP back-end and should be saved as <code>/etc/asterisk/res_ldap.conf</code>.</p>
<pre>
[_general]
url=ldaps://ldap.example.com:636
protocol=3
basedn="dc=example,dc=com"
user=cn=Directory Manager
pass=LDAP-PASSWORD

[config]
additionalFilter=(objectClass=AstConfig)
filename = AstConfigFilename
category = AstConfigCategory
variable_name = AstConfigVariableName
variable_value = AstConfigVariableValue
cat_metric = AstConfigCategoryMetric
commented = AstConfigCommented

[extensions]
context  =  AstContext
exten  =  AstExtension
priority = AstPriority
app = AstApplication
appdata = AstApplicationData
additionalFilter=(objectClass=AsteriskExtension)

[sip]
name = cn
amaflags = AstAccountAMAFlags
callgroup = AstAccountCallGroup
callerid = AstAccountCallerID
canreinvite = AstAccountCanReinvite
context = AstAccountContext
dtmfmode = AstAccountDTMFMode
fromuser = AstAccountFromUser
fromdomain = AstAccountFromDomain
fullcontact = AstAccountFullContact
host = AstAccountHost
ipaddr = AstAccountIPAddress
insecure = AstAccountInsecure
mailbox = AstAccountMailbox
md5secret = AstAccountRealmedPassword
nat = AstAccountNAT
deny = AstAccountDeny
permit = AstAccountPermit
pickupgroup = AstAccountPickupGroup
port = AstAccountPort
qualify = AstAccountQualify
restrictcid = AstAccountRestrictCID
rtptimeout = AstAccountRTPTimeout
rtpholdtimeout = AstAccountRTPHoldTimeout
type = AstAccountType
disallow = AstAccountDisallowedCodec
allow = AstAccountAllowedCodec
MusicOnHold = AstAccountMusicOnHold
regseconds = AstAccountExpirationTimestamp
regcontext = AstAccountRegistrationContext
regexten = AstAccountRegistrationExten
CanCallForward = AstAccountCanCallForward
defaultuser = AstAccountDefaultUser
regserver = AstAccountRegistrationServer
additionalFilter = (objectClass=AsteriskSIPUser)
</pre>
<p>The <em>config</em>, <em>extensions</em>, and <em>sip</em> sections of this file map Asterisk configuration options to LDAP attributes and do not need to be customized. The <em>_general</em> section contains the following options:</p>
<dl>
<dt>url</dt>
<dd>The URL pointing to the organization&#8217;s LDAP server. The example above uses LDAP over SSL on port 636.</dd>
<dt>protocol</dt>
<dd>The LDAP version to use.</dd>
<dt>basedn</dt>
<dd>The base DN used for queries.</dd>
<dt>user</dt>
<dd>The name of the LDAP administrator. <em>Directory Manager</em> is the name used by the Fedora Directory Server.</dd>
<dt>pass</dt>
<dd>The LDAP directory manager&#8217;s password.</dd>
</dl>
<h2>Configuring LDAP</h2>
<p>With the exception of actual users and extensions, our simple Asterisk installation is fully configured. We will now finish our installation by adding users and extensions to our LDAP database. First, we need to install an Asterisk schema for LDAP at <code>/etc/dirsrv/slapd-DOMAIN/schema/99asterisk.ldif</code>. After the schema has been installed, restart FDS using <code>service dirsrv restart</code>.</p>
<pre>
dn: cn=schema
#
attributeTypes: (
  NAME 'AstContext'
  DESC 'Asterisk Context'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstExtension'
  DESC 'Asterisk Extension'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstPriority'
  DESC 'Asterisk Priority'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstApplication'
  DESC 'Asterisk Application'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstApplicationData'
  DESC 'Asterisk Application Data'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountAMAFlags'
  DESC 'Asterisk Account AMA Flags'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountCallerID'
  DESC 'Asterisk Account CallerID'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountContext'
  DESC 'Asterisk Account Context'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountMailbox'
  DESC 'Asterisk Account Mailbox'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstMD5secret'
  DESC 'Asterisk Account MD5 Secret'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountDeny'
  DESC 'Asterisk Account Deny'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountPermit'
  DESC 'Asterisk Account Permit'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountQualify'
  DESC 'Asterisk Account Qualify'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountType'
  DESC 'Asterisk Account Type'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountDisallowedCodec'
  DESC 'Asterisk Account Disallowed Codec'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountExpirationTimestamp'
  DESC 'Asterisk Account Allowed Codec'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountRegistrationContext'
  DESC 'Asterisk Account AMA Flags'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountRegistrationExten'
  DESC 'Asterisk Account AMA Flags'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountNoTransfer'
  DESC 'Asterisk Account AMA Flags'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountCallGroup'
  DESC 'Asterisk Account Call Group'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountCanReinvite'
  DESC 'Asterisk Account Can Reinvite'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountDTMFMode'
  DESC 'Asterisk Account DTMF Flags'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountFromUser'
  DESC 'Asterisk Account From User'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountFromDomain'
  DESC 'Asterisk Account From Domain'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountFullContact'
  DESC 'Asterisk Account Full Contact'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountHost'
  DESC 'Asterisk Account Host'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountInsecure'
  DESC 'Asterisk Account Insecure'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountNAT'
  DESC 'Asterisk Account NAT'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountPickupGroup'
  DESC 'Asterisk Account PickupGroup'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountPort'
  DESC 'Asterisk Account Port'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountRestrictCID'
  DESC 'Asterisk Restrict CallerID'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountRTPTimeout'
  DESC 'Asterisk RTP Timeout'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountRTPHoldTimeout'
  DESC 'Asterisk RTP Hold Timeout'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountRealmedPassword'
  DESC 'Asterisk RTP Hold Timeout'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountAllowedCodec'
  DESC 'Asterisk Account Allowed Codec'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountMusicOnHold'
  DESC 'Asterisk Account Allowed Codec'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountCanCallForward'
  DESC 'Asterisk Can CAll Forward'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountSecret'
  DESC 'Asterisk Can CAll Forward'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountName'
  DESC 'Asterisk Account Username'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstConfigFilename'
  DESC 'Asterisk LDAP Configuration Filename'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstConfigCategory'
  DESC 'Asterisk LDAP Configuration Category'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstConfigCategoryMetric'
  DESC 'Asterisk LDAP Configuration Category Metric'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstConfigVariableName'
  DESC 'Asterisk LDAP Configuration Variable Name'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstConfigVariableValue'
  DESC 'Asterisk LDAP Configuration Variable Value'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstConfigCommented'
  DESC 'Asterisk LDAP Configuration Commented'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountIPAddress'
  DESC 'Asterisk Account IP Address'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountDefaultUser'
  DESC 'Asterisk Account Default User'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstAccountRegistrationServer'
  DESC 'Asterisk Account Registration Server'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
objectClasses: (
  NAME 'AsteriskExtension'
  DESC 'PBX Extension Information for Asterisk'
  SUP top
  AUXILIARY
  MUST cn
  MAY ( AstContext $ AstExtension $ AstPriority $ AstApplication
      $ AstApplicationData )
  )
#
objectClasses: (
  NAME 'AsteriskIAXUser'
  DESC 'IAX2 User information for Asterisk'
  SUP AsteriskExtension
  AUXILIARY
  MUST cn
  MAY ( AstAccountAMAFlags $ AstAccountCallerID $ AstAccountContext
      $ AstAccountFullContact $ AstAccountHost $ AstAccountMailbox $ AstMD5secret
      $ AstAccountDeny $ AstAccountPermit $ AstAccountPort $ AstAccountQualify
      $ AstAccountType $ AstAccountDisallowedCodec $ AstAccountExpirationTimestamp
      $ AstAccountRegistrationContext$ AstAccountRegistrationExten
      $ AstAccountNoTransfer $ AstAccountName )
  )
#
objectClasses: (
  NAME 'AsteriskSIPUser'
  DESC 'SIP User information for Asterisk'
  SUP AsteriskExtension
  AUXILIARY
  MUST cn
  MAY ( AstAccountAMAFlags $ AstAccountCallGroup $ AstAccountCallerID
      $ AstAccountCanReinvite $ AstAccountContext $ AstAccountDefaultUser
      $ AstAccountDTMFMode $ AstAccountFromUser $ AstAccountFromDomain
      $ AstAccountFullContact $ AstAccountHost $ AstAccountInsecure
      $ AstAccountIPAddress $ AstAccountMailbox $ AstAccountRealmedPassword
      $ AstAccountNAT $ AstAccountDeny $ AstAccountPermit $ AstAccountPickupGroup
      $ AstAccountPort $ AstAccountQualify $ AstAccountRestrictCID
      $ AstAccountRTPTimeout $ AstAccountRTPHoldTimeout $ AstAccountType
      $ AstAccountDisallowedCodec $ AstAccountAllowedCodec $ AstAccountMusicOnHold
      $ AstAccountExpirationTimestamp $ AstAccountRegistrationContext
      $ AstAccountRegistrationExten $ AstAccountRegistrationServer
      $ AstAccountCanCallForward $ AstAccountSecret $ AstAccountName )
  )
#
objectClasses: (
  NAME 'AsteriskConfig'
  DESC 'Asterisk configuration Information'
  SUP top
  AUXILIARY
  MUST cn
  MAY ( AstConfigFilename $ AstConfigCategory $ AstConfigCategoryMetric
      $ AstConfigVariableName $ AstConfigVariableValue $ AstConfigCommented )
  )
</pre>
<p>We may now create two SIP users, one for our Ekiga installation and the other for our Cisco telephone. If you write the following LDIF into a file, you may load it into the LDAP database using <code>ldapadd -x -D "cn=Directory Manager" -W -f PATH-TO-LDIF</code>.</p>
<pre>
dn: ou=sippeers,dc=example,dc=com
ou: sippeers
objectClass: top
objectClass: organizationalUnit

dn: cn=user1,ou=sippeers,dc=example,dc=com
objectClass: top
objectClass: AsteriskSIPUser
cn: user1
AstAccountCallerID: 2001
AstAccountHost: dynamic
AstAccountRealmedPassword: {MD5}a94775781e5bb7d3e4ec047c56f0acc5
AstAccountContext: default
AstAccountType: friend

dn: cn=user2,ou=sippeers,dc=example,dc=com
objectClass: top
objectClass: AsteriskSIPUser
cn: user2
AstAccountCallerID: 2002
AstAccountHost: dynamic
AstAccountRealmedPassword: {MD5}3c7806fa6e6c3416d57f2de223cdea5d
AstAccountContext: default
AstAccountType: friend
</pre>
<p>The example above defines a minimal SIP user. The attributes used are:</p>
<dl>
<dt>cn</dt>
<dd>The SIP user&#8217;s account name.</dd>
<dt>AstAccountCallerID</dt>
<dd>The user&#8217;s caller ID information.</dd>
<dt>AstAccountHost</dt>
<dd>The user&#8217;s host. The <em>dynamic</em> keyword allows a user&#8217;s telephone to dynamically register its IP address by logging into Asterisk.</dd>
<dt>AstAccountRealmedPassword</dt>
<dd>The account&#8217;s password. The hash of a user&#8217;s password may be generated by executing <code>echo -n "SIPUSER:example.com:PASSWORD" | md5sum</code></dd>
<dt>AstAccountContext</dt>
<dd>The context this user will exist in. This determines which extension context applies to this user. Extension contexts were defined in <code>extensions.conf</code>.</dd>
<dt>AstAccountType</dt>
<dd>Defines the type of client. Asterisk sends calls to peers (i.e., a SIP provider). The user type may place calls only. Friends are both peers and users.</dd>
</dl>
<p>Once a user is defined, one may test Asterisk. Start the Asterisk service by executing <code>service asterisk start</code> as root. Execute an Asterisk shell using the command <code>asterisk -rv</code>. At Asterisk&#8217;s prompt, execute <code>sip show peer user1 load</code>. Asterisk should print all of the information for user1.</p>
<p>Once you have defined a user, you may start writing your dial plan. First, we will associate a phone number with each user. Use <code>ldapadd</code> to add the following to your LDAP database:</p>
<pre>
dn: ou=extensions,dc=example,dc=com
ou: extensions
objectClass: top
objectClass: organizationalUnit

dn: cn=2001-1,ou=extensions,dc=example,dc=com
cn: 2001-1
objectClass: top
objectClass: AsteriskExtension
AstContext: users
AstExtension: 2001
AstPriority: 1
AstApplication: Dial
AstApplicationData: SIP/user1,20

dn: cn=2002-1,ou=extensions,dc=example,dc=com
cn: 2002-1
objectClass: top
objectClass: AsteriskExtension
AstContext: users
AstExtension: 2002
AstPriority: 1
AstApplication: Dial
AstApplicationData: SIP/user2,20
</pre>
<dl>
<dt>AstContext</dt>
<dd>The context in which this extension exists.</dd>
<dt>AstExtension</dt>
<dd>The extension ID (e.g., what you dial to reach this extension).</dd>
<dt>AstPriority</dt>
<dd>Each extension can execute several commands when it receives a call. The priority determines the order in which commands are executed.</dd>
<dt>AstApplication</dt>
<dd>The command to execute when the extension receives a call. The command <em>Dial</em> connects to another Asterisk user.</dd>
<dt>AstApplicationData</dt>
<dd>Arguments, separated with commas (without spaces), and passed to a command. The <code>Dial</code> has two arguments. The first is the user that the call will be connected to. The second is the number of seconds to wait before quitting.</dd>
</dl>
<p>In order to facilitate testing our installation, we will define the following additional extension. This extension executes three commands to implement an echo test that may be reached by dialing &#8216;600.&#8217;</p>
<pre>
dn: cn=600-1,ou=extensions,dc=example,dc=com
cn: 600-1
objectClass: top
objectClass: AsteriskExtension
AstContext: demo
AstExtension: 600
AstPriority: 1
AstApplication: Playback
AstApplicationData: demo-echotest

dn: cn=600-2,ou=extensions,dc=example,dc=com
cn: 600-2
objectClass: top
objectClass: AsteriskExtension
AstContext: demo
AstExtension: 600
AstPriority: 2
AstApplication: Echo

dn: cn=600-3,ou=extensions,dc=example,dc=com
cn: 600-3
objectClass: top
objectClass: AsteriskExtension
AstContext: demo
AstExtension: 600
AstPriority: 3
AstApplication: Playback
AstApplicationData: demo-echodone
</pre>
<p> After schema edits, FDS must be restarted using <code>service dirsrv restart</code>.</p>
<p>The basic Asterisk configuration is now complete. Restart the Asterisk service using <code>service asterisk restart</code>.</p>
<h2>Configuring the Ekiga VoIP client</h2>
<p>Ekiga is a software VoIP application that supports SIP. Its configuration is straightforward. The first time Ekiga is executed by a user, it provides a wizard that allows one to configure the user&#8217;s full name,<br />
ekiga.net account (this is not required for the purpose of this article), connection type, audio devices, and video devices. Once the software is configured, setup a SIP account by clicking on <strong>Edit&rarr;Accounts</strong> and selecting add. Figure 1 displays an account configured for our SIP user identified as <em>user1</em>.</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2699545118/" title="asterisk-ldap-figure1-en by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3028/2699545118_2022a665d5_o.png" width="352" height="268" alt="asterisk-ldap-figure1-en" /></a></p>
<div class="”caption”">Figure 1. Ekiga Account Configuration</div>
<p>After an account is set up, it must be activated. Figure 2 shows that the account I just configured is displayed in Ekiga&#8217;s list. Click the checkbox to activate the account.</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2699545130/" title="asterisk-ldap-figure2-en by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3259/2699545130_c9482ab961.jpg" width="500" height="203" alt="asterisk-ldap-figure2-en" /></a></p>
<div class="”caption”">Figure 2. Ekiga Account Activation</div>
<p>Figure 3 shows Ekiga&#8217;s main interface window. Here, you can see how many accounts have been registered. In order to test your configuration, make a SIP connection to extension 600 and perform an echo test.</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2699545132/" title="asterisk-ldap-figure3-en by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3032/2699545132_4efc8ce9ff_o.png" width="300" height="421" alt="asterisk-ldap-figure3-en" /></a></p>
<div class="”caption”">Figure 3. Ekiga Primary Interface</div>
<h2>Configuring a Cisco VoIP telephone</h2>
<p>As mentioned before, using a Cisco phone to connect to Asterisk using SIP requires Cisco&#8217;s SIP software. When a Cisco 7900 Series telephone boots, it will try to configure itself using TFTP. We will place some firmware and configuration files on our server so that the phone will boot properly for our installation.</p>
<p>In order to enable TFTP on the Asterisk server, edit <code>/etc/xinetd.d/tftp</code> and set <em>disable</em> to <em>no</em>. The TFTP daemon is configured on Fedora to serve files out of <code>/var/lib/tftpboot</code>. After you have modified its configuration, restart xinetd with the command <code>service xinetd restart</code>. Cisco&#8217;s SIP software package provides the files P0S3-08-2-00.sb2, P0S3-08-2-00.sbn and P0S3-08-2-00.loads. Copy these files to <code>/var/lib/tftpboot</code>.</p>
<dl class="adnote">
<dt>Note:</dt>
<dd>The filenames used by your Cisco firmware may be slightly different. Cisco&#8217;s naming convention is P0S3-xxx-y-zz, where x is the major version, y is the minor version, and z is the subversion. P0S3 indicates SIP firmware, P003 indicates SCCP firmware, and P0M3 indicates MGCP firmware.</dd>
</dl>
<p>When booting SIP firmware, the telephone will look for three configuration files: OS79XX.TXT, SIPDefault.cnf, and SIP<em>MAC-ADDRESS</em>.cnf. These files should also<br />
be placed in <code>/var/lib/tftpboot</code>.</p>
<p>OS79XX.TXT contains one line: the firmware version to load. Mine contains <em>P0S3-08-2-00</em>.</p>
<p>SIPDefault.cnf contains configurations common to all SIP telephones. The following example lists the image version and the address of our Asterisk server, and instructs the telephones to register with Asterisk:</p>
<pre>
image_version: P0S3-08-2-00 ;
proxy1_address: 192.168.0.10 ;
proxy_register: "1" ;
</pre>
<p>Per-telephone configurations are stored in a file named after the telephone&#8217;s MAC address. The telephone&#8217;s MAC address may be found in its configuration menu. This configuration will correspond with the SIP information found in LDAP and should be saved as SIP<em>MAC-ADDRESS</em>.cnf:</p>
<pre>
line1_name : user2
line1_authname : user2
line1_password : PLAINTEXT-PASSWORD
</pre>
<p>The first step in preparing the telephone is to clear any existing configuration. This may be done by pressing <code>**# settings 3</code> to access an unlocked <em>Network<br />
Configuration</em> menu. Here, find the <em>Erase Configuration</em> menu item and select it. Restart the phone and return to the <em>Network Configuration</em> menu. Ensure <em>DHCP Enabled</em> is set. Reboot the phone.</p>
<p>The phone will pull its network configuration from DHCP and should now respond to pings. Return to the <em>Network Configuration</em> menu and deactivate DHCP. Select the <em>TFTP Server 1</em> option and set it to your Asterisk / TFTP server. Do not disable DHCP or manually set a TFTP server if your DHCP server provides your TFTP server&#8217;s IP address. Reboot the telephone and it should load the SIP software and configuration. As the phone boots, you may see it request files using TFTP by watching the Asterisk server&#8217;s <code>/var/log/messages</code> log.</p>
<p>Once the telephone boots, test its configuration by dialing <code>600</code>. This will execute an echo test. After the echo test, you may make a Cisco telephone to Ekiga call by dialing 2001.</p>
<h2>Configuring voicemail</h2>
<p>In this section, we will cover configuring Asterisk to provide a voicemail system. The configuration process is similar to that of SIP users and extensions, so this should also serve to reinforce the techniques covered in those sections. We will configure the voicemail module, the external<br />
configuration engine, and the real-time LDAP back-end. After the configuration files are setup, we will add information to the LDAP database.</p>
<p><code>/etc/asterisk/voicemail.conf</code> is similar to <code>sip.conf</code> and<br />
<code>extensions.conf</code>. This file configures the voicemail module. As with SIP users and extensions, we will configure global parameters in a file, leaving extension-specific parameters to be configured in LDAP:</p>
<pre>
[general]
searchcontexts=yes
</pre>
<p>Add the following line to <code>/etc/asterisk/extconfig.conf</code> in order to activate the real-time LDAP back-end for voicemail:</p>
<pre>
voicemail =&gt; ldap,"dc=example,dc=com",voicemail
 </pre>
<p>Map Asterisk voicemail configuration options to LDAP attributes by adding the following to <code>/etc/asterisk/res_ldap.conf</code>:</p>
<pre>
[voicemail]
context = AstVMContext
mailbox = AstVMMailbox
password = AstVMPassword
fullname = AstVMFullname
email = AstVMEmail
pager = AstVMPager
tz = AstVMTz
attach = AstVMAttach
saycid = AstVMSaycid
dialout = AstVMDialout
callback = AstVMCallback
review = AstVMReview
operator = AstVMOperator
envelope = AstVMEnvelope
sayduration = AstVMSayduration
saydurationm = AstVMSaydurationm
sendvoicemail = AstVMSendvoicemail
delete = AstVMDelete
nextaftercmd = AstVMNextastercmd
forcename = AstVMForcename
forcegreetings = AstVMForcegreetings
hidefromdir = AstVMHidefromdir
stamp = AstVMStamp
additionalFilter = (objectClass=AsteriskVoicemail)
</pre>
<p>Now we will move to updating our LDAP database. First, we must add to the LDAP schema that we installed earlier. The following will add support for the attributes required to provide basic voicemail:</p>
<pre>
attributeTypes: (
  NAME 'AstVMMailbox'
  DESC 'Asterisk Voicemail Mailbox'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstVMPassword'
  DESC 'Asterisk Voicemail Password'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstVMFullname'
  DESC 'Asterisk Voicemail Fullname'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
attributeTypes: (
  NAME 'AstVMEmail'
  DESC 'Asterisk Voicemail Email'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  )
#
objectClasses: (
  NAME 'AsteriskVoicemail'
  DESC 'Voicemail information for Asterisk'
  SUP top
  MUST cn
  MAY ( AstContext $ AstVMMailbox $ AstVMPassword $ AstVMFullname
      $ AstVMEmail )
  )
</pre>
<p>Add the following LDIF to the LDAP database using <code>ldapadd</code> in order to add voicemail support for the extensions 2001 and 2002:</p>
<pre>
dn: ou=voicemail,dc=example,dc=com
ou: voicemail
objectClass: top
objectClass: organizationalUnit

dn: cn=2001,ou=voicemail,dc=example,dc=com
cn: 2001
objectClass: top
objectClass: AsteriskVoicemail
AstContext: users
AstVMMailbox: 2001
AstVMPassword: 1234
AstVMFullname: User 1
AstVMEmail: user1@example.org

dn: cn=2002,ou=voicemail,dc=example,dc=com
cn: 2002
objectClass: top
objectClass: AsteriskVoicemail
AstContext: users
AstVMMailbox: 2002
AstVMPassword: 1234
AstVMFullname: User 2
AstVMEmail: user2@example.org

dn: cn=2000-1,ou=extensions,dc=example,dc=com
cn: 2000-1
objectClass: top
objectClass: AsteriskExtension
AstContext: users
AstExtension: 2000
AstPriority: 1
AstApplication: Voicemailmain

dn: cn=2001-2,ou=extensions,dc=example,dc=com
cn: 2001-2
objectClass: top
objectClass: AsteriskExtension
AstContext: users
AstExtension: 2001
AstPriority: 2
AstApplication: Voicemail
AstApplicationData: 2001,u

dn: cn=2002-2,ou=extensions,dc=example,dc=com
cn: 2002-2
objectClass: top
objectClass: AsteriskExtension
AstContext: users
AstExtension: 2002
AstPriority: 2
AstApplication: Voicemail
AstApplicationData: 2002,u
</pre>
<p>The second entry defines a mailbox for extension 2001. It uses the following options:</p>
<dl>
<dt>AstContext</dt>
<dd>The context in which this mailbox exists.</dd>
<dt>AstVMMailbox</dt>
<dd>The extension that this mailbox corresponds to.</dd>
<dt>AstVMPassword</dt>
<dd>The password used to access the mailbox.</dd>
<dt>AstVMFullname</dt>
<dd>The full name of the mailbox owner.</dd>
<dt>AstVMEmail</dt>
<dd>The mailbox owner&#8217;s email address.</dd>
</dl>
<p>Entity four defines an extension, 2000, that will provide access to the voicemail system when dialed.</p>
<p>Entity five adds a command to extension 2001 that executes the <code>Voicemail</code> and provides access to the voicemail system. This command will execute if the <code>Dial</code> command defined earlier is not answered within 20 seconds.</p>
<p>To test the voicemail system, use Ekiga to dial <code>2002</code>. If you don&#8217;t answer the call on the other end, then you should be directed to Asterisk&#8217;s voicemail system. To listen to new voicemail, dial <code>2000</code>.</p>
<h2>Conclusion</h2>
<p>This article demonstrated how to install Asterisk on a Fedora system and configure SIP users, extensions, and voicemail. We installed all user data into an LDAP database in order to keep it consolidated.</p>
<p>Asterisk has far too many features to cover in one article. The VoIP Wiki has a <a href="http://www.voip-info.org/wiki/view/Asterisk">section dedicated to Asterisk</a> and is a great place to learn more. The VoIP Wiki covers topics such as hooking Asterisk up to the standard public-switched telephone network using direct inward dialing and automatically emailing voicemail messages to users. You can even find information on how to route calls to a user based on his Jabber presence. Clearly, Asterisk is capable of a wide range of applications. And, perhaps best of all, it&#8217;s entirely open source!</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/rhredhatmagazine.wordpress.com/986/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/rhredhatmagazine.wordpress.com/986/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rhredhatmagazine.wordpress.com/986/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rhredhatmagazine.wordpress.com/986/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rhredhatmagazine.wordpress.com/986/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rhredhatmagazine.wordpress.com/986/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rhredhatmagazine.wordpress.com/986/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rhredhatmagazine.wordpress.com/986/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rhredhatmagazine.wordpress.com/986/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rhredhatmagazine.wordpress.com/986/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rhredhatmagazine.wordpress.com/986/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rhredhatmagazine.wordpress.com/986/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=986&subd=rhredhatmagazine&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://magazine.redhat.com/2008/07/24/open-source-telephony-a-fedora-based-voip-server-with-asterisk/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">The editorial team</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3028/2699545118_2022a665d5_o.png" medium="image">
			<media:title type="html">asterisk-ldap-figure1-en</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3259/2699545130_c9482ab961.jpg" medium="image">
			<media:title type="html">asterisk-ldap-figure2-en</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3032/2699545132_4efc8ce9ff_o.png" medium="image">
			<media:title type="html">asterisk-ldap-figure3-en</media:title>
		</media:content>
	</item>
		<item>
		<title>NetworkManager: Secret weapon for the Linux road warrior</title>
		<link>http://magazine.redhat.com/2008/07/22/networkmanager-secret-weapon-for-the-linux-road-warrior/</link>
		<comments>http://magazine.redhat.com/2008/07/22/networkmanager-secret-weapon-for-the-linux-road-warrior/#comments</comments>
		<pubDate>Tue, 22 Jul 2008 22:21:19 +0000</pubDate>
		<dc:creator>kylegonzales</dc:creator>
				<category><![CDATA[Fedora]]></category>
		<category><![CDATA[Red Hat Enterprise Linux]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2008/07/22/networkmanager-secret-weapon-for-the-linux-road-warrior/</guid>
		<description><![CDATA[For years I have envied how easy my Windows- and Mac-based peers had it when traveling with their laptops.  They connect to hotspots with ease, get online while I was still logging into root and running some tools.  It just wasn&#8217;t fair.  I wanted an integrated easy-to-use tool that did not require [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=981&subd=rhredhatmagazine&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>For years I have envied how easy my Windows- and Mac-based peers had it when traveling with their laptops.  They connect to hotspots with ease, get online while I was still logging into root and running some tools.  It just wasn&#8217;t fair.  I wanted an integrated easy-to-use tool that did not require bringing up a shell or logging into root.</p>
<p>I now have that tool in NetworkManager.  In this article I will explain what NetworkManager is, what capabilities exist in the tool (in both Fedora and Red Hat Enterprise Linux), and what you can do to extend it to give you more control over your system than before.</p>
<h2>What is NetworkManager?</h2>
<p>NetworkManager is a software utility that allows a desktop user to manage wired, wireless, modem, WWAN/3G, and VPN network connectivity from a single source. It does not require root access or manual editing of configuration files.</p>
<p>NetworkManager started as a Gnome project and initially appeared in Fedora. It is now supported on multiple desktop environments (Gnome, KDE, Xfce, etc.) and in multiple distributions (Fedora, SuSE, Ubuntu, Gentoo, Debian, etc.).  NetworkManager uses dbus and hal to provide network status updates to other desktop applications, allowing them to alter their operation based on this information.  For instance, if NetworkManager shows the network is offline, then apps like Evolution and Pidgin will put themselves into offline mode andwait for the network to come online.<span id="more-981"></span></p>
<h2>How is the NetworkManager software deployed on the system?</h2>
<p>NetworkManager is deployed in two parts.  The first part is the NetworkManager daemon, which is found in the package NetworkManager.  This daemon should be set to start while the system is booting.  This can be accomplished by entering the following command as root:</p>
<pre>
    # /sbin/chkconfig NetworkManager on
</pre>
<p>You can also start NetworkManager manually by entering the following command as root:</p>
<pre>
    # /sbin/service NetworkManager start
</pre>
<p>The second part is the user client, which normally takes the form of an applet.  This applet (nm-applet) can be found in the NetworkManager-gnome package, and should be part of the basic Gnome desktop installation.  You will not need to add this applet to your desktop.  Gnome will add the nm-applet control to the Notification Area applet when the NetworkManager daemon is active.</p>
<h2>How does NetworkManager work?</h2>
<p>For the user, most everything will be done via the NetworkManager applet.  Exactly what needs to be done depends on the type of networking the user needs to activate.</p>
<h3>Wired network</h3>
<p>If the system the user is logged into is on a wired network (Ethernet), the user does not need to do anything.  NetworkManager will look for the link on the network port.  When the link is active, it will bring up the interface and then ask for network information via DHCP.</p>
<h3>Wireless Network</h3>
<p>If the user is trying to connect via wireless, NetworkManager is especially helpful.  As long as the wireless device is active, NetworkManager will scan for available networks and will attempt to connect to the last network you connected to that it can see.  If the network it is trying to connect to is a secure network (using WEP, WPA, WPA2, or LEAP) it will request the appropriate security information.  Once the information is entered, NetworkManager will try to store this information into the GNOME keyring manager.</p>
<p>To connect to a different network than the one that NetworkManager chooses, simply click on the applet and choose a different wireless network.</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2693123353/" title="NM-Wireless by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3272/2693123353_311e143803_o.png" width="398" height="430" alt="NM-Wireless" /></a></p>
<h3>WWAN network (3G/EVDO/HSDPA/RTTx1/EDGE)</h3>
<p>With the release of NetworkManager 0.70, users can now choose WWAN networking.  Most of these cards require activation in Windows, but NetworkManager can handle the auto-configuration some cards need for use under Linux.  Other cards may still require some minimal account information to activate and use.</p>
<p>If the card is plugged in when NetworkManager starts, it will be autodetected and an attempt to auto-configure the card will be made when you request a connection to the network.  If auto-configuration is successful, the user can then just select the card in the applet menu and connect.</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2693937432/" title="NM-CDMA by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3151/2693937432_99df6a5ed0_o.png" width="398" height="301" alt="NM-CDMA" /></a></p>
<h3>VPN connectivity</h3>
<p>Once a successful network connection has been made, the user can also use NetworkManager to activate a VPN connection.  Currently, there are modules providing support for OpenVPN and Cisco (via vpnc) VPN connectivity.</p>
<p>The VPN connection will be configured, activated, and deactivated via the applet.  Username, password, group passwords, and other information can be stored in the GNOME keyring manager, or the user can choose to be prompted to enter some—or all—of the information at each login.</p>
<h2>What else can NetworkManager do?</h2>
<p>Beside managing your network connectivity, NetworkManager has another key feature. NetworkManager can run scripts when there is a network state change on any interface, using the network interface and the up/down state as variables. In prior releases, this functionality was provided by a separate daemon called NetworkManagerDispatcher. As of NetworkManager 0.70 in Fedora 9, this functionality is now integrated into NetworkManager itself.</p>
<p>In Bash scripts written for NetworkManager, the variable <code>$1</code> equals the interface whose state has changed and triggered the script. Variable <code>$2</code> equals the state of the interface (up or down). No other variables are needed.</p>
<p>Let&#8217;s take a look at one of the scripts that is included with Fedora 9:</p>
<pre>
# cat /etc/NetworkManager/dispatcher.d/05-netfs

#!/bin/sh

export LC_ALL=C

if [ "$2" = "down" ]; then
        /sbin/ip route ls | grep -q ^default || {
                [ -f /var/lock/subsys/netfs ] &amp;&amp; /etc/rc.d/init.d/netfs stop
        }
fi

if [ "$2" = "up" ]; then
        /sbin/ip -o route show dev "$1" | grep -q '^default' &amp;fi
</pre>
<p>When an interface comes up and adds itself as the default route, the script starts the netfs service. This script also stops the netfs service when an interface goes down and no default route remains.  Effectively, this will mount your NFS and CIFS shares when you have access to the network, and will unmount those same shares when the network goes down.  Using this script as an example, you can easily write your own scripts to run various commands as the network state changes.</p>
<h2>How can I best use NetworkManager in the field?</h2>
<p>Now that you have a good idea of how NetworkManager works and what it can do, let&#8217;s talk about how to best use NetworkManager in the field. Now that you have NetworkManager managing your network connectivity, make sure your network interfaces are not trying to start on boot. Nothing is more annoying than having your laptop tell you that your wired network is not available when you are sitting on a plane.  If you are using NetworkManager 0.70 (currently in Fedora 9), you should also disable the network service itself, as it may conflict with NetworkManager.</p>
<p>You can go further, writing NetworkManager scripts to activate various services only when they are needed. Many of the init scripts in Linux make the assumption that your system is a server or a workstation with continuous access to the network. Things like ntp, cups, sshd, even rhnsd do not need to be running while you have no network connectivity. These services can be disabled, set to run only when NetworkManager starts them via a custom script on a network state change.</p>
<p>Using the previously posted script as a guide, a script to manage sshd might look like this:</p>
<pre>
# cat /etc/NetworkManager/dispatcher.d/10-sshd

#!/bin/sh
#
# Start and stop sshd based on network availability using NetworkManager
#

export LC_ALL=C

if [ "$2" = "down" ]; then
        /sbin/ip route ls | grep -q ^default || {
                [ -f /var/lock/subsys/sshd ] &amp;&amp; /etc/rc.d/init.d/sshd stop
        }
fi

if [ "$2" = "up" ]; then
        /sbin/ip -o route show dev "$1" | grep -q '^default' &amp;fi
</pre>
<p>You could substitute &#8220;rhnsd&#8221; or &#8220;cups&#8221; for &#8220;sshd&#8221;, and the script should work equally well for those tasks..</p>
<p>If you are a administrator tasked with managing Red Hat or Fedora systems of remote employees, the scripting functionality can be even more handy. You can write a script that looks for the activation of the VPN interface then sends an email letting you know the system is online. You could have the system check in with a Satellite server located within your firewall, installing updates you previously scheduled for it. The possible uses here are many.</p>
<h2>The student is now the master</h2>
<p>No longer do I envy my Windows-based peers and their easy  mobile connectivity. NetworkManager is constantly impressing me, adding functionality and allowing me to be more efficient on the road. This Swiss Army knife of Linux networking gives me the control I need over my connectivity whether at home, coffee house, or airport. Now that you know what NetworkManager is, how it works, and how best to use it, try it out of your own system. I trust you will find NetworkManager works as well for you as it did for me.</p>
<h2>More information</h2>
<ol>
<li><a href="http://www.gnome.org/projects/NetworkManager">NetworkManager main project page</a></li>
<li><a href="http://fedoraproject.org/wiki/Tools/NetworkManager">NetworkManager in Fedora</a></li>
<li><a href="http://www.freedesktop.org/wiki/Software/dbus">dbus</a> and <a href="http://www.freedesktop.org/wiki/Software/hal">hal</a></li>
<li><a href="http://en.opensuse.org/Projects/KNetworkManager">KNetworkManager</a></li>
</ol>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/rhredhatmagazine.wordpress.com/981/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/rhredhatmagazine.wordpress.com/981/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rhredhatmagazine.wordpress.com/981/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rhredhatmagazine.wordpress.com/981/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rhredhatmagazine.wordpress.com/981/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rhredhatmagazine.wordpress.com/981/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rhredhatmagazine.wordpress.com/981/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rhredhatmagazine.wordpress.com/981/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rhredhatmagazine.wordpress.com/981/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rhredhatmagazine.wordpress.com/981/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rhredhatmagazine.wordpress.com/981/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rhredhatmagazine.wordpress.com/981/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=981&subd=rhredhatmagazine&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://magazine.redhat.com/2008/07/22/networkmanager-secret-weapon-for-the-linux-road-warrior/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">kylegonzales</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3272/2693123353_311e143803_o.png" medium="image">
			<media:title type="html">NM-Wireless</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3151/2693937432_99df6a5ed0_o.png" medium="image">
			<media:title type="html">NM-CDMA</media:title>
		</media:content>
	</item>
		<item>
		<title>JBoss Drools meets Hibernate</title>
		<link>http://magazine.redhat.com/2008/07/11/jboss-drools-meets-hibernate/</link>
		<comments>http://magazine.redhat.com/2008/07/11/jboss-drools-meets-hibernate/#comments</comments>
		<pubDate>Fri, 11 Jul 2008 20:31:36 +0000</pubDate>
		<dc:creator>kijanowski</dc:creator>
				<category><![CDATA[JBoss]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2008/07/11/jboss-drools-meets-hibernate/</guid>
		<description><![CDATA[Jaroslaw is a JBoss QA Engineer based in Poland, and recently published an introduction to Drools that he kindly shared with us. This second piece covers Drools (or JBoss Rules), the open source business rules engine&#8230; in this case combining it with Hibernate.
This article is presented here in its entirety (with a trackback).  The [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=966&subd=rhredhatmagazine&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><em>Jaroslaw is a JBoss QA Engineer based in Poland, and recently published an <a href="http://www.kijanowski.eu/index.php?site=articles&amp;article=introduction&amp;lang=en">introduction to Drools</a> that he kindly shared with us. This second piece covers <a href="http://en.wikipedia.org/wiki/Drools">Drools (or JBoss Rules)</a>, the open source business rules engine&#8230; in this case combining it with <a href="http://en.wikipedia.org/wiki/Hibernate_%28Java%29">Hibernate</a>.</p>
<p>This article is presented here in its entirety (with a trackback).  The original can be found on <a href="http://www.kijanowski.eu/index.php?site=articles&amp;article=drools_hibernate&amp;lang=en">Jaroslaw&#8217;s site</a>.  This article is also available in <a href="http://www.kijanowski.eu/index.php?site=articles&amp;article=drools_hibernate&amp;lang=de">German</a> and <a href="http://www.kijanowski.eu/index.php?site=articles&amp;article=drools_hibernate&amp;lang=pl">Polish</a>.</em></p>
<h2>Justification:</h2>
<p>Drools evaluates facts which are present in the working memory. But could it also reason over data stored in a relational database? This feature would extend Drools&#8217; range of applicability and since this is an often asked question in the mailing list, it&#8217;s worth to know the answer which sounds: &#8220;of course Drools can!&#8221;</p>
<h2>Abstract:</h2>
<p>Hibernate, one of the most favorite <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">ORM</a> tools, allows to handle data stored in a relational database. This article will describe how one can access a Hibernate session from inside the rule engine. I will use PostgreSQL as a data source. Besides that I will create two classes, Game and Player, having a many-to-many relationship.<span id="more-966"></span></p>
<ol>
<li><a href="#newproject">Creating a new Drools project</a></li>
<li><a href="#classes">Class files</a></li>
<li><a href="#hibernate">Hibernate</a></li>
<li><a href="#drools">Drools</a></li>
<li><a href="#howdoesitwork">How does it work?</a></li>
<li><a href="#final">Results</a>
<li><a href="#summary">Summary</a></li>
</ol>
<h2><a name="newproject">Creating a new Drools project</a></h2>
<p><i>You still don&#8217;t have installed the Drools 4.0.7 Eclipse Workbench? Just have a look at this article: <a href="http://www.kijanowski.eu/index.php?site=articles&amp;article=introduction&amp;lang=en">&#8220;Rules fall from your eyes&#8221;</a>.</i></p>
<p>Menu File -&gt; New -&gt; Project -&gt; Drools &#8211; &gt; Rule Project -&gt; Next. Provide the project&#8217;s name, drools-hibernate-demo, and click on Next, to <b>uncheck</b> the example files</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2658892369/" title="fig2-1_step1 by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3096/2658892369_0eea61eb8e.jpg" width="500" height="458" alt="fig2-1_step1" /></a></p>
<h2><a name="classes">Class files</a></h2>
<p>Create a package &#8220;eu.kijanowski.drools.hibernate&#8221; in the src/main/java directory. We will use two class files, Player.java and Game.java. They have a many-to-many relationship, since one player can own many games and one game can be owned by many players <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><i>Class Game.java</i></p>
<pre>
package eu.kijanowski.drools.hibernate;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Game implements Serializable {
	private static final long serialVersionUID = 1L;
	private Long id = null;
	private String name;
	private double price;
	private int levels;
	private Set players = new HashSet();

	public Game() {
	}

	public Game(String name, double price, int levels) {
		this.name = name;
		this.price = price;
		this.levels = levels;
	}

	public Long getId() {
		return id;
	}

	@SuppressWarnings("unused")
	private void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public int getLevels() {
		return levels;
	}

	public void setLevels(int levels) {
		this.levels = levels;
	}

	public Set getPlayers() {
		return players;
	}

	public void setPlayers(Set players) {
		this.players = players;
	}

	public String toString() {
		return name + " with " + levels + " levels for " + price;
	}
}
</pre>
<p><i>Class Player.java</i></p>
<pre>
package eu.kijanowski.drools.hibernate;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Player implements Serializable {
	private static final long serialVersionUID = 1L;
	private Long id;
	private String name;
	private int age;
	private Set games = new HashSet();

	public Player() {
	}

	public Player(String name, int age, HashSet games) {
		this.name = name;
		this.age = age;
		this.games = games;
	}

	public Long getId() {
		return id;
	}

	@SuppressWarnings("unused")
	private void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public Set getGames() {
		return games;
	}

	public void setGames(Set games) {
		this.games = games;
	}

	public String toString() {
		return name;
	}
}
</pre>
<h2><a name="hibernate">Hibernate</a></h2>
<p>Without going into details, <a href="http://www.hibernate.org/6.html">download the binaries</a>, Hibernate Core 3.2.6 and extract the archive.</p>
<p>In our project create a directory called lib and copy over following files:</p>
<ul>
<li>hibernate-3.2.6.GA/lib/antlr-2.7.6.jar</li>
<li>hibernate-3.2.6.GA/lib/asm.jar</li>
<li>hibernate-3.2.6.GA/lib/cglib-2.1.3.jar</li>
<li>hibernate-3.2.6.GA/lib/commons-collections-2.1.1.jar</li>
<li>hibernate-3.2.6.GA/lib/commons-logging-1.0.4.jar</li>
<li>hibernate-3.2.6.GA/lib/dom4j-1.6.1.jar</li>
<li>hibernate-3.2.6.GA/hibernate3.jar</li>
<li>hibernate-3.2.6.GA/lib/jta.jar</li>
</ul>
<p>Now we have to add these libraries to the &#8220;build path&#8221;: from the menu choose Project -&gt; Properties -&gt; Java Build Path -&gt; Libraries and	then Add External JARs and navigate to the project&#8217;s lib directory.	Mark all files and click OK.</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2658892523/" title="fig2-2_libs by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3276/2658892523_dd6937c6a2.jpg" width="470" height="500" alt="fig2-2_libs" /></a></p>
<p>It&#8217;s time to configure Hibernate. In the src/main/java directory create a file called hibernate.cfg.xml:</p>
<pre>

         org.postgresql.Driver
         jdbc:postgresql://localhost/droolsdb
         droolsuser

         1
         org.hibernate.dialect.PostgreSQLDialect
         org.hibernate.transaction.JDBCTransactionFactory

         thread
         org.hibernate.cache.NoCacheProvider
         true
         create
</pre>
<p>As you see, we&#8217;re going to use the org.postgresql.Driver class,	hence we need to add another library to our project. From the <a href="http://jdbc.postgresql.org/download.html">PostgreSQL home	page</a> we can download the required driver. I&#8217;m using <a href="http://jdbc.postgresql.org/download/postgresql-8.2-508.jdbc3.jar">8.2-508	JDBC 3</a>. Don&#8217;t forget to add it to the Java Build Path, like we did with the hibernate library.</p>
<p>It&#8217;s time to <a href="http://www.postgresql.org/ftp/source/v8.2.9/">download</a> and start PostgreSQL and create a user and schema.</p>
<pre>
/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data&gt;logfile 2&gt;&amp;1 &amp;
/usr/local/pgsql/bin/createuser -h 127.0.0.1 -p 5432 -U postgres -s -d -R droolsuser
/usr/local/pgsql/bin/createdb -h 127.0.0.1 -p 5432 -U postgres -O droolsuser droolsdb
</pre>
<p>The last step is mapping &#8211; this is connecting the world of Java	objects with the world of relations (tabels). Create model.hbm.xml in the eu.kijanowski.drools.hibernate package:</p>
<pre>

				player_id_seq

				game_id_seq
</pre>
<h2><a name="drools">Drools</a></h2>
<p>We&#8217;re almost there. We olny have to create the rule file and a testing class which will start our example. But how are we going to use Hibernate in our application? Well, in our testing class we will create a Hibernate session and provide it to the rule engine&#8217;s working memory as a constant global value. This allows us to access the database from inside the rule file. Next we will create a query and access the result&#8217;s objects using the keyword &#8220;from&#8221;. Let&#8217;s do this:</p>
<p><i>Class DroolsHibernateTest.java</i></p>
<pre>
package eu.kijanowski.drools.hibernate;

import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.WorkingMemory;
import org.drools.compiler.PackageBuilder;
import org.drools.rule.Package;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class DroolsHibernateTest {

	private final static SessionFactory factory;
	static {
		Configuration cfg = new Configuration().configure();
		factory = cfg.buildSessionFactory();
	}

	public static final void main(String[] args) {
		try {

			Game g1 = new Game("BF2", 39.99, 5);
			Game g2 = new Game("AoE3", 129.99, 45);
			Game g3 = new Game("BF3", 139.99, 15);

			HashSet games1 = new HashSet();
			games1.add(g1);
			games1.add(g2);
			games1.add(g3);
			HashSet games2 = new HashSet();
			games2.add(g1);
			games2.add(g3);

			Player p1 = new Player("jarek", 26, games1);
			Player p2 = new Player("ewelina", 25, games2);

			System.out.println(p1.getGames());
			System.out.println(p2.getGames());

			/* open a Hibernate session and persist data */
			Session session = factory.openSession();
			Transaction tx = session.beginTransaction();
			session.save(p1);
			session.save(p2);
			tx.commit();
			session.close();

			/* Let's verify the persisted data */
			session = factory.openSession();
			tx = session.beginTransaction();

			List players = session.createCriteria(Player.class).list();
			System.out.println(players.size() + " player(s) found:");
			for (Iterator iter = players.iterator(); iter.hasNext();) {
				Player player = (Player) iter.next();
				System.out.println(player.getName() + " has following games: "
						+ player.getGames());
			}
			tx.commit();
			session.close();

			// load up the rulebase
			RuleBase ruleBase = readRule();
			WorkingMemory workingMemory = ruleBase.newStatefulSession();

			/* pass a hibernate session to the working memory as a global */
			session = factory.openSession();
			workingMemory.setGlobal("hibernateSession", session);

			workingMemory.fireAllRules();
			session.close();

		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

	private static RuleBase readRule() throws Exception {
		// read in the source
		Reader source = new InputStreamReader(DroolsHibernateTest.class
				.getResourceAsStream("/Demo.drl"));

		PackageBuilder builder = new PackageBuilder();

		// this will parse and compile in one step
		builder.addPackageFromDrl(source);

		// get the compiled package (which is serializable)
		Package pkg = builder.getPackage();

		// add the package to a rulebase (deploy the rule package).
		RuleBase ruleBase = RuleBaseFactory.newRuleBase();
		ruleBase.addPackage(pkg);
		return ruleBase;
	}

}
</pre>
<p>The rule file can be created using the drools plug-in. Just click on the src/main/rules directory and from the menu File -&gt; New -&gt; Other&#8230; click Drools -&gt; Rule Resource:</p>
<p><a href="http://www.flickr.com/photos/redhatmagazine/2658892635/" title="fig2-3_demodrl by redhatmag, on Flickr"><img src="http://farm4.static.flickr.com/3189/2658892635_58deebe2a6.jpg" width="414" height="500" alt="fig2-3_demodrl" /></a></p>
<p><i>Demo.drl</i></p>
<pre>
package eu.kijanowski.drools.hibernate

global org.hibernate.Session hibernateSession;

rule "hibernate_from"
	when
		game:Game() from hibernateSession.createQuery("select games from Player p where p.age &gt;= :age").setProperties( {"age" : 18 }).list()
	then
		System.out.println("The game "+game.getName() +"is owned by "+game.getPlayers());
end
</pre>
<h2><a name="howdoesitwork">How does it work?</a></h2>
<p>Let&#8217;s have a look at the <b>global</b> keyword in the rule file. This allows us to provide the rule engine with constants and variables from outside. Potential usecases are:</p>
<ul>
<li>return results back to the application
<li>
<li>access services, like Hibernate, JMS, file writers, email senders, etc.</li>
</ul>
<p>What&#8217;s worth to know is that you should <b>never change a global</b>, when you use it in the condition part (LHS) of a rule. Moreover globals are <b>not designed to share any data</b> between rules, this can be done via facts living in the working memory.</p>
<p>The condition element <b>from</b> allows to access data from other sources than the working memory. These can be Collectins, Maps and results coming from called methods. In our scenario we&#8217;ve created a query and received a list of games.</p>
<h2><a name="final">Results</a></h2>
<p>After running our example (Run as -&gt; Java Application) the console will show:</p>
<pre>
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Environment 

INFO: Hibernate 3.2.6
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Environment
INFO: hibernate.properties not found
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: Bytecode provider name : cglib
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Environment 

INFO: using JDK 1.4 java.sql.Timestamp handling
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Configuration configure
INFO: configuring from resource: /hibernate.cfg.xml
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: Configuration resource: /hibernate.cfg.xml
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.Configuration addResource
INFO: Reading mappings from resource : eu/kijanowski/drools/hibernate/model.hbm.xml
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: eu.kijanowski.drools.hibernate.Player -&gt; PLAYERS
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.HbmBinder bindCollection
INFO: Mapping collection: eu.kijanowski.drools.hibernate.Player.games -&gt; PLAYERS_GAMES
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: eu.kijanowski.drools.hibernate.Game -&gt; GAMES
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.HbmBinder bindCollection
INFO: Mapping collection: eu.kijanowski.drools.hibernate.Game.players -&gt; PLAYERS_GAMES
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.Configuration doConfigure
INFO: Configured SessionFactory: null
Jun 14, 2008 8:58:12 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Using Hibernate built-in connection pool (not for production use!)
Jun 14, 2008 8:58:12 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Hibernate connection pool size: 1
Jun 14, 2008 8:58:12 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: autocommit mode: false
Jun 14, 2008 8:58:12 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: using driver: org.postgresql.Driver at URL: jdbc:postgresql://localhost/droolsdb
Jun 14, 2008 8:58:12 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: connection properties: {user=droolsuser, password=****}
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: RDBMS: PostgreSQL, version: 8.2.5
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC driver: PostgreSQL Native Driver, version: PostgreSQL 8.2 JDBC3 with SSL (build 508)
Jun 14, 2008 8:58:12 AM org.hibernate.dialect.Dialect 

INFO: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Jun 14, 2008 8:58:12 AM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Transaction strategy: org.hibernate.transaction.JDBCTransactionFactory
Jun 14, 2008 8:58:12 AM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Connection release mode: auto
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL inserts for batching: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
Jun 14, 2008 8:58:12 AM org.hibernate.hql.ast.ASTQueryTranslatorFactory
INFO: Using ASTQueryTranslatorFactory
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JPA-QL strict compliance: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.NoCacheProvider
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Named query checking : enabled
Jun 14, 2008 8:58:12 AM org.hibernate.impl.SessionFactoryImpl
INFO: building session factory
Jun 14, 2008 8:58:12 AM org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
Jun 14, 2008 8:58:12 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: Running hbm2ddl schema export
Jun 14, 2008 8:58:12 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: exporting generated schema to database
Jun 14, 2008 8:58:13 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: schema export complete
[BF3 with 15 levels for 139.99, BF2 with 5 levels for 39.99, AoE3 with 45 levels for 129.99]
[BF3 with 15 levels for 139.99, BF2 with 5 levels for 39.99]
Hibernate: select nextval ('player_id_seq')
Hibernate: select nextval ('game_id_seq')
Hibernate: select nextval ('game_id_seq')
Hibernate: select nextval ('game_id_seq')
Hibernate: select nextval ('player_id_seq')
Hibernate: insert into PLAYERS (NAME, AGE, PLAYER_ID) values (?, ?, ?)
Hibernate: insert into GAMES (NAME, PRICE, LEVELS, GAME_ID) values (?, ?, ?, ?)
Hibernate: insert into GAMES (NAME, PRICE, LEVELS, GAME_ID) values (?, ?, ?, ?)
Hibernate: insert into GAMES (NAME, PRICE, LEVELS, GAME_ID) values (?, ?, ?, ?)
Hibernate: insert into PLAYERS (NAME, AGE, PLAYER_ID) values (?, ?, ?)
Hibernate: insert into PLAYERS_GAMES (PLAYER_ID, GAME_ID) values (?, ?)
Hibernate: insert into PLAYERS_GAMES (PLAYER_ID, GAME_ID) values (?, ?)
Hibernate: insert into PLAYERS_GAMES (PLAYER_ID, GAME_ID) values (?, ?)
Hibernate: insert into PLAYERS_GAMES (PLAYER_ID, GAME_ID) values (?, ?)
Hibernate: insert into PLAYERS_GAMES (PLAYER_ID, GAME_ID) values (?, ?)
Hibernate: select this_.PLAYER_ID as PLAYER1_0_0_, this_.NAME as NAME0_0_, this_.AGE as AGE0_0_ from PLAYERS this_
2 player(s) found:
Hibernate: select games0_.PLAYER_ID as PLAYER1_1_, games0_.GAME_ID as GAME2_1_, game1_.GAME_ID as GAME1_2_0_, game1_.NAME as NAME2_0_, game1_.PRICE as PRICE2_0_, game1_.LEVELS as LEVELS2_0_ from PLAYERS_GAMES games0_ left outer join GAMES game1_ on games0_.GAME_ID=game1_.GAME_ID where games0_.PLAYER_ID=?
jarek has following games: [AoE3 with 45 levels for 129.99, BF3 with 15 levels for 139.99, BF2 with 5 levels for 39.99]
Hibernate: select games0_.PLAYER_ID as PLAYER1_1_, games0_.GAME_ID as GAME2_1_, game1_.GAME_ID as GAME1_2_0_, game1_.NAME as NAME2_0_, game1_.PRICE as PRICE2_0_, game1_.LEVELS as LEVELS2_0_ from PLAYERS_GAMES games0_ left outer join GAMES game1_ on games0_.GAME_ID=game1_.GAME_ID where games0_.PLAYER_ID=?
ewelina has following games: [BF3 with 15 levels for 139.99, BF2 with 5 levels for 39.99]
Hibernate: select game2_.GAME_ID as GAME1_2_, game2_.NAME as NAME2_, game2_.PRICE as PRICE2_, game2_.LEVELS as LEVELS2_ from PLAYERS player0_ inner join PLAYERS_GAMES games1_ on player0_.PLAYER_ID=games1_.PLAYER_ID inner join GAMES game2_ on games1_.GAME_ID=game2_.GAME_ID where player0_.AGE&gt;=?
Hibernate: select players0_.GAME_ID as GAME2_1_, players0_.PLAYER_ID as PLAYER1_1_, player1_.PLAYER_ID as PLAYER1_0_0_, player1_.NAME as NAME0_0_, player1_.AGE as AGE0_0_ from PLAYERS_GAMES players0_ left outer join PLAYERS player1_ on players0_.PLAYER_ID=player1_.PLAYER_ID where players0_.GAME_ID=?
The game BF2is owned by [jarek, ewelina]
Hibernate: select players0_.GAME_ID as GAME2_1_, players0_.PLAYER_ID as PLAYER1_1_, player1_.PLAYER_ID as PLAYER1_0_0_, player1_.NAME as NAME0_0_, player1_.AGE as AGE0_0_ from PLAYERS_GAMES players0_ left outer join PLAYERS player1_ on players0_.PLAYER_ID=player1_.PLAYER_ID where players0_.GAME_ID=?
The game BF3is owned by [jarek, ewelina]
Hibernate: select players0_.GAME_ID as GAME2_1_, players0_.PLAYER_ID as PLAYER1_1_, player1_.PLAYER_ID as PLAYER1_0_0_, player1_.NAME as NAME0_0_, player1_.AGE as AGE0_0_ from PLAYERS_GAMES players0_ left outer join PLAYERS player1_ on players0_.PLAYER_ID=player1_.PLAYER_ID where players0_.GAME_ID=?
The game AoE3is owned by [jarek]
The game BF2is owned by [jarek, ewelina]
The game BF3is owned by [jarek, ewelina]
</pre>
<h2><a name="summary">Summary</a></h2>
<p>This article shows how you can easily integrate Hibernate with the Drools rule engine. This allows you to reason over data, which does not only live in the working memory, but also in an external database.</p>
<div class="caption">All images and content copyright © 2008 Jaroslaw Kianowski. All rights reserved. Used with permission.</div>
<h2>Related articles</h2>
<ul>
<li><a href="http://www.redhatmagazine.com/2008/03/27/video-mark-proctor/">Video: Mark Proctor and JBoss Drools</a></li>
<li><a href="http://www.redhatmagazine.com/2008/05/01/video-mark-proctor-part-2-origins-and-uses-of-jboss-drools/">Video: Mark Proctor, part 2: Origins and uses of JBoss Drools</a></li>
</ul>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/rhredhatmagazine.wordpress.com/966/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/rhredhatmagazine.wordpress.com/966/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rhredhatmagazine.wordpress.com/966/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rhredhatmagazine.wordpress.com/966/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rhredhatmagazine.wordpress.com/966/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rhredhatmagazine.wordpress.com/966/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rhredhatmagazine.wordpress.com/966/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rhredhatmagazine.wordpress.com/966/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rhredhatmagazine.wordpress.com/966/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rhredhatmagazine.wordpress.com/966/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rhredhatmagazine.wordpress.com/966/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rhredhatmagazine.wordpress.com/966/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=magazine.redhat.com&blog=5816259&post=966&subd=rhredhatmagazine&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://magazine.redhat.com/2008/07/11/jboss-drools-meets-hibernate/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">kijanowski</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3096/2658892369_0eea61eb8e.jpg" medium="image">
			<media:title type="html">fig2-1_step1</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3276/2658892523_dd6937c6a2.jpg" medium="image">
			<media:title type="html">fig2-2_libs</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3189/2658892635_58deebe2a6.jpg" medium="image">
			<media:title type="html">fig2-3_demodrl</media:title>
		</media:content>
	</item>
	</channel>
</rss>