====== Jetty 11 ======
**Tento dokument je zde pouze z informativních důvodů, instalujete-li Jetty, jděte na stránku s [[:cs:tech:idp:5:jetty|aktuálním návodem]].**
===== Authbind =====
Nejdříve nainstalujeme Authbind:
# Instalace Authbind
apt install authbind
V adresáři ''/etc/authbind/byport'' vytvoříme soubory ''80'' a ''443'' s tímto obsahem:
jetty
Souborům změníme práva:
# Změna práv u souborů 80 a 443
chmod 644 /etc/authbind/byport/80 /etc/authbind/byport/443
===== Instalace =====
Dále potřebujeme nainstalovat Javu 17:
# Instalace Javy 17
apt install openjdk-17-jre
Nyní nastavíme proměnnou //JAVA_HOME// pro současnou i budoucí relace:
# Nastavení proměnné JAVA_HOME
eval $(echo "export JAVA_HOME=/usr" | tee -a /root/.bashrc)
Jelikož //Jetty11// není součástí balíčků Debianu, stáhneme následující soubory ze stránek projektu:
# Stažení Jetty
wget -P /opt \
https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/11.0.16/jetty-home-11.0.16.tar.gz \
https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/11.0.16/jetty-home-11.0.16.tar.gz.asc \
https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/11.0.16/jetty-home-11.0.16.tar.gz.sha1
# Přepnutí do adresáře /opt
cd /opt
# Kontrola SHA1 otisku
echo -e '\t jetty-home-11.0.16.tar.gz' >> jetty-home-11.0.16.tar.gz.sha1
sha1sum -c jetty-home-11.0.16.tar.gz.sha1
# Kontrola GPG podpisu
gpg --verify jetty-home-11.0.16.tar.gz.asc
# Rozbalení archivu
tar -xzf jetty-home-11.0.16.tar.gz
# Přesunutí adresáře
mv jetty-home-11.0.16 jetty11
# Vytvoření adresáře se základem jetty11-idp
mkdir -p /opt/jetty11-idp/etc
===== Konfigurace =====
Nakonfigurovat Jetty pro běh Shibboleth IdP je velice triviální, protože stačí stáhnout již připravené konfigurační soubory a pouze v některých z nich udělat drobné změny.
==== idp.mod ====
Vytvoříme si v Jetty tzv. modul pro Shibboleth IdP, který obsahuje veškeré závislosti, jež budou pro běh IdP vyžadovány.
V adresáři ''/opt/jetty11/modules'' si tedy vytvoříme soubor ''idp.mod'' s tímto obsahem:
[description]
Shibboleth IdP
[depend]
annotations
deploy
ext
http
http2
https
jsp
jstl
plus
requestlog
resources
rewrite
server
servlets
ssl
[files]
tmp/
==== keystore ====
Pro šifrovanou komunikaci bude IdP využívat TLS certifikát. Ten je možné získat na službě [[https://tcs.cesnet.cz|TCS CESNET]]. //V případě, že nemáte ke službě TCS přístup, můžete využít zdarma certifikát od [[https://letsencrypt.org|Let's Encrypt]] anebo si zakoupit certifikát u libovolné důvěryhodné certifikační autority.//
Získaný certifikát (zde označený jako ''cert.pem'') musíme nejprve doplnit o mezilehlý certifikát **vyjma kořenového certifikátu** (zde označený ''chain.pem'').
# Spojení koncového a mezilehlého certifikátu
cat cert.pem chain.pem > jetty.txt
Následně si certifikát (''jetty.txt'') a privátní klíč (''key.pem'') převedeme do formátu PKCS#12. Nejprve zadáme heslo k privátnímu klíči (''key.pem'') a následně dvakrát úplně nové heslo, které si vygenerujeme pomocí ''openssl'' //a poznamenáme!//
# Generování nového hesla
openssl rand -hex 20
# Převod certifikátu do formátu PKCS#12
openssl pkcs12 -export -inkey key.pem -in jetty.txt -out jetty.pkcs12
Pak již zbývá jen do adresáře ''/opt/jetty11-idp/etc'' nakopírovat soubor ''jetty.pkcs12'' a přejmenovat ho na ''keystore.p12'' s TLS certifikátem, kterému nastavíme práva ''640'' a skupinu ''jetty''.
# Přesunutí souboru keystore.12
mv jetty.pkcs12 /opt/jetty11-idp/etc/keystore.p12
# Vytvoření uživatele jetty
useradd -s /bin/false -d /opt/jetty11 jetty
# Změna práv ke keystoru
chmod 640 /opt/jetty11-idp/etc/keystore.p12
chgrp jetty /opt/jetty11-idp/etc/keystore.p12
Heslo, které jsme si vygenerovali pomocí příkazu ''openssl'' a použili ho, následně použijeme v dalším kroku, kde heslo vložíme do konfiguračního souboru ''idp.ini''.
==== idp.ini ====
V adresáři ''/opt/jetty11-idp/start.d'' si vytvoříme konfigurační soubor ''idp.ini'' s tímto obsahem:
# ---------------------------------------
# Module: idp
# Shibboleth IdP
# ---------------------------------------
--module=idp
# Allows setting Java system properties (-Dname=value)
# and JVM flags (-X, -XX) in this file
--exec
# Newer garbage collector that reduces memory needed for larger metadata files
-XX:+UseG1GC
# Maximum amount of memory that Jetty may use
-Xmx1500m
# Keystore password
jetty.sslContext.keyStorePassword=FIXME
# Truststore password
jetty.sslContext.trustStorePassword=FIXME
# KeyManager password
jetty.sslContext.keyManagerPassword=FIXME
# HTTP
jetty.http.host=127.0.0.1
jetty.http.port=80
# HTTPS
jetty.ssl.host=0.0.0.0
jetty.ssl.port=443
# Disable SSL renegotiation
jetty.sslContext.renegotiationAllowed=false
# Hide Jetty version
jetty.httpConfig.sendServerVersion=false
etc/tweak-ssl.xml
V souboru pak musíme nastavit ještě následující hesla na hodnotu vygenerovanou v předchozím kroku pomocí příkazu ''openssl'':
jetty.sslContext.keyStorePassword= ___HESLO___
jetty.sslContext.trustStorePassword= ___HESLO___
jetty.sslContext.keyManagerPassword= ___HESLO___
==== tweak-ssl.xml ====
V adresáři ''/opt/jetty11-idp'' si vytvoříme soubor ''tweak-ssl.xml'', v němž definujeme zakázané a povolené šifry a protokoly:
- .*DES.*
- .*DSS.*
- .*MD5.*
- .*NULL.*
- .*RC4.*
- .*_RSA_.*MD5$
- .*_RSA_.*SHA$
- .*_RSA_.*SHA1$
- TLS_DHE_RSA_WITH_AES_128.*
- TLS_DHE_RSA_WITH_AES_256.*
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
- SSL
- SSLv2
- SSLv2Hello
- SSLv3
- TLS_ECDHE.*
==== idp.xml ====
V adresáři ''/opt/jetty11-idp/webapps'' si vytvoříme konfigurační soubor, který zajistí, že v kontejneru Jetty poběží Shibboleth IdP. Soubor s názvem ''idp.xml'' bude mít tento obsah:
false
false
true
==== index.jsp ====
Vytvoříme adresář ''/opt/jetty11-idp/webapps/root'' a následně do souboru ''index.jsp'' umístíme přesměrování na stránku naší domovské organizace.
**Změňte ''www.example.org'' na domovskou adresu své organizace!**
# Vytvoření složky pro statický web v Jetty
mkdir -p /opt/jetty11-idp/webapps/root
# Vytvoření přesměrování na domovskou stránku
echo '<% response.sendRedirect("https://www.example.org"); %>' > \
/opt/jetty11-idp/webapps/root/index.jsp
==== Knihovny ====
Shibboleth IdP 5.0.0 bez viditelných oznámení — podobně jako řada 4 — obsahuje //commons-dbcp2.jar// a //commons-pool2.jar//, takže není nutné tyto knihovny dodávat do Jetty.
Jetty potřebuje pro správnou funkčnost do složky s externími knihovnami ''/opt/jetty11-idp/lib/ext'' nalinkovat pouze //mariadb-java-client.jar//, což je JDBC konektor do databáze MariaDB, kam se ukládají persistentní identifikátory uživatelů a souhlasy s uvolněním osobních informací. JDBC pro MariaDB jsme nainstalovali v [[mariadb|předchozím kroku]] instalací balíčku ''libmariadb-java''.
# Vytvoření složky lib/ext
mkdir -p /opt/jetty11-idp/lib/ext
# Vytvoření symbolického odkazu na JDBC
ln -s /usr/share/java/mariadb-java-client.jar \
/opt/jetty11-idp/lib/ext/mariadb-java-client.jar
===== Bezpečnost =====
Tento krok není pro běh IdP nutný, ale je velice vhodný pro zvýšení bezpečnosti uživatelů, kteří budou do přihlašovací stránky na IdP zadávat svá uživatelská jména a hesla.
==== jetty-rewrite.xml ====
V adresáři ''/opt/jetty11-idp/etc/'' vytvoříme soubor ''jetty-rewrite.xml'' s následujícím obsahem:
Zkontrolujte si zejména **Content-Security-Policy** hlavičku!
Pokud se v prohlížeči na IdP nenačtou např. styly nebo obrázky, je to chybějícími záznamy právě v Content-Security-Policy hlavičce. Pokud byste např. chtěli povolit načítání obrázků ze všech [šifrovaných] URL adres (a ne jenom z URL adresy serveru s IdP, čili //'self'//), pak musíte upravit //img-src// následovně: ''img-src: 'self' https:''.
Používáte-li pro obrázky formát SVG, který v sobě obsahuje definici kaskádových stylů, nezapomeňte do //style-src// přidat ještě hodnotu //'unsafe-inline'//, jinak se styly na SVG obrázek neaplikují. Výsledná definice pro styly tedy bude muset vypadat takto: ''style-src 'unsafe-inline' 'self'.''
//I přes tyto počáteční problémy se však toto bezpečnostní opatření vyplatí, protože webový prohlížeč odmítne uživatelům načíst podstrčené soubory, pokud by se to útočníkovi nějak povedlo.//
**Budete-li používat výchozí přihlašovací stránku IdP, budete mít s těmito pravidly drobný zádrhel. Výchozí přihlašovací stránka zobrazuje loga služeb. Pokud však v //img-src// nebudete mít ''https:'', loga se vám na přihlašovací stránce zobrazovat nebudou. A to nevypadá moc hezky. Zvažte tedy úpravu souboru ''views/login.vm'', anebo povolte načítání __všech__ obrázků po protokolu //https//.**
- REQUEST
- ASYNC
*
Strict-Transport-Security
max-age=15768000
*
X-Content-Type-Options
nosniff
*
X-Xss-Protection
1; mode=block
*
X-Frame-Options
DENY
*
Content-Security-Policy
default-src 'self'; style-src 'self'; script-src 'self' 'unsafe-inline'; img-src 'self'; font-src 'self'; frame-ancestors 'none'
*
Referrer-Policy
no-referrer-when-downgrade
===== Služba =====
Vytvoříme soubor služby jetty11 pomocí následující příkazu:
# Vytvoření služby jetty11 pro systemd
systemctl edit --full --force jetty11.service
Po překopírování níže uvedeného obsahu soubor **uložíme**:
[Unit]
Description=Jetty 11 Web Application Server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE
# Configuration
Environment="JETTY_HOME=/opt/jetty11"
Environment="JETTY_STATE=/opt/jetty11-idp/jetty11/jetty.state"
Environment="JETTY_RUN=/opt/jetty11-idp/jetty11"
Environment="JAVA_OPTS=-Djava.awt.headless=true"
EnvironmentFile=-/opt/jetty11/default/jetty11
# Security
User=jetty
Group=jetty
PrivateTmp=yes
NoNewPrivileges=true
WorkingDirectory=/opt/jetty11-idp/
LogsDirectory=jetty11
LogsDirectoryMode=750
ProtectSystem=strict
ReadWritePaths=/opt/jetty11-idp/logs/
ReadWritePaths=/opt/jetty11-idp/jetty11/
TimeoutSec=infinity
# Lifecycle
Type=forking
ExecStart=/opt/jetty11/bin/jetty.sh start
PIDFile=/opt/jetty11-idp/jetty11/jetty.pid
SuccessExitStatus=143
Restart=on-failure
# Logging
SyslogIdentifier=jetty11
[Install]
WantedBy=multi-user.target
Dále si ještě vytvoříme pracovní adresáře a stavový soubor pro Jetty:
# Vytvoření složek pro jetty11
mkdir /opt/jetty11-idp/{jetty11,logs}
# Upravení práv složek
chown jetty /opt/jetty11-idp/{jetty11,logs}
# Vytvoření souboru stavu jetty
touch /opt/jetty11-idp/jetty11/jetty.state
chown jetty:jetty /opt/jetty11-idp/jetty11/jetty.state
===== Modul rewrite =====
Před samotným spuštěním Jetty, přidáme a povolíme modul //rewrite// pomocí následujícího příkazu:
export JETTY_HOME=/opt/jetty11
export JETTY_BASE=/opt/jetty11-idp
cd $JETTY_HOME
java -jar start.jar --add-modules=rewrite
===== Restart =====
Konfigurace je hotová, čili můžeme Jetty spouštět po startu operačního systému a zároveň restartovat:
# Spouštět Jetty po startu operačního systému
systemctl enable jetty11
# Restartování Jetty
systemctl restart jetty11
Přesvědčíme se, že vše funguje:
# Kontrola síťových spojení
ss -tlpn | fgrep java
Měli bychom vidět, že port ''80'' poslouchá pouze na adrese ''127.0.0.1'' a port ''443'' na všech adresách:
# Kontrola síťových spojení
LISTEN 0 50 [::ffff:127.0.0.1]:80 *:* users:(("java",pid=15630,fd=61))
LISTEN 0 50 *:443 *:* users:(("java",pid=15630,fd=55))
Vyzkoušíme, jestli funguje přesměrování na domovskou stránku naší organizace:
# Vyzkoušení přesměrování
wget -S -O/dev/null http://localhost
wget -S -O/dev/null https://`hostname -f`