pondělí 4. března 2013

Něco málo o SSL (HTTPS)

Jen malá poznámka ohledně dnešní zdlouhavé a otravné a frustrující zkušenosti s HTTPS, SoapUI a AS WebLogic. Prostě se dá říct, že nastávaly dvě možnosti:
  • handshake failed
  • HTTP 403, Permission Denied.

HTTPS a WS-Security

S čím jsem ale dosud neměl zkušenost, je WS-Security; ještě dopoledne jsem si myslel, že šifrování SOAP komunikace je prostě dílo HTTPS. Během dne jsem pomalu začínal chápat, že jsem vedle jak ta jedle.
Zatímco HTTPS (HTTP over TLS/SSL) šifruje veškerou komunikaci, WS-Security používá obyčejné HTTP (nebo i HTTPS) a šifruje se jen payload (tj. data v SOAP) - pro představu, uvidíte něco takového (namespaces jsem umazal a trochu to naformátoval):

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
  <S:Header>
    <wsse:Security>
      <xenc:ReferenceList>
        <xenc:DataReference URI="#ED-1"/>
      </xenc:ReferenceList>
    </wsse:Security>
  </S:Header>
  <S:Body>

    <xenc:EncryptedData Id="ED-1" Type="http://www.w3.org/2001/04/xmlenc#Content">
      <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
      <ds:KeyInfo>
        <wsse:SecurityTokenReference wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey">
          <wsse:Reference URI="#null"/>
        </wsse:SecurityTokenReference>
      </ds:KeyInfo>
      <xenc:CipherData>
        <xenc:CipherValue>[zašifrovaná data v Base64]</xenc:CipherValue>
      </xenc:CipherData>
    </xenc:EncryptedData>
  </S:Body>
</S:Envelope>

SoapUI

Návodem se zdržovat nebudu, najdete jich na internetu hromadu.
Nastavení SoapUI ani jeho dokumentace navíc vůbec nepočítá s lidskou naivitou, a tak velká část blogů a fór radí neúplné nesmysly na podobně neúplné otázky. Člověk pak ze zoufalství všude nastavuje keystore, všude nastavuje klíče, certifikáty, prostě klasický shotgun debugging, který ale k cíli nevede.
SoapUI mi tedy rozhodně s řešením nepomohlo, neb navíc vytrvale odmítalo vzít na vědomí nastavení -Djavax.net.debug=all a v logu nebylo stále nic než jen tříslovné chybové hlášení.
Jen aby bylo jasno - k nastavení HTTPS stačí jen otevřít globální nastavení SoapUI, tj. File - Preferences - SSL Settings, nastavit keystore a jeho heslo - hotovo. Nezapomeňte nastavení uložit, což má SoapUI taky celkem nepřirozeně jako další položku menu.
Všechna ostatní nastavení v projektu (Outgoing/Incoming keystore, Encryption, atd.) se týkají WS-Security a pokud vám jde jen o HTTPS, můžete je ignorovat.

OpenSSL

Po šesti hodinách střílení z brokovnice jste rádi, že jste se nezastřelili sami. Přišel čas zapnout mozek. Dobrá, zkusíme to přes OpenSSL, blbé SoapUI!
Vyexportujete si klíče i všechny certifikáty z JKS do PEM souborů. Spustíte OpenSSL a postupně mu nasázíte všechny argumenty - klíč, klientský certifikát, důvěryhodné certifikáty. Vypnete ověření hostname i serverového certifikátu, pro všechny případy. A - ono to funguje! Blbé SoapUI!!! No počkat, ale něco tu nehraje ...

Meanwhile ...

Moje panika nakazila i místní. Někteří také stříleli z brokovnic, někteří ale zavětřili, že tu opravdu něco nehraje. Všechno jsem dělal dobře (jeden znal i SoapUI, byť také úplně nerozuměl kouzlům WS-Security, ale věděl, že to mám všechno vyházet. Nepomohlo to, ale budiž.
Mezitím mi ale server začal odpovídat jinak, namísto věčného HTTP 403 - tentokrát na žádné HTTP nedošlo a přišlo rovnou "Handshake failed: Bad certificate."
Asi hodinu mi trvalo, než mi došlo, že server mluví o mém certifikátu, který mi místní autorita s pomocí Windows bezmyšlenkovitě podepsala a já si bláhově myslel, že když to funguje přes OpenSSL, musí být problém v nastavení SoapUI.

Pointa

Když moje největší posila (toho člověka jsem začal mít rád, neb mě citelně táhl správným směrem) už asi počtvrté přišla - a kdesi mezi jejími větami jsem zachytil slovo "Extension" ... svitlo mi. Jen jsem nevěděl, jak se vlastně Extensions k certifikátům přidávají ... to už teď taky vím: dokumentace keytool

Kdybyste náhodou zařizovali klíč a klientský certifikát pro SSL (HTTPS) a divili se, proč to pořád končí handshake failed, zatímco přes OpenSSL, kterému dáte privátní klíč (PEM), klientský certifikát (PEM) a ca-certs (další PEM), to chodí ... Váš klientský certifikát postrádá Extensions, čili schválená použití certifikátu, který pak tím pádem není možno použít pro šifrování ani autentizaci.
Extensions k certifikátu generujete s žádostí o podpis, příp. je tam může přihodit i podepisující, soudě podle dokumentace. Např. šifrování, dešifrování, podpis ... Každá Extension má své vlastní OID, ostatně viz parametr -ext v dokumentaci keytool a např. MSDN: Certificate Extensions

Závěrem budiž konstatováno, že SoapUI blbé není.

Zamyšlení

Shodou okolností řeším problém s HTTPS - stařičký CISCO loadbalancer mu totiž nerozumí, tudíž nemůže balancovat. Jen mě tak napadlo, že s použitím WS-Security se nějaké HTTPS vůbec nemusí řešit.
Jenže - u HTTPS je komplikací i samotné sledování komunikace, tj. řekl bych, že je co se týče bezpečnosti o řád jinde.
Na druhou stranu, každá proxy potřebuje požadavek rozšifrovat, než ho pošle dál. To by u HTTP a WS-Security nemusela.
A zase ... když bude proxy s loadbalancerem v cestě jediná, resp. do cesty se strčí Apache, který komunikaci na vstupu do uzavřené části zbaví šifrování,  nač řešit WS-Security. Tu bych řešil v případě nějaké ohromné infrastruktury, do které přistupuje kde kdo ...

Nebo se pletu?