Sunday, June 1, 2014

Active/Passive and Active/Active ESB workers with HAproxy

I’m not going to mention about what is the HAproxy ..etc. If you are new to it, please go around Google and come back :).

Environment

 OS : Linux , JDK:  1.6.0_32,  WSO2 ESB 4.8.1 , HAproxy 1.4

1. First install HAproxy.

sudo apt-get install haproxy

2. Enable the HAproxy.

Open the file below and replace the default value 0 to 1.

sudo  vi /etc/default/haproxy

ENABLED=1

3. Open the file below and add the proxy configuration. (You can replace default configuration from the following sample config).

sudo vi /etc/haproxy/haproxy.cfg

global
        maxconn 4096
        user haproxy
        group haproxy
        daemon
        quiet
        nbproc 2
defaults
        log global
        mode http
        option httplog
        option dontlognull
        retries 3
        option redispatch
        maxconn 2000
        contimeout 5000
        clitimeout 50000
        srvtimeout 50000
        stats enable
        stats auth admin:admin
listen  ESB-Cluster *:90
        mode http
        monitor-uri /haproxy-test
        balance roundrobin
        option httpchk HEAD / HTTP/1.0
        option forwardfor
        cookie LSW_WEB insert nocache
        option httpclose
        server esb-01 xxx.xxx.xxx.xxx:8281 cookie s1 check
        server esb-02 xxx.xxx.xxx.xxx:8282 cookie s1 backup check
        redispatch
        stats admin if TRUE 

If you like to know about those properties and what it is does, please go through the official documentation .


4. Some important properties of above HAproxy configuration.

stats enable

Once you enable the stats, you can see the stats on the HTML page.

stats auth admin:admin

The stats page is secured using the basic auth.

server esb-01 xxx.xxx.xxx.xxx:8281 cookie s1 check
server esb-02 xxx.xxx.xxx.xxx:8282 cookie s1 backup check

I’m going to use two ESB worker nodes, esb-01,a and esb-02. I have set the cookie to s1 and s2.  
The “check” means, the proxy doing the health check to servers. The “backup” means , I’m going to use the esb-02 node as the passive worker node.

balance roundrobin

Load balance algorithm is roundrobin. (You can find the other algorithms in the documentation)

If you need more info, please go through the official documentation.

3. Start the HAproxy.

sudo service haproxy start {stop, restart, status}


4. Create two nodes of ESB worker cluster.

According to above configurations esb-01 running on offSet 1 and  and esb-02 running on port offSet 2. If you are new to WSO2 ESB and clustering, please go through the documentations[1]


5. Copy the following sample proxy configuration (EchoProxy.xml)to the proxy-services directory of worker ESB nodes. (Please change the address uri of the echo service according to your environment).

<ESB_HOME>/repository/deployment/server/synapse-configs/default/proxy-services

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="EchoProxy"
       transports="https http"
       startOnLoad="true"
       trace="disable">
   <description/>
   <target>
      <endpoint>
         <address uri="http://ajith-t530:8290/services/echo?wsdl"/>
      </endpoint>
      <inSequence>
         <log>
            <property name="printSend" value="******************************"/>
         </log>
      </inSequence>
      <outSequence>
         <send/>
         <log>
            <property name="printResponse" value="-------------------------------"/>
         </log>
      </outSequence>
   </target>
</proxy>


6) Start another fresh  ESB with port offSet 10, that ESB will use the service(echo) hosting endpoint.

7. Start  all the servers. Now if you refresh HAproxy stats page, you can see the colors are changed according to the server status.

Green - Active ESB worker (esb-01)
Blue    - Passive ESB worker(esb -02)

Now you should see the following info logs in the ESB nodes (worker) due to health check of the
HAproxy.



8. Create a SOAPUI project for the proxy service and send a requests through the HAproxy.

http://xxx.xx.com:90/services/EchoProxy

Now you should observe that the HAproxy send the request only to the  esb-01. Because in above HAproxy config, we have mentioned that the worker esb-02 as the  backup instance.



9. Now create new load test  (in SoapUI project ) using that Request1 and start the load test. So now you should see still the esb-01 is responding, then shut down the esb-01 while load is sending to HAproxy. When esb-01 is shutting down HAproxy will dispatch the request to the backup esb-02 and it will start  responding  to the requests.


