Showing posts with label Tomcat. Show all posts
Showing posts with label Tomcat. Show all posts

Securing Tomcat

This post explains how you can enable SSL on Tomcat.

Let's first create a self-signed certificate.

[CATALINA_HOME]>keytool -genkey -alias webapp -keyalg RSA -keystore keystore.jks
The above will create a keystore with the name keystore.jks in side [CATALINA_HOME].

Also, notice that here we used webapp as the CN - so, we need to edit the file C:\WINDOWS\system32\drivers\etc\hosts and add the following entry - so we can make our certificate trusted by the browser.

127.0.0.1 webapp

Now, lets edit - [CATALINA_HOME]\conf\server.xml to make Tomcat SSL enabled.

<Service name="Catalina">

<!-- Add the following -->
<!-- 'tomcat' is the password you gave while creating keystore.jks -->
<!-- Make sure keystore.jks is inside [CATALINA_HOME] -->
<Connector port="8443"
maxHttpHeaderSize="8192"
maxThreads="150"
minSpareThreads="25"
maxSpareThreads="75"
enableLookups="false"
disableUploadTimeout="true"
acceptCount="100"
scheme="https"
secure="true"
clientAuth="false"
sslProtocol="TLS"
keystoreFile="keystore.jks"
keystorePass="tomcat"/>
</Service>
All set, hit the url, https://webapp:8443 - now broswer will give you a warning saying that your certificate is not trusted.

Install the cert in the browser to get rid of the warning.

Secure your services with Active Directory user credentials

This post explains how you could secure your web srevices with Microsoft Active Directory[AD] user credentials.

In other words, your services could only be accessed by a set of users who belongs to a certain group in AD.

Let's start configuring AD first.

I have setup my AD on Windows 2003 Server [IP:192.168.1.3] and it looks like as shown in the image below.

In our case we'll be deploying our services with Axis2 running on Tomcat.

You can download Axis2 WAR distribution from here and deploy it on Tomcat.

In order to authenticate users against AD, Tomcat should have access to the AD user base.

Let's first create an AD user, which can be used by Tomcat to access AD.

This user can be of any name, we'll just say 'tomcat'.

Now we need to delegate the task, 'Read all user information' - to the user 'tomcat'.

[Users --> Right Click --> Delegate Control]

Done, with it. Lets create a new group called 'facilelogin' - where the members of this group will be given access to the secured web services.

Once created, add any user to that group - I'll add the 'administrator' - so, this user will be able to access secured services.

All set - we are done with the AD configurations - let's setup Tomcat.

Find the file [CATALINA_HOME]\conf\server.xml and edit to add the following.
<!-- You need to add new configurations inside this tag -->
<Engine name="Catalina" defaultHost="localhost">

<!-- Make sure you comment out this line from your current configuration -->
<!-- Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/ -->

<!-- Add following new configuration -->
<!-- Compare the values with the Active Directory image shown above -->  
<!-- I am running my AD on 192.168.1.3 -->    
<Realm className="org.apache.catalina.realm.JNDIRealm"
connectionName="cn=tomcat,cn=users,dc=home,dc=com"
connectionPassword="1qaz2wsx@"
connectionURL="ldap://192.168.1.3:389"
userRoleName="member"
userBase="cn=Users,dc=home,dc=com"
userPattern="cn={0},cn=Users,dc=home,dc=com"
roleBase="cn=Users,dc=home,dc=com"
roleName="cn"
roleSearch="(member={0})"
roleSubtress="false"
userSubtree="true"
/>

</Engine>
Once this is done - let's open the file [CATALINA_HOME]\webapps\axis2\WEB-INF\web.xml and edit to add the following.
<web-app> 

