# Axis2 / Rampart - XML-Datei verschlüsseln & versenden



## Sleepwalker (11. Okt 2010)

Hallo,

ich versuche gerade mich fürs Studium in Axis2 und Rampart einzuarbeiten, habe aber totale Startschwierigkeiten.
Vorweg eine vllt. blöde Frage: Brauche ich zwingend J2EE? Ich benutze sonst nur J2SE (1.5_16 ist in diesem Fall die Vorgabe).

Meine Aufgabe besteht darin, eine bereits fertige XML-Datei anhand eines gegebenen KeyStores mit einem p12 und p7b Zertifikat zu verschlüsseln, verschicken und dann auf eine Antwort zu warten (und diese dann wieder zu entschlüsseln).

Die tagelange Suche in Google hat mir nicht viel geholfen, außer dass ich diese kleinen Tutorial-WebServices zum Laufen bekomme, was ja auch nicht so dramatisch ist. Das hilft mir nur leider nicht wirklich.

War es korrekt, dass ich Rampart runterladen musste und die Module in Axis2 einfügen? Ich dachte, Rampart ist Teil von Axis2. Bekam nämlich sonst Fehler?!

Jedenfalls sind das hier meine rudimentären Anfänge laut einer Anleitung, die ich danach nicht mehr nachvollziehen kann:

```
public static void main(String[] args) {
        // Endpoint address
        String sTargetURL = "https://foo.com/Endpoint";
        // KeyStore
        System.setProperty("javax.net..ssl.trustStore", "C:\\foo.jks");
        System.setProperty("javax.net..ssl.trustStorePassword", "123");
        // Get secure context
        try {
            ConfigurationContext cfgct = ConfigurationContextFactory.createConfigurationContextFromFileSystem("C:\\axis2-1.5.1\\repository\\", "C:\\axis2-1.5.1\\conf\\axis2.xml");
            
        } catch (AxisFault ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
```

*Mein Problem*: Wie "nehme" ich jetzt eine fertige XML-Datei, verschlüssel und versende sie? Ich bin völlig aufgeschmissen, weil ich nirgends etwas dazu finde.



Folgende Eintragungen sollten in den Konfigurationsdateien gemacht werden, falls das von Interesse ist.
axis2.xml

```
<module ref="rampart" />
	<parameter name="OutflowSecurity">
      <action>
        <items>Timestamp Signature Encrypt</items>
        <user>server</user>
        <passwordCallbackClass>test.PWCBHandler</passwordCallbackClass>
		<signaturePropFile>client.properties</signaturePropFile>
        <signatureKeyIdentifier>DirectReference</signatureKeyIdentifier>
        <encryptionKeyIdentifier>SKIKeyIdentifier</encryptionKeyIdentifier>
        <encryptionUser>ency</encryptionUser>
      </action>
    </parameter>

    <parameter name="InflowSecurity">
      <action>
        <items>Signature Timestamp Encrypt</items>
		<enableSignatureConfirmation>false</enableSignatureConfirmation>
        <passwordCallbackClass>test.PWCBHandler</passwordCallbackClass>
		<decryptionUser>server</decryptionUser>
	    <decryptionPropFile>client.properties</decryptionPropFile>
		<signaturePropFile>client.properties</signaturePropFile>
      </action>
    </parameter>
```

client.properties:

```
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=123
org.apache.ws.security.crypto.merlin.file=C:\\foo.jks
```


Vielen Dank (schon für's Lesen des ganzen Zeugs).

Grüße,

Tobias


----------



## ramon98 (15. Okt 2010)

Ein paar Teilfragen kann ich beantworten, aber den "interessanten" Teil leider nicht.



Sleepwalker hat gesagt.:


> Vorweg eine vllt. blöde Frage: Brauche ich zwingend J2EE? Ich benutze sonst nur J2SE (1.5_16 ist in diesem Fall die Vorgabe).



Du benötigt einen Webserver oder genauer einen Servlet-Container, damit man das Axis2-WAR deployen kannst.  Mit einem Tomcat alleine würde es auch gehen.




Sleepwalker hat gesagt.:


> War es korrekt, dass ich Rampart runterladen musste und die Module in Axis2 einfügen? Ich dachte, Rampart ist Teil von Axis2. Bekam nämlich sonst Fehler?!



Rampart ist ein optionales Addon zu Axis2. Daher wares korrekt, dass du es separat runtergeladen hast.

Hast du mal auf wso2.org nachgeschaut? Wenn man dort kein Tutorial für ein Axis2-Problem findet, dann nirgendwo ;-)

    Rainer