10. Start the esb-01 again, Now you should see that HAproxy dispatch all the request back to esb-01 and esb-02 stop responding.


Active/Active worker ESB.

Now if you want to achieve the active/active setup, remove the “backup” property from the esb-02 configuration of the HAproxy settings (/etc/haproxy/haproxy.cfg) and restart the HAproxy.(No need to restart the ESB nodes)

sudo service haproxy restart

11.  Start the load test again, Now you should see both workers (active/active) are responding and HAproxy sending the request to the workers in roundrobin manner.


In my next post i’m planning to discuss about the SSL configurations with HAproxy.
Enjoy !! :)

Wednesday, March 26, 2014

Overwrite property in registry mount.

The following configuration section is a part of the mount configuration.

<mount path="/_system/config" overwrite="true|false|virtual">
        <instanceId>instanceid</instanceId>
        <targetPath>/_system/nodes</targetPath>
</mount>

The overwrite property can be a one of following three value

1. true

If the overwrite is true, the existing resources/collections  of the mount location will be removed before establishing the mount.

2. false

If the overwrite is false, the existing resources of the mount location will NOT  be removed before establishing the mount. But error will be logged if the same resources already exist.

3. virtual

If the overwrite is virtual, the existing resources of the mount location will be kept as it is, but mount will be added on top of it. If the existing resource is a mount or a symbolic link overwriting will not happen.

Tuesday, March 18, 2014

Mount (jdbc) WSO2 ESB registry to WSO2 Governance Registry Server with H2.


When you start the vanilla distribution of wso2 servers (WSO2 ESB , WSO2 Governance Registry , WSO2 Application Server ..etc) the default registry database is  "Embedded mode H2" . In this mode of connection it allows only one connection to the database.  Therefore if you need to mount ESB to external Governance Registry server, then it should have started with "Server mode H2"

Governance Registry Configurations:

1. Add the following  H2DatabaseConfiguration to the carbon.xml to start the Governance Registry with "Server mode H2.
<H2DatabaseConfiguration>        
        <property name="tcp" />
        <property name="tcpPort">9092</property>
        <property name="tcpAllowOthers" />        
</H2DatabaseConfiguration>
2. Change the <url> of the default WSO2_CARBON_DB in master-datasources.xml file.
Format:
jdbc:h2:tcp://<server>[:<port>]/[<path>]<databaseName>
Eg:
<url>jdbc:h2:tcp://localhost/~/h2-mount/wso2greg-4.6.0/repository/database/WSO2CARBON_DB;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000</url>
3. Start the Governance Registry server.

ESB Configurations

1. Add the following data source configuration for mount database in master-datasources.xml.
<datasource>
            <name>WSO2_CARBON_DB_mount</name>
            <description>The datasource used for mounting registry databse</description>
            <jndiConfig>
                <name>jdbc/WSO2CarbonDB_mount</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:h2:tcp://localhost/~/h2-mount/wso2greg-4.6.0/repository/database/WSO2CARBON_DB;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000</url>
                    <username>wso2carbon</username>
                    <password>wso2carbon</password>
                    <driverClassName>org.h2.Driver</driverClassName>
                    <maxActive>50</maxActive>
                    <maxWait>60000</maxWait>
                    <testOnBorrow>true</testOnBorrow>
                    <validationQuery>SELECT 1</validationQuery>
                    <validationInterval>30000</validationInterval>
                </configuration>
            </definition>
</datasource>
 2. Add the following mount configuration in registry.xml
    <dbConfig name="wso2registry_mount">
        <dataSource>jdbc/WSO2CarbonDB_mount</dataSource>
    </dbConfig>  

    <remoteInstance url="https://localhost:9443/registry">
        <id>instanceid</id>
        <dbConfig>wso2registry_mount</dbConfig>
        <readOnly>false</readOnly>
        <enableCache>true</enableCache>
        <registryRoot>/</registryRoot>
        <cacheId>carbon@jdbc:h2:tcp://localhost/~/h2-mount/wso2greg-4.6.0/repository/database/WSO2CARBON_DB;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000</cacheId> 
    </remoteInstance>

    <mount path="/_system/config" overwrite="true">
        <instanceId>instanceid</instanceId>
        <targetPath>/_system/nodes</targetPath>
    </mount>
    <mount path="/_system/governance" overwrite="true">
        <instanceId>instanceid</instanceId>
        <targetPath>/_system/governance</targetPath>
    </mount>
