CopyDisable

Sunday 6 January 2013

WebPasswordSafe LDAP authentication problem

I faced a problem while configuring LDAP authentication in WebPasswordSafe. My configuration was as follows:

<bean id="authnContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
        <property name="url" value="ldap://192.168.20.1:389" />
        <property name="userDn" value="CN=Websafe,OU=IT Infra,OU=L6 Users,DC=mkmumbai,DC=local" />
        <property name="password" value="xxxxxxxx" />
</bean>
    <bean id="authnLdapTemplate" class="org.springframework.ldap.core.LdapTemplate">
        <constructor-arg ref="authnContextSource" />
</bean>
<bean id="ldapAuthenticator" class="net.webpasswordsafe.server.plugin.authentication.LdapAuthenticator">
        <property name="ldapTemplate" ref="authnLdapTemplate" />
        <property name="filter" value="(&amp;(objectclass=person)(sAMAccountName=$1))" />
        <property name="base" value="DC=mkmumbai,DC=local" />
</bean>

But login was getting failed. I got the following

DEBUG [http-80-1]: ldap error authenticating: Unprocessed Continuation Reference(s); nested exception is javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name 'dc=mkmumbai,dc=local'
2013-01-02 12:21:15,106 DEBUG [http-80-1]: LdapAuthenticator: login success for websafe? false

 

Where as with the following configuration, LDAP authentication was successful.

<bean id="authnContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://192.168.20.1:389" />
<property name="userDn" value="CN=Websafe,OU=IT Infra,OU=L6 Users,DC=mkmumbai,DC=local" />
<property name="password" value="xxxxxxxx" />
</bean>
<bean id="authnLdapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="authnContextSource" />
</bean>
<bean id="ldapAuthenticator" class="net.webpasswordsafe.server.plugin.authentication.LdapAuthenticator">
<property name="ldapTemplate" ref="authnLdapTemplate" />
<property name="filter" value="(&amp;(objectclass=person)(sAMAccountName=$1))" />
<property name="base" value="OU=IT Infra,OU=L6 Users,DC=mkmumbai,DC=local" />
</bean>

 

In our active directory setup, users are placed in different OUs as per our policy. For LDAP search, the base has to be DC=mkmumbai,DC=local otherwise authentication LDAP search will not be successful. So to resolve this issue, I used the following LDAP configuration (I have added the line <property name="referral" value="follow"/> ) which worked for me:

 

<bean id="authnContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
       
<property name="referral" value="follow"/>
        <property name="url" value="ldap://192.168.20.1:389" />
        <property name="userDn" value="CN=Websafe,OU=IT Infra,OU=L6 Users,DC=mkmumbai,DC=local" />
        <property name="password" value="xxxxxxxx" />
    </bean>
    <bean id="authnLdapTemplate" class="org.springframework.ldap.core.LdapTemplate">
        <constructor-arg ref="authnContextSource" />
    </bean>
    <bean id="ldapAuthenticator" class="net.webpasswordsafe.server.plugin.authentication.LdapAuthenticator">
        <property name="ldapTemplate" ref="authnLdapTemplate" />
        <property name="filter" value="(&amp;(objectclass=person)(sAMAccountName=$1))" />
        <property name="base" value="DC=mkmumbai,DC=local" />
    </bean>

Saturday 5 January 2013

Shell script to run Pentaho as service

For this blog post I am using Ubuntu Linux 12.04 and Pentaho 4.5. This script will start/stop pentaho bi-server and the administration console. Also this script will show the running status of the pentaho bi-server and the administration console.

I am naming this script as pentaho (as my service name)

#pico pentaho

#!/bin/sh
# Startup script for Pentaho BI Server and Administration Console
# Author: Pranab Sharma
http://pe-kay.blogspot.in/
# Usage: ./pentaho.sh start | stop | restart | status

JAVA_OPTS="-Djava.awt.headless=true"
case "$1" in
start)

cd /usr/local/pentaho-4.5/biserver-ce

$cmd ./start-pentaho.sh >> biserver.log &
# Start admin console
cd /usr/local/pentaho-4.5/administration-console

$cmd ./start-pac.sh >> admin-console.log &
;;
stop)

cd /usr/local/pentaho-4.5/administration-console

$cmd ./stop-pac.sh >> admin-console.log &

cd /usr/local/pentaho-4.5/biserver-ce

$cmd ./stop-pentaho.sh >> biserver.log &
;;
restart)
$0 stop
$0 start
;;
status)
admin_pid=$(ps -ef | grep pentaho-open-admin-console | grep -v grep | awk '{print $2}')
if [ ! -z "$admin_pid" ]
then
echo "Pentaho Admin Console is running with PID $admin_pid"
else
echo "Pentaho Admin Console is not running"
fi
biserver_pid=$(ps -ef | grep biserver-ce | grep -v grep | awk '{print $2}')
if [ ! -z "$biserver_pid" ]
then
echo "Pentaho BiServer is running with PID $biserver_pid"
else
echo "Pentaho BiServer is not running"
fi
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit 0

 

Make this script executable

# chmod +x pentaho

Copy the script to /etc/init.d