----------



## Keo (15. Okt 2010)

> Meine Aufgabe besteht darin, eine bereits fertige XML-Datei anhand eines gegebenen KeyStores mit einem p12 und p7b Zertifikat zu verschlüsseln, verschicken und dann auf eine Antwort zu warten (und diese dann wieder zu entschlüsseln).


Wenn du die Datei ver- und entschlüsseln musst, gehe ich davon aus, dass du Client und Server realisieren sollst.
1. Als Erstes solltest du die generelle Kommunikation via Webservice mit Axis2 verstehen. Hierfür gibt es genügend Tutorials wie hier: Eclipse WTP Tutorials - Creating Bottom Up Web Service via Apache Axis2

2. Danach solltest du dich damit beschäftigen, wie du eine Datei an ein Webservice übertragen kannst. Wie wäre es, wenn du deine XML-Datei als SOAP-Attachement überträgst. Infos hier: Using SOAP with Attachments in Apache Axis2 | WSO2 Oxygen Tank

3. Wenn du dann so weit bist, kannst du dich mit der Security beschäftigen. Hierzu gibt es viele Möglichkeiten: Du kannst beispielsweise die Verbindung über TLS/SSL verschlüsseln oder den gesamten SOAP-Nachrichteninhalt mit Rampart absichern. Letzteres ist sicherlich aufwendiger und wird daher auch oft nicht angewendet, zumal es auch keine größere Sicherheit bietet. Die TLS-Verschlüsselung ist sehr einfach. Allgemeine Infos zu Security hier: Sicherheit für SOAP mit Tomcat und Axis


----------



## Sleepwalker (18. Okt 2010)

Morgen,

vielen Dank für eure Antworten.

@ramon98: Meine Aufgabe ist es, nur einen Client zu erstellen, der jedoch noch eine Antwort innerhalb von einigen Sekunden zurück bekommt. Daher benötige ich keinen Server, soweit ich die Doku verstehe?! Ich soll zumindest nichts bereitstellen.

@keo:
Zu deinem ersten Punkt, ich habe zum Verständnis WebService in Java nachvollzogen. Vllt. sollte ich dort noch einige andere Sachen durchgehen, denn die Theorie ansich ist mir glaube ich klar. Nur an der Umsetzung hapert's.

Zu 2.: Die SOAP-Nachricht ist vorgegeben. Darin wird durch die Verschlüsselung im Header ein security-Element hinzugefügt und der Body soll verschlüsselt werden.

Zu 3.: Ist leider der gleiche Mist. Es ist vorgegeben, wie verschlüselt werden soll. Der KeyStore dafür besteht auch bereits.

Gruß,

Tobias


----------



## Noctarius (18. Okt 2010)

Wenn du weißt wie verschlüsselt werden muss kannst du doch den Body verschlüsseln, bevor du ihn an AXIS übergibst, oder nicht?
Ansonsten wird es bestimmt etwas wie einen Interceptor Mechanismus geben.


----------



## Sleepwalker (18. Okt 2010)

Noctarius hat gesagt.:


> Wenn du weißt wie verschlüsselt werden muss kannst du doch den Body verschlüsseln, bevor du ihn an AXIS übergibst, oder nicht?



Ja, genau. Die Frage ist nur "wie". Wie sage ich Axis2, dass das eine fertige SOAP-Nachricht ist, die ich da als Datei einlesen und dann verschlüsseln will?
Wenn man sie mit Axis2 erstellt, hat man sie ja direkt als Objekt in der Hand, aber genau das habe ich ja nicht.


----------



## Noctarius (18. Okt 2010)

Achso, nee das wird nicht funktionieren. Ich dachte der Body wäre nur ein Objekt und keine ganze Nachricht.

Wie gesagt Axis2, Interceptor sollten ganz gute Suchbegriffe sein oder Axis2, Encryption, Body oder oder oder.


----------



## Sleepwalker (18. Okt 2010)

Danbke, klingt nicht so gut für mich...
Was genau soll denn der "Interceptor" machen? Bzw. inwiefern soll mir so etwas helfen?


----------



## Noctarius (18. Okt 2010)

Der Interceptor wird (so ist es in anderen Frameworks) irgendwo als eine Art Listener dazwischen geschaltet und gibt dir noch mal die Möglichkeit etwas (z.B. die fertige SOAP Nachricht) zu bearbeiten oder so.

Weiß auch nicht ob es sowas in Axis2 gibt, falls nicht wirst du dir sowas eventuell mit AOP selber bauen müssen.

