Archiv

Archiv für die Kategorie ‘Oracle SOA Suite’

Purging of failed SOA components

In the previous post the preferred settings of heavily used SOA composites was demonstrated. It was shown that with the correct settings applied only failed component instances are persisted in the database. This post discusses the purging possibilities of such component instances.

As stated in the earlier post, we are now facing a situation where the composite instance itself is not persisted, only its failed component instances. Since the composite is heavily used, even a short outage of a system used by the composite can lead to a huge amount of failures. Having resolved these faults, the need often arises to clear these faults from the system so that fault monitoring is not disturbed by them.

Instances without faults are not persisted in this case because no information from the composite is needed, so a straightforward approach would be to delete the failed instances with Enterprise Manager. In this case, however, this is not possible because the composite instance itself is not persisted and instance purging in Enterprise Manager is based on the composite instance.

Another possibility is to use the database purging scripts supplied by Oracle. These scripts are automatically present in the SOAINFRA schema once the schema is created with the RCU utility. If purging is done with the help of these scripts, the failed orphaned component instances are deleted with the purging run. However, purging generally has fixed time slots and it might be difficult to bring that slot forward if the failed component instances are to be deleted sooner.

The functions used by the purging scripts, however, are also available on their own. A sample script to delete the failed orphaned components could therefore be constructed by using the functions present in the SOAINFRA schema. The same functions can also be found in the scripts which are automatically supplied with every SOA Suite and JDeveloper installation and can be found in the subdirectory rcu/integration/soainfra/oracle/soa_purge under the installation directory.


DECLARE

  min_creation_date TIMESTAMP;
  max_creation_date TIMESTAMP;
  batch_size INTEGER;
  retention_period TIMESTAMP;
  composite_dn VARCHAR2(125);
  soa_partition_name VARCHAR2(10);
  composite_name VARCHAR2(100);
  composite_revision VARCHAR2(10);
  mediator_deleted BOOLEAN;
  decision_deleted BOOLEAN;
  bpel_deleted BOOLEAN;
  fabric_deleted BOOLEAN;

BEGIN

  min_creation_date := to_timestamp('2013-01-01','YYYY-MM-DD');
  max_creation_date := to_timestamp('2013-03-31','YYYY-MM-DD');
  batch_size := 20000;
  retention_period := max_creation_date;
  soa_partition_name := 'PARTITION';
  composite_name := 'TestProcess';
  composite_revision := '1.0';

  IF soa_partition_name IS NOT NULL THEN
    composite_dn := soa_partition_name;
    IF composite_name IS NOT NULL THEN
      composite_dn := composite_dn || '/' || composite_name;
      IF composite_revision IS NOT NULL THEN
          composite_dn := composite_dn || '!' || composite_revision;
      END IF;
    END IF;
  END IF;

  bpel_deleted := soa_orabpel.deleteNoCompositeIdInstances(
                                    p_min_creation_date => min_creation_date,
                                    p_max_creation_date => max_creation_date,
                                    p_older_than => retention_period,
                                    p_rownum => batch_size,
                                    soa_partition_name => soa_partition_name,
                                    composite_name => composite_name,
                                    composite_revision => composite_revision);

  mediator_deleted := soa_mediator.deleteNoCompositeIdInstances(
                                    p_min_creation_date => min_creation_date,
                                    p_max_creation_date => max_creation_date,
                                    p_older_than => retention_period,
                                    p_rownum => batch_size,
                                    composite_dn => composite_dn);

  decision_deleted := soa_decision.deleteNoCompositeIdInstances(
                                    p_min_creation_date => min_creation_date,
                                    p_max_creation_date => max_creation_date,
                                    p_older_than => retention_period,
                                    p_rownum => batch_size,
                                    composite_dn => composite_dn);

  fabric_deleted := soa_fabric.deleteNoCompositeIdInstances(
                                    min_created_date => min_creation_date,
                                    max_created_date => max_creation_date,
                                    retention_period => retention_period,
                                    batch_size => batch_size,
                                    composite_dn => composite_dn);

  IF (bpel_deleted OR mediator_deleted OR decision_deleted OR fabric_deleted) THEN
    dbms_output.put_line('Further instances may be present in the system, please rerun the script to delete these');
  ELSE
    dbms_output.put_line('All orphaned instances deleted');
  END IF;

END;
/

This script can be executed in the SOAINFRA schema on demand – even without starting the purging run – thereby assuring fault monitoring efficiency. Keep in mind that while the script is running in the database, performance of the application might be slightly lower because of increased database load. Therefore it is advisable to limit the run time of the script by narrowing the number of processed component instances – either by selecting the composite itself or if that is not possible selecting an appropriate batch size, thereby limiting the number of deleted component instances in one run.

Kategorien:Oracle SOA Suite

Improve performance and maintenance of heavily used SOA composites