# cp pentaho /etc/init.d

That’s it, our pentaho service is ready.

Sample run of this service:

image

Thursday 3 January 2013

Using self-signed certificate in Tomcat for secure connection

For one of our in-house applications (running on Tomcat), I had to implement SSL. All the communications to that application must be secure, as the application will store some sensitive information. As we are going to use this application inside our organization, so I had decided to deploy self-signed certificate instead of paying money and buying certificate from some CA.

Step 1: Generate self-signed certificate

Creating self-signed certificate is very easy, and I am going to use the keytool program which comes with JDK. Using keytool I will create a keystore file to store the server's private key and self-signed certificate.
root@pranabs:~# keytool -genkey -alias tomcat -keyalg RSA -keystore /usr/local/tomcat/conf/.keystore -validity 365
Enter keystore password:
Re-enter new password:
What is your first and last name?
  [Unknown]:  MY CA
What is the name of your organizational unit?
  [Unknown]:  Development
What is the name of your organization?
  [Unknown]:  M Ltd.
What is the name of your City or Locality?
  [Unknown]:  Pune
What is the name of your State or Province?
  [Unknown]:  Maharashtra
What is the two-letter country code for this unit?
  [Unknown]:  IN
Is CN=MY CA, OU=Development, O=M Ltd., L=Pune, ST=Maharashtra, C=IN correct?
  [no]:  yes

Enter key password for <tomcat>
        (RETURN if same as keystore password):


-genkey: Generates a key pair (a public key and associated private key). Wraps the public key into an X.509 v1 self-signed certificate, which is stored as a single-element certificate chain. This certificate chain and the private key are stored in a new keystore entry identified by alias.
-alias: All keystore entries (key and trusted certificate entries) are accessed via unique aliases.
-keyalg: specifies the algorithm to be used to generate the key pair.
-keystore: keytool command creates a new keystore file, in the home directory of the user under which the command was run, and named it as .keystore. To specify a different location or filename, the –keystore parameter is used.
-validity: It specifies the number of days for which the certificate should be considered valid.
When we run the command, we will first be prompted for the keystore password. Enter the password for the keystore. This password we have to specify in tomcat’s server.xml file.
Next we have to enter general information about the Certificate, such as company, contact name, and so on. Later if somebody access some secure page, he/she can view these information of the certificate. Here we have to make sure that the information that we entered are acceptable by our users.
Finally, we have to enter the key password, this password is for the certificate that we are generating. Here we must enter the same password as we entered for the keystore password (this is a tomcat restriction).

Step 2: Edit tomcat configuration file

Here we are going to configure tomcat’s https connector. Open tomcat’s server.xml configuration file. In my config file tomcat is configured to use port 80 (tomcat default 8080) for http connection and port 443 (tomcat default 8443) for https connection. In https connector, specify the keystoreFile and keystorePass attributes.
# pico /usr/local/tomcat/conf/server.xml
<Connector port="80" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="443" />

<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               keystoreFile="/usr/local/tomcat/conf/.keystore"  keystorePass="xxxxxxxx"    />

Save the file.

Step 3: Configure Tomcat to redirect HTTP requests to HTTPS.

Edit the web.xml file of the application
#pico /usr/local/tomcat/webapps/myapp/WEB-INF/web.xml
and add the following lines:

<web-app ……….>
…….
…….
…….
 <security-constraint>
        <web-resource-collection>
         <web-resource-name>myapp</web-resource-name>
         <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
         <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
   </security-constraint>


</web-app>

Save the file and restart tomcat. That’s it and we are done, our application is now secured Smile.

Tuesday 1 January 2013

Using Multi authentication in WebPasswordSafe