3. If you are ruining ESB in same machine, change the default port <Offset> in carbon.xml  to prevent the port conflicts with Governance Registry server.

Eg: 
<Offset>1</Offset>
4. Start the ESB sever.

5. Logged in to the ESB server and browse the registry to verify that mount has established.


Note: We don't recommend to use the H2 as the mount database for production setup. However this method is useful for the users who don't  have rights to create the databases (MySQL , Oracle ..etc) in their corporate database system but still want to demo/test the registry space sharing/mounting.   

Wednesday, February 12, 2014

The custom artifact drop down populator for WSO2 Governance Registry.

Configurable Governance Artifacts (RXT) is the another way to extend the functionality of  WSO2 Governance Registry. The RXT feature provides way to define your own data model very easily.

Please go through the official documentation to learn more about RXT [1].

[1]http://docs.wso2.org/pages/viewpage.action?pageId=22185121

Here I'm going to show you how to write a drop down populator to list the given type of artifacts.

Lets say we have already stored set of WSDL files in governance registry.
Now we want a drop down field in add service page to select the related WSDL file.

To achieve  this requirement you can write simple drop down populator implementing DropDownDataPopulator interface.

/*
*  Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you under the Apache License,
*  Version 2.0 (the "License"); you may not use this file except
*  in compliance with the License.
*  You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.sampl.rxt.populator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.governance.generic.stub.beans.xsd.ContentArtifactsBean;
import org.wso2.carbon.governance.generic.ui.clients.ManageGenericArtifactServiceClient;
import org.wso2.carbon.governance.generic.ui.utils.DropDownDataPopulator;

import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServletRequest;

public class WSDLPopulator implements DropDownDataPopulator {

    private static final Log log = LogFactory.getLog(WSDLPopulator.class);
    String[] out = new String[1];

    @Override
    public String[] getList(HttpServletRequest httpServletRequest, ServletConfig servletConfig) {

        try {
            ManageGenericArtifactServiceClient client =
                    new ManageGenericArtifactServiceClient(servletConfig, httpServletRequest.getSession());

            ContentArtifactsBean artifactsBean = client.listContentArtifacts("application/wsdl+xml");
            if (artifactsBean.getName() != null && artifactsBean.getName().length > 0) {
                return artifactsBean.getName();
            } else {
                out[0] = "None";
            }

        } catch (Exception e) {
            log.error("An error occurred while obtaining the WSDL list", e);
        }
        return out;
    }
}


Now when you go to add a service, you can pick the available WSDL name from the WSDL drop down list.

 

Thursday, January 30, 2014

Secure custom properties file using secure vault.






The WSO2 secure vault is an implementation of synapse secure vault (modified version), it  is used to secure plain text password which is contains in configuration  files of WSO2 products.  Please go through the below link to get more information[1].

[1]http://docs.wso2.org/display/Carbon420/WSO2+Carbon+Secure+Vault

Here I'm going to show you, how can we secure the password in configuration property  file. This is very useful when we write custom extensions for WSO2 products.

Lets assume that our new custom module has flowing properties  file(myconf-test.properties) and need to secure the plain text password using the WSO2 secure vault.

myconf.module.serverUrl=http://localhost:9443/servies
myconf.module.remote=true
myconf.module.username=admin
myconf.module.password=admin

1.) Create file myconf-test.properties inside the [product_home]/repository/conf/ and add the above content.

2) If you haven't done before,  run the following command at least one time inside the
[product_home]/bin to generate the secret-conf.properties file with default values,  at the sametime cipher-text.properties and other WSO2 config files(according to the default settings in cipher-tool.properties)  also will be updated.  If you have already execute this command you can directly start with step 2.
sh ciphertool.sh -Dconfigure
i). Now you have to provide the answers for the following questions ?
[Please Enter Primary KeyStore Password of Carbon Server : ]

Answer: wso2carbon

ii) If you check the secret-conf.properties, you should see that file has updated with following settings.
   Note:~ Content of the file will be changed depending on the product.


keystore.identity.location=/home/ajith/wso2/product/wso2greg-4.6.0/repository/resources/security/wso2carbon.jks
keystore.identity.type=JKS
keystore.identity.store.password=identity.store.password
keystore.identity.store.secretProvider=org.wso2.carbon.securevault.DefaultSecretCallbackHandler
secretRepositories.file.provider=org.wso2.securevault.secret.repository.FileBaseSecretRepositoryProvider
secretRepositories.file.location=repository/conf/security/cipher-text.properties
secretRepositories=file
keystore.identity.key.password=identity.key.password
carbon.secretProvider=org.wso2.securevault.secret.handler.SecretManagerSecretCallbackHandler
keystore.identity.key.secretProvider=org.wso2.carbon.securevault.DefaultSecretCallbackHandler
keystore.identity.alias=wso2carbon


2.) Go to the [product_home]/bin and execute the following command to generate the encrypted value for the clear text  password.


sh ciphertool.sh 

i) It will prompt following  console for input value.  Answer: wso2carbon


[Please Enter Primary KeyStore Password of Carbon Server : ]

ii)Then it will appear second console for  following input value.
     (Answer: According to our property file, the plain text password is "admin".)

[Enter Plain text value :]
[Please Enter value Again :]

iii) Now you should see the following output on the console.

Encryption is done Successfully


Encrypted value is : 
MpfXhKP+iJSImA/KNa+DoOXCPQAyF3JLhlFNAdG6F3naWK+N1/WEWOJkFx4kK34i1VtkywNN9SiC
MRQGTFw+nqzK5/INgcFFdoxv49lM/FJw8CyXKQ0JWdxw5QJPtrjJzvGp6Rj6xt4ysb6HdG5uNG+a
1E0lqdmzGUYQ6oejIlk=

3). Open the cipher-text.properties file, which is under [product_home]/repository/conf/security and add the following entry.

myconf.module.password=MpfXhKP+iJSImA/KNa+DoOXCPQAyF3JLhlFNAdG6F3naWK+N1/WEWOJkFx4kK34i1VtkywNN9SiC
MRQGTFw+nqzK5/INgcFFdoxv49lM/FJw8CyXKQ0JWdxw5QJPtrjJzvGp6Rj6xt4ysb6HdG5uNG+a
1E0lqdmzGUYQ6oejIlk=

4). Open the myconf-test.properties file and update the key/value of password field.

myconf.module.serverUrl=http://localhost:9443/servies
myconf.module.remote=true
myconf.module.username=admin
myconf.module.password=secretAlias:myconf.module.password

5). You can use the following Java class to resolve the the password at your custom extension code.

(  Note: If you open from IDE , please point the [product_home]/repository/components/plugins
             to class path.)

ModuleProperties.java

/*
*  Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you under the Apache License,
*  Version 2.0 (the "License"); you may not use this file except
*  in compliance with the License.
*  You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.sampl.rxt.populator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.governance.generic.stub.beans.xsd.ContentArtifactsBean;
import org.wso2.carbon.governance.generic.ui.clients.ManageGenericArtifactServiceClient;
import org.wso2.carbon.governance.generic.ui.utils.DropDownDataPopulator;

import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServletRequest;

public class WSDLPopulator implements DropDownDataPopulator {

    private static final Log log = LogFactory.getLog(WSDLPopulator.class);
    String[] out = new String[1];

    @Override
    public String[] getList(HttpServletRequest httpServletRequest, ServletConfig servletConfig) {

        try {
            ManageGenericArtifactServiceClient client =
                    new ManageGenericArtifactServiceClient(servletConfig, httpServletRequest.getSession());

            ContentArtifactsBean artifactsBean = client.listContentArtifacts("application/wsdl+xml");
            if (artifactsBean.getName() != null && artifactsBean.getName().length > 0) {
                return artifactsBean.getName();
            } else {
                out[0] = "None";
            }

        } catch (Exception e) {
            log.error("An error occurred while obtaining the WSDL list", e);
        }
        return out;
    }
}

6). You can checkout the complete sample from the following SVN location[1].

 [i].Open the build.xml and change the value of the "product.home" property to your  product home directory.

Execute the ant command inside the project home (SecureVaultSample) to build the jar file.

[i]https://svn.wso2.org/repos/wso2/people/ajith/blog/SecureVaultSample/

7). Put the jar file which is under target to [product_home]/repository/components/lib.

8). Start the server . (sh wso2server.sh)

9).  When starting the server, it will prompt the following command input to enter the key store password. The answer is "wso2carbon". Then  server will start successfully.


[Enter KeyStore and Private Key Password :]

10). If you planing to  start the server as  background process , then you need to do the following steps before start the server.

i. Create a file named "password-tmp.txt" in <PRODUCT_HOME>/ directory. Add "wso2carbon" (the primary keystore password) to this file and save. By default, the password provider assumes that both private key and keystore passwords are the same. If not, the private key password must be entered in the second line of the file.

ii. Keystore password will be picked up from the "password-tmp.txt" file. Once the server starts, this file is automatically deleted from the file system. Make sure to add this temporary file back whenever you start the sever as a background process. If you name of the password file "password-persist.txt" instead of "password-tmp.txt", then the file will not be deleted after the server starts. Therefore, it will not be required to provide the password in subsequent startups.

11. Finally, if you initialize the ModuleProperties class in your custom extension code (new ModuleProperties() ) you should be able to get the resolved password from that Object.

The summary of the process showing in following diagram.



Wednesday, January 29, 2014

Secure custom configuration file(XML) using WSO2 secure vault.


The WSO2 secure vault is an implementation of synapse secure vault (modified version), it  is used to secure plain text password which is contains in configuration  files of WSO2 products.  Please go through the below link to get more information[1].

[1]http://docs.wso2.org/display/Carbon420/WSO2+Carbon+Secure+Vault

Here I'm going to show you, how can we secure the plain text password which contains in our own configuration file(XML type). This is very useful when we write custom extensions for WSO2 products.

Lets assume that our new custom module has flowing configuration file(myconf-test.xml) and need to secured the plain text password using the WSO2 secure vault.

<myconf>
   <module serverURL="local://services/" remote="false">
       <username>admin</username>
       <password>admin</password>
   </module>
 </myconf>

1). Open the cipher-tool.properties file which is under <product_home>/repository/conf/security and add the following entry.

myconf.module.password=myconf-test.xml//myconf/module/password,true

2). Open the cipher-text.properties which is under <product_home>/repository/conf/security
and add the following entry.

myconf.module.password=[admin]

3). Go to the <product_home>/bin and execute the following command.

sh ciphertool.sh  -Dconfigure

4).  Now you have to provide the answers for the following questions ?

[Please Enter Primary KeyStore Password of Carbon Server : ]

 Answer is : wso2carbon

5). After enter the keystore  password , you should see the success message in the console output.

Protected Token [myconf.module.password] is updated in myconf-test.xml successfully

6). If you look at the myconf-test.xml again, you should see the password element has been modified as bellow.

<password svns:secretAlias="myconf.module.password">password</password>

7). If you look at the cipher-text.properties file again, you should see the following like entry has been update.

myconf.module.password=Tihb7iTeIrcfWXI6i0m+tMw7OUZKFbSSfl+ngNVS8usB0Q2igFZfBAEFvlq4vPJhZc+b59kuVFBl\nwmfVEWHUDmw3+Nz1JJJl1yds8RA5MV+YrMTuQpl0az2/suW7qJnLvO/fMDTPICQBF8TMxdr3KG5G\nsBym+1MW4B3zuwEtR5g\=

7). Following java class  used to read the configuration file from the distribution and resolved the
     secured password.

    (  Note: If you open from IDE , please point the <product_home>/repository/components/plugins
       to class path.)

ModuleConfig.java


/*
 * Copyright (c) 2006, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.sample.securevault;


import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.securevault.SecretResolver;
import org.wso2.securevault.SecretResolverFactory;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;


// Following sample contains the password element, that is one going to be secure using WSO2 secure vault.

/**
 * 
 * 
 * admin
 * admin
 * 
 * 
 */