10. März 2013 1 Kommentar

As stated in a previous post, heavily used transient BPEL processes should be configured with some well-defined parameters in order to avoid storing too much data in the database, thus optimizing performance.

However, even if BPEL processes inside the composite are configured this way, data of other components like mediators and the composite itself are all stored in the database. How much information is stored can be influenced by the audit level setting. As of documentation, the audit levels are defined as follows:

  • Off: No composite instance tracking and payload tracking information is collected. No more composite instances can be created. No logging is performed. Note that disabling logging and the display of instances in Oracle Enterprise Manager Fusion Middleware Control Console can result in a slight performance increase for processing instances. Instances are created, but are not displayed.
  • Development: Enables both composite instance tracking and payload detail tracking. However, this setting may impact performance. This level is useful largely for testing and debugging purposes.
  • Production: Composite instance tracking is collected, but the Oracle Mediator service engine does not collect payload details and the BPEL process service engine does not collect payload details for assign activities (payload details for other BPEL activities are collected). This level is optimal for most normal production operations.

Generally, the SOA Infrastructure audit level is set to Production or Development – depending on the environment – and the composites are set to inherit this audit level. In case of an intensively used composite this means that a lot of data is persisted in the database.

The audit level, however, can be overridden for every composite. Since the data from the transient, short-lived composites is not needed, the setting Off for the relevant composite should be an interesting option to consider. Three questions must be answered:

  1. How much information is persisted from the composite instance?
  2. How much information is persisted from the component instances inside the composite?
  3. What happens in case of an error?

Our tests have shown that although the instances successfully complete, no information is stored in the database at all. Neither for the composite instance, nor for any business rule, BPEL or mediator instances inside it. In case of an unhandled error, however, the erroneous component instance is persisted in the database with the details of the error. The composite instance is not saved. This means that the error is seen in the error handling console, it can even be handled if a fault policy is configured, but no information about the corresponding composite instance can be obtained. The composite instance id is set to Unavailable.

faults

We have seen that setting the composite level to Off in case of transient composites causes less data to be stored in the database, thereby increasing performance. The more instances of the composites created per day, the higher the benefit of this approach.

We have also seen, however, that the composites should be well tested before setting this option because it can be quite cumbersome to track the origin of the error. This setting is therefore ideal for a production environment with heavy load, but suboptimal for a development environment with only a handful of instances but the need for extensive testing. This calls for a different setting in each environment.

The audit level setting of a composite can be modified via Enterprise Manager but it can also be defined during deployment, the latter one being more efficient in this case. In order to do so, the following property needs to be added to the composite.xml:

<property name="auditLevel" many="false">Off</property>

The setting here will be treated as the default setting but like many other properties, this setting can be overridden with a deployment plan containing the following:

<composite name="<COMPOSITE_NAME>">
  <property name="auditLevel">
    <replace>Development</replace>
  </property>

</composite>

By using deployment plans, the problem of needing different audit level settings in different environments can be easily solved: the audit level of an intensively used transient composite can be set to Off in a production environment whereas the Development setting can be used in a development environment.

Kategorien:Oracle SOA Suite

Access multiple SOA / BPM Virtual Machines from different computers in your network

