Java 9 on kymmenen kertaa nopeampaa!

Törmäsin mielenkiintoiseen ilmiöön taannoin. Valmistelin esitystä suorituskyvystä ja Java muistimallista, ja ajoin eräänlaista benchmark sovellusta Dockerin avulla eri virtuaalikoneissa. Sovelluksen ideana on sisältää aika typerästi kirjoitettua mutta varsin tavanomaista Java-koodia. Silmukoita, ehtolauseita, merkkijonojen käsittelyä, laskentaa, kokoelmien käsittelyä, ja kellottaa paljonko kaikkeen menee aikaa. Tällä voidaan myös nähdä nykyaikaisen virtuaalikoneen itseään optimoiva vaikutus – kun ajo jatkuu, nopeus yleensä kasvaa. Tässä on sovelluksen mittaustuloksia Oracle Java 6 Docker kontissa ajettuna:

Screenshot 2016-10-16 13.19.54.png

Eli, yhden kierroksen aika on n. 84 sekuntia, laskien 82 sekuntiin jahka virtuaalikone vähän ”lämpenee” eli käytännössä jit-kääntää enemmän koodia ja tekee muita tarvittavia optimointeja.

 

Tässä on OpenJDK+Java 8 ajotulokset:

Screenshot 2016-10-16 13.23.31.png

Kuten tuloksista näkyy, uudempi virtuaalikone optimoi usein tehokkaammin. Tässä kierrosajat pyörivät n. 62 sekunnin pinnassa – Java 6 verraten on irronnut noin 20 sekuntia, tai 1/4 suoritusajasta. Paras kierrosaika oli jopa 52 sekuntia. Aika hyvä tulos!

Kokeillaanpa G1 roskankeruualgoritmilla:

Screenshot 2016-10-16 13.35.12.png

Oops! Vaikka G1 on teoriassa kauneinta ja uusinta mitä roskankeruualgoritmeihin tulee, se ei ole joka ongelmaan optimaalinen ratkaisu. Suoritusajat vaihtelevat 98 ja 104 sekunnin välillä ja ovat nousemaan päin. Tällä sovelluksella ja tämän koneen muistilla tässä tuli takapakkia, huonompi suorituskyky. Varmaan tästä syystä G1 ei ole vielä oletusalgoritmina vaan pitää erikseen kytkeä päälle lisäparametrilla -XX:+UseG1GC.

Java 9 julkaistaan vasta pitkällä ensi vuonna. Siitä on kuitenkin jo prereleaseja liikkeellä, ja jopa Docker virtuaalikuva. Tämän ansiosta on lasten leikkiä ajaa sama koodi Java 9:llä. Tulokset tässä:

Screenshot 2016-10-16 13.36.26.png

WUT? Sama koodi, tekee saman asian, sama koneympäristö ja resurssit. Suoritusajat vaihtelevat 9 ja 12 sekunnin  välillä. Karkeasti ottaen noin kymmenen kertaa nopeampaa kuin useimmat muut testiajot, ja yli viisi kertaa nopeampaa kuin paras tulos tähän asti.

Jotain on muuttunut. Mitä, en tiedä vielä. Epäilen että yksi tekijä voi olla Jigsaw moduulimallit. Toinen tekijä lienee, että on taas opittu tunnistamaan joku negatiivinen koodaustapa, ja optimoimaan sen suoritus. Tulokset tuskin ovat yleispäteviä, ne pätevät lähinnä tähän tyypilliseen koodiesimerkkiin mitä käytin, ja tähän ympäristöön. Docker välissä voi myös vaikuttaa jotain, tuskin kuitenkaan paljoa. Niin tai näin, koodi otti taas kerran hurjan tehokkuushypyn. Tätä herkkua olisi luvassa ensi vuonna.

Virtuaalikoneiden ihanuus on siinä, että nautit kaikista edistysaskelista, ilman koodimuutoksiakin. IBM nimesi juuri oman open source JDK 9 versionsa JIT-kääntäjän Testarossaksi, joten veikkaisin että sieltä on myös suurta hyvyyttä tulossa.

p.s. Docker on ihana keksintö!

p.p.s. Niin on Cathode terminaalikin :p

 

Spring Boot, Java 8, AngularJS, ja Heroku pilvipalvelu

Tuli ajankohtaiseksi puskea Spring Boot sovellus Herokun alle tarjoiltavaksi. Heroku on siitä vänskä palveluntarjoaja että sieltä saa ilmaisella jäsenyystasolla jo jonkun verran prosessoriaikaa, ja resursseja – samoin kuin Google App Enginestä (ainakin aikoinaan).

Homma ei mennyt ihan heittämällä, joten kirjailen taas vähän kokemuksia ja säätöjä tähän. Omassa tapauksessani muutama kiemura johtui siitä että olin yhdistänyt sekä Javaa että Angularia samaan pakettiin – ja Heroku parka meni sekaisin sen suhteen mitä pitäisi buildata ja miten. Muuten Spring Boot + Heroku on taivaassa tehty liitos, mahtava yhdistelmä!

Mitä tarvitaan/esivalmistelut:

