č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).

pátek 15. května 2015

Postup instalace Enterprise Architect ve wine s připojením k projektu v databázi

Následující postup byl odzkoušen na Enterprise Architect verze 10.0.1009 v distribuci lubuntu 14.04 a 14.10 s wine verze 1.6.2

1) Pokud existuje, smazat adresář ~/.wine
2) export NO_AT_BRIDGE=1
3) WINEARCH=win32 winecfg
4) winetricks msxml3 # install MSXML3 support.
5) winetricks msxml4 # install MSXML4 support.
6) winetricks mdac28 # install data access components
7) winecfg
- Knihovny - najít "oledb32" v "Nové nastavení pro knihovnu" - tlačítko "Přidat" - vybrat ji v "Existující nastavení knihoven" - tlačítko "Upravit" - zakliknout "Nativní (Windows)" - tlačítko "OK" - tlačítko "OK"
8) wine  easetupfull1009.exe
9) wine msiexec /i mysql-connector-odbc-5.3.4-win32.msi
10) wine control
poklikat na "Data Sources" - karta "User DSN" - "Add" - "MySQL ODBC 5.3 Unicode Driver" - "Dokončit"
Data Source Name: ea_repository
TCP/IP Server: IP adresa databáze (někdy tam nejde psát, tak si to napsat do jiného políčka, zkopírovat do schránky Ctrl+X a vložit Ctrl+V)
Port: port databáze (MySQL defaultně 3306)
User: user_databáze
Password: heslo_usera_databáze
Database: jmeno_databáze
tlačítko "Test" a pak "OK", zase "OK" - "Soubor" - "Konec"
11) wine EA.exe (nebo uvést celou cestu k nainstalovanému EA.exe)
12) "Open Project" - "Connect to Server" - "Connection Wizard" - "Microsoft OLE DB Provider for ODBC Drivers" - "Next >>" - User data source name: ea_repository (z kroku 10) - "Test Connection" - "OK" - "Open"

Řešení možných problémů:
1) Pokud je EA příliš pomalý mohlo by pomoci nastavení "Tools" - "Options" - "Diagram" - "Appereance" - Renderer: Basic
2) V některých případech nastala chyba projevující se tímto výpisem:
 err:msidb:get_tablecolumns column 1 out of range  
 err:msidb:get_tablecolumns column 2 out of range  
 fixme:storage:create_storagefile Storage share mode not implemented.  
 err:msidb:get_tablecolumns column 1 out of range  
 err:msidb:get_tablecolumns column 2 out of range  
 err:msidb:get_tablecolumns column 1 out of range  
 err:msidb:get_tablecolumns column 2 out of range  
 err:msidb:get_tablecolumns column 1 out of range  
 err:msidb:get_tablecolumns column 2 out of range  
 err:msidb:get_tablecolumns column 3 out of range  
 err:msidb:get_tablecolumns column 1 out of range  
 err:msidb:get_tablecolumns column 2 out of range  
 err:msidb:get_tablecolumns column 3 out of range  
 err:msidb:get_tablecolumns column 1 out of range  
 err:msidb:get_tablecolumns column 2 out of range  
 err:msidb:get_tablecolumns column 3 out of range  
 err:msidb:get_tablecolumns column 1 out of range  
 err:msidb:get_tablecolumns column 2 out of range  
 err:msidb:get_tablecolumns column 3 out of range  
Problém vyřešila instalace novější (development) verze wine 1.7. Postup je zde.

středa 29. října 2014

SSH tunel skrz http(s) proxy

Popis situace:
PC - pracovní stanice
HTTP Proxy - Proxy server umožňující připojení do internetu. Umožňuje pouze připojování na vzdálené porty 80 a 443 pouze prostřednictvím protokolu HTTP na vybrané webové stránky.
ssh server- počítač umístění v internetu s veřejnou IP adresou na němž je nainstalovaný SSH server.

Cílem je umožnit pracovní stanici připojit se do internetu i způsobem, který proxy neumožňuje (na proxy nepovolené protokoly, webové stránky,...).

Nutné podmínky docílení kýženého stavu:
  • pravidla proxy musí umožňovat přístup na IP adresu či DNS ssh serveru (zde prodejna.biz).
  • ssh server na počítači prodejna.biz musí být možné nainstalovat na portu, který je povolen na HTTP proxy (v tomto případě 80 nebo 443).
