WP5: Guide to installing Apache AXIS
This guide describes how to install Apache AXIS server
with GSI-secured access and how to write clients for it.
Please note, that older versions of Globus Toolkit 3 named Technology Preview
used the Globus 2 model of securing communication on transport level (the same level as SSL).
Newer versions of GT3, namely the Alpha releases, are moving
in the direction of message level security, it means that
communication is done over plain HTTP connection, but
SOAP messages are themselves encrypted and digitaly signed
using XML Encryption and XML Signature standards.
This document describes only transport level security.
Contents:
Apache AXIS is a pure Java implementation for clients and servers of
WebServices. Support for GSI tranport-level security was added in
Globus Toolkit 3, it uses Java CoG and
java SSL implementation for creating GSI sockets. AXIS server needs
Tomcat servlet
container to run. All of them need Java to run.
So download
Install JDK, it means run the installation script, set JAVA_HOME environment variable to the directory where JDK was extracted, and add "$JAVA_HOME/bin/java" to your PATH.
Put downloaded files into some directory and issue following commands:
mkdir gsiws
cd gsiws
tar xzvf ../jakarta-tomcat-4.1.27.tar.gz
mv jakarta-tomcat-4.1.27 tomcat-4.1.27
tar xzvf ../gt3.0.2-core-bin.tar.gz ogsa-3.0.2/lib ogsa-3.0.2/tomcat ogsa-3.0.2/webapps
mkdir -p tomcat-4.1.27/webapps/axis/WEB-INF/lib
mkdir tomcat-4.1.27/webapps/axis/WEB-INF/classes
cp ogsa-3.0.2/tomcat/common/lib/* tomcat-4.1.27/common/lib/
cp ogsa-3.0.2/tomcat/server/lib/cog-tomcat.jar tomcat-4.1.27/server/lib/
cp ogsa-3.0.2/lib/ogsa.jar tomcat-4.1.27/webapps/axis/WEB-INF/lib/
cp ogsa-3.0.2/lib/cog-axis.jar tomcat-4.1.27/webapps/axis/WEB-INF/lib/
cp ogsa-3.0.2/lib/axis.jar tomcat-4.1.27/webapps/axis/WEB-INF/lib/
cp ogsa-3.0.2/lib/wsdl4j.jar tomcat-4.1.27/webapps/axis/WEB-INF/lib/
cp ogsa-3.0.2/lib/xmlsec.jar tomcat-4.1.27/webapps/axis/WEB-INF/lib/
cp ogsa-3.0.2/webapps/ogsa/WEB-INF/web.xml tomcat-4.1.27/webapps/axis/WEB-INF/
Now make changes described in Security Support in GT3-Alpha3 documentation:
Edit file tomcat-4.1.27/conf/server.xml and
make this change (you can use patch to do it):
99a100,121
> <!-- Define a GSI HTTP/1.1 Connector on port 8443
> Supported parameters include:
> proxy // proxy file for server to use
> or
> cert // server certificate file in PEM format
> key // server key file in PEM format
>
> cacertdir // directory location containing trusted CA certs
> gridMap // grid map file used for authorization of users
> debug // "0" is off and "1" and greater for more info
> -->
> <Connector className="org.apache.catalina.connector.http.HttpConnector"
> port="8443" minProcessors="5" maxProcessors="75"
> enableLookups="true" authenticate="true"
> acceptCount="10" debug="1" scheme="httpg" secure="true">
> <Factory className="org.globus.tomcat.catalina.net.GSIServerSocketFactory"
> proxy="/etc/grid-security/hostproxy.pem"
> cacertdir="/etc/grid-security/certificates"
> gridMap="/etc/grid-security/grid-mapfile"
> debug="3"/>
> </Connector>
>
164a187,188
>
> <Valve className="org.globus.tomcat.catalina.valves.CertificatesValve" debug="1" />
Change the line proxy="/etc/grid-security/hostproxy.pem"
to a real location of your machine's proxy. By default there is none, but
you can create it by joining files hostcert.pem and
hostkey.pem in /etc/grid-security/ directory.
The hostproxy.pem
file should be owned by the user under which Tomcat will run
and access rights should be set to 400.
You will need root privileges on that system (or ask your administrator),
and you can do it using following commands:
su - root
cd /etc/grid-security/
cat hostcert.pem hostkey.pem >hostproxy.pem
chown tomcatuser hostproxy.pem
chmod 400 hostproxy.pem
exit
Then change file tomcat-4.1.27/bin/catalina.sh by adding classes to CLASSPATH. Without this step the Java system classloader will not find classes
needed to handle httpg protocol:
CLASSPATH="$CLASSPATH":"$CATALINA_HOME"/bin/bootstrap.jar
CLASSPATH="$CLASSPATH":"$CATALINA_HOME/common/lib/cog-jglobus.jar":"$CATALINA_HOME/common/lib/log4j-core.jar"
CLASSPATH="$CLASSPATH":"$CATALINA_HOME/common/endorsed/xercesImpl.jar":"$CATALINA_HOME/common/endorsed/xmlParserAPIs.jar"
CLASSPATH="$CLASSPATH":"$CATALINA_HOME/common/lib/puretls.jar":"$CATALINA_HOME/common/lib/jce-jdk13-117.jar"
CLASSPATH="$CLASSPATH":"$CATALINA_HOME/common/lib/cryptix32.jar":"$CATALINA_HOME/common/lib/cryptix-asn1.jar"
CLASSPATH="$CLASSPATH":"$CATALINA_HOME/common/lib/cryptix.jar"
A standard Axis server has a default WebService called "Version"
with method "String getVersion()" which we can use to test
the installation. But because we used Axis packed in GT3, this webservice
is not deployed by default, so we must make it available first (this
was not necessary in Alpha versions of GT3).
Let's set up necessary classes first:
for i in $PWD/ogsa-3.0.2/lib/*.jar . ; do CLASSPATH=$CLASSPATH:$i ; done
export CLASSPATH
Now create a deployment file deploy.wsdd with following content:
<deployment
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="Version" provider="java:RPC">
<parameter name="allowedMethods" value="getVersion"/>
<parameter name="className" value="org.apache.axis.Version"/>
</service>
</deployment>
and deploy the service by doing:
cd tomcat-4.1.27/webapps/axis/WEB-INF/
java org.apache.axis.utils.Admin server ../../../../deploy.wsdd
cd -
That should create a file server-config.wsdd which
specifies available services.
Now you can run the Tomcat server:
cd tomcat-4.1.27/bin
./startup.sh
cd ../..
mozilla http://localhost:8080/axis/servlet/AxisServlet &
The last command will display deployed services. You can
try to call the Version.getVersion() operation
by visiting http://localhost:8080/axis/services/Version?method=getVersion, it will return XML
representing SOAP response of the operation.
The running AXIS server is listening on two ports - on port 8080 without GSI and on port 8443 with GSI.
The WSDL description for this service is accesible on port 8080 on URL with ?wsdl appended.
We will use WSDL2Java tool to generate client classes. Run
java -Djava.protocol.handler.pkgs=org.globus.net.protocol \
org.apache.axis.wsdl.WSDL2Java -v \
--NStoPkg http://localhost:8080/axis/services/Version=versionclient \
http://localhost:8080/axis/services/Version?wsdl
It will use WSDL description of the Version service
to generate connection classes in subdirectory versionclient.
Create a client file CallVersion.java:
import versionclient.*;
import java.net.URL;
import java.rmi.Remote;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.SimpleTargetedChain;
import org.apache.axis.client.Service;
import org.apache.axis.client.Stub;
import org.apache.axis.configuration.SimpleProvider;
import org.globus.axis.transport.GSIHTTPSender;
import org.globus.axis.transport.GSIHTTPTransport;
import org.globus.axis.util.Util;
import org.ietf.jgss.GSSCredential;
import org.globus.gsi.gssapi.auth.Authorization;
/**
* Calls a Version webservice.
*/
public class CallVersion
{
static SimpleProvider p;
/**
* Prepares httpg handler.
*/
static {
p = new SimpleProvider();
p.deployTransport("httpg", new SimpleTargetedChain(new GSIHTTPSender()));
Util.registerTransport();
}
public static void main(String [] args) throws Exception {
String url="httpg://your.machine.org:8443/axis/services/Version";
VersionServiceLocator s = new VersionServiceLocator();
s.setEngineConfiguration(p);
Version v = s.getVersion(new URL(url));
//preparePort(v,...);
System.out.print("Version: "+v.getVersion());
}
/**
* Sets properties of Call when default are not enough.
*/
static void preparePort(Remote ws,GSSCredential proxy,Authorization auth) {
Stub stub = (Stub) ws;
stub._setProperty(GSIHTTPTransport.GSI_CREDENTIALS, proxy);
stub._setProperty(GSIHTTPTransport.GSI_AUTHORIZATION, auth);
stub._setProperty(GSIHTTPTransport.GSI_MODE, GSIHTTPTransport.GSI_MODE_NO_DELEG);
}
}
Provide a real machine name in URL, as this is checked against the server's certificate. Beware,
the name of the machine must map to IP address, which maps back to the same name !
Also, the name must be the same as used in the host certificate, so if your host
certificate (contained in hostproxy.pem referenced from
tomcat-4.1.27/conf/server.xml) has DN for example
O=Grid,O=MyOrg,CN=host/your.machine.org,
you must use the name your.machine.org in the URL, otherwise
server authentication will fail.
Don't forget to have a valid user proxy certificate, which has its DN
listed in /etc/grid-security/grid-mapfile on the server machine,
otherwise user authentication will fail.
Now compile and run:
$javac CallVersion.java
$java CallVersion
Version: Apache Axis version: 1.1
Built on Jun 18, 2003 (03:41:59 CDT)
The CallVersion client registers httpg as a valid protocol,
locates the service, sets connection properties and calls Version with GSI on port 8443.
It can happen that the client fails with exception
No client transport named 'httpg' found!
at org.apache.axis.client.AxisClient.invoke(AxisClient.java:183)
at org.apache.axis.client.Call.invokeEngine(Call.java:2564)
at org.apache.axis.client.Call.invoke(Call.java:2553)
at org.apache.axis.client.Call.invoke(Call.java:2248)
at org.apache.axis.client.Call.invoke(Call.java:2171)
at org.apache.axis.client.Call.invoke(Call.java:1691)
at versionclient.VersionSoapBindingStub.getVersion(VersionSoapBindingStub.java:96)
at CallVersion.main(CallVersion.java:31)
It was found that it is caused by having file wsif.jar in CLASSPATH
on the beginning, before other GT3 jars. You can remove the file from your CLASSPATH
or change order of the files in that case.
Writing clients for other WebServices is similar, run the WSDL2Java
tool for generating client classes, then write a main class which registers httpg transport
and specifies connection properties.
Creating and deploying new services into GSI-enabled AXIS is
the same as into non-GSI AXIS, so follow the
AXIS User Guide.
The only difference is that when using GSI for user credentials delegation, you can get the delegated proxy using:
MessageContext ctx = MessageContext.getCurrentContext();
GSSCredential cred =
(GSSCredential)ctx.getProperty(GSIConstants.GSI_CREDENTIALS);
inside methods of the deployed WebService.
A quick guide how to write a WebService
Create an interface for the WebService as Java interface:
package mypackage;
public interface MyService {
public String getSomething(String s,int i,float f, double d);
}
and compile it into mypackage/MyService.class.
To specify parameter names, create its implementation class:
package mypackage;
public class MyServiceImpl implements MyService {
public String getSomething(String s,int i,float f, double d) {
return s+i+f+d;
}
}
and compile it with debuging enabled: javac -g mypackage/MyServiceImpl.java
Then generate a WSDL file for that interface by:
java org.apache.axis.wsdl.Java2WSDL \
--output MyService.wsdl \
--location "httpg://acrab.ics.muni.cz:8443/axis/services/MyService" \
--namespace "urn:SomeMyURI" \
--PkgtoNS "mypackage"="urn:SomeMyURI" \
--implClass mypackage.MyServiceImpl \
mypackage.MyService
where "urn:SomeMyURI" is a unique namespace identifying this WebService and location
value is the default service location.
Then generate Java classes from that WSDL file by:
java -Djava.protocol.handler.pkgs=org.globus.net.protocol \
org.apache.axis.wsdl.WSDL2Java -v \
--server-side \
--deployScope Application \
--NStoPkg urn:SomeMyURI=mypackage \
--output classes \
MyService.wsdl
it will create several files in the classes/mypackage directory.
Implement some actual behavior inside mypackage/MyServiceSoapBindingImpl.java.
package mypackage;
import org.apache.axis.MessageContext;
import org.ietf.jgss.GSSCredential;
import org.globus.axis.gsi.GSIConstants;
import java.rmi.RemoteException;
public class MyServiceSoapBindingImpl implements MyService{
public String getSomething(String s, int i, float f, double d) throws RemoteException {
MessageContext ctx = MessageContext.getCurrentContext();
GSSCredential cred =
(GSSCredential)ctx.getProperty(GSIConstants.GSI_CREDENTIALS);
String userDN = (String)ctx.getProperty(GSIConstants.GSI_USER_DN);
String userID = (String)ctx.getProperty(GSIConstants.GSI_AUTH_USERNAME);
return "[s="+s+",i="+i+",f="+f+",d="+d+"]\n"+
"GSI_CREDENTIALS="+cred+"\n"+
"GSI_USER_DN="+userDN+"\n"+
"GSI_AUTH_USERNAME="+userID+"\n";
}
}
Compile and deploy:
cd classes
javac mypackage/*.java
cp -r mypackage ../tomcat-4.1.27/webapps/axis/WEB-INF/classes/
cd ../tomcat-4.1.27/webapps/axis/WEB-INF/
java org.apache.axis.utils.Admin server ../../../../classes/mypackage/deploy.wsdd
If you want to be able to extract delegated credentials, change
tomcat-4.1.27/webapps/axis/WEB-INF/server-config.wsdd
Add CredentialHandler handler in <requestFlow> section of <globalConfiguration> block:
<requestFlow>
<handler type="java:org.globus.axis.handler.CredentialHandler"/>
...
<requestFlow/>
Restart the TomCat server.
That's it. You can see the deployed service on URL
http://localhost:8080/axis/servlet/AxisServlet and call it
using the same code as for Version, just change it to:
MyServiceServiceLocator s = new MyServiceServiceLocator();
s.setEngineConfiguration(p);
MyService m = s.getMyService();
System.out.print("MyService: "+m.getSomething("A",1,2.0f,3.0d));
Have fun with WebServices ;-)
Sent any comments to Martin Kuba.
Last updated: $Date: 2003/11/11 09:35:53 $
|