<security-constraint> 
<web-resource-collection>
<web-resource-name>secured services 
<url-pattern>/services/* 
</web-resource-collection>
<auth-constraint> 
<!-- This is mapped to the 'facilelogin' group in AD -->
<role-name>facilelogin 
</auth-constraint> 
</security-constraint> 

<login-config> 
<auth-method>BASIC 
<realm-name>facilelogin 
</login-config> 

</web-app>
All set - let's restart Tomcat.

Let's see how we could invoke the above secured service with a web service client.

Here, the only difference is you need to setup the HTTP header attributes appropriately.

Also, in this case user credentials are not carried by the SOAP header, but the transport header.
package org.apache.ws.axis2;

import java.util.Properties;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.transport.http.HttpTransportProperties;

public class Client {

public static void main(String[] args) throws Exception {
ServiceClient client = null;
Options options = null;
OMElement response = null;
HttpTransportProperties.Authenticator authenticator = null;
Properties properties = null;

client = new ServiceClient();
options = new Options();
options.setAction("urn:getVersion");
options.setTo(new EndpointReference("http://localhost:8080/axis2/services/Version"));

authenticator = new HttpTransportProperties.Authenticator();
// Add user creadentials to the transport header
// This user belongs to the 'facilelogin' group in AD
authenticator.setUsername("administrator");
authenticator.setPassword("prabath");
authenticator.setRealm("facilelogin");

properties = new Properties();
properties.put(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, authenticator);

options.setProperties(properties); 
client.setOptions(options);

response = client.sendReceive(getPayload());

System.out.println(response);
}

private static OMElement getPayload() {
OMFactory factory = null;
OMNamespace ns = null;
OMElement elem = null;
factory = OMAbstractFactory.getOMFactory();
ns = factory.createOMNamespace("http://axisversion.sample", "ns1");
elem = factory.createOMElement("getVersion", ns); 
return elem;
}
}

Secure your services with HTTP Basic Authentication

This post explains how you could secure your web service with HTTP Basic Authentication.

Let's download Axis2 WAR distribution from here and deploy it on Tomcat.

Start Tomcat, and hit the url, http://localhost:8080/axis2/services/Version?wsdl, you'll find no issues in accessing it.

Let's try to protect Axis2 services with HTTP Basic Authentication.

We need to define a new role first, who will be given access.

Find the file [CATALINA_HOME]\conf\tomcat-users.xml and edit it to add the following role and the user.

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="facilelogin"/>
<user username="prabath" password="prabath" roles="facilelogin"/>
</tomcat-users>
Now let's restricts access to all our web services to the above defined role.

Open the file [CATALINA_HOME]\webapps\axis2\WEB-INF\web.xml and edit to add the following.

<web-app>

<security-constraint>
<web-resource-collection>
<web-resource-name>secured services</web-resource-name>
<url-pattern>/services/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>facilelogin</role-name>
</auth-constraint>
</security-constraint>

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>facilelogin</realm-name>
</login-config>

</web-app>
All set - let's restart Tomcat.

Hit the url, http://localhost:8080/axis2/services/Version?wsdl and you'll be asked for the user credentials.

Let's see how we could invoke the above secured service with a web service client.

Here, the only difference is you need to setup the HTTP header attributes appropriately.

Also, in this case user credentials are not carried by the SOAP header, but the transport header.

package org.apache.ws.axis2;

import java.util.Properties;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.transport.http.HttpTransportProperties;

public class Client {

public static void main(String[] args) throws Exception {
ServiceClient client = null;
Options options = null;
OMElement response = null;
HttpTransportProperties.Authenticator authenticator = null;
Properties properties = null;

client = new ServiceClient();
options = new Options();
options.setAction("urn:getVersion");
options.setTo(new EndpointReference("http://localhost:8080/axis2/services/Version"));

authenticator = new HttpTransportProperties.Authenticator();
// Add user creadentials to the transport header
authenticator.setUsername("prabath");
authenticator.setPassword("prabath");
authenticator.setRealm("facilelogin");

properties = new Properties();
properties.put(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, authenticator);

options.setProperties(properties);
client.setOptions(options);

response = client.sendReceive(getPayload());

System.out.println(response);
}

private static OMElement getPayload() {
OMFactory factory = null;
OMNamespace ns = null;
OMElement elem = null;
factory = OMAbstractFactory.getOMFactory();
ns = factory.createOMNamespace("http://axisversion.sample", "ns1");
elem = factory.createOMElement("getVersion", ns);
return elem;
}
}


POST /axis2/services/Version HTTP/1.1
Content-Type: text/xml; charset=UTF-8
SOAPAction: "urn:getVersion"
User-Agent: Axis2
Transfer-Encoding: chunked
Authorization: Basic cHJhYmF0aDpwcmFiYXRo
Host: localhost:8080