Aplikácia Shibboleth IdP je napísaná v jazku Java. Na jej spustenie budeme potrebovať Oracle JDK. Najskôr musíme na stránke http://www.oracle.com/technetwork/java/javase/downloads/index.html odkliknúť súhlas s lic. podmienkami Oracle: http://www.oracle.com/technetwork/java/javase/downloads/index.html

Potom stiahneme instalačný balíček (skopírujeme URL z webu - inštalujem JDK 8):

yum install jdk-8u192-linux-x64.rpm

Kontrola, či je Java nainštalovaná správne:

update-alternatives --display java

alebo

java -version

Ak sme inštalovali Javu z RPM od Oracle, JAVA_HOME treba nastaviť na adresár:

/usr/java/latest

Pridáme export JAVA_HOME do ~/.bashrc a ~/.bash_profile

JAVA_HOME=/usr/java/latest
export JAVA_HOME

Kvôli lepším možnostiam šifrovania treba doinštalovať JCE.

JCE stiahneme zo stránky Oracle podobne ako JDK (so súhlasom): http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

Zip archív rozbalime:

unzip -x jce_policy-8.zip

Rozbalené súbory skopírujeme na príslušné miesto do JAVA_HOME:

cp UnlimitedJCEPolicyJDK8/*.jar /usr/java/jdk1.8.0_192-amd64/jre/lib/security/

Ako aplikačný server budeme používať Jetty (podľa odporúčania Shibbloleth).

Server Jetty bude bežať pod neprivilegovaným používateľom (aj ked spúšťať sa bude pod rootom, ale o tom neskôr), ktorého treba vytvoriť:

groupadd idp
useradd -m -g idp -s /bin/bash idp

Stiahneme instalačný balík z webu (napr 9.3): http://central.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.3.25.v20180904/

Rozbalíme balík, presunieme ho do /opt a premenujeme na jetty:

tar -zxvf jetty-distribution-9.3.25.v20180904.tar.gz
mv jetty-distribution-9.3.25.v20180904 /opt/
mv /opt/jetty-distribution-9.3.25.v20180904 /opt/jetty

Zmeníme vlastníka adresára:

chown -R idp:idp /opt/jetty

Vytvoríme konfiguračný súbor v /etc

vim /etc/default/jetty

s obsahom:

JETTY_HOME=/opt/jetty
JETTY_BASE=/opt/jetty

Prepneme sa do používateľa idp a nakonfigurujeme Jetty pre potreby IdP:

su idp
cd /opt/jetty
java -jar /opt/jetty/start.jar --add-to-startd=http,https,logging,deploy,jsp,jstl,plus,servlets,annotations,ext,resources,logging,requestlog,setuid,rewrite

Upravíme konfiguračný súbor http.ini.

vim /opt/jetty/start.d/http.ini

HTTP len pre localhost na porte 80:

--module=http
jetty.http.host=localhost
jetty.http.port=80

HTTPS bude počúvať na štandartnom porte 443:

vim /opt/jetty/start.d/ssl.ini
jetty.ssl.port=443

Kvôli spúšťaniu jetty pod neprivilegovaným používateľom na privilegovanom porte:

vim /opt/jetty/start.d/setuid.ini
# ---------------------------------------
# Module: setuid
--module=setuid

## SetUID Configuration
jetty.setuid.startServerAsPrivileged=false
jetty.setuid.userName=idp
jetty.setuid.groupName=idp
jetty.setuid.umask=002

Vytvoríme domovskú strúnku pre web server (stále pod používateľom idp - obsah stránky podľa uváženia - môže byť aj presmerovanie na inú stránku).

mkdir -p /opt/jetty/webapps/root
vim /opt/jetty/webapps/root/index.html

Pripravíme server pre aplikáciu Shebboleth IdP:

mkdir /opt/jetty/tmp

Vytvoríme konfiguračný súbor aplikácie:

vim /opt/jetty/webapps/idp.xml

s obsahom:

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Set name="war">/opt/shibboleth-idp/war/idp.war</Set>
    <Set name="contextPath">/idp</Set>
    <Set name="extractWAR">false</Set>
    <Set name="copyWebDir">false</Set>
    <Set name="copyWebInf">true</Set>
    <Set name="tempDirectory">/opt/jetty/tmp</Set>
</Configure>
vim /opt/jetty/start.d/server.ini

Nebude sa zobrazovať verzia servera:

jetty.httpConfig.sendServerVersion=false

Content-Security-Policy by sme si mali upraviť podľa našich potrieb ale zatiaľ to necháme tak.

vim /opt/jetty/etc/jetty-rewrite.xml
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
 
<Configure id="Server" class="org.eclipse.jetty.server.Server">
 
  <!-- =========================================================== -->
  <!-- configure rewrite handler                                   -->
  <!-- =========================================================== -->
  <Call name="insertHandler">
    <Arg>
      <New class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
        <Set name="rewriteRequestURI"><Property name="jetty.rewrite.rewriteRequestURI" deprecated="rewrite.rewriteRequestURI" default="true"/></Set>
        <Set name="rewritePathInfo"><Property name="jetty.rewrite.rewritePathInfo" deprecated="rewrite.rewritePathInfo" default="false"/></Set>
        <Set name="originalPathAttribute"><Property name="jetty.rewrite.originalPathAttribute" deprecated="rewrite.originalPathAttribute" default="requestedPath"/></Set>
 
 
        <!-- Set DispatcherTypes  -->
        <Set name="dispatcherTypes">
          <Array type="javax.servlet.DispatcherType">
            <Item><Call class="javax.servlet.DispatcherType" name="valueOf"><Arg>REQUEST</Arg></Call></Item>
            <Item><Call class="javax.servlet.DispatcherType" name="valueOf"><Arg>ASYNC</Arg></Call></Item>
          </Array>
        </Set>
 
 
        <Call name="addRule">
          <Arg>
            <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
              <Set name="pattern">*</Set>
              <Set name="name">Strict-Transport-Security</Set>
              <Set name="value">max-age=15768000</Set>
            </New>
          </Arg>
        </Call>
 
        <Call name="addRule">
          <Arg>
            <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
              <Set name="pattern">*</Set>
              <Set name="name">X-Content-Type-Options</Set>
              <Set name="value">nosniff</Set>
            </New>
          </Arg>
        </Call>
 
        <Call name="addRule">
          <Arg>
            <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
              <Set name="pattern">*</Set>
              <Set name="name">X-Xss-Protection</Set>
              <Set name="value">1; mode=block</Set>
            </New>
          </Arg>
        </Call>
 
        <Call name="addRule">
          <Arg>
            <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
              <Set name="pattern">*</Set>
              <Set name="name">X-Frame-Options</Set>
              <Set name="value">DENY</Set>
            </New>
          </Arg>
        </Call>
 
        <Call name="addRule">
          <Arg>
            <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
              <Set name="pattern">*</Set>
              <Set name="name">Content-Security-Policy-Report-Only</Set>
              <Set name="value">default-src 'self'; style-src 'self' https://maxcdn.bootstrapcdn.com; script-src 'self' https://maxcdn.bootstrapcdn.com https://ajax.googleapis.com; img-src 'self'; font-src https://maxcdn.bootstrapcdn.com; frame-ancestors 'none'</Set>
            </New>
          </Arg>
        </Call>
 
        <Call name="addRule">
          <Arg>
            <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
              <Set name="pattern">*</Set>
              <Set name="name">Referrer-Policy</Set>
              <Set name="value">no-referrer-when-downgrade</Set>
            </New>
          </Arg>
        </Call>
 
      </New>
    </Arg>
  </Call>
</Configure>

Certifikát budem generovať ako root (exit).

Pripravime si SSL certifikát, ktorý budeme potrebovať ďalej.

Vygenerovanie novej žiadosti o cerifikát:

cd /root/ssl_cert
openssl req -new -newkey rsa:2048 -nodes -keyout demoidpkey -out demoidp.csr

Sôbor .csr poslať na podpis (stačí obsah sôboru). Podpísaný certifikát premenujeme na demoidp.crt.

Momentálne by sme mali mať v adresáari /root/ssl_cert tieto certifikáty:

  • demoidp.crt
  • demoidp.csr
  • demoidp.key
  • DigiCertCA.crt

Súbor so žiadosťou demoidp.csr už nebudeme potrebovať.

Certifikáty musíme „zlúčiť“ do jedného sôboru:

cat demoidp.crt DigiCertCA.crt > jetty-cert.txt

Vytvorený sôbor prevedieme do formátu PKCS #12. Pri tejto operácii budeme vyzvaný na zadanie hesla. Heslo si zapamätáme (označíme si ho ako Heslo1):

openssl pkcs12 -export -inkey demoidp.key -in jetty-cert.txt -out jetty-cert.pkcs12

Certifikát importujeme do keystore (súbor keystore sa vytvorí v adresári, kde zadávame príkaz - pozor aby boli práva na zápis). Pri vytváraní budeme požiadaný o vytvorenie nového hesla (označíme si ho Heslo2) a zadanie pôvodného hesla k certifikatu (Heslo1).

$JAVA_HOME/bin/keytool -importkeystore -srckeystore jetty-cert.pkcs12 -srcstoretype PKCS12 -destkeystore keystore

Keystore presunieme do /etc a zmeníme mu oprávnenia:

mv keystore /opt/jetty/etc
chown idp:idp /opt/jetty/etc/keystore

Pomocou jetty-util vygenerujeme obsfukované verzie hesiel Heslo1 a Heslo2:

java -cp /opt/jetty/lib/jetty-util-9.3.25.v20180904.jar org.eclipse.jetty.util.security.Password <Heslo2>

Výstupom príkazu bude niečo ako:

2018-12-06 12:28:09.771:INFO::main: Logging initialized @97ms
sKbH...Q5r9Q
OBF:1rxd1f9t1...1l5b1pbe1dv01v2n1f8t1rvh
MD5:b31221...a3b41cbac61f

Podobne treba obsfukovať aj Heslo1

java -cp /opt/jetty/lib/jetty-util-9.3.25.v20180904.jar org.eclipse.jetty.util.security.Password <Heslo1>

Výstupom príkazu bude niečo ako:

2018-12-06 12:30:12.968:INFO::main: Logging initialized @98ms
YAbK...3tRm
OBF:1sa31i7i1vfx...61jlf1e1z1vgx1i8g1sb7
MD5:34cdf9c2...904d366401d6

Obsfukované heslá zadáme do súboru start.d/ssl.ini:

vim /opt/jetty/start.d/ssl.ini

Heslá pre keyStorePassword a trustStorePassword su rovnaké:

jetty.sslContext.keyStorePassword=OBF:1rxd1f9t1v1r...1f8t1rvh        #Heslo2
jetty.sslContext.keyManagerPassword=OBF:1sa31i7i1vfx1...1i8g1sb7     #Heslo1
jetty.sslContext.trustStorePassword=OBF:1rxd1f9t1v1r...1v2n1f8t1rvh  #Heslo2

Zakážeme málo bezpečné šifry:

Vytvoríme súbor /opt/jetty/etc/tweak-ssl.xml

vim /opt/jetty/etc/tweak-ssl.xml

Obsah súboru:

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
  <!-- Zakázání starých a nedůvěryhodných šifer -->
  <Call name="addExcludeCipherSuites">
    <Arg>
      <Array type="String">
        <Item>.*DES.*</Item>
        <Item>.*DSS.*</Item>
        <Item>.*MD5.*</Item>
        <Item>.*NULL.*</Item>
        <Item>.*RC4.*</Item>
        <Item>.*_RSA_.*MD5$</Item>
        <Item>.*_RSA_.*SHA$</Item>
        <Item>.*_RSA_.*SHA1$</Item>
        <Item>TLS_DHE_RSA_WITH_AES_128.*</Item>
        <Item>TLS_DHE_RSA_WITH_AES_256.*</Item>
      </Array>
    </Arg>
  </Call>
 
  <!-- Zakázání nedůvěryhodných protokolů -->
  <Call name="addExcludeProtocols">
    <Arg>
     <Array type="java.lang.String">
       <Item>SSL</Item>
       <Item>SSLv2</Item>
       <Item>SSLv2Hello</Item>
       <Item>SSLv3</Item>
     </Array>
    </Arg>
  </Call>
 
  <!-- Povolení Forward Secrecy -->
  <Set name="IncludeCipherSuites">
    <Array type="String">
      <Item>TLS_DHE_RSA.*</Item>
      <Item>TLS_ECDHE.*</Item>
    </Array>
  </Set>
 
</Configure>

Pridáme obsah súboru do konfigurácie https:

echo /opt/jetty/etc/tweak-ssl.xml >> /opt/jetty/start.d/https.ini

Ak sme niekde omylom zle nastavili oprávnenia nastavíme ich znovu:

chown idp:idp -R /opt/jetty

Vytvoríme definíciu služby pre systemd:

Jetty treba spušťať pod rootom a potom keď otvorí port 80 a 443 sa „znížia“ jeho oprávnenia na idp. Používateľ idp tie porty nevie otvoriť.

vim /etc/systemd/system/jetty.service
#
# A basic systemd configuration for Jetty to start on boot 
# 
# Uses the Service scenario of 'oneshot' run as root
# and once the process has run, it is considered successful
# regardless of error code (even 'FAILURE') as jetty
# may take longer to start than jetty.sh observes it's logs 
# for.  
#
#

[Unit]
Description=Jetty Web Application Server
After=network.target

[Install]
WantedBy=multi-user.target
Alias=jetty.service
 
[Service]
Type=oneshot

# Execute pre and post scripts as root
PermissionsStartOnly=true

# The process will be considered active after it exits
RemainAfterExit=yes

# Note on the Start we do not wait for successful start.
# This is to allow the container to run beyond the jetty shell script
# in cases where it takes very long to start and results in jetty.sh
# reporting FAILED.  It's a false positive on failure.

ExecStart=-/opt/jetty/bin/jetty.sh start
ExecStop=/opt/jetty/bin/jetty.sh stop
ExecReload=/opt/jetty/bin/jetty.sh restart 
TREBA TO ESTE OTESTOVAT (asi ten unitfile nefunguje)

Povoliť HTTPS na firewalle:

firewall-cmd --zone=public --permanent --add-service=https
firewall-cmd --reload

Spustiť jetty:

systemctl daemon-reload
systemctl enable jetty
systemctl start jetty

Po spustení (chvíľu to trvá) by mala fungovať homepage po nasmerovaní browsera na demoidp.sanet.sk.

Zistenie stavu servera:

/opt/jetty/bin/jetty.sh check
  • install-idp-jetty.txt
  • Posledná úprava: 2019/07/23 13:55