edit:
Erster Treffer bei Google: Axis2 Execution Framework &mdash; Developer.com
Sieht ganz interessant aus


----------



## Keo (18. Okt 2010)

> Wie sage ich Axis2, dass das eine fertige SOAP-Nachricht ist, die ich da als Datei einlesen und dann verschlüsseln will?
> Wenn man sie mit Axis2 erstellt, hat man sie ja direkt als Objekt in der Hand, aber genau das habe ich ja nicht.


Ich verstehe deine Anforderung noch immer nicht. Was für eine Datei willst Du denn einlesen und verschlüsseln? Die XML-Struktur? Das gängige Vorgehen ist, dass du als Webservice-Konsument eine WSDL-Spezifikation (Datei.wsdl) zur Verfügung gestellt bekommst. Mit dieser wsdl generierst du Stubs und kannst in den genierten Pojo-Klassen ein SOAP-Envelope bearbeiten.
In der wsdl können durch "ws-policy" auch Security-Spezifikationen definiert werden. In deiner Anleitung im ersten Beitrag hast du lediglich die Verbindung via https verschlüsselt und das Tool Rampart genutzt um ein Security-Token im SOAP-Header per Callback hinzufügen. Die SOAP-Nachricht wird hierbei aber nicht verschlüsselt, sondern "nur" die SSL-Verbindung. Wenn dir diese Anforderung ausreicht, habe noch Source-Code rumliegen:


```
ConfigurationContext  ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem( thePath, null );
//generated stubs from wsdl        
WebserviceStub    stub     = new WebserviceStub( ctx, theURL );
ServiceClient client = stub._getServiceClient();

Options options = new Options();        
options.setProperty( RampartMessageData.KEY_RAMPART_POLICY,loadPolicy( "/conf/policy.xml" ) );
options.setTimeOutInMilliSeconds( 60000 );

EndpointReference targetEPR = new EndpointReference( mURL );

// this username is authenticated against the PWHandlerClient class
options.setUserName( "user" );
options.setPassword( "password" );
options.setTo( targetEPR );
client.setOptions( options );

client.engageModule( "addressing" );        
client.engageModule( "rampart" );
stub._setServiceClient( client );


private static Policy loadPolicy( String theFile ) throws Exception {
    StAXOMBuilder builder = new StAXOMBuilder( theFile );
    return PolicyEngine.getPolicy( builder.getDocumentElement() );
}

public class PWHandlerClient implements CallbackHandler {

public void handle( Callback[] callbacks ) throws IOException,
    UnsupportedCallbackException {

    for( int i = 0; i < callbacks.length; i++ ){
        WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[ i ];
        String id = pwcb.getIdentifer();
        if( "user".equals( id ) ){
            pwcb.setPassword( "password" );
        }
    }
}
```

Policy.xml
[XML]<wspolicy wsu:Id="UTOverTransport" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
                                     xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
    <wsp:ExactlyOne>
      <wsp:All>
        <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <wspolicy>
            <sp:TransportToken>
              <wspolicy>
                <sp:HttpsToken RequireClientCertificate="false"/>
              </wspolicy>
            </sp:TransportToken>
            <sp:AlgorithmSuite>
              <wspolicy>
                <sp:Basic256/>
              </wspolicy>
            </sp:AlgorithmSuite>
            <sp:Layout>
              <wspolicy>
                <sp:Lax/>
              </wspolicy>
            </sp:Layout>
            <sp:IncludeTimestamp/>
          </wspolicy>
        </sp:TransportBinding>
        <sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
            <wspolicy>
                <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" />
          </wspolicy>
        </sp:SignedSupportingTokens>

        <ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
            <ramp:user>user</ramp:user>
            <rampasswordCallbackClass>de.webservice.client.security.PWHandlerClient</rampasswordCallbackClass>
        </ramp:RampartConfig>

      </wsp:All>
    </wsp:ExactlyOne>
</wspolicy>
[/XML]


----------



## Sleepwalker (19. Okt 2010)

Hallo Keo,

deine genannten Anforderungen sind ansich schon richtig für das "Ganze". Wir haben eine WSDL und einen Java KeyStore mit Zertifikaten zur Verfügung gestellt bekommen. Damit sollen dann die Nachrichten generiert und anschließend verschickt werden. Doch ganz so trivial ist das leider nicht, dazwischen gibt es noch einige Schritte, die jetzt zu sehr ins Detail gehen.