– Yksi Spring Boot sovellus, jossa esim. In-Memory tietokanta ja AngularJS UI sisään paketoituna – ei niin välttämätöntä, mikä hyvänsä Spring Boot käy lopulta, mutta kannat vaativat toki esim extratyötä

– Projekti pitäisi olla git versioitu, se tekee heroku käytön suorastaan naurettavan helpoksi

– Tietty Heroku free tier tunnukset tarvitaan, ja ne tulisi olla tiedossa

– Heroku Toolbelt asennettuna omalle käyttöjärjestelmällesi

– Pientä lisäjännää: Haluat ehkä lisätä bower_components tyyppiset vendor javascript kirjastot gittiin, koska jos buildaat projektin Java builderillä, mitään automatiikkaa javascript/angular puolelle ei ole, eli sen mitä lähetät Herokuun tulisi olla joko Mavenin kautta buildattua automaattisesti, tai sitten esirouskuteltua staattista sisältöä. bower_components pusku gittiin on muutenkin paras käytäntö koska ulkomaan repositoryt tai interweb eivät noin muutenkaan ole aina buildatessa saatavana, joten näillä mennään!

Ja sitten touhuamaan. Aluksi kannattaa lisätä projektiin muutama tiedosto, ellei niitä jo ennestään löydy. Tarvitset settings.properties tiedoston, Procfile tiedoston, ja application.properties tiedoston. Näistä kaksi ensimmäistä liittyy Heroku-alustaan, ja viimeinen on Spring Boot standarditiedosto – joka on luontevaa tallettaa /config kansioon.

