CAS server per Liferay, vTiger CRM e Pentaho

Autenticazione

Se per portale intendiamo un’insieme di pagine web da cui accedere ad informazioni e/o applicazioni diverse, una delle criticità principali è legata all’autenticazione degli utenti.

Scenario

In uno scenario ipotetico oltre al portale sarà necessario accedere a diverse applicazioni come ad esempio: al gestionale, al CRM (magari basato su vTiger), alla Business Intelligence (ad esempio, basata su Pentaho).

Quindi avremmo la necessità di avere a disposizione le credenziali di accesso per:

  1. Il portale
  2. Il gestionale
  3. Il crm
  4. La BI

Soluzione 0

Gestione manuale delle credenziali di accesso degli utenti in ogni sistema, senza preoccuparsi che in ogni sistema esista lo stesso utente con la stessa password.

Questo di per sé rappresenta un punto di inefficienza e quanto meno si potrebbe fare in modo che in ogni sistema siano definiti gli stessi utenti con le stesse password, lasciando tale (ingrato compito) ad un amministratore di sistema.

Soluzione 1

Gestione manuale delle credenziali di accesso degli utenti in ogni sistema, avendo cura che in ogni sistema esista lo stesso utente con la stessa password.

Caso 1

Situazione: il portale è usato come soluzione di document management e non vi sono integrazioni “vere e proprie” con le altre applicazioni aziendali

Ora immaginiamo che un generico utente faccia quello che segue:

  1. Apre il browser e si collega al portale per consultare un documento interno.
  2. Di seguito, sempre con il browser, apre il crm per consultare la lista delle proprie attività.

Nel caso in cui sia stata adottata la soluzione 1 l’utente dovrebbe prima autenticarsi con il portale e poi dovrebbe re-inserire le stesse credenziali per accedere al CRM.

Le credenziali da ricordare sono le stesse, ma comunque vanno inserite due volte.

Soluzione 2

Per semplificare la vita all’amministratore di sistema (che non è certamente la prima preoccupazione di un CEO/CIO) si potrebbe pensare che sia il portale che il crm (per rimanere nell’esempio) condividano lo stesso database utenti in cui verificare le credenziali.

Ciò è possibile, ma è necessario che ogni sistema coinvolto sia in grado di autenticare gli utenti con lo stesso meccanismo (solitamente LDAP).

Caso 2

Situazione: il portale è usato come soluzione di document management e integra alcune funzionalità del CRM (ad esempio la lista delle attività da fare relativa all’utente collegato al portale)

Ora immaginiamo che un generico utente faccia quello che segue:

  1. Apre il browser e si collega al portale per consultare un documento interno.
  2. Di seguito, sempre all’interno del portale, accede ad una pagina dove può direttamente consultare la lista delle proprie attività.

Per fare quanto sopra descritto l’utente si collegherà al portale fornendo le sue credenziali e poi non si dovrà più preoccupare di inserirle di nuovo anche se accede a funzioni/dati di altri sistemi.

Ovviamente nessuna delle soluzioni descritte in precedenza soddisferebbe i requisiti illustrati in questo caso.

Qui è necessario che, una volta che l’utente abbia fornito correttamente le sue credenziali, ciascuno dei sistemi coinvolti riconosca che l’utente è “valido” tutte le volte che questi farà accesso ad un sistema diverso.

L’idea è quella di mettere “al centro” il sistema di autenticazione facendo in modo che ciascuno dei sistemi coinvolti verifichi la richiesta di accesso dell’utente con il sistema centrale.

L’utente si autentifica una sola volta e parliamo quindi di Single Sign On (SSO).

Soluzione 3: CAS

Una delle possibilità per implementare una soluzione di SSO è quella di utilizzare il Central Authentication Service (CAS).