public class ModuleConf {

    private static final Log log = LogFactory.getLog(ModuleConf.class);

    private String username;
    private String password;
    private String serverURL;
    private String remote;

    public ModuleConf() {
        FileInputStream fileInputStream = null;
        //Assumed that configuration file is under the /repository/conf
        String configPath = CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + "conf" +
                File.separator + "myconf-test.xml";

        File registryXML = new File(configPath);
        if (registryXML.exists()) {
            try {
                fileInputStream = new FileInputStream(registryXML);

                StAXOMBuilder builder = new StAXOMBuilder(fileInputStream);
                OMElement configElement = builder.getDocumentElement();
                //Initialize the SecretResolver providing the configuration element.
                SecretResolver secretResolver = SecretResolverFactory.create(configElement, false);
                OMElement module = configElement.getFirstChildWithName(new QName("module"));

                if (module != null) {
                    username = module.getFirstChildWithName(new QName("username")).getText();

                    //same entry used in cipher-text.properties and cipher-tool.properties.
                    String secretAlias = "myconf.module.password";

                    //Resolved the secret password.
                    if (secretResolver != null && secretResolver.isInitialized()) {
                        if (secretResolver.isTokenProtected(secretAlias)) {
                            password = secretResolver.resolve(secretAlias);
                        } else {
                            password = module.getFirstChildWithName(new QName("password")).getText();
                        }
                    }
                    serverURL = module.getAttributeValue(new QName("serverURL"));
                    remote = module.getAttributeValue(new QName("remote"));
                }
            } catch (XMLStreamException e) {
                log.error("Unable to parse myconf-test.xml", e);
            } catch (IOException e) {
                log.error("Unable to read myconf-test.xml", e);
            } finally {
                if (fileInputStream != null) {
                    try {
                        fileInputStream.close();
                    } catch (IOException e) {
                        log.error("Failed to close the FileInputStream, file : " + configPath);
                    }
                }
            }
        }
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public String getServerURL() {
        return serverURL;
    }

    public boolean isRemote() {
        return Boolean.valueOf(remote);
    }
}


8). You can checkout complete sample project(SecureVaultSample) from the following SVN location.

 [i]. After that open the build.xml and change the value of the "product.home" property to your  product home directory.