In this article I’d like to explain how to share multiple instances of Oracle’s Pre-built Virtual Machine for SOA Suite and BPM Suite across different computers in your network. Three requirements we had to address:

  1. Call of external services like GeoNames (http://www.geonames.org/postal-codes/) from within the BPM Suite VM
  2. Connection to multiple BPM Suite VMs from Host (e.g. JDeveloper and Browser)
  3. Connection to multiple BPM Suite VMs from different developer computers in the network
  4. Share data between VMs and developer computers via FTP

The default options already support connections between host and client. However the target here was to address multiple independent VMs from different computers in the same network. I described the approach in my article on Inside BPM and SOA. Have fun!

Composite Management: Undeployment with WLST or ANT

Oracle BPM / SOA Suite offers different options to deploy or delete composites. You can use the Enterprise Manager, the Weblogic Scripting Tool (WLST) or ANT. In complex environments with many different composites and versions it is hard to undeploy them one by one and manually. If you are interested in a script solution for this visit my post under Inside BPM and SOA.

Wiederverwendung von Daten und Services in Oracle SOA / BPM Suite

Ein wichtiger Aspekt in einer Serviceorientierten Architektur ist die Veröffentlichung von Metadaten potenziell wiederverwendbarer SOA-Artefakte. Mit den Metadata Services (MDS) bietet die Oracle SOA/BPM Suite eine solche Komponente an, um die zentrale Verwaltung und Bereitstellung von Schnittstellen (WSDL), Daten (XSD), Geschäftsregeln (Rules), FaultPolicies (XML) und Geschäftsereignissen (EDL) zu ermöglichen (siehe nachfolgende Abbildung). Somit können Daten und Dokumente zur Design- und Laufzeit applikationsübergreifend angeboten werden und die Duplizierung von Code wird reduziert.

Ohne eine solche Komponente müssten derartige Artefakte entweder für verschiedene Projekte dupliziert abgelegt oder direkt auf dem Applikationsserver referenziert werden. Diese beiden Ansätze bringen jedoch Nachteile mit sich. Während die lokale Mehrfachspeicherung von Schnittstellen (WSDL) und Datenbeschreibungen (XSD) in unterschiedlichen Projekten zu Inkonsistenzen führen kann, ist die direkte Referenzierung auf einen Applikationsserver an dessen Erreichbarkeit gebunden. Ist dieser etwa aus Wartungsgründen vorübergehend nicht verfügbar, so würde die Entwicklung in dem Moment ebenfalls gestört werden.

Die Verwendung des MDS führte in unseren SOA-Projekten zu folgenden Erkenntnissen und Best Practices:

  • Die Versionierung von Services und Daten ist für den Betrieb einer SOA unumgänglich und muss bereits im Rahmen des Service-Designs berücksichtigt werden (Service Lifecycle Management). Dies gilt insbesondere für Schnittstellen und Datenobjekte, die in verschiedenen Projekten wiederverwendet werden sollen. Andernfalls bedeuten Änderungen an diesen Komponenten einen erhöhten Entwicklungsaufwand und wenig Potenzial für Wiederverwendung.
  • Das MDS unterstützt die Software-Entwicklung nach dem „Contract-first Prinzip“. Nach dem Design der Schnittstelle durch den Service-Architekten, wird diese in das MDS geladen und steht dem Service-Entwickler zur Implementierung bereit.
  • Als Best Practice hat sich zur Entwicklungszeit die Verwendung eines lokalen MDS-Repositories bewährt. Dieses wird bereits mit der Standard-Installation des Oracle JDevelopers bereitgestellt. Auf performante Art und Weise kann somit die zukünftige Speicherung von verteilten Artefakten in einem zentralen Repository von Beginn an berücksichtigt werden. Besonders vorteilhaft ist dabei auch, dass jeder Entwickler eine eigene Lokation für seine Metadaten besitzt und nicht jeder Entwicklungsschritt sofort deployed werden muss.
  • Zur Laufzeit stellt die Oracle SOA Suite ein zentrales MDS-Repository auf dem Server bereit, in welches die verteilten Schnittstellen, Daten, Event-Definitionen und Fault-Policies im Rahmen des Applikations-Deployments bereitgestellt werden.
  • Unabhängig ob das lokale oder das Server-MDS verwendet werden soll, so erfolgt die Referenzierung der Inhalte aus einem SCA Composite mit Hilfe einer einheitlichen URL: oramds:/apps/<ORDNER>/<Service>.wsdl. Somit ist beim Wechsel zwischen lokalem und zentralem MDS keine gesonderte Code-Anpassung erforderlich.
  • Die Bereitstellung zentraler Schnittstellen bringt den Vorteil mit sich, dass beispielsweise beim Neustart des Applikationsservers alle SOA-Applikationen völlig unabhängig voneinander gestartet werden können und somit nicht an eine spezielle Reihenfolge gebunden sind, da alle Schnittstellenbeschreibungen von Beginn an verfügbar sind.
  • Die Administration des MDS Repositories zum Export, Import oder Löschen der Metadaten kann über den Enterprise Manager, ANT oder das Weblogic Scripting Tool (WLST) erfolgen.

Standard-based integration of human interaction in SOA

26. Mai 2012 1 Kommentar

IT infrastructures and systems following the SOA paradigm are build upon standards. In such scenarios BPMN 2.0 can be used for the automation of business processes for example. The processes can be executed by a process engine. In such business processes the integration of human actors is often needed, to make complex decisions that cannot be made by a machine. The communication between the human actor and the process engine is done by tasks, which are often managed by separate task engines. Authorized users are able to work on the tasks using a provided task UI, a so called inbox or tasklist application. As one can see there are at least two consumers for the services provided by a task engine: the task UIs and the process engines.

Although a specification, the WS-HT (WS Human Task) specification, for the standard-based integration of human interaction in SOA is available, task engine interfaces are vendor-specific and not standard-based actually, e.g. using RMI or native Java method invocation for communication. This leads to the following problems:

  • Portability issues
  • Interoperability issues
  • Tight coupling

To deal with the problems of vendor-specific interfaces in the area of human interaction, I defined a adapter framework, the Generic Human Interaction Adapter (GHIA), which provides a interface that is based on the definitions propagated by the WS-HT specification. Features of the GHIA-Framework are a standard-based interface (SOAP based on WS-HT and REST) and the opportunity to transparently communicate with more than one task-engine, e.g. for the synchronization of different inboxes. Scenarios where the GHIA-Framework can be used, delivering a great benefit, are:

  • Integration scenarios (more than one task-engine is used)
  • Decoupling scenarios (e.g. for decoupling task UIs from the vendor-specific inerfaces)
  • Migration scenarios (when moving from one release to a higher one, to ensure that long running process with human interaction can be ended within the older versioned plattform)
To validate the framework I have implemented a prototyp, using a subset of the operations defined by WS-HT, where the task-enignes from the Oracle BPM Suite 11g and the Activiti BPM Platform 5.8 are integrated transparently behind one standard-based interface. For this scenario using the GHIA framework leads to the following architectural layout:
The prototyp shows that the intended expectations I made before starting the implementation of the framework could be met. As a result a lightweight and easily extendable framework has been created which will be refined, and extended over the next months. Interested readers will be kept updated about the further evolution of the GHIA framework in this blog.

Macht SOA ohne MDM Sinn?

Der Titel ist gewiß etwas reisserich – bringt die Kernfrage aber auf den Punkt. In etlichen Retrospektiven der SOA-Programme taucht immer wieder ein Problem auf. Wie gehen wir mit den grundlegenden Business Services um, die Daten und vor Allem Stammdaten betreffen? Zur Einstimmung auf die Herausforderung eine kurze Einleitung.

Ein wesentlicher Nutzen der SOA liegt in der losen Kopplung der IT-Komponenten. Hierdurch wird die Wiederverwendung der Komponenten forciert und die Flexibilität beim Einsatz dieser Komponenten zur Unterstützung neuer Funktionalitäten bzw. Prozessabläufe vereinfacht. Hierbei werden allgemeingültige Komponenten (bzw. Services) für die konsistente Datenpflege und Abfrage der Stammdaten benötigt. Es werden zwei unterschiedliche Sichten hierdurch unterstützt:

  • Wiederverwendbare Geschäftslogik zur Pflege und Validierung der Stammdaten (Stammdaten Business Services)
  • Wiederverwendbare Informationen zur Nutzung in den Geschäftsprozessen (Stammdaten Information Services)

Führt man imRahmeen der SOA eine Service-Dekomposition durch, erkennt man, dass im Rahmen der wiederverwendbaren Services auch Dienste benötigt werden, die servicedomänenübergreifend zentrale Aufgaben für die Verwaltung des Lebenszyklus der Stammdaten übernehmen. In diesem Zusammenhang wird man auf der Ebene der Datenzugriffe, auch unabhängig von einem Stammdatenvorgaben-Vorhaben, auf typische Schwierigkeiten bei der Verwaltung und Pflege der Stammdaten stoßen:

  • Probleme bei der einheitlichen Prüfung der Qualität der Stammdaten
  • Performanceprobleme bei der Propagierung der Daten in die Sub-Systeme
  • Herausforderungen beim Datenschutz und der Datensicherheit in Abhängigkeit vom Lebenszyklusstadium der Daten

Stammdaten Business Services

Der Zugriff auf Stammdatenobjekte wie Produkt, Kunde oder Geschäftspartner wird über alle Unternehmensbereiche und somit quer zu den Funktions- und Verwaltungsbereichen benötigt. Jan Werner Schemm (siehe auch „Zwischenbetriebliches Stammdatenmanagement“, Springer, 2009) meint hierzu, dass  „durch ihren hohen Wiederverwendungswert und die vergleichsweise einfache Standardisierung bildet der Zugriff auf Stammdatenobjekte ideale Servicekandidaten.“ Dieser Meinung sind auch die Masons oft SOA, die die Zugriffe auf Stammdatenobjekte als „Business Entity Services“ auffassen und aufzeigen, dass Stammdatenservices einen erheblichen Anteil der entwickelten Dienste in der SOA ausmachen. Hier zudem ist auch ein Trend erkennbar, der wiederum Schemm schön zusammenfasst: „Die zu beobachtende Bündelung von Stammdatenservices in eigenständigen Anwendungsdomänen nimmt die Entwicklung von Applikationsarchitekturen vorweg: Zukünftig werden zentrale Stammdatensysteme, die Dienste für den Zugriff auf globale Stammdatenobjekte anbieten, eine noch bedeutendere Rolle in den Anwendungsarchitekturen spielen“ .

Somit wird das Stammdatenmanagement ( MDM, Master Data Management) zu einen fundamentalem Baustein der SOA selbst. Mit Etablierung einer SOA im Unternehmen wird die Häufigkeit der Nutzung von zentralen Stammdatendiensten steigen und somit implizit die Wiederverwendung. Somit ist die Etablierung zentraler verwalteter Dienste für den Datenzugriff und deren Verarbeitung  ein sinnvoller nächster Schritt.

 

MDM Information Services

Bei der Service-Dekomposition entsteht die Notwendigkeit von zentralen Stammdaten-Services. Diese unterstützen den weiterführenden, eher strategischen Ansatz der Implementierung einer „Information-as-a-Service (IaaS)“.

Die grundlegende Idee ist recht einfach: Damit nicht jede Anwendung oder jeder Service selbst den Zugriff auf die Daten implementieren muss, wird eine Facade genutzt, die den Zugriff an das IaaS delegiert. Das könnte man sogar als eine Virtualisierung der Datenzugriffe sehen, da die Datenquellen nun transparent zu der aufrufenden Schicht sind. So erlangt man eine zentrale Kontrolle über die typischen CRUD-Operationen auf den benötigten Stammdaten. Die Kontrolle über die Validierungen ist nun gewährleistet und die Inkonsistenzen bei der Wartung der unterschiedlichen Anwendungen und Services wurden gelöst.

Verfolgt man diesem Ansatz im Rahmen der MDM, so können über technische bzw. organisatorische Maßnahmen die drei grundlegenden Herausforderungen durch den Ansatz „Information-as-a-Service (IaaS)“ bewältigt werden. Aus Sicht des Konsumenten bedeutet dies:

Definition: Die Bedeutung (Semantik) von Stammdaten und deren Attributen müssen einheitlich und konsistent implementiert sein. Hierzu gehören auch die Verfügbarkeit der Definition und die Eineindeutigkeit der selbigen Definition.

Qualität: Die Prüfung der Datenqualität kann jetzt auf einer „virtualisierten“ Plattform stattfinden, komplett transparent für den Consumer, der die Stammdaten verändern. Das Repository der IaaS sichert eine gemeinsame Semantik und ein Regelwerk für die Validierung. Auch dies verhindert Inkonsistenzen.

Governance: Der letzte Punkt ist nun das Management des Lebenszyklus der Services der IaaS. Dieses lässt sich sofort über die etablierten Governance-Ansätze für das Management von Services im SOA-Umfeld abdecken.

Zusammengefasst folge ich hieraus, dass eine SOA ohne MDM-Ansätze immer ein wenig zu kurz geraten wird und eine Unzufriedenheit bei der Nutzbarkeit (Datenqualität) der Stammdaten bestehen bleiben wird.

Die Empfehlung kann nur lauten: Im Rahmen der SOA auch das Thema Stammdatenmanagement behutsam anzugehen.

Ein kurzer Werbeblock in eigener Sache: Das Buch „Master Data Management: Strategie, Organisation, Architektur“ (http://www.dpunkt.de/buecher/3761/master-data-management.html) beschreibt, wie man zu einer abgestimmten Vision in seinem MDM-Vorhaben gelangt und wie man messbare Ziele entwickelt. Es werden Methoden und Vorgehensweisen beschrieben, damit schon bei der Planung des MDM-Vorhabens ein klares Bild über die notwendige Aufbau- und Ablauforganisation entsteht und das MDM-Vorhaben durch einen passenden Architekturentwurf unterstützt wird, sodass die meist mehrjährige Entwicklung zielgerichtet erfolgen kann. Letztlich beschreiben wir Ansätze zur Entwicklung einer Einführungsstrategie und Roadmap für MDM. Als Ergebnis ist ein fast 500-seitiges Handbuch zur Planung von MDM entstanden

OWSM Custom Assertion zur Absicherung einzelner Services per IP-Adresse

An diesem Beispiel soll die Erstellung einer OWSM (Oracle Web Services Manager) Custom Assertion vorgestellt werden. Die Custom Assertions erlauben es, nahezu beliebige Policies zu erstellen, die wie die von Oracle vorgefertigten Policies auf Service-Endpunkte, SOA Komponenten oder auch Service-Referenzen angewendet werden können. Typischerweise kümmern sich diese Policies um Authentifizierung und Autorisierung.

Unser Anwendungsfall: wir möchten einen bestimmten Service nur für bestimmte IP-Adressen zugreifbar machen. Die Vorstellung ist, dass wir eine Liste mit gültigen IP-Adressen für den jeweiligen Service konfigurieren. Alle Requests, die von anderen Adressen kommen, sollen abgelehnt werden.

Diese Funktionalität ist in der SOA Suite leider nicht Out-Of-The-Box vorhanden.

1. Projekt-Setup

Um das Projekt aufzusetzen wird in JDeveloper einfach ein Standard-Java-Projekt erstellt.

Bevor die Entwicklung starten kann, müssen einige Bibliotheken für OWSM und SOA in den Build-Pfad eingebunden werden. Die genaue Beschreibung spare ich mir an dieser Stelle – wer möchte kann jederzeit die aktuelle Liste aus dem fertigen Projekt (siehe unten) kopieren (Tipp: Einfach die .jpr-Datei mit einem Texteditor bearbeiten und sämtliche Library References rüberkopieren – nach einem Refresh in JDev, sind die Bibliotheken dort bekannt).

2. Grundstruktur der Assertion-Klasse

Grundsätzlich ist eine Custom Assertion lediglich eine einzige Klasse, die von oracle.wsm.policyengine.impl.AssertionExecutor erbt. Hier ist unser erstes Grundgerüst:

public class ClientIpAssertion extends AssertionExecutor {
    private final static Logger LOG = Logger.getLogger(ClientIpAssertion.class.getName());
 
    protected IAssertion mAssertion = null;
    protected IExecutionContext mEcontext = null;
    protected oracle.wsm.common.sdk.IContext mIcontext = null;

    public IResult execute(IContext iContext) {

       // Hier wird die Assertion ausgefuehrt
    }
 
    public void init(IAssertion iAssertion, IExecutionContext iExecutionContext, IContext iContext) {
        mAssertion = iAssertion;
        mEcontext = iExecutionContext;
        mIcontext = iContext;
    }
 
    public void destroy() {
    }
}

Die Methode init() wird vom OWSM zum Initialisieren aufgerufen. Hier kommen schonmal grundsätzlich einige Umgebungsobjekte mit, die später noch wichtig sind, um z.B. die Parameter auszulesen.

Die Methode destroy() wird beim Zerstören der Klasse aufgerufen. Falls man irgendwelche Ressourcen belegt hat, kann man diese hierin freigeben.

3. Metadaten

Neben der Implementierung der Assertion benötigt man noch eine XML-Datei (ClientIpAssertion.xml) mit einigen Metadaten zur Assertion.

<orawsp:AssertionTemplate xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy"
                          orawsp:Id="ClientIp"
                          orawsp:attachTo="generic" orawsp:category="security"
                          orawsp:description="Client IP assertion verifies the client IP address to be in a configured list of addresses"
                          orawsp:displayName="Client IP"
                          orawsp:name="custom/CientIp"
                          xmlns:custom="http://schemas.oracle.com/ws/soa/custom">
  <custom:custom-executor orawsp:Enforced="true" orawsp:Silent="false"
                   orawsp:category="security/custom"
                   orawsp:name="WSSecurity_Custom_Assertion">
    <orawsp:bindings>
      <orawsp:Implementation>com.opitzconsulting.clientipassertion.ClientIpAssertion</orawsp:Implementation>
      
      <orawsp:Config orawsp:configType="declarative" orawsp:name="ClientIp">
        <orawsp:PropertySet orawsp:name="clientip">
          <orawsp:Property orawsp:contentType="required"
                           orawsp:name="allowedIpAddresses" orawsp:type="string">
            <orawsp:Value>127.0.0.1</orawsp:Value>
          </orawsp:Property>
        </orawsp:PropertySet>
      </orawsp:Config>
    </orawsp:bindings>
  </custom:custom-executor>
</orawsp:AssertionTemplate>

Hierin wird z.B. die ID der Assertion festgelegt (hier: “ClientIp”), woran die Policy angehängt werden kann (hier: “generic”, sprich kann überall verwendet werden – man könnte es auch auf Service-Endpunkte, SOA Komponenten oder SOA Referenzen einschränken) und weitere allgemeine Infos wie ein Anzeigename, Beschreibung, usw.

Im Tag “orawsp:Implementation” wird der vollständige Name der Implementierungsklasse angegeben. Besonders interessant ist der nächste Abschnitt, der die möglichen Konfigurationsparameter der Assertion zusammen mit Standardwerten enthält. Hier: Ein Parameter “allowedIpAddresses” vom Typ “string” mit dem Standardwert “127.0.0.1″.

Diese Konfigurationsparameter können später im Enterprise Manager konfiguriert werden, wenn man sich aus den Assertions eine eigene Policy zusammenbaut (siehe Deployment).

4. IP-Vergleich

Kommen wir zum Kern der Assertion: Vergleich der Client IP Addresse mit einer Liste von erlaubten IP-Addressen. Da dieser Vergleich für jeden Aufruf ausgeführt werden muss, erfolgt die Implementierung vollständig in der execute()-Methode.

 public IResult execute(IContext iContext) {
        IResult result = new Result();
        result.setStatus(IResult.FAILED);
 
        // Abschnitt A
        IMessageContext.STAGE stage = ((IMessageContext)iContext).getStage();
        LOG.fine("stage=" + stage);
        if (stage != IMessageContext.STAGE.request) {
            LOG.fine("Nothing to process on this stage");
            result.setStatus(IResult.SUCCEEDED);
            return result;
        }
        
        // Abschnitt B
        SOAPBindingMessageContext soapbindingmessagecontext = (SOAPBindingMessageContext)iContext;
 

        String remoteAddress = soapbindingmessagecontext.getRemoteAddr();
        String[] allowedIpAddresses = new String[] { "127.0.0.1" };
 
        boolean clientIpValid = false;
        for (String allowedIpAddress : allowedIpAddresses) {
            if (allowedIpAddress.equals(remoteAddress)) {
                clientIpValid = true;
            }
        }
 
        // Abschnitt C
        if (clientIpValid) {
            result.setStatus(IResult.SUCCEEDED);
        } else {
            WSMException exception = new WSMException("Client IP address " + remoteAddress + " is not allowed");
            result.setFault(exception);
            result.setStatus(IResult.FAILED);
        }
 

        return result;
    }

Als allererstes initialisieren wir ein IResult-Objekt mit einem Fehlerstatus – per Default soll ein Fehler zurückkommen.

Im Abschnitt A geht es zunächst darum, zu prüfen, in welchem Stage wir uns befinden. Die Policy wird grundsätzlich für Request und Reply ausgeführt. Da für unsere Policy nur der Request Stage interessant ist geben wir für alle anderen Fälle ein SUCCEEDED zurück und beenden an dieser Stelle die Bearbeitung.

In Abschnitt B holen wir uns zuerst die Remote IP Addresse aus dem SOAPBindingMessageContext. Hinweis: Es könnte auch sein, dass hier kein SOAPBindingMessageContext vorliegt, falls der Aufruf nicht über ein SOAP Binding erfolgt, sondern z.B. über ein Direct Binding. Dieser Fall wird hier vernachlässigt.

Dann legen wir – vorerst hardcodiert – ein Array mit gültigen IP-Adressen ein. Trifft der Vergleich einer IP-Adresse dieser Liste mit der Remote-Adresse zu, so wird die Variable clientIpValid auf true gesetzt.

In Abschnitt C wird ein entsprechendes Result gesetzt auf Basis von clientIpValid. Interessant ist hier vor allem der Fehlerfall. Hier sollte man eine brauchbare Fehlerbeschreibung eintragen, da diese bei Fehlschlag an den Aufrufer zurückgesandt wird. Hinweis: Es gibt keinen Flow Trace und keine Composite Instance, falls eine der eingehenden Policies fehlschlägt – dadurch wird diese Fehlermeldung doppelt wichtig, wenn man nicht lange Zeit Logs durchwühlen möchte.

Die Assertion kann nun deployed werden und wird nur noch Requests von 127.0.0.1 durchlassen.

5. Parameter übergeben

Natürlich wollen wir die IP-Adressen nicht hardcodieren, vor allem, weil man dann für jede Änderung der IP-Adressen die komplette SOA Suite neustarten müsste – außerdem kann man die Assertion dann nicht wiederverwenden.

Wir haben den Parameter in den Metadaten oben bereits definiert. Nun brauchen wir also noch eine Möglichkeit, diesen in der Assertion auszulesen. Dazu verwenden wir folgendes Code-Schnipsel:

    private Properties configProps = new Properties(); 

    private void retrieveConfiguration() {
        IAssertionBindings bindings = ((SimpleAssertion)(mAssertion)).getBindings();
        if (bindings != null) {
            List<IConfig> cfgl = bindings.getConfigs();
            if (!cfgl.isEmpty()) {
                IConfig cfg = cfgl.get(0);
                List<IProperty> configProperties = cfg.getProperties();
                if (configProperties != null) {
                    for (IProperty configProperty : configProperties) {
                        String propName = configProperty.getName();
                        String propValue = configProperty.getValue();
                        if (propValue == null || propValue.trim().isEmpty())
                            propValue = configProperty.getDefaultValue();
                        if (propValue != null)
                            configProps.setProperty(propName, propValue);
                    }
                }
            }
        }
    } 

 

    public void init(IAssertion iAssertion, IExecutionContext iExecutionContext, IContext iContext) {
        mAssertion = iAssertion;
        mEcontext = iExecutionContext;
        mIcontext = iContext;
        retrieveConfiguration(); // Dieser Aufruf wurde hinzugefügt
    }

Diese Methode sollte am Besten aus der init()-Methode aufgerufen werden, da OWSM die init()-Methode immer aufrufen wird, wenn eine Änderung der Konfiguration erfolgt und sich somit die Policyversion erhöht.

Nun stehen alle Properties in dem privaten Property-Objekt configProps und können von dort verwendet werden. Da wir davon ausgehen, dass hier eine “,”-separierte Liste mit IP-Adressen drin steht, ersetzen wir unsere zuvor hardcodierte Liste durch folgendes:

     String[] allowedIpAddresses = 
                 ScenarioUtils.getConfigPropertyValue(
                     "allowedIpAddresses", 
                     soapbindingmessagecontext, 
                     configProps, 
                     null)
                 .split(",");

Und schon wird die konfigurierte Liste an erlaubten Adressen für die Prüfung herangezogen.

6. Deployment

Das Deployment erfolgt mit den folgenden Schritten:

  • JAR mit der Assertion in DOMAIN_HOME/lib kopieren
  • SOA Suite neustarten
  • Im EM unter Weblogic-Domain -> Web Services -> Policies -> Assertion Templates die Assertion importieren (ClientIpAssertion.xml)
  • Im EM unter Weblogic-Domain -> Web Services -> Policies eine neue Policy erstellen
  • In die Policy die Assertion “custom/ClientIp” einfügen und unten unter “Assertion-Inhalt” die Liste mit IP-Addressen vom Standard-Wert aus abändern

Nun kann die Policy analog anderer Sicherheitspolicies an Service-Endpunkte angehängt werden, die dann nur noch von bestimmten IP-Adressen aus aufgerufen werden können.

Zusammenfassung

Die Entwicklung eigener Policies ist immer dann hilfreich, wenn man in der SOA Suite eine bestimmte Anforderung in Bezug auf Security umsetzen möchte, die nicht Out-Of-The-Box geboten ist. Auf diese Weise haben wir beispielsweise auch eine Weitergabe der Authentifizierung im Payload realisiert, so dass unsere BPEL-(Geschäfts-)Prozesse frei von Authentifizierungsdetails bleiben.

Das komplette Projekt mit der oben erstellen Policy gibt es hier zum Download:
ClientIPAssertion.zip

Kategorien:JDeveloper, Oracle SOA Suite Schlagworte: , ,

HTTP Binding für namespacelose Elemente

In einem Kundenprojekt sollte ein System an die SAO Suite (11.1.1.5)
angeschlossen werden, das seine Nachrichten zwar als XML-Strukturen
per HTTP-POST verschickt, jedoch keinen Namespace für diese angibt.

Die Möglichkeit die einem hierzu wahrscheinlich als Erstes in den Kopf
kommt, das HTTP Binding, scheitert aber schon im Wizard mit folgender Meldung:

Fehlermeldung des HTTP Bindings bei namenlosen Schemata

Als Alternative den Socket Adapter zu verwenden oder ein Servlet vor das zu
erstellende Composite zu schalten klingt nur nach einer sehr mäßigen Lösung.

Durch gutes Zureden lässt sich das HTTP Binding dann aber doch zur Verarbeitung
von namenlosen XML-Elementen überreden.

Nachfolgend werden die hierzu nötigen Schritte beschrieben. Als Ausgangsbasis
dient dabei das unten aufgeführte Schema. Zu beachten ist, dass kein
Target Namespace oder Default Namespace angegeben ist.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="myElement" type="xsd:string"/>
</xsd:schema>

1. Target Namespace temporär hinzufügen
Um den Wizard zufriedenzustellen muss zunächst temporär das
targetNamespace-Attribut in die Schemadefinition eingefügt werden. Der
eingetragene Namespace ist hierbei nicht weiter wichtig.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://something.com">
  <xsd:element name="myElement" type="xsd:string"/>
</xsd:schema>

2. HTTP Binding Endpunkt erstellen
Jetzt kann im Wizard das Element zur Erzeugung des HTTP Binding
Endpunkts ohne Fehlermeldung ausgewählt werden.

3. Temporären Namespace wieder entfernen
Der eben hinzugefügte Namespace kann nun wieder entfernt werden.

4. WSDL des HTTP Binding Endpunkts anpassen
Da sich der Namespace des Schemas geändert hat, ist die generierte
WSDL des HTTP Binding Endpunkts ungültig geworden. In dieser muss
das Import-Element, wegen des fehlenden Namespaces, in ein
Include-Element geändert und das Namespaceprefix vor dem Message-Type
entfernt werden.

...
    <wsdl:types>
        <schema xmlns="http://www.w3.org/2001/XMLSchema">
            <include schemaLocation="schema.xsd"/>
        </schema>
    </wsdl:types>
    <wsdl:message name="myElement_msg_in">
        <wsdl:part name="myElement" element="myElement"/>
    </wsdl:message>
...

5. Deployment und Test
Der HTTP Binding Endpunkt sollte nun mit Nachrichten ohne Namespace
aufrufbar sein. Die Testkonsole im EM quittiert an dieser Stelle ihren
Dienst zwar mit einer SoapTestException, normale HTTP-POST
Nachrichten, etwa per curl, werden jedoch korrekt verarbeitet.

Nachfolgend noch zwei Screenshots aus dem EM.

Ablauf im EM

Die Nachricht ist im EM erkennbar:
Nachricht im EM

6. Viel Spaß damit haben

Server offline and soa-infra down: How-to undeploy SOA composites

Did you already have the problem that you couldn’t restart your server because of a certain (maybe broken) composite? Did you ever wish to perform an undeployment of your composites while soa-infra is down? Read my blogpost under inside-bpm-and-soa to see how-to get rid of thos composites even when the soa-infra is not available.


Follow

Bekomme jeden neuen Artikel in deinen Posteingang.