Tässä niiden sisältö:

  • /settings.properties (asettaa JDK versioksi 8)
    • system.properties=1.8
  • /Procfile (kertoo mikä sovellus ja mistä käynnistyy)
    • web: java $JAVA_OPTS -jar target/*.jar
  • /config/application.properties (määrittää käyttäämän serveriporttina PORT ympäristömuuttujaa, tai 8080 jos sitä ei löydy)
    • server.port: ${port:8080}

Näistä tosiaan application.properties saattaa olla jo tehtynä, ja voi olla muussa kansiossakin, eli ole tarkkana. Se on Spring Boot perustiedostoja.

Nyt voidaan alkaa touhuamaan. Lisää kaikki edellämainitut git repositoryyn, commitoi, ja jatka näillä Heroku komennoilla:

  • heroku login (tänne sitten tunnareita ja salasanaa Herokun mukaan)
  • heroku create (luo sovelluksen, ja käytännössä määrittelee uuden remote repositoryn nimeltä heroku)
  • heroku buildpack:set https://github.com/heroku/heroku-buildpack-java (asettaa builderiksi juuri Java, eikä esim. NodeJS tms)
  • heroku ps:scale web=1 (asettaa käyttöön yhden dynon, ellei ole jo – nyt on resursseja ajamaan sovellusta)

Voiton puolella jo! Nyt voidaan puskea sovellus herokuun, tähän tapaan:

git push heroku master

Seuraa tarkkaan ilmoituksia mitä näkyy – etenkin jos virheilmoituksia ilmenee. Jos kaikki sujui hyvin, voit nyt avata sovelluksen:

heroku open

Toimiko? Onnittelut! Jos ei pelannut, tässä muutama debugging niksi:

  • Tarkista Heroku logit komennolla: heroku logs –tail
  • Tarkista web dynojen status komennolla: heroku ps

Huomioi että jos dynoja on vain yksi käynnissä, Heroku nukuttaa sen jos tuntiin ei ole ollut käyttöä. Näin ollen se käynnistyy hitaanlaisesti kun sitä taas tarvitaan. Tämän voi kiertää laittamalla kaksi dynoa – tai enemmän:

heroku ps:scale web=2

Huomaa että free tier antaa vain 750 dyno-tuntia, joten kahden dynon voimalla ei piisaa tehoja kuin puoleen kuukauteen ilmaistasolla. Muista myös sammutella dynot kun et niitä enää tarvitse, komennolla:

heroku ps:scale web=0

Näin! Spring Boottia voi siis tunkea Raspberry Pi kakkoseen, tai pilveen. Vaikuttaa aika toimivalta alustalta nykymuodossaan.

Tässä hyvä linkki myös artikkeliin jossa käsitellään Heroku multi-buildpack strategiaa – eli miten voit buildata sekä Java että JavaScript puolen erikseen sillä suunnalla.

https://devcenter.heroku.com/articles/using-grunt-with-java-and-maven-to-automate-javascript-tasks

Itse käytin joskus aikanaan Eirslett Maven-Grunt pluginia, joka osaa imaista node, npm, bower jne työkalustot paikallisiksi ja käyttää niitä projektin alta – mutta se oli aika monimutkainen ja kömpelökin ratkaisu. Monella on tarpeista riippuen ollut menestystä myös ihan exec-maven pluginin kanssa javascript prosessoinnissa, mutta sen ongelmana on että node pitäisi olla koneeseen asennettuna etukäteen.

Java 8 Optional – oikea käyttö

Olen käytellyt Java 8 versiota tuotannossa jo useammassa paikassa yli vuoden verran, mutta Optional luokasta en ole kirjoitellut – enkä suuremmin käyttänyt. Olen kuitenkin suuri NullPointerException:ien vihaaja (emmekö me kaikki) ja olen aiemmin vähennellyt niitä lähinnä hyvillä paluuarvo ja parametrikäytännöillä. Tämähän on yleisimpiä ja viheliäisimmin metsästettäviä poikkeuksia Javassa – kiitos poikkeuksien kuplimisen.

Syy miksi en ole kirjoitellut tai käytellyt Optionalia vielä on että esimerkit joita olen nähnyt sen käytöstä ovat olleet surkeita. Kun Javan päälle laastarilappu-liimataan uusia piirteitä, käy usein niin että lääke on sivuvaikutuksiltaan pahempi kuin alkuperäinen sairaus. Ja Optional-paluuarvon tarkistaminen if-lauseilla on juuri sitä. Hyi!

Nyt näin kuitenkin ihan virkistävän uuden blogipostauksen jossa muistuteltiin muistakin tavoista. Teen myöhästyneen uudenvuodenlupauksen testailla näitä itsekin, ja katsoa tykästynkö. Ideana on korvata Optional-arvon tarkistus ehtolauseessa sen omilla funktioilla ja ominaisuuksilla, ja näin saada koodista luettavampaa silti säilyttäen fiksumpi null pointer käsittely.

Ytimessään idea on tässä:

Optional<String> result = service.find("id");
final String value = result.orElseGet(() -> "<absent>").trim();

Tämä on jo itselle ihan sopiva tapa, pystyn lukemaan sen. Artikkelin kirjoittajalla oli toinenkin idea, joka koski Optional käyttöä kokoelmana, näin:

Optional<String> result = service.find("id");
String value = result.map(String::trim).orElse("<absent>");
Tästä en ole ihan varma, jotenkin häiritsee ajatus että vedetään collections apit hatusta mukaan, mutta kiitokset luettavuudesta saa tämäkin.
Artikkelin kirjoittajalla oli pari muutakin hyvää pointtia, joten en ala kopioimaan niitä tähän vaan pidetään tätä artikkelia teaserinä. Jos mielenkiinto heräsi, kipin kapin lukemaan alkuperäinen artikkeli tuosta alta 😉

Ja artikkelin lähde:

https://www.voxxed.com/blog/2015/02/defence-java-8s-optional-use/

Raspberry Pi 2 kotiutui

Posti toi mukanaan paketin, jossa oli uudentuoksuinen Raspberry Pi 2 kapistus. Sille löytyykin heti käyttöä, mutta maltoin napsia pari kuvaa ja jaan vähän ensivaikutalmia tässä. Pahoittelen kuvien Nexus 6-laatua, liikkeellä on paljon laadukkaampaakin kuvitusta 😉

Raspberry Pi 2

Kuten on toitotettua, laite on aiempaa moninkerroin tehokkaampi, 900MHz quad core prosessorilla varustettu, ja kuitenkin alkuperäisen hintainen. Muitakin muutoksia löytyy rautapuolelta.

USB portteja on nyt kahden sijasta hubitettu neljä, ja muistikorttikin on pienentynyt MicroSD-kokoon.

USB Portit

Muistikortit

Komposiittivideo löytyy nykyään audioportista. Muuten tutun kaltainen kapistus. Jaahas, ei sitten muuta kuin käyttistä kortille.

Nyt on valinnanvaraa taas hiukan enemmän. Itse olen tykästynyt ennestään Raspbianiin jossa tulee Oraclen Javaa heti mukana hard floatilla. Mutta tarjolla myös mm. Snappy Ubuntu Corea, Pidoraa, Noobsia, Risc OS:ia, ja tietenkin se Windows 10.

Mutta mennään Raspbianilla vielä toistaiseksi, pari projektia mielessä sen päälle. Ja sinne plutkahti perus-käyttöönoton päälle vanha tuttu Java 8 (kuuluu nykyään distroon, ei vaadi sen enempää), ja uutena tulokkaana node.js, npm, sekä mongodb. Hassua kyllä nämä viimeisimmät vaativat erityisvimpautuksia raspbianiin – mutta eivät toki kovin ihmeellisiä. Tahkosin toimivat komennot scripteinä talteen – postailen ne ehkä vastaisuudessa tännekin. Tässä on vähän varaa valita haluaako kääntää itse vai käyttää muiden tekemiä 3rd party paketteja. Mongon kääntäminen ja asennus vei viimeksi tunteja (siinä muuten hyvä benchmarkki uudelle) joten tuikkasin 3rd party paketeista kaiken kehiin.

Tästä kuuluu ehkä vähän lisää joku toinen kerta 😉

JavaOne 2014 käynnissä

Jep, JavaOne 2014 on taas käynnissä San Franciscossa. En ole tänä vuonna itse paikan päällä, mutta aika on merkattuna kalenteriin ja seuraan mielenkiinnolla etänä.

Missä mennään tällä hetkellä on Java 8 SE käyttöönotto Lambdoineen kaikkineen, ja ME 8 on myös julkaistu, ja EE 8 työn alla seuraavaksi. Olen blogaillut aiemmin jo Javan seuraavista askelista, Java SE 9 tulee ehkä viimein näyttämään mitä Project Jigsaw – Javan modulaarisuusjärjestelmä tarkoittaa. Se ei ole lopulta erityisen seksikäs aihe, mutta se on tärkeä. Javasta on vuosien saatossa tullut aikamoinen bloat, turvoke 😉 Ajatus modulaarisemmasta Javasta on hyvä skaalatessa pienempään päin, ja Mavenin suosio näyttää että moduulien avulla skaalaus ylöspäin on myös tärkeää. Jos viimein saadaan Javaan tukea myös moduulien versioiden huomioimiseen ihan ydintasolla, paketista tulee aika kova. Brian Goetz valitettavasti komennettiin alas lavalta kesken Java 10 mallailun 😉

Jigsaw projektissa on hyvä huomata kaksi vaihetta. Vaihe 1 on purkaa Javan hurja ristiinviittaus-spaghetti pakettien välillä ja saada Javan parikymmentämegaisesta ytimestä aidosti modulaarisempi. Tätähän aloitettiin jo joskus Java 6u10 aikoihin nimellä kernel. Toinen askel on sitten alkaa käyttämään tätä moduulijärjestelmää omien ohjelmistojen kehitykseen yhtälailla, Mavenin tapaan. Tarkoituksena ei näillä näkymin ole kuitenkaan korvata Maveniä repository-puolella, lähinnä moduulien riippuvuuksien julistuksessa. Riippuvuudethan sitten voivat olla paikallisia tai verkon yli noudettavia.

Vaikka on mukava tarkkailla mitä tulevaisuus tuo mukanaan, Java 9 on vielä aika kaukaista. Tämä vuosi 2014 on edelleen Java version 8 ramp-up aikaa: Lambdoissa, rajapintojen oletusmetodeissa, ja kokoelmakirjastojen uusissa stream-piirteissä on sulateltavaa runsaasti ja harva niitä vielä arjessa käyttää. Sertifiointi Java 8:lle on tätä kirjoittaessa vasta beta-tasossa, ja sekin mielenkiintoisella tavalla uusittu.

Tuolla tech keynote joka on klassisesti ollut kiinnostava avaus koko tapahtumalle:

http://medianetwork.oracle.com/video/player/3811045975001

Goetz saa kyytiä kohdassa 34:27 alkaen 😉

Java 8 + Glassfish 4 asennus Debian Linuxiin – osa 2

Viimeksi asenneltiin Debianiin glassfishiä. Tässä pari edistynyttä niksiä:

32-bit kirjastot 64-bit debianiin

64-bit debian ei välttämättä suostu ajelemaan pkg työkalua jolla voi päivitykset tehdä – se valittaa ia32-libs paketista ja pythonista. Ongelma: kun yrität asentaa paketin, se valittaa riippuvuuksista joita ei olekaan. Ratkaisu tässä:

sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libjpeg62:i386
sudo apt-get install ia32-libs

Nice.

Glassfish asennuksen päivittäminen ajan tasalle.

Nyt voit päivitellä lasikalan uusimpiin kirjastoihin pkg työkalulla esim. näin:

#stop Glassfish
sudo service GlassFish_domain1 stop

# Switch to being user 'glassfish'
sudo su --shell /bin/bash glassfish 

/opt/glassfish4/bin/pkg -R /opt/glassfish4 list
/opt/glassfish4/bin/pkg -R /opt/glassfish4 image-update -v

exit # Revert to being old caffeine-deprived yourself

Muista ajaa kaikki tiedostoja luovat komennot kuten päivitykset ja käynnistykset glassfish-tunnuksella. Jos teet jotain muulla, voit korjata tilanteen päivittelemällä omistajuudet taas glassfish-kansioon ja/tai poistamalla esim. tilapäistiedostot ja cachet. Näin saat omistajuudet kuntoon:

sudo chown glassfish:glassfish -R /opt/glassfish4

 

Oletuksena zip-versio Glassfish ei omaa etähallintaa ja sen admin-salasana on tyhjä, ja master-salasana ’changeit’ – eli ei kovin käyttökelpoinen eikä turvallinen. Korjataanpa nämä.

Glassfish työkalut polkuun

Jatko-operaatioita ajatellen on kätevää lisätä Glassfish bin kansio polkuun, jotta pääset työkaluihin suoraan käsiksi. Tässä vinkit siihen:

#run these as glassfish to generate right ownerships for files
sudo su --shell /bin/bash glassfish

#These will help running the tools:
cd ~
nano .bashrc

#Set up environment for user 'glassfish': edit .bashrc and add this to end:

export PATH="${PATH}":/opt/glassfish4/glassfish/bin

# save file in editor

Testaa voitko ajaa komennon: asadmin. Ellei, kirjaudu ulos ja sisään.

Glassfish master password

Master password on tosiaan oletuksena: changeit – joten muutetaanpa se. Valitettava seuraus on, että muutos päivittää myös avain-ja sertifikaattitiedostoja, joten on taas oltava omistajuuksien kanssa tarkkana. Tässä ohjeistusta:

#if you're glassfish user, exit back to your normal user:
exit

#make sure glassfish is stopped
sudo service GlassFish_domain1 stop

#run these as glassfish to generate right ownerships for files
sudo su --shell /bin/bash glassfish

#Backup default passwords, if you got already master-password file, backup it too:
cd /opt/glassfish4/glassfish

tar cf passwords.orig.tar domains/domain1/config/domain-passwords domains/domain1/config/keystore.jks domains/domain1/config/cacerts.jks

Tässä kohtaa on olemassa varmuuskopio passwords.orig.tar josta löytyy alkuperäiset tiedostot. Nyt muutetaan niitä:

Change master password
asadmin change-master-password --savemasterpassword=true domain1
# Enter the current master password> [By default this is 'changeit']
# Enter the new master password> [e.g. 'Y0uW1llN3v3rGu3ssTh1sL33tP4ssw0rd!']
# Enter the new master password again>
# After entering the new master password twice, there is a pause of several
# seconds. Then you will find new versions of 'master-password'
# 'domain-passwords' 'keystore.jks' and 'cacerts.jks'.

Sitten kokeillaan toimiiko homma – nämä komennot kysyvät salasanaa, anna siihen valitsemasi master password.

# Your chosen master password should unlock both keystores, and reveal
# two certificates in keystore.jks, and many additional ones in cacerts.jks.
keytool -list -v -keystore domains/domain1/config/keystore.jks 
keytool -list -v -keystore domains/domain1/config/cacerts.jks

Ja jos meni jotain pieleen, aina on varmuuskopiot. Toivottavasti ne menivät oikein alunperin, kai tarkistit ne? 😉 Jos kaikki ok, näin voit palauttaa tarvittaessa alkuperäiset tiedostot jos jotain meni pahasti pieleen:

#if you mess up, you can return the backups by going to /opt/glassfish4/glassfish and running: tar -xvf passwords.orig.tar

 Admin-salasana ja etähallinnan aktivointi

Oletuksena tosiaan admin-salasana on tyhjä, ja etähallinta disabloituna. Näin saat korjattua nämä puutteet:

#exit to normal account, sudo start server - it needs to be running
exit
sudo service GlassFish_domain1 start
sudo su --shell /bin/bash glassfish

# enable remote administration for glassfish 

asadmin enable-secure-admin

# ja tässä kohtaa syytä buutata taas palvelin jotta asetukset
# astuvat voimaan

exit
sudo service GlassFish_domain1 restart
sudo su --shell /bin/bash glassfish

Nyt on tilaisuus tallettaa nämä tiedot paikallisesti, siten että linux-tunnuksiltasi ei salasanaa kysellä:

########Store admin password, to enable automatic login to localhost:4848
asadmin login
# Enter admin user name [Enter to accept default]> [Just press Enter]
# Enter admin password> [e.g. whatever you selected earlier]
# Login information relevant to admin user name [admin] for host [localhost] and admin port [4848] stored at [/home/glassfish/.gfclient/pass] successfully.
# Make sure that this file remains protected. Information stored in this file will be used by administration commands to manage associated domain.
# Command login executed successfully.

Eli, tämän tiedoston voit kopioida haluamiesi linux-tunnusten kotihakemiston alle, .gfclient/pass kansioon. Sen oikeudet voit muuttaa niin että vain user omaa oikeudet päästä tähän käsiksi. Muista säätää myös omistajuus oikein, eli omistajaksi ko tunnus.

Voit myös tuikata admin-konsolin vain https-protokollalle:

#Enable https for remote access to admin console
# Requests to http://xxx:4848 are redirected to https://xxx:4848

asadmin set server-config.network-config.protocols.protocol.admin-listener.security-enabled=true

Glassfish käyttämään portteja 80 ja 443 – ilman root oikeuksia

Jos haluat Glassfishin operoivan porteissa 80 ja 443 – mutta et halua ajaa sitä root tunnuksin jotka normaalisti vaaditaan ko porttien käyttöön  – voit tehdä /etc/init.d/GlassFish_domain1 tiedoston loppuun seuraavat reititykset – näin nämä ajetaan root tunnarilla, mutta itse glassfish normaalisti glassfish tunnarilla – ja portit 80 ja 443 ovat käytössä.

iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8181

 Sertifikaatit uusiksi

Glassfish oletussertifikaatit ovat tasan samat mitä jokainen käyttää – ei kovin turvallista. Tässä ohjeita miten voit tehdä uudet avaimet omaan käyttöön:

# Ensure that you are running as user 'glassfish'!!
# Ensure GlassFish is stopped

#Inspect keystore.jks
cd /opt/glassfish4/glassfish/domains/domain1/config/
keytool -list -keystore keystore.jks -storepass [whateverismymasterpassword]

#Update keystore.jks

keytool -delete -alias s1as -keystore keystore.jks -storepass [whateverismymasterpassword]

keytool -delete -alias glassfish-instance -keystore keystore.jks -storepass [whateverismymasterpassword]

keytool -genkeypair -alias s1as -dname "CN=myservername,OU=myunit,O=MyOrganization,L=MyTown,C=FI" -keyalg RSA -keysize 2048 -validity 3650 -keystore keystore.jks -keypass [whateverismymasterpassword] -storepass [whateverismymasterpassword]

keytool -genkeypair -alias glassfish-instance -dname "CN=myservername,OU=myunit,O=MyOrganization,L=MyTown,C=FI" -keyalg RSA -keysize 2048 -validity 3650 -keystore keystore.jks -keypass [whateverismymasterpassword] -storepass [whateverismymasterpassword]

#Check keystore.jks

keytool -list -keystore keystore.jks -storepass [whateverismymasterpassword]

#Export certificates from keystore.jks

keytool -exportcert -alias s1as -file s1as.cert -keystore keystore.jks -storepass [whateverismymasterpassword]

keytool -exportcert -alias glassfish-instance -file glassfish-instance.cert -keystore keystore.jks -storepass [whateverismymasterpassword]

#Update cacerts.jks

keytool -delete -alias s1as -keystore cacerts.jks -storepass [whateverismymasterpassword]

keytool -delete -alias glassfish-instance -keystore cacerts.jks -storepass [whateverismymasterpassword]

keytool -importcert -alias s1as -file s1as.cert -keystore cacerts.jks -storepass [whateverismymasterpassword]

#Trust this certificate? [no]: [Enter 'yes']

keytool -importcert -alias glassfish-instance -file glassfish-instance.cert -keystore cacerts.jks -storepass [whateverismymasterpassword]

#Trust this certificate? [no]: [Enter 'yes']

#Check cacerts.jks and tidy up

keytool -list -keystore cacerts.jks -storepass [whateverismymasterpassword]

rm s1as.cert glassfish-instance.cert

exit

Done! Nyt on uudet ja omat avaimet serverillä, ja aiemman vaiheen ansiosta uudella master salasanalla suojattuna. Tässä voi välivaiheena allekirjoituttaa sertifikaattinsa jollain virallisella taholla jos haluaa tuotantokäyttöön sopivan vimpaimen.

Serveriheaderien obfuskointi – äläpä kerro enempää!

Yksi oma lempiaiheeni tietoturvassa on ollut suojata systeemeitä siten että ne eivät kerro tarpeettoman paljon itsestään .- esim. header joka sanoo: X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7) – suorastaan kirkuu googlettamaan seuraavaksi haavoittuvuuksia, oletustunnuksia, ja täsmähyökkäysohjelmia. Mitä vähemmän paljastaa tietoa ulospäin sen vaikeampaa on heti tietää mitä hyökkäyksiä soveltaa. Vielä kierompaa on näyttää misinformaatiota – esim. ajaa IIS palvelinta joka väittää olevansa Glassfish tai Glassfishiä joka väittää olevansa Websphere jne.

Tässä komennot joilla voit tukahduttaa näitä headereita. Huom! Ne muuttavat domain1/config/domain.xml tiedostoa, joten syytä taas olla glassfish tunnuksena sisässä (komento whoami kertoo mikä on tunnuksesi). Glassfish serverin tulee olla päällä.

#start glassfish if it's not running
sudo service GlassFish_domain1 start

#Ensure that you are running as user 'glassfish'!!
sudo su --shell /bin/bash glassfish

#Check HTTP headers
# Check HTTP response headers (as shown below) to make sure that there are
# clues as to the server or its version. Look for any mention of
# 'GlassFish', 'X-Powered-By', etc. If necessary:

asadmin create-jvm-options -Dproduct.name=

asadmin set server.network-config.protocols.protocol.http-listener-1.http.xpowered-by=false

asadmin set server.network-config.protocols.protocol.http-listener-2.http.xpowered-by=false

asadmin set server.network-config.protocols.protocol.admin-listener.http.xpowered-by=false

Samalla voit myös tsekata virhesivut, esim. 404 sivua ei löydy kertoo usein paljonkin serveristä. Se on muutenkin hyvä ottaa omaan haltuun. Voit tehdä tämän toki sovelluskohtaisenakin, mutta tässä on serverikohtainen asetus:

asadmin set server.http-service.virtual-server.server.property.send-error_1="code=404 path=/opt/glassfish4/glassfish/globalhtml/404.html reason=Resource_not_found"

Tämä menee domain.xml:ään – jota toki voi käsinkin muokata. Muillekin virheilmoituksille voi tehdä vastaavia. Saatat myös haluta disabloida/poistaa/vaihtaa juuri-kontekstin oletussivun ja sovelluksen.

Lopuksi tietysti buutataan mylly

#Restart to take effect

exit

sudo service GlassFish_domain1 restart

Virtuaalikoneen säädöt ja muisti

Virtuaalikoneen tuunaus on ihan oma taiteenlajinsa – sitä voi harrastaa web-admin konsolista, tai domain.xml tiedostoa editoimalla, mutta onnistuu se komentoriviltäkin:

#List current JVM options

asadmin list-jvm-options

# Now update some important JVM settings. 
# Of course use memory as you need to, so if you like 64GB max heap, go for it!

asadmin delete-jvm-options -Xmx512m
asadmin create-jvm-options -Xmx2048m
asadmin create-jvm-options -Xms1024m

# and run with -client or -server optimizations
# -client boots up faster, server optimizes tighter on longer run
# -client is now the default, so if you like -server:

asadmin delete-jvm-options -client
asadmin create-jvm-options -server

Siinä kaikki tällä erää. Moderni sovelluspalvelin on sillä tavalla kiehtova paketti että se sisältää hurjasti piirteitä, palveluita, ja yksityiskohtia. Monet näistä periaatteista pätevät hyvinkin muihinkin servereihin, kuten Tomcat ja JBOSS, ja miksei myös WebSphere/Weblogic. Toivottavasti näistä on apua.

 

Java 8 + Glassfish 4 asennus Debian Linuxiin – osa 1

Ajattelin kirjailla kokemuksia Glassfish Linux asennuksesta, 64-bittiseen Debianiin. Osaan 1 laitan perusohjeistusta, osaan 2 tulee sudenkuoppia ja yksityiskohtia.

Olen kirjoitellut jo aiemmin tästä Raspberry Pi vinkkelistä, mutta tässä vähän lisää yksityiskohtia. Tarinaa olen haalinut hyvistä muista blogeista, ja pistän linkkiä loppuun, mutta ainakin paras niistä on häviämässä netistä joten pistän tämän itsellekin talteen.

Testailin juuri asennuksia AWS pilvipalvelun 64-bittiseen Ubuntuun, ja näyttäisi pelittävän ihan heittämällä myös sinne.

Alkuun tarvitaan Java, JDK 7 tai 8, itsellä tietenkin 8. Tästä taisin juuri kirjailla, miten Java on lisenssiteknisistä syistä vähän jännä asennella. Mutta tässä Oracle JDK 8 litaniat:

#make sure you're up-to-date
sudo apt-get update
sudo apt-get upgrade

#install oracle jdk 8
sudo echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | sudo tee /etc/apt/sources.list.d/webupd8team-java.list
sudo echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | sudo tee -a /etc/apt/sources.list.d/webupd8team-java.list
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EEA14886
sudo apt-get update
sudo apt-get install oracle-java8-installer
java -version

Löytyykö sieltä Java? Hienoa!

Glassfish oletusasennus käyttelee root tunnaria joka on vähän hyi hyi. Tämän vuoksi meidän kannattaa tehdä prosessille uusi käyttäjätunnus, glassfish. Jos lähdet tälle polulle, muista että muokatessa glassfish kansion tiedostoja tai ajaessa prosessia, se tulisi aina tehdä glassfish tunnarien alla. Muuten voi syntyä tiedostoja joihin glassfish-serveriprosessi ei omaa pääsyä, esim. temp, cache, jne. Sen voi onneksi aina korjata chownaamalla koko glassfish hierarkian.

#Add a new user called 'glassfish' with group 'glassfish'
sudo adduser --system --group --home /home/glassfish [--shell /bin/bash] glassfish
#Enable an existing user to be a GlassFish administrator. Repeat for additional users.
sudo usermod -a -G glassfish existingUserAccountName
# can check your groups with:
groups #list should include 'glassfish' - remember to relogin here!

Sitten tuikataan Glassfish 4 zip release paikalleen:

#get glassfish 4 release
cd ~
wget http://download.java.net/glassfish/4.0/release/glassfish-4.0.zip

sudo apt-get install unzip
sudo unzip -d /opt/ glassfish-4.0.zip 

#glassfish is owner of this folder
sudo chown -R glassfish:glassfish /opt/glassfish4
#glassfish can freely access bin folders and autodeploy
sudo chmod -R ug+rw /opt/glassfish4
#glassfish can execute binaries
sudo chmod -R ug+rwx /opt/glassfish4/bin
sudo chmod -R ug+rwx /opt/glassfish4/glassfish/bin
#others are not allowed to access glassfish
sudo chmod -R o-rwx /opt/glassfish4/

Seuraavaksi fiksataan proaktiivisesti yksi asia: Java seiskan viimeisimmissä päivityksissä – ja myös Java 8:ssa – on tiukennettu tietoturva-asetuksia. Tästä johtuen esim. Derby tietokantaa ei saa käyntiin ellei sitä salli policyissä. Tässä on karu tapa lisätä kaikelle ajettavalle Java-koodille oikeus käyttää Derby-porttia. Tätä voi tiukentaa halutessaan esim. kansiokohtaiseksi:

#edit $JAVA_HOME/jre/lib/security/java.policy, insert following between existing grant blocks:
grant {
 // allows Derby to claim port 1527
 permission java.net.SocketPermission "localhost:1527", "listen,resolve";
};

Seuraavaksi päräytetään vaihtaen glassfish tunnarille – jotta luotavat tiedostot menevät oikeille omistussuhteille ja oikeuksille. Käynnistetään derby ja glassfish jotta voidaan todeta toimiiko kaikki:

#now, run glassfish server & database
sudo su --shell /bin/bash glassfish
whoami # should say 'glassfish'
/opt/glassfish4/bin/asadmin start-database
/opt/glassfish4/bin/asadmin start-domain domain1

Kaikki hyvin? Voit testata varmuudeksi löytääkö selain portit:

http://localhost:8080

https://localhost:8181

http://localhost:4848

Jos näyttää hyvältä, on aika sammutella Glassfish, ja poistua glassfish tunnuksesta takaisin omaan:

/opt/glassfish4/bin/asadmin stop-domain domain1
/opt/glassfish4/bin/asadmin stop-database
exit

Jos kaikki löytyy, voit seuraavaksi asentaa tämän palveluna. Aloitetaan Glassfishin omalla työkalulla:

sudo /opt/glassfish4/bin/asadmin create-service

Valitettavasti käynnistysscripti jonka tämä luo on täyttä moskaa. Jos käynnistäisit nyt koneen, se ei toimisi. Siinä on monia virheitä:
– init.d scriptit ajetaan ennenkuin esim. profile tiedostot ja niiden pathit on käsitelty. Näin mitään työkaluja ei ole patheissa vaan pathit pitää exportoida erikseen, tai viitata koko absoluuttisilla poluilla
– scriptistä puuttuu service header tiedostot jotka estävät sen toiminnan
– oletusscripti ajelee serveriä roottina, joten jos sinne pujahtaa pätkä ilkeämmän puoleista koodia jonkun haavoittuvuuden vuoksi…. WORLD DOMINATION!!!
– derby kanta olisi myös hyvä käynnistellä ja sammutella
– olisi kiva saada status tietoja

Joten, korvataan scripti parannetulla versiolla. Avaa editori:

sudo nano /etc/init.d/GlassFish_domain1

Jyrää vanha moska tällä, säädä tarpeen mukaan vastaamaan omia polkujasi tai tarpeitasi:

#! /bin/sh
### BEGIN INIT INFO
# Provides: glassfish
# Required-Start: $remote_fs $network $syslog
# Required-Stop: $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Starts GlassFish
# Description: Starts GlassFish application server
### END INIT INFO
# We need this, since NetworkServerControl uses $JAVA_HOME to find java
export JAVA_HOME="/usr/lib/jvm/java-8-oracle"
GLASSFISH=/opt/glassfish4
DERBY_BIN=/opt/glassfish4/javadb/bin
case "$1" in
start)
 echo "Starting GlassFish from $GLASSFISH"
 sudo -u glassfish -E "$GLASSFISH/bin/asadmin" start-database
 sudo -u glassfish -E "$GLASSFISH/bin/asadmin" start-domain domain1
 ;;
stop)
 echo "Stopping GlassFish from $GLASSFISH"
 sudo -u glassfish -E "$GLASSFISH/bin/asadmin" stop-domain domain1
 sudo -u glassfish -E "$GLASSFISH/bin/asadmin" stop-database
 ;;
restart)
 $0 stop
 $0 start
 ;;
status)
 echo "# GlassFish at $GLASSFISH:"
 sudo -u glassfish -E "$GLASSFISH/bin/asadmin" list-domains | grep -v Command
 sudo -u glassfish -E "$GLASSFISH/bin/asadmin" list-domains | grep -q "domain1 running"
 if [ $? -eq 0 ]; then
 sudo -u glassfish -E "$GLASSFISH/bin/asadmin" uptime | grep -v Command
 echo "\n# Deployed applications:"
 sudo -u glassfish -E "$GLASSFISH/bin/asadmin" list-applications --long=true --resources | grep -v Command echo "\n# JDBC resources:"
 sudo -u glassfish -E "$GLASSFISH/bin/asadmin" list-jdbc-resources | grep "jdbc/"
 fi
 echo "\n# Derby:"
 sudo -u glassfish -E "$DERBY_BIN/NetworkServerControl" ping | sed "s/^.* : //"
 ;;
*)
 echo "Usage: $0 {start|stop|restart|status}"
 exit 1
 ;;
esac
exit 0

Nättiä kuin kesäheinän teko. Tässä voi olla vielä parannettavaa mutta itselle ainakin varsin tyydyttävä toiminta. Pistä kommenttia jos tulee parannuksia itsellesi mieleen!

Aja seuraavaksi palvelun testi:

#test that it works:
/etc/init.d/GlassFish_domain1 start
/etc/init.d/GlassFish_domain1 status
/etc/init.d/GlassFish_domain1 stop

Jup, status voi heittää vähän autentikointivirheitä koska kannassa ei ole glassfish käyttäjää. Mutta palvelun pitäisi käynnistyä ja sammua tätä kautta. Seuraavaksi uudelleenasennetaan tämä palveluna, ja testataan että se toimii edelleen:

#cool, now let's update the autorun part with the script:
sudo update-rc.d GlassFish_domain1 defaults

#test that it works as a service
sudo service GlassFish_domain1 start

#if it seems to work, test that it REALLY works: 
sudo reboot

#and verify by connecting to http://thisservername:8080 and http://thisservername:4848

Nice? Yeah, hyvin pelittää. Ensi kerralla voitaisiin näperrellä servosta turvallisempi ja tehokkaampi.

Linuxin kanssa on kiva pitkästä aikaa puuhailla. Niissä servereissä on erona winkku servoihin että kun johonkin ei koske pitkään aikaan ja sen melkein unohtaa, se toimii yhtä hienosti kuin asennuspäivänä 😉

Linkkivinkki mitä itse eniten käytin: http://www.physics.usyd.edu.au/~rennie/glassfish.html