K připojení k ssh serveru přes HTTP proxy budeme potřebovat nainstalovat aplikaci corkscrew. Předpokládejme následující:
  • na ssh serveru máme vytvořen účet sshaccount.
  • HTTP proxy běží na httpproxy.cz a portu 8080
  • K HTTP proxy je třeba autentizace, která je uložená v souboru auth
  • SSH server je dostupný na portu 443
  • Na pracovní stanici neběží nic na portu 8080
Obsahem souboru auth je pouze login a heslo oddělené dvojtečkou.
Následující příkaz spustí na lokálním počítači server SOCKS5 na portu 8080 (parametr -D):
ssh -ND 8080 sshaccount@prodejna.biz -o "ProxyCommand corkscrew httpproxy.cz 8080 prodejna.biz 443 auth"

V prohlížeči je pak třeba nastavit proxy takto:

Od této chvíle budou všechny požadavky směrovány SSH tunelem skrz HTTP Proxy na prodejna.biz.
Aby nebylo nutné psát takto dlouhý příkaz můžeme do souboru ~/.ssh/config umístit následující dva řádky:
Host prodejna.biz
ProxyCommand corkscrew httpproxy.cz 8080 prodejna.biz 443 ~/auth

a následně použít zjednodušený příkaz:
ssh -ND 8080 sshaccount@prodejna.biz

Nebo si jednoduše namapovat vzdálený disk k lokálnímu adresáři:
sshfs sshaccount@prodejna.biz: ~/remote
kde adresář ~/remote musí před voláním příkazu již existovat.

pondělí 3. března 2014

Ovlivnění generovaného WADL

Při buildování REST aplikací, s využitím implementace Jersey, se automaticky generuje i WADL. Tento je možné částečně doplňovat. Nyní ukáži postup přidávání dokumentačních elementů do generovaného WADL.

1) Vytvořím soubor application-doc.xml, tento soubor obsahuje stručný popis aplikace. Příklad:

 <applicationDocs targetNamespace="http://wadl.dev.java.net/2009/02">  
     <doc title="Post Code" xml:lang="en">Title and high level description</doc>  
 </applicationDocs>

2) Vytvořím soubor application-grammars.xml obsahující umístění vlastních XML schemat. Příklad:
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>  
 <grammars xmlns="http://wadl.dev.java.net/2009/02"   xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xi="http://www.w3.org/1999/XML/xinclude">  
   <include href="../xsd/schema.xsd" />  
 </grammars>  

3) Vytvořím potomka třídy WadlGeneratorConfig, v kterém budou uvedeny oba XML soubory vytvořené v předchozích krocích. Navíc je přidán soubor resourcedoc.xml, který bude vygenerován.

 package biz.prodejna.rest  
 import com.sun.jersey.api.wadl.config.WadlGeneratorConfig;  
 import com.sun.jersey.api.wadl.config.WadlGeneratorDescription;  
 import com.sun.jersey.server.wadl.generators.WadlGeneratorApplicationDoc;  
 import com.sun.jersey.server.wadl.generators.WadlGeneratorGrammarsSupport;  
 import com.sun.jersey.server.wadl.generators.resourcedoc.WadlGeneratorResourceDocSupport;  
 import java.util.List;  
 public class MyWadlGeneratorConfig extends WadlGeneratorConfig {  
   @Override  
   public List<WadlGeneratorDescription> configure() {  
     return generator( WadlGeneratorApplicationDoc.class )  
      .prop( "applicationDocsStream", "application-doc.xml" )  
      .generator( WadlGeneratorGrammarsSupport.class )  
      .prop( "grammarsStream", "application-grammars.xml" )  
      .generator( WadlGeneratorResourceDocSupport.class )  
      .prop( "resourceDocStream", "resourcedoc.xml" )  
      .descriptions();  
   }  
 }  

4) Třídu vytvořenou v předchozím kroku uvedu jako inicializační parametr JerseyServletu ve web.xml

 <servlet>  
     <servlet-name>JerseyServlet</servlet-name>  
     <servlet-class>  
       com.sun.jersey.spi.container.servlet.ServletContainer  
     </servlet-class>  
     <init-param>  
       <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>  
       <param-value>true</param-value>  
     </init-param>  
     <init-param>  
       <param-name>com.sun.jersey.config.property.WadlGeneratorConfig</param-name>  
       <param-value>biz.prodejna.rest.MyWadlGeneratorConfig</param-value>  
     </init-param>  
     <load-on-startup>1</load-on-startup>  
 </servlet>  