Nun ist meine Teilaufgabe, eine bereits fertige SOAP-Datei zu nehmen, zu verschlüsseln und zu versenden (und auf die Antwort zu warten). Weiter als bis zum ConfigurationContext bin ich dabei leider nicht gekommen...dabei arbeite ich nach einer Doku. Ich habe hier Beispielnachrichten rumliegen, da sind bei der Verschlüsselten zusätzliche Informationen im Header und der Body ist verschlüsselt. Das sollte mit meiner Rampart Konfiguration allerdings schon klappen, wenn ich eine Nachricht verschicken will. So, wie ich das verstanden habe (Rampart ist ja bereits konfiguriert).
Gibt es irgendwo eine gute Einführung in diese ganze Thematik? Ich hab' das Gefühl mir fehlt da noch eine ganze Menge, irgendwie.

Jedenfalls, wenn das mit dem Einlesen der fertigen Nachricht nicht klappt muss ich selbst die Datei generieren, was ich eigentlich vermeiden wollte. Werde mir deinen Code mal in Ruhe anschauen und mich dann wieder melden.
Vielen Dank schon einmal.

Gruß,

Tobias


----------



## Sleepwalker (28. Okt 2010)

Hallo,

ich bin jetzt ein Stück weiter, habe aber noch einige Fragen.
Erstmal Axis2:
Ich kann ja von NetBeans aus schon eine WSDL-Datei einlesen, wenn ich einen WebClient erzeuge. Der generierte Code sieht allerdings anders aus, als wenn ich Axis2 zur Erstellung benutze. Wie kann ich für dieses Vorhaben Axis2 in NetBeans einbinden?

Nun zu XMLBeans:
Ich habe ein .xsd Schema, das ich benutzen kann. Laut Manual kann mittels XMLBeans Dateien einlesen, wenn diese passend zum Schema sind. Somit wäre meine Fragestellung ganz oben falsch gestellt. Hat da jemand Erfahrungen, wie das unter NetBeans geht?
Danke.

Gruß,

Tobias


----------



## wowa (1. Nov 2010)

Hallo,

ich kann mit den Axis2Tools und dem Modul Rampart unter Eclipse keinen Web Service mit SSL Verschlüsselung erstellen. Wenn ich in der services.xml die Policys definiere wie: 

"<wspolicy wsu:Id="UTOverTransport" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">" 

dann bekomme ich beim Erstellen des Services die Meldung: "You must select a valid services.xml file". Die services.xml Datei habe ich aus einem Tutorial, sollte also korrekt sein. Wie kann ich diese ür die Security-Namespaces  in Eclipse einbinden bzw. bekannt machen? 

Vielen Dank im Voraus!


----------



## Sleepwalker (19. Nov 2010)

Moin,

also, ich kann nun den Body mittels XMLBeans parsen und den Header erstellen oder komplette Nachrichten erstellen und die Verschlüsselung mit RAMPart haut auch hin. Habe aber gerade ein kleines Problem.

Ich bekomme am Ende immer einen AxisFault, weil das Rückgabe-Dokument vom Aufruf des WebServices nicht mit dem erwarteten Format übereinstimmt. XMLBeans meckert dann.
Ich würde jetzt gerne irgendwie an die unverschlüsselte Nachricht kommen, um das nachvollziehen zu können. Mit TCPMon sehe ich natürlich nur die verschlüsselte Nachricht.

Wie komme ich an den unverschlüsselten Inhalt, trotz AxisfFault? Der "messageContext" ist irgendwie leer?!
Danke im Voraus.

Gruß,

Tobias


----------



## Happo (15. Jun 2011)

Ich versuche auch schon seit längerem einen WebService mit WS-Security zu sichern.
Eine Signierung der Nachrichten ist mir auch schon gelungen, allerdings sollen Teile der Nachricht verschlüsselt werden.
Dabei tritt nun das Problem auf, dass wenn ich das Rampart Modul engage, der Webservice nicht gerufen wird.
Schalte ich das Modul aus, erhalte ich eine missing wsse exception.
Sieht einer den Fehler in meinem Code oder hat schon einmal so ein Problem gehabt?