WebPasswordSafe (http://code.google.com/p/webpasswordsafe/) is a Web based secure password store, and it supports multiple users with delegated access controls. The installation guide is available at http://webpasswordsafe.googlecode.com/svn/trunk/docs/AdministratorGuide.html

I deployed it and initially faced some issues when I tried to implement LDAP authentication using Active Directory. I would like to mention one point here, I found that in many applications which use LDAP authentication, automatically create a local user in the application whenever the user tries to login for the first time using LDAP login. But here I had to create a local user first with the same username as his/her LDAP login, then the user can use his/her LDAP credentials to login to the application.

WebPasswordSafe has few different authentication modes to authenticate a user. For my deployment I found Multi authentication most suitable, which allows using multiple Authenticator implementations for different sets of users. e.g. for admin user I can use local authentication and for other users I can use LDAP authentication.

So my webpasswordsafe-service.xml file that looks like (for using multi authentication):

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!--
    Copyright 2008-2012 Josh Drummond
   
    This file is part of WebPasswordSafe.
   
    WebPasswordSafe is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
   
    WebPasswordSafe is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
   
    You should have received a copy of the GNU General Public License
    along with WebPasswordSafe; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-->
<beans xmlns="
http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xsi:schemaLocation="
    
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- core services -->
   
    <context:component-scan base-package="net.webpasswordsafe.server.service" />

    <!-- pluggable services -->
   
    <bean id="passwordGenerator"
        class="net.webpasswordsafe.server.plugin.generator.SimpleRandomPasswordGenerator" >
        <property name="passwordLength" value="14" />
        <property name="allowLowercase" value="true" />
        <property name="allowUppercase" value="true" />
        <property name="allowNumeric" value="true" />
        <property name="specialChars" value="" />
        <property name="excludeChars" value="O0l1" />
    </bean>

 

    <bean id="authenticator"
        class="net.webpasswordsafe.server.plugin.authentication.IPLockoutAuthenticator">
        <property name="authenticator" ref="userLockoutAuthenticator" />
        <property name="failedLoginThreshold" value="10" />
        <property name="lockoutLength" value="1440" />
        <property name="whitelist">
            <set>
                <value>127.0.0.1</value>
            </set>
        </property>
    </bean>

    <bean id="userLockoutAuthenticator"
        class="net.webpasswordsafe.server.plugin.authentication.UserLockoutAuthenticator">
        <property name="authenticator" ref="multiAuthenticator" />
        <property name="failedLoginThreshold" value="5" />
        <property name="whitelist">
            <set>
                <value>admin</value>
            </set>
        </property>
    </bean>


   <bean id="multiAuthenticator"
        class="net.webpasswordsafe.server.plugin.authentication.CompositeAuthenticator">
        <property name="authenticators">
            <list>
                <map>
                    <entry key="users">
                        <list>
                            <value>admin</value>
                        </list>
                    </entry>
                    <entry key="authenticator" value-ref="localAuthenticator"></entry>
                </map>
                <map>
                    <entry key="anyUser" value="true" />
                    <entry key="authenticator" value-ref="ldapAuthenticator"></entry>
                </map>
            </list>
        </property>
    </bean>

 

   <bean id="authnContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
        <property name="url" value="ldap://192.168.20.1:389" />
        <property name="userDn" value="CN=pranab,OU=Staff,DC=mkcl,DC=local" />
        <property name="password" value="12345678" />
    </bean>
    <bean id="authnLdapTemplate" class="org.springframework.ldap.core.LdapTemplate">
        <constructor-arg ref="authnContextSource" />
    </bean>
    <bean id="ldapAuthenticator" class="net.webpasswordsafe.server.plugin.authentication.LdapAuthenticator">
        <property name="ldapTemplate" ref="authnLdapTemplate" />
        <property name="filter" value="(&amp;(objectclass=person)(sAMAccountName=$1))" />
        <property name="base" value="OU=Staff,DC=mkcl,DC=local" />
    </bean>

 

   <bean id="localAuthenticator"
        class="net.webpasswordsafe.server.plugin.authentication.LocalAuthenticator">
    </bean>

   
    <bean id="roleRetriever"
        class="net.webpasswordsafe.server.plugin.authentication.LocalRoleRetriever">
        <property name="adminUsers">
            <set>
                <value>admin</value>
            </set>
        </property>
    </bean>

    <bean id="authorizer"
        class="net.webpasswordsafe.server.plugin.authorization.DefaultAuthorizer">
    </bean>
 
    <bean id="auditLoggerLog4j"
        class="net.webpasswordsafe.server.plugin.audit.Log4jAuditLogger">
        <property name="delimiter" value=" || " />
    </bean>
       
    <bean id="auditLoggerDatabase"
        class="net.webpasswordsafe.server.plugin.audit.DatabaseAuditLogger" />
   
    <bean id="auditLogger"
        class="net.webpasswordsafe.server.plugin.audit.CompositeAuditLogger">
        <property name="auditLoggers">
            <list>
                <ref bean="auditLoggerLog4j" />
                <ref bean="auditLoggerDatabase" />
            </list>
        </property>
    </bean>
       
    <!--  Encryption related settings, these should not be changed after initial deployment otherwise
          data may be corrupted or unreadable -->
         
    <!-- ## Uncomment for Jasypt Encryption -->
    <bean id="digester" class="net.webpasswordsafe.server.plugin.encryption.JasyptDigester">
        <property name="passwordEncryptor" ref="passwordEncryptor" />
    </bean>
    <bean id="passwordEncryptor" class="org.jasypt.util.password.StrongPasswordEncryptor" />
    <bean id="encryptor" class="net.webpasswordsafe.server.plugin.encryption.JasyptEncryptor">
        <property name="stringEncryptor" ref="strongEncryptor" />
    </bean>
    <bean id="bcProvider" class="org.bouncycastle.jce.provider.BouncyCastleProvider" />
    <bean id="strongEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
        <property name="algorithm" value="${encryptor.jasypt.algorithm}" />
        <property name="provider" ref="bcProvider" />
        <property name="password" value="${encryptor.jasypt.password}" />
        <property name="keyObtentionIterations" value="${encryptor.jasypt.keyObtentionIterations}" />
    </bean>

   
       
</beans>

 

 

After using the application, I found that the admin user can see passwords of any user, even though permissions for those passwords were not given to the admin user. After some search I found this issue:

http://code.google.com/p/webpasswordsafe/issues/detail?id=47

So again building the application by commenting the  BYPASS_PASSWORD_PERMISSIONS line in DefaultAuthorizer.java file worked for me. Now the admin user was not able to see the passwords (which were not shared with the admin user).