Management of several independant portals

Presentation

The problem here is to host several portals with no link between them. This is the case if you propose hosting services for several customers.

For example, we will configure LemonLDAP::NG to manage acme1.com and acme2.com. Each domain will have its own portal and its own protected applications.

Of course, we can do that easily with 2 differents Apache instance (on two different servers, or on different ports on the same server), but to manage it in one Apache instance, it requires some customization. Indeed, LemonLDAP::NG is build to redirect all unauthenticated request to one unique portal.

So we will now configure the WebSSO with two domains (acme1.com and acme2.com), with their own portals (auth.acme1.com and auth.acme2.com), and their own applications (test.acme1.com and test.acme2.com).

Conditionnal portal in Handler

Just override the portal value in Handler package init method. Edit handler/MyHandler.pm:

PACKAGE->init(
    {
        # Dynamic portal
        portal => '($vhost =~ /acme2.com/) ? "http://auth.acme2.com" : "http://auth.acme1.com"',
    });

Note: $vhost will be replaced by $apacheRequest->hostname for each HTTP request.

Conditionnal portal and domain in Portal

AS for the Handler, just use perl code to set portal and domain values. Edit portal/index.pl:

my $portal = Lemonldap::NG::Portal::SharedConf->new(
    {
        # Manage different portals and domains
        portal => "http://".$ENV{HTTP_HOST}."/",
        domain => ($ENV{HTTP_HOST} =~ /^.*?.(.*)$/)[0],
    });

You have to edit portal/error.pl too:
my $portal_url  = "http://".$ENV{HTTP_HOST}."/";


Note: we just use here the value of environment variable HTTP_HOST.

Apache configuration



You will have to configure 2 wirtual hosts for the portals, and set a specific ErrorDocument for protected applications. Do this in etc/apache2.conf:

# Portals
<VirtualHost *>
        ServerName auth.acme1.com

DocumentRoot /usr/local/lemonldap-ng/htdocs/portal/ DirectoryIndex index.pl

<Location /status> PerlHeaderParserHandler My::Package->status </Location>

<Directory /usr/local/lemonldap-ng/htdocs/portal/> Options +ExecCGI Order deny,allow Allow from all </Directory>

LogLevel warn ErrorLog /var/log/httpd/acme1-error.log CustomLog /var/log/httpd/acme1-access.log combined </VirtualHost>

<VirtualHost *> ServerName auth.acme2.com

DocumentRoot /usr/local/lemonldap-ng/htdocs/portal/ DirectoryIndex index.pl

<Location /status> PerlHeaderParserHandler My::Package->status </Location>

<Directory /usr/local/lemonldap-ng/htdocs/portal/> Options +ExecCGI Order deny,allow Allow from all </Directory>

LogLevel warn ErrorLog /var/log/httpd/acme2-error.log CustomLog /var/log/httpd/acme2-access.log combined </VirtualHost>

# Applications <VirtualHost *> ServerName test.acme1.com

ErrorDocument 403 http://auth.acme1.com/error.pl

DocumentRoot /usr/local/lemonldap-ng/htdocs/test/ DirectoryIndex index.pl

PerlHeaderParserHandler My::Package

<Location /refresh> PerlHeaderParserHandler My::Package->refresh </Location>

<Directory /usr/local/lemonldap-ng/htdocs/test/> Options +ExecCGI Order deny,allow Allow from all </Directory>

LogLevel warn ErrorLog /var/log/httpd/test-acme1-error.log CustomLog /var/log/httpd/test-acme1-access.log combined </VirtualHost>

<VirtualHost *> ServerName test.acme2.com

ErrorDocument 403 http://auth.acme2.com/error.pl

DocumentRoot /usr/local/lemonldap-ng/htdocs/test/ DirectoryIndex index.pl

PerlHeaderParserHandler My::Package

<Location /refresh> PerlHeaderParserHandler My::Package->refresh </Location>

<Directory /usr/local/lemonldap-ng/htdocs/test/> Options +ExecCGI Order deny,allow Allow from all </Directory>

LogLevel warn ErrorLog /var/log/httpd/test-acme2-error.log CustomLog /var/log/httpd/test-acme2-access.log combined </VirtualHost>

Portal customization

LemonLDAP::NG is configured to manage the 2 domains, but not to display different skins and application menu. This is the last step.

First create 2 skins in portal/skins/ directory: Please refer to this page for more information.

Then create 2 XML application list in etc/:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE menu SYSTEM "apps-list.dtd">
<menu>
    <category name="Business">
        <application id="test">
                <name>TEST</name>
                <uri>http://test.acme1.com</uri>
                <description>TET description</description>
                <logo>test-logo.png</logo>
                <display>auto</display>
        </application>
    </category>
</menu>
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE menu SYSTEM "apps-list.dtd">
<menu>
    <category name="Business">
        <application id="test">
                <name>TEST</name>
                <uri>http://test.acme2.com</uri>
                <description>TET description</description>
                <logo>test-logo.png</logo>
                <display>auto</display>
        </application>
    </category>
</menu>

Please refer to this page for more information.

Now hack a bit the portal script to select skin and menu depending on the called host, in portal/index.pl:

my $skin        = "pastel";
my $skin_dir    = "/usr/local/lemonldap-ng/htdocs/portal/skins";
my $appsxmlfile = "/usr/local/lemonldap-ng/etc/apps-list.xml";
my $appsimgpath = "apps/";

if ( $ENV{HTTP_HOST} =~ /acme1.com/) { $skin = "acme1"; $appsxmlfile = "/usr/local/lemonldap-ng/etc/acme1.xml"; } if ( $ENV{HTTP_HOST} =~ /acme2.com/) { $skin = "acme2"; $appsxmlfile = "/usr/local/lemonldap-ng/etc/acme2.xml"; }

Do the same (just for skin) for portal/error.pl:

my $skin        = "pastel";
my $skin_dir    = "/usr/local/lemonldap-ng/htdocs/portal/skins";

if ( $ENV{HTTP_HOST} =~ /acme1.com/) { $skin = "acme1"; } if ( $ENV{HTTP_HOST} =~ /acme2.com/) { $skin = "acme2"; }

It is finished! Just restart Apache and test your installation.