Execute the ant command inside the project home to build the jar file.

[i]https://svn.wso2.org/repos/wso2/people/ajith/blog/SecureVaultSample/

9). Put the jar file which is under target to <product_home>/repository/components/lib.

10). Start the server . (sh wso2server.sh)

11).  When starting the server, it will prompt the following command input to enter the key store password. The answer is "wso2carbon". Then  server will start successfully.


[Enter KeyStore and Private Key Password :]

12). If you planing to  start the server as  background process , then you need to do the following steps before start the server.

i. Create a file named "password-tmp.txt" in <PRODUCT_HOME>/ directory. Add "wso2carbon" (the primary keystore password) to this file and save. By default, the password provider assumes that both private key and keystore passwords are the same. If not, the private key password must be entered in the second line of the file.

ii. Keystore password will be picked up from the "password-tmp.txt" file. Once the server starts, this file is automatically deleted from the file system. Make sure to add this temporary file back whenever you start the sever as a background process. If you name of the password file "password-persist.txt" instead of "password-tmp.txt", then the file will not be deleted after the server starts. Therefore, it will not be required to provide the password in subsequent startups.

13. Finally, if you initialize the ModuleConf class in your custom extension code (new ModuleConf() ) you should be able to get the resolved password from that Object.

Note:

The SecretCallbackHandler is defined in the secret-conf.properties file inside the <product_home>/repository/conf/security.

 The default implementation is set to org.wso2.carbon.securevault.DefaultSecretCallbackHandler.
 You can find the source in the SVN location[2]

[2]https://svn.wso2.org/repos/wso2/carbon/kernel/branches/4.2.0/core/org.wso2.carbon.securevault/4.2.0/src/main/java/org/wso2/carbon/securevault/DefaultSecretCallbackHandler.java

If you want , you can write your own implementation as well, for that you should write your own implementation extending the AbstractSecretCallbackHandler.

Eg: MyConfSecretCallbackHandler.java 


* Copyright (c) 2006, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.sample.securevault;

import org.wso2.securevault.secret.AbstractSecretCallbackHandler;
import org.wso2.securevault.secret.SingleSecretCallback;


public class MyConfSecretCallbackHandler extends AbstractSecretCallbackHandler {
    @Override
    protected void handleSingleSecretCallback(SingleSecretCallback singleSecretCallback) {
        singleSecretCallback.setSecret("wso2carbon");
    }
}

Build the jar which includes  your own SecretCallbackHandler and add the fully qualified class name in secret-conf.properties instead of org.wso2.carbon.securevault.DefaultSecretCallbackHandler.


The summary of the process showing in following diagram.