úterý 2. června 2020

Několik tipů k WSO2 BPS

Vzhledem k tomu, že dokumentace k WSO2 BPS není dokonalá a někdy je třeba pátrat delší čas, rozhodl jsem se pár postřehů z práce s tímto produktem zapsat sem.
Více o BPMN na wikipedii.

BPS má REST API pomocí kterého lze řídit (spouštět, získávat info,...) procesy. Podrobněji v Activiti dokumentaci
Jak lze koordinovat human tasky je zdokumentováno.

TimerStartEvent - spouštění procesu v požadovaný čas nebo opakovaně

  • V tomto prvku je možné definovat 3 property. Je třeba vždy definovat právě jednu, ostatní jsou totiž ignorovány. 
  • Výrazy musí být dle ISO 8601, to lze zvalidovat.
  • Pokud se ve výrazu definuje časové pásmo (např. +02:00) nefunguje dle očekávání
  • Tipy jak definovat výrazy: https://github.com/cylc/cylc-flow/wiki/ISO-8601 (příklad spuštění každý den v 9 hodin: R/T09:00/P1D
MessageStartEvent
REST Task - spouštění REST requestů
  • Pokud chci POSTem poslat prázdné body, je třeba v body uvést alespoň {} jinak volání skončí výjimkou
  • je třeba definovat buď Output Variable name nebo Output Variable Mappings, ne oboje.
(Exclusive) Gateway

čtvrtek 23. dubna 2020

Transport error: 401 Error: Unauthorized ve WSO2

Při použití Basic auth a patřičném nastavení property Authorization může přesto nastat výjimka
 org.apache.axis2.AxisFault: Transport error: 401 Error: Unauthorized  
      at org.apache.axis2.transport.http.HTTPSender.handleResponse(HTTPSender.java:371)  
      at org.apache.axis2.transport.http.HTTPSender.sendViaGet(HTTPSender.java:109)  

To může být způsobeno firewallem, za kterým WSO2 produkt je a který vyžaduje onu autorizaci. Řešením může být nastavení property Proxy-Authorization. Více v dokumentaci.

středa 22. dubna 2020

Peer not authenticated + SSL peer failed hostname validation for name: null

Při volání serveru přes https, v tomto případě volání endpointu z WSO2, nastala chyba:
 HTTPSender Unable to sendViaGet to url[https://myserver/context]  
 javax.net.ssl.SSLPeerUnverifiedException: SSL peer failed hostname validation for name: null  
      at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.verifyHostname(TLSProtocolSocketFactory.java:233)  
      at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:186)  

Zkusil jsem spustit znovu s parametrem
 -Djdk.internal.httpclient.disableHostnameVerification=true  

a následovala výjimka:
 HTTPSender Unable to sendViaGet to url[https://myserver/context]  
 javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated  
      at sun.security.ssl.SSLSessionImpl.getPeerCertificates(Unknown Source)  
      at org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory.verifyHostName(SSLProtocolSocketFactory.java:276)  

Pokud byl request proveden pomocí curl, tak fungoval
 curl -X GET --cacert /C/certs/root_cert.cer 'https://myserver/context ' -H 'Authorization: Basic QVBJOk1vbmV0YTIwMjA=' -v  

Zkusil jsem openssl
 OpenSSL> s_client -connect myserver:443  
 Loading 'screen' into random state - done  
 CONNECTED(000008C0)  
 write:errno=10054  
 ---  
 no peer certificate available  
 ---  
 No client certificate CA names sent  
 ---  
 SSL handshake has read 0 bytes and written 317 bytes  
 ---  
 New, (NONE), Cipher is (NONE)  
 Secure Renegotiation IS NOT supported  
 Compression: NONE  
 Expansion: NONE  
 No ALPN negotiated  
 ---  
 error in s_client  
Zde je vidět, že server nevrátil certifikát.

Zkusil jsem znovu s parametrem -servername
 openssl s_client -connect myserver:443 -servername myserver  

Také je vhodné ověřit, že server podporuje TLSv1.2:
 openssl s_client -connect myserver:443 -tls1_2 -servername myserver  

V obou případech bylo vidět, že server certifikát vrací. Parametr -servername nastavuje TLS SNI (Server Name Indication) extension v ClientHello message během handshake, jak je popsáno v dokumentaci.
Při následném prohlédnutí ClientHello zprávy pomocí wiresharku bylo patrné, že neobsahuje server_name extension (více o tématu zde). Tato je pro některé servery nutná (i když dle RFC6066 nepovinná) - jeden webový server může sloužit více doménám a jaký certifikát použít se rozhoduje právě na základě obsahu server_name.
V javě lze vypnout nebo povolit (defaultní stav) SNI pomocí parametru
 -Djsse.enableSNIExtension=true  

Naštěstí jsem narazil na informaci, že Java nastavuje extension server_name pouze pro FQDN, což myserver není (podobně jako např. localhost).
Pokud tedy chceme z javy volat server, který v handshake protokolu Client Hello vyžaduje extension server_name, je třeba aby tento měl FQDN a samozřejmě odpovídající certifikát, který máme umístěn i v našem truststore.

pátek 10. ledna 2020

WSO2: Paralelní zpracování v multitenantním prostředí

Pokud chceme na WSO2 provádět paralelní zpracování, lze k tomu, v závislosti na naší potřebě, využít jednoho z dvou mediátorů: clone a iterate. Oba mediátory obsahují element target, který má v obou případech shodnou implementaci třídou org.apache.synapse.mediators.eip.Target. Z tohoto důvodu také oba mediátory umožňují použít shodné elementy sequential (pomiňme nyní, že v dokumentaci mediatoru clone není uveden) a continueParent.
Atribut sequential uvádí, zda mají být jednotlivé targety zpracovávány sekvenčně. Pokud však použijete sequential="false" (defaultní hodnota) jsou mediatory v targetu spouštěny nečekaně pod carbon.super tenantem. To může způsobit nemožnost volání endpointů, protože k nim carbon.super tenant nemusí být subscribnutý (subscribnout carbon.super v multitenantním prostředí není dobrý nápad) nebo nevlastní patřičný autentizační token.
Atribut continueParent určuje, zda má být zachován původní payload. Další, pro nás klíčovou, vlastností použití tohoto atributu je i zpracování mediatoru bez čekání na jeho výsledek. Více uvedeno v Example 2.

Předpokládejme, že jsme chtěli paralelně volat dvě sekvence (obsahujících např. volání endpointů):

<clone sequential="false">
    <target>
        <sequence key="firstSequence"/>
    </target>
    <target>
        <sequence key="secondSequence"/>
    </target>
</clone>

Z důvodu uvedeného výše to však v multitenantním prostředí není možné. Požadovanou funkci ale bude mít následující řešení:

<clone sequential="true" continueParent="true">
    <target>
        <sequence key="firstSequence"/>
    </target>
</clone>
<sequence key="secondSequence"/>

Pokud budeme chtít takto paralelně volat více sekvencí, je tedy třeba každou umístit do vlastního clone.
Pokud má být sekvence v clone volána způsobem fire-and-forget, pak je třeba na konec clone umístit mediator
<drop/> - jinak by následující flow bylo voláno vícenásobně (z každého clone znovu).