```
package de.security.tutorial;

import java.io.InputStream;
import java.rmi.RemoteException;

import javax.xml.stream.XMLStreamException;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyEngine;
import org.apache.rampart.RampartMessageData;

import de.security.tutorial.ServerStub.GetWelcomeResponse;

public class Client {
	
	/**
     * Load policy file from classpath.
     */
    private static Policy loadPolicy(String name) throws XMLStreamException {
    	ClassLoader loader = new ClassLoader() {};
        InputStream resource = loader.getResourceAsStream(name);
        StAXOMBuilder builder = new StAXOMBuilder(resource);
        return PolicyEngine.getPolicy(builder.getDocumentElement());
    }
	
	public static void main(String[] arg) throws RemoteException{
		String url = "http://localhost:8080/axis2/services/Server";
		try {
			// get Modulrepository
			ConfigurationContext ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem("WebContent/WEB-INF/", null);
			
			// create new Stub
			ServerStub stub = new ServerStub(ctx, url);
			
			// configure and engage Rampart
	        ServiceClient client = stub._getServiceClient();
	        Options options = client.getOptions();
	        
	        Policy policy = loadPolicy("policy.xml");
//	        client.getAxisService().getPolicySubject().attachPolicy(policy);
	        options.setProperty(RampartMessageData.KEY_RAMPART_POLICY, policy);
	        options.setUserName("libuser");
	        options.setPassword("books");

	        client.setOptions( options );	        
	        client.engageModule( "addressing" );        
	        client.engageModule( "rampart" ); // hier passiert der Fehler
	        stub._setServiceClient( client );
	        
	        // send request
	        GetWelcomeResponse response = stub.getWelcome();
	        
	        // print response to console
	        if(response.local_returnTracker){
	        	String string = response.get_return();
	        	System.out.println(string);
	        }
	        
		} catch(Exception e) {
			System.out.println("Exception: " + e.getMessage());
		}
		
	}

}
```

Hier ist auch noch meine Policy, falls es an der liegen sollte.


```
<?xml version="1.0" encoding="UTF-8"?>

<wsp:Policy wsu:Id="SigEncr"
	xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
	xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
	<wsp:ExactlyOne>
		<wsp:All>
			<sp:AsymmetricBinding
				xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
				<wsp:Policy>
					<sp:InitiatorToken>
						<wsp:Policy>
							<sp:X509Token
								sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
								<wsp:Policy>
									<sp:RequireThumbprintReference />
									<sp:WssX509V1Token10 />
								</wsp:Policy>
							</sp:X509Token>
						</wsp:Policy>
					</sp:InitiatorToken>
					<sp:RecipientToken>
						<wsp:Policy>
							<sp:X509Token
								sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never">
								<wsp:Policy>
									<sp:RequireThumbprintReference />
									<sp:WssX509V3Token10 />
								</wsp:Policy>
							</sp:X509Token>
						</wsp:Policy>
					</sp:RecipientToken>
					<sp:AlgorithmSuite>
						<wsp:Policy>
							<sp:TripleDesRsa15 />
						</wsp:Policy>
					</sp:AlgorithmSuite>
					<sp:Layout>
						<wsp:Policy>
							<sp:Strict />
						</wsp:Policy>
					</sp:Layout>
					<sp:IncludeTimestamp />
					<sp:OnlySignEntireHeadersAndBody />
				</wsp:Policy>
			</sp:AsymmetricBinding>
			<sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
				<wsp:Policy>
					<sp:MustSupportRefKeyIdentifier />
					<sp:MustSupportRefIssuerSerial />
				</wsp:Policy>
			</sp:Wss10>
			<sp:SignedParts
				xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
				<sp:Body />
			</sp:SignedParts>
			<sp:EncryptedParts
				xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
				<sp:Body />
			</sp:EncryptedParts>
			<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
				<ramp:user>clientkey</ramp:user>
				<ramp:encryptionUser>serverkey</ramp:encryptionUser>
				<ramp:passwordCallbackClass>de.security.tutorial.PWCBHandler
				</ramp:passwordCallbackClass>
				<ramp:signatureCypto>
					<ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
						<ramp:property
							name="org.apache.ws.security.crypto.merlin.keystore.type">JKS</ramp:property>
						<ramp:property name="org.apache.ws.security.crypto.merlin.file">D:/keystore/client.keystore
						</ramp:property>
						<ramp:property
							name="org.apache.ws.security.crypto.merlin.keystore.password">nosecret</ramp:property>
					</ramp:crypto>
				</ramp:signatureCypto>

				<ramp:encryptionCypto>
					<ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
						<ramp:property
							name="org.apache.ws.security.crypto.merlin.keystore.type">JKS</ramp:property>
						<ramp:property name="org.apache.ws.security.crypto.merlin.file">D:/keystore/client.keystore
						</ramp:property>
						<ramp:property
							name="org.apache.ws.security.crypto.merlin.keystore.password">nosecret</ramp:property>
					</ramp:crypto>
				</ramp:encryptionCypto>

			</ramp:RampartConfig>

		</wsp:All>
	</wsp:ExactlyOne>
</wsp:Policy>
```


----------