Da Wikipedia: “Il JA-SIG Central Authentication Service (CAS) (http://www.jasig.org/cas) è un servizio single sign-on libero (originariamente sviluppato dall’Università di Yale) che permette alle applicazioni web la possibilità di rinviare tutte le autenticazioni a un server centrale o a più server di fiducia. Numerosi client sono disponibili gratuitamente, inclusi client per JavaMicrosoft .NetPHPPerl,ApacheuPortalLiferay (http://www.liferay.com) e altri.”

La scelta del CAS è dettata dal fatto di dover garantire SSO tra Liferay Portal ed una serie di applicazioni.

Funzionamento del CAS

 

  1. Liferay Portal supporta nativamente CAS (integra un CAS-Client): http://www.liferay.com/community/wiki/-/wiki/Main/CAS+Liferay+6+Integration
  2. vTiger CRM può essere integrato con CAS: http://www.docstoc.com/docs/62049254/How-to-install-vTiger-and-integrate-with-Cas
  3. Pentaho supporta CAS: http://wiki.pentaho.com/display/ServerDoc2x/Single+Sign-On+with+CAS
  4. Esistono client “ufficiali” per utilizzarli in altre integrazioni:
    1. .Net Cas Client
    2. Acegi as CAS Client
    3. CAS Client for Java 3.0
    4. CAS Client for Java 3.1
    5. mod_auth_cas
    6. phpCAS
  1. Esiste una numerosa serie di client “unofficial” e una buona documentazione su come integrare un applicazione con CAS: https://wiki.jasig.org/display/CAS/CASifying+Applications

Note sulla configurazione di CAS nell’ambiente demo di miazienda.

Cas necessita di un application server, pertanto è stato sfruttato il server srvport-demo.miazienda.com in cui è già installato Tomcat 7 per Liferay Portal.

Inoltre per un utilizzo effettivo occorre che le comunicazioni tra le applicazioni da integare e il CAS siano sicure (utilizzino cioè il protocollo https).

Per prima cosa è stato quindi necessario configurare il Tomcat del server srvport-demo per il supporto SSL.

Nel dominio demo miazienda.com il domain controller srvdc-demo è anche una Certification Authority, per cui si è deciso di utilizzare tale CA per la richiesta e l’emissione dei certificati SSL necessari al server srvport-demo.

Certificati SSL

Quindi sul server srvport-demo:

Sono state create/modificate le seguenti variabili di ambiente:

JAVA_HOME=C:\liferay-portal\tomcat-7.0.23\jre1.6.0_20\win
Path=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\MySQL\MySQL Server 5.5\bin;C:\liferay-portal\tomcat-7.0.23\jre1.6.0_20\win\bin

Dalla directory C:\liferay-portal\tomcat-7.0.23\jre1.6.0_20\win\lib\security sono stati eseguiti i comandi seguenti:

keytool -genkey -keysize 2048 -keyalg RSA -alias srvport-demo.miazienda.com -keystore keystore.jks

(alla richiesta del campo nome e cognome  stato inserito il fqdns del server: srvport-demo.miazienda.com; la scelta del nome alias uguale a quella del server non è indispensabile; la password usata per proteggere il keystore.jks è changeit)

Dopo di che si è passati a generare la certicate signing request:

keytool -certreq -alias srvport-demo.miazienda.com -file srvport.csr -keystore keystore.jks

Tale file è stato aperto con il notepad e tutto il suo contenuto è stato copiato nella clipboard.

Poi sul server srvdc-demo (accedendo tramite amministratore del dominio: IMPORTANTE se no il resto non funziona come descritto) tramite browser si è acceduto al link della CA: http://localhost/certsrv/

Qui è stato selezionato il link Request a certificate -> advanced certificate request -> Submit a certificate request by using a base-64-encoded CMC or PKCS #10 file, or submit a renewal request by using a base-64-encoded PKCS #7 file.
Qui è stato incollato nel campo Saved Request il contenuto della clipboard ed è stato scelto il valore Web Server per il campo Certificate Template. A questo punto il sistema ha generato direttamente il certificato ed ha presentato 2 link: uno per scaricare il certificato stesso (salvato come srvport-demo.miazienda.com.cer)  e uno per scaricare la catena di Certification Authorities (CA Chain; salvato come chaincer.p7b). Entrambi i certificati sono stati copiati nella directory C:\liferay-portal\tomcat-7.0.23\jre1.6.0_20\win\lib\security e da qui sono stati eseguiti i due comandi seguenti:

keytool -import -alias  srvport-demo.miazienda.com -keystore keystore.jks -trustcacerts -file chaincer.p7b

keytool -import -alias  srvport-demo.miazienda.com -keystore keystore.jks -file srvport-demo.miazienda.com.cer


SSL per Tomcat

A questo punto si è passati alla configurazione di Tomcat.

Nel file C:\liferay-portal\tomcat-7.0.23\conf\server.xml aggiungiamo

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
        maxThreads="150" scheme="https" secure="true"
        clientAuth="false" 	   
        keystoreFile="jre1.6.0_20\win\lib\security\keystore.jks" 
	keystorePass="changeit" 
	keyAlias="srvport-demo.miazienda.com"
	sslProtocol="TLS" />

Stoppiamo e riavviamo Tomcat.

Effettuiamo un test collegandoci con un browser all’indirizzo

https://srvport-demo.miazienda.com:8443

Riceveremo una segnalazione di sicurezza che in sostanza afferma che non viene riconosciuta l’Authority che ha rilasciato il certificato. Normalmente tutti i broswer riconoscono un certo numero di CA “commerciali” come ad esempio Verisign mentre, ovviamente, non sanno nulla dell’authority che ha emesso il nostro certificato (cioè non conoscono la CA CA-miazienda). Quindi per evitare che ogni volta che si accede al sito in questione appaia l’avviso di sicurezza, occorre installare nel pc il certificato della ca “CA-miazienda”. Per far questo andiamo su http://srvdc-demo.miazienda.com/certsrv/ (accediamo con un utente del dominio miazienda) e nella pagina selezioniamo il link Download a CA certificate, certificate chain, or CRL -> Download CA certificate.

Apriamo il certificato, e facciamo click sul pulsante “Installa certificato…”

D’ora in poi accedendo in https al server srvport-demo non riceveremo più avvisi di sicurezza.

Il servizio CAS

Ora occorre installare e configurare il servizio CAS.

Scarichiamo CAS da http://www.jasig.org/cas e all’interno del file compresso appena scaricato individuiamo il file \cas-server-$VERSION\modules\cas-server-webapp-$VERSION.war

  1. Aggiungiamo il file war per il CAS, cas-server-webapp-<$VERSION>.war (rinominandolo cas-web), nel folder webapps, $TOMCAT_HOME\webapps.
  2. Avviamo tomcat.
  3. Verifichiamo che esista la seguente directory, (questo significa che il deploy è avvenuto con successo), {$TOMCAT_HOME\webapps\cas-web},
  4. Fermiamo il server tomcat.
  5. Aggiungiamo al file pom.xml file nella cartella META-INF, $TOMCAT_HOME\webapps\cas-server-webapp-$VERSION\META-INF\maven\org.jasig.cas\cas-server-webapp:
<dependency>
  <groupId>${project.groupId}</groupId>
  <artifactId>cas-server-support-ldap</artifactId>
  <version>${project.version}</version>
</dependency>
  1. Modifichiamo il file  $TOMCAT_HOME\webapps\cas-web\WEB-INF\deployerConfigContext.xml come segue:
    1. Aggiungiamo la bean per l’autenticazione LDAP:
      <bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
      <property name="pooled" value="false"/>
      <property name="url" value="ldap://192.168.15.9:389" />
      <property name="userDn" value="CN=Administrator,CN=Users,DC=miazienda,DC=com"/>
      <property name="password" value="-password-"/>
      <property name="baseEnvironmentProperties">
      <map>
      	<entry key="com.sun.jndi.ldap.connect.timeout" value="3000" />
      	<entry key="com.sun.jndi.ldap.read.timeout" value="3000" />
      	<entry key="java.naming.security.authentication" value="simple">
      	</map>
      	</property>
      </bean>
      
    2. Rimuoviamo l’handler dell’autenticazione demo, org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler, dalla proprietà atheauthenticationHandlers della bean org.jasig.cas.authentication.AuthenticationManagerImpl.
    3. Aggiungiamo l’handler LDAP alla proprietà authenticationHandlers della bean authenticationHandler:
      <bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler"
      	p:filter="mail=%u"
      	p:searchBase="OU=UtentiPortale,OU=Demo,DC=miazienda,DC=com"
      	p:contextSource-ref="contextSource" />
      </beans>
      
    4. Prendiamo il file cas-server-support-ldap-$VERSION.jar dal file dell’installazione CAS e mettiamolo in $TOMCAT_HOME\webapps\cas-web\WEB-INF\lib.
    5. Mettiamo il file spring-ldap-X.Y.Z.RELEASE-all.jar nella directory $TOMCAT_HOME\webapps\cas-web\WEB-INF\lib. Può essere scaricato da http://www.springsource.org/ldap. X.Y.Z va sostituito con l’ultima versione.

E’ possibile testare il corretto avvio del server CAS tramite il seguente URL:

https://srvport-demo.miazienda.com:8443/cas-web/login

vTiger e CAS

Sul server srvmonitor-demo.miazienda.com è stato installato vTiger accessibile al seguente url

http://srvmonitor-demo.miazienda.com/crm

Si vuole raggiungere l’obiettivo di garantire l’autenticazione degli utenti vTiger tramite CAS

NOTA BENE
Gli utenti di vTiger devono avere un corrispondente utente definito nel server CAS

Ad esempio se in Vtiger ho uno username m.rossi, nel CAS server deve “esistere” il corrispondente utente m.rossi.

La password dell’utente in vTiger non ha alcun significato.

Versioni del sistema operativo e di alcune componenti del server srvmonitor-demo.miazienda.com

  1. OS                CentOs 5.7
  2. vTiger                5.3.0
  3. Apache        2.0
  4. PHP                5.3.10
  5. Mysql                5.0.77

Installazione del client phpCAS

Download del client CAS in PHP (versione utilizzata 1.3.1)

https://wiki.jasig.org/display/CASC/phpCAS

Installazione dei moduli php necessari al CAS client in particolare il supporto a CURL, SSL e DOM

Creare una directory CAS sotto la directory modules nella root di vTiger.

Copiare il contenuto della cartella CAS-1.3.1 nella directory modules/CAS della root di vTiger.

Modifiche al file modules/Users/Authenticate.php

Sostituire le righe

global $mod_strings, $default_charset;
$focus = new Users();// Add in defensive code here.
$focus->column_fields["user_name"] = to_html($_REQUEST['user_name']);
$user_password = vtlib_purify($_REQUEST['user_password']);
$focus->load_user($user_password);

con le seguenti:

global $mod_strings, $default_charset;
require_once('modules/CAS/CAS.php');
phpCAS::setDebug();
phpCAS::client(CAS_VERSION_2_0,'srvport-demo.miazienda.com',8443,'cas-web',FALSE);
phpCAS::setNoCasServerValidation();
phpCAS::forceAuthentication();
$focus = new Users();
$focus->column_fields["user_name"] = phpCAS::getUser();
$user_password = "no_use";
$focus->load_user_cas($user_password);

Aggiungere la seguente funzione al file modules/Users/Users.php

/**
         * This function s for CAS Authentication.  FMDP 06-05-2012.
         * @param  $user_password
         */
        function load_user_cas($user_password) {
                $usr_name = $this->column_fields["user_name"];
                if(isset($_SESSION['loginattempts'])){
                        $_SESSION['loginattempts'] += 1;
                } else{
                        $_SESSION['loginattempts'] = 1;
                }
                if($_SESSION['loginattempts'] > 5){
                        $this->log->warn("security: " . $usr_name . " has attempted to login ".$_SESSION['loginattempts'] . " times.");
                }
                $this->log->debug("starting user load for $usr_name");
                $validation = 0;
                unset($_SESSION['validation']);
                if( !isset($this->column_fields["user_name"]) || $this->column_fields["user_name"] == "" || !isset($user_password) || $user_password == "")

return null;
                $encrypted_password = $this->encrypt_password($user_password);
                $authcheck = true;

                $query = "select * from $this->table_name where user_name='$usr_name'";

                $result = $this->db->requiresingleresult($query, false);

                $row = $this->db->fetchbyassoc($result);
                echo $this->id = $row['id'];
                $user_hash = strtolower(md5($user_password));

                // if there is no user_hash is not present or is out of date, then create a new one.
                if(!isset($row['user_hash']) || $row['user_hash'] != $user_hash){
                        $query = "update $this->table_name set user_hash='$user_hash' where id='{$row['id']}'";
                        $this->db->query($query, true, "error setting new hash for {$row['user_name']}: ");
                }
                $this->loadpreferencesfromdb($row['user_preferences']);
                if ($row['status'] != "inactive") $this->authenticated = true;
                unset($_SESSION['loginattempts']);
                return $this;
        }

Nel file index.php nella root di vTiger aggiungere dopo la chiamata session_start();

if(isset($_GET['ticket']) && $_GET['ticket'] != '' && !isset($_SESSION['phpCAS'])){
  include('modules/Users/Authenticate.php');
}

Test

  1. Riavviare Apache.
  2. Accedere tramite browser a vTiger
  3. Nella finestra di login (è irrilevante ciò che si mette nei campi user e password) fare click su Login
  4. Verrete rediretti alla pagina di autenticazione del server CAS (l’utente con cui vi autenticate deve esistere come username in vTiger)
  5. Autenticatevi
  6. Verrette rediretti alla home page di vTiger