Mule, Glassfish, Netbeans ja Webservices

Perjantaina käytin koko työpäivän ja illan webserviceiden kanssa näpräilyyn töissä tehtävää integraatioarkkitehtuuri-pilottia varten. Tutkin ja kokeilin miltä näyttää ja tuntuu tehdä palveluita Sunin työkaluilla Metro-webservice stackiin Glassfishissa ja toisaalta palveluita Muleen joko Apache Axisin tai CXF:n avulla.

Raaviskelin päätäni Mulen kanssa jonkun verran, kun uuden version ( 2.X ) dokumentaatio on puutteellista, ja wikistä löytyy yleensä vain version 1.X esimerkit. Mulen mukana tulevat esimerkkisovellukset toki auttavat liikkeelle, mutta sen jälkeen vaaditaankin omaa selvitystyötä – että pääsee selville miten asiat toimivat.

Omalla kohdallani Mulen testicaset osoittautuivat hyväksi lähteeksi neuvoille ( TDD for the win! ), vaikka aluksi yritinkin postituslistojen kautta päästä perille best practiceista. Käytännössä vastauksien löytäminen on postauksien joukosta vaikeaa ja yhden developerin vihjeen mukaan päädyinkin tutkimaan test caseja, ja opiskelemaan asioita niiden kautta.

Testcasejen pohjalta oli helppoa saada esimerkiksi Acegi-security toimimaan, mutta ennen kuin sinne asti pääsi – oli takana monia väärinymmärryksiä ja kokeiluja wikin vanhan dokumentaation kautta. Lievää tylsyyttä kuitenkin aiheutti huomata, että kun sain Acegin toimimaan – ei sillä pystynytkään authentikoimaan ja auktorisoimaan käyttäjiä CXF:n kanssa, vaan ainoastaan Axis-webservicestackin kanssa.

Löysin vielä toivoa antaneita vinkkejä parista blogipostauksesta, mutta tiet olivat lopulta umpikujia. Lopputuloksena oli siis menetettyjä tunteja ja vuodatettua hikeä, jonka jälkeen oli pakko nostaa kädet pystyyn ja sanoa että Mule 2:n kanssa on sittenkin parempi käyttää Axista ja suojata se Acegi-http filtterillä, jos haluaa http basic suojauksella webservicejä tehdä. Jos taas ottaa käyttöön WS-Securityn, niin siihen löytyy ratkaisut CXF:n puolelta. Tosin niidenkin käyttöönotossa hieman virittelyä, mutta malli löytyy sentään testicaseista.

Webservice securityä testasin kuitenkin Netbeansin ja Glassfishin puolella suhteettoman onnistuneesti. Itseasiassa käyttökokemus oli niin hyvä, että aloin miettimään kokonaan arkkitehtuurisesti ratkaisujen tekemistä niin – että palvelut joiden kanssa vaaditaan WS-Securityä ( esim. toimiminen ulkopuolisten kanssa ) rakennettaisiin Glassfishin Metro stackin päälle ja clientit Netbeansilla.

Pohjaksi testeihin otin Netbeans tutorialin: http://www.netbeans.org/kb/60/websvc/wsit.html

Kyseinen demo-koodi tulee suoraan Netbeansin mukana, joten sen pohjalta oli helppo testata teknologiaa käytännössä. Ensimmäinen kompastuskivi kuitenkin tuli eteen siinä, että aikaisemmin asentamani Glassfish oli vanhempaa versiota (glassfish-installer-v2ur1) ja jostain syystä en saanut laitettua sen keystoreen oikeita sertifikaatteja vaikka yritin. Päivittämällä Glassfish update 2:een kaikki kuitenkin toimi ilman ongelmia.

Mielenkiintoista vääntöä ja kamppailua oli kuitenkin siinä kuinka saada omia sertifikaatteja luotua ja otettua käyttöön WS-securityä varten. Normaalisti kun perus-SSl sertifikaatin tekemiseen riittää suoraan javan oman keytoolin käyttö, on WS-Securityssä /WSIT:ssä tarpeen käyttää v3 sertifikaattia jossa on SubjectIdentity-kenttä mukana.

Sitä varten taas joutui kaivamaan esiin openssl:n ja kikkailemaan sertifikaattien kanssa, ennen kuin ne sai lisättyä Javan keystoreen. Hyvää harjoittelua silti, vaikka aikaa meni hemmetisti ja päätä tuli hakattua seinään useita kertoja.

OpenSSL:n kohdalla kannattaa olla tarkkana myös oman konfiguraationsa kanssa, ettei siitä tule yllätyksiä. OS X:llä konfiguraatio on /System/Library/OpenSSL -pathissa. Openssl-komennolla saa toki käytettävän konffin selville seuraavasti: openssl version -d


Luodaan aluksi oma juuriCA:

openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 365

Tarkistettu subject key identifier: openssl x509 -in cacert.crt -noout -text

Luodaan uusi request palvelimelle:
openssl req -new -nodes -out server-req.pem -keyout server-key.pem

Signataan se:
openssl ca -out server-cert.pem -infiles server-req.pem