5) Aby byl vygenerován soubor resourcedoc.xml je třeba do pom.xml přidat maven javadoc plugin s docletem com.sun.jersey.wadl.resourcedoc.ResourceDoclet.

 <plugin>  
    <groupId>org.apache.maven.plugins</groupId>  
    <artifactId>maven-javadoc-plugin</artifactId>  
    <version>2.9.1</version>  
    <executions>  
        <execution>  
            <goals>  
                <goal>javadoc</goal>  
            </goals>  
            <phase>compile</phase>  
        </execution>  
    </executions>  
    <configuration>  
        <encoding>UTF-8</encoding>  
        <verbose>false</verbose>  
        <show>public</show>  
        <subpackages>biz.prodejna.rest</subpackages>  
        <doclet>com.sun.jersey.wadl.resourcedoc.ResourceDoclet</doclet>  
        <docletPath>${path.separator}${project.build.outputDirectory}</docletPath>  
        <docletArtifacts>  
            <docletArtifact>  
            <groupId>com.sun.jersey.contribs</groupId>  
            <artifactId>wadl-resourcedoc-doclet</artifactId>  
            <version>${jersey-release-version}</version>  
        </docletArtifact>  
        <docletArtifact>  
            <groupId>com.sun.jersey</groupId>  
            <artifactId>jersey-server</artifactId>  
            <version>${jersey-release-version}</version>  
        </docletArtifact>  
        <docletArtifact>  
            <groupId>xerces</groupId>  
            <artifactId>xercesImpl</artifactId>  
            <version>2.6.1</version>  
        </docletArtifact>  
        </docletArtifacts>  
        <!-- the following option is required as a work around for  
        version 2.5 of the javadoc plugin which will be used  
        by a maven version > 2.0.9 -->  
        <useStandardDocletOptions>false</useStandardDocletOptions>  
        <additionalparam>-output ${project.build.outputDirectory}/resourcedoc.xml</additionalparam>  
     </configuration>  
 </plugin>  

6) Aby se generovaly doc elementy i k jednotlivým parametrům je do pom.xml třeba přidat závislost

 <dependency>  
   <groupId>javax.ws.rs</groupId>  
   <artifactId>javax.ws.rs-api</artifactId>  
   <version>2.0</version>  
 </dependency>  

Nyní by celé řešení mělo být funkční. Pokud přijdete na to jak v elementech parametrů generovat atribut required můžete mi o tom dát vědět do diskuze níže. Nebo máte jiný způsob jak co nepřesněji definovat REST API? I o tom se rád dočtu.

úterý 4. února 2014

IptabLes a IptabLex

Možná se Vám v procesech objevili dva (třeba i v několika kopiích), které nadměrně zatěžují procesor a jmenují se jak je uvedeno v nadpisu. Možná máte i velký upload (TCP Retransmission) na převážně Čínské IP adresy. Pravděpodobně také máte spuštěný nějaký servletový kontejner.
Problém může nastat pokud na svém počítači hostujete aplikaci využívající Struts 2 verze 2.3.15 nebo starší.
Následující kroky se mi osvědčili při odstranění uvedeného malware:
  1.  Undeploy aplikací využívající uvedenou verzi Struts 2.
  2.  v /boot odstranit všechny soubory .IptabLe* a IpabLe*
  3. v /etc/rc* odstrnit všechny soubory S55IptabLe*
  4. Zkontrolujte jestli nemáte nevítaného hosta: cat /etc/passwd|grep '/bin/bash'
  5. Rebuild a deploy aplikací s nejnovější verzí Struts 2
A takovéto requesty (u mě z adresy 60.190.218.252) onen problém způsobují:

POST /videos.action HTTP/1.1
User-Agent: Mozilla/5.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue
Connection: Keep-Alive
redirect:${%23res%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23res.setCharacterEncoding(%22UTF-8%22),%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{%22killall%22%2C%22%2Fboot%2F.IptabLes%22})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23e%3dnew%20char[20000],%23d.read(%23e),%23res.getWriter().println(%23e),%23res.getWriter().flush(),%23res.getWriter().close()}