Tarkistetaan että kyseessä on v3 sertifikaatti ja SubjectIdentity paikoillaan:
openssl x509 -in server-cert.pem -noout -text

Muokataan sertifikaatti pkcs12-muotoon, jotta sen voi WebServiceDeveloperPackin mukana tulevalla apuohjelmalla importoida keystoreen:
openssl pkcs12 -export -in server-cert.pem -inkey server-key.pem -out server.pfx

Tehdään import:
cd /Users/huima/programming/tools/wsdp/xws-security/bin
pkcs12import -file /Users/huima/programming/certificates/server.pfx -alias tmdp_server -keystore /Users/huima/programming/appserver/glassfish/domains/domain1/config/keystore.jks -storepass changeit -pass changeit

Tehdään export keystoresta:
keytool -export -file tmdp_server.cer -keystore keystore.jks -alias tmdp_server -storepass changeit

Tarkistetaan vielä keytoolilla, että kaikki tarvittavat tiedot ovat tallessa:
keytool -printcert -file tmdp_server.cer

Tehdään import truststoreen:
keytool -import -alias tmdp_server -keystore cacerts.jks -file tmdp_server.cer

Ja valmista.

Jos ei halua käyttää/ladata WSDP:tä, toinen tapa hoitaa asia olisi kuvattuna seuraavan linkin takana:
See: http://www.agentbob.info/agentbob/79-AB.html

Kannattaa kuitenkin huomioida sivulla kommenteissa oleva viimeinen kommentti, jossa on ImportKey-ohjelmaan bugifiksi!

changed certs = (Certificate[])c.toArray(); (line 147) to
(Certificate[])c.toArray(new Certificate[0]);

Kun fiksin laittaa paikoilleen, toimii ketjutetut seritifikaatit ilman ongelmia.

Omalla kohdallani meni siis seuraavalla tavalla:

openssl pkcs8 -topk8 -nocrypt -in server-key.pem -inform PEM -out key.der -outform DER
openssl x509 -in server-cert.pem -inform PEM -out cert.der -outform DER
openssl x509 -in rootca.pem -inform PEM -out root.der -outform DER

cat cert.der root.der > allcer.der

java ImportKey key.der allcer.der

Sen jälkeen exportoidaan uduesta keystoresta avain:
keytool -export -alias importkey -file serverb-cert.cer -keystore keystore.ImportKey

Katsotaan että se on validi:
keytool -printcert -file huimacert.cer

Ja ihan huvin vuoksi tehdään sama vielä openssl:n työkaluilla:
openssl x509 -inform der -in huimacert.cer -out huimacert.pem
openssl x509 -in huimacert.pem -text -noout

Jos taas meinaa Glassfissä käyttää ko. sertifikaattia pääsertifikaattina, pitää ensiksi poistaa default-sertifikaatti keystoreista aliakselta s1as. Toinen vaihtoehto olisi korvata s1as alias konfiguraatioissa jollain toisella ja laittaa ko. aliaksella uusi sertifikaatti keystoreihin.

Remove from keystore:
keytool -delete -alias s1as -keystore keystore.jks
keytool -delete -alias s1as -keystore cacerts.jks
keytool -list -keystore keystore.jks -storepass changeit | grep as

keytool -import -alias a1as -file huimacert.cer -keystore cacerts.jks
keytool -import -alias a1as -file huimacert.cer -keystore keystore.jks

Toinen tärkeä oppiminen liittyi WSIT:ssä käyttäjän usernamen saamiseen webservicessä esiin sen jälkeen, kun Metro on hoitanut authentikoinnin esimerkiksi sertifikaatilla tai UserNameTokenilla WS-Securityn mukaisesti.

Vastoin parempaa luuloani Principal ei ollutkaan saatavilla suoraan WebServiceContextista, vaan piti poimia allaolevan koodin mukaisesti kierteen kautta.

//inject WebServiceContext
@Resource
private WebServiceContext context;

//in the webservice method do the following

Subject clientSubject = null;
try {
clientSubject = com.sun.xml.wss.SubjectAccessor.getRequesterSubject(context);
} catch(Exception e) {
//handle exception
e.printStackTrace();
}

if (clientSubject != null) {
Set principals = clientSubject.getPrincipals();
for (Iterator it = principals.iterator(); it.hasNext();) {
System.out.println("Client Principals:" + it.next());
}
} else {
System.out.println("Client Principal not set");
}

Koodi puolestaan löytyy Sunin java.net-foorumeilta.

This entry was posted in java, programming, Uncategorized. Bookmark the permalink.

Vastaa

Täytä tietosi alle tai klikkaa kuvaketta kirjautuaksesi sisään:

WordPress.com-logo

Olet kommentoimassa WordPress.com -tilin nimissä. Log Out / Muuta )

Twitter-kuva

Olet kommentoimassa Twitter -tilin nimissä. Log Out / Muuta )

Facebook-kuva

Olet kommentoimassa Facebook -tilin nimissä. Log Out / Muuta )

Google+ photo

Olet kommentoimassa Google+ -tilin nimissä. Log Out / Muuta )

Muodostetaan yhteyttä palveluun %s