Toto je staršia verzia dokumentu!
Inštalácia Shibboleth
IdP budeme inštalovať na Centos 7 podľa návodu uverejneného na https://www.eduid.cz/cs/tech/idp (s príslušnými zmenami).
yum install vim wget unzip ntp
NTP
Kvôli správnej funkcionalite IdP je dôležité aby mal server nastavený presný čas. To zabezpečíme spustením služby ntpd.
systemctl enable ntpd systemctl start ntpd
Po chvíli je možné vidieť zoznam serverov, s ktorými prebieha synchronizácia:
ntpq -p
Oracle Java
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
Java Cryptography Extension
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/
Jetty
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
Konfigurácia 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>
Ďalšie nastavenia a zabezpečenie
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>
SSL
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
Dokončenie inštalácie Jetty
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)
Firewall
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
Shibboleth IdP
Stiahneme a rozbalíme inľtalačný balíček:
wget https://shibboleth.net/downloads/identity-provider/3.4.1/shibboleth-identity-provider-3.4.1.tar.gz tar -xzf shibboleth-identity-provider-3.4.1.tar.gz
Spustíme inštaláciu:
./shibboleth-identity-provider-3.4.1/bin/install.sh
Výstup:
Source (Distribution) Directory (press <enter> to accept default): [/root/shibboleth-identity-provider-3.4.1] Installation Directory: [/opt/shibboleth-idp] Hostname: [demoidp.sanet.sk] SAML EntityID: [https://demoidp.sanet.sk/idp/shibboleth] Attribute Scope: [sanet.sk] Backchannel PKCS12 Password: <Heslo3> Re-enter password: <Heslo3> Cookie Encryption Key Password: <Heslo4> Re-enter password: <Heslo4> Warning: /opt/shibboleth-idp/bin does not exist. Warning: /opt/shibboleth-idp/edit-webapp does not exist. Warning: /opt/shibboleth-idp/dist does not exist. Warning: /opt/shibboleth-idp/doc does not exist. Warning: /opt/shibboleth-idp/system does not exist. Generating Signing Key, CN = demoidp.sanet.sk URI = https://demoidp.sanet.sk/idp/shibboleth ... ...done Creating Encryption Key, CN = demoidp.sanet.sk URI = https://demoidp.sanet.sk/idp/shibboleth ... ...done Creating Backchannel keystore, CN = demoidp.sanet.sk URI = https://demoidp.sanet.sk/idp/shibboleth ... ...done Creating cookie encryption key files... ...done Rebuilding /opt/shibboleth-idp/war/idp.war ... ...done BUILD SUCCESSFUL Total time: 3 minutes 8 seconds
Presunieme inštalačný adresár do /opt
(zatial neviem načo) a nastavíme opravnenia:
mv shibboleth-identity-provider-3.4.1 /opt/ chown -R idp:idp /opt/shibboleth-id*
Reštartujeme Jetty, servlet by sa mal nahrať:
systemctl restart jetty
Stav IdP môžeme zobraziť príkazom:
/opt/shibboleth-idp/bin/status.sh
Funkčnost je možné overiť aj zobrazením stránky v prehliadači: https://demoidp.sanet.sk/idp
Konfigurácia IdP
Prepnúť sa na používateľa idp:
su - idp
Aby Shibboleth poznal cestu k Jave aj pod neprivilegovaným učtom musíme ju špecifikovať:
JAVA_HOME=/usr/java/latest /opt/shibboleth-idp/bin/reload-service.sh -id shibboleth.ReloadableAccessControlService
conf/idp.properties
V konfigurácii idp nastavíme premennú idp.cookie.secure
na true (odkomentovať a zmeniť na true):
vim /opt/shibboleth-idp/conf/idp.properties
idp.cookie.secure = true
a reštartujeme jetty (ako root)
systemctl restart jetty
conf/access-control.xml
Tu je možné obmedziť prístup k stránkam so špeciálnou funkcionalitou (pre adminov):
vim /opt/shibboleth-idp/conf/access-control.xml
<util:map id="shibboleth.AccessControlPolicies"> <entry key="AccessByIPAddress"> <bean id="AccessByIPAddress" parent="shibboleth.IPRangeAccessControl" p:allowedRanges="#{ {'127.0.0.1/32', '194.160.39.60/32', '194.160.44.13/32'} }" /> </entry> ...
Znovunačitame konfigurácie (pokiaľ robíme pod userom idp musíme stále zadávať JAVA_HOME):
JAVA_HOME=/usr/java/latest /opt/shibboleth-idp/bin/reload-service.sh -id shibboleth.ReloadableAccessControlService
Teraz by malo byť možné z vybraných IP zobraziť napríklad info o stave idp: https://demoidp.sanet.sk/idp/status
conf/ldap.properties
Zaitaľ sa mi nepodarilo nakonfigurovať IdP tak aby mu stačilo spojenie s LDAP bez SSL. Možno je to bug: http://shibboleth.net/pipermail/users/2015-August/023536.html
Pre použitie SSL treba stiahnuť ssl certifikat z LDAP servera:
openssl s_client -showcerts -connect io.fpv.umb.sk:636 </dev/null 2>/dev/null|openssl x509 -outform PEM > /opt/shibboleth-idp/credentials/ldap-server.crt
vim /opt/shibboleth-idp/conf/ldap.properties
idp.authn.LDAP.authenticator = bindSearchAuthenticator idp.authn.LDAP.ldapURL = ldaps://ldap.umb.sk:636 idp.authn.LDAP.useStartTLS = false idp.authn.LDAP.useSSL = true idp.authn.LDAP.connectTimeout = PT3S idp.authn.LDAP.responseTimeout = PT3S idp.authn.LDAP.sslConfig = certificateTrust idp.authn.LDAP.trustCertificates = %{idp.home}/credentials/ldap-server.crt idp.authn.LDAP.baseDN = ou=users,dc=ldap,dc=umb,dc=sk idp.authn.LDAP.subtreeSearch = true idp.authn.LDAP.userFilter = (uid={user}) idp.authn.LDAP.bindDN = cn=demoidp,ou=system,ou=users,dc=ldap,dc=umb,dc=sk idp.authn.LDAP.bindDNCredential = ------- heslo pre ldap usera ------- idp.attribute.resolver.LDAP.ldapURL = %{idp.authn.LDAP.ldapURL} idp.attribute.resolver.LDAP.connectTimeout = %{idp.authn.LDAP.connectTimeout:PT3S} idp.attribute.resolver.LDAP.responseTimeout = %{idp.authn.LDAP.responseTimeout:PT3S} idp.attribute.resolver.LDAP.baseDN = %{idp.authn.LDAP.baseDN:undefined} idp.attribute.resolver.LDAP.bindDN = %{idp.authn.LDAP.bindDN:undefined} idp.attribute.resolver.LDAP.bindDNCredential = %{idp.authn.LDAP.bindDNCredential:undefined} idp.attribute.resolver.LDAP.useStartTLS = %{idp.authn.LDAP.useStartTLS:true} idp.attribute.resolver.LDAP.trustCertificates = %{idp.authn.LDAP.trustCertificates:undefined} idp.attribute.resolver.LDAP.searchFilter = (uid=$resolutionContext.principal)
conf/metadata-providers.xml
vim /opt/shibboleth-idp/conf/metadata-providers.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- This file is an EXAMPLE metadata configuration file. --> <MetadataProvider id="ShibbolethMetadata" xsi:type="ChainingMetadataProvider" xmlns="urn:mace:shibboleth:2.0:metadata" xmlns:resource="urn:mace:shibboleth:2.0:resource" xmlns:security="urn:mace:shibboleth:2.0:security" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:resource http://shibboleth.net/schema/idp/shibboleth-resource.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd"> <!-- safeID --> <MetadataProvider id="safeid-metadata" xsi:type="FileBackedHTTPMetadataProvider" backingFile="%{idp.home}/metadata/safeid.xml" metadataURL="https://www.safeid.sk/metadata/metadata.safeid.sk.xml" maxRefreshDelay="PT2H"> <MetadataFilter xsi:type="SignatureValidation" requireSignedRoot="true" certificateFile="%{idp.home}/credentials/SAFEID_metadata_signer.pem" /> </MetadataProvider> </MetadataProvider>
Stiahnuť verejný kľúč pre kontrolu podpisu metadát:
cd /opt/shibboleth-idp/credentials wget https://www.safeid.sk/metadata/cert/SAFEID_metadata_signer.pem
Reštart služby pre načítanie metadát:
JAVA_HOME=/usr/java/latest /opt/shibboleth-idp/bin/reload-service.sh -id shibboleth.MetadataResolverService
Kontrola, či sa metadata stiahli:
ls -l /opt/shibboleth-idp/metadata/
Vo výpise by sa mal nachádzať súbor safeid.xml
s aktuálnym časom vytvorenia.
conf/attribute-resolver.xml
cd /opt/shibboleth-idp/conf mv attribute-resolver-ldap.xml attribute-resolver.xml
TODO: Doplnit alebo nalinkovat obsah suboru attribute-resolver.xml
conf/attribute-filter.xml
Tu definujeme, ktoré atribúty budeme uvolnovať a komu.
vim /opt/shibboleth-idp/conf/attribute-filter.xml
TODO: Doplnit alebo nalinkovat obsah suboru attribute-filter.xml
metadata/idp-metadata.xml
Tu treba doplniť metadata.
vim /opt/shibboleth-idp/metadata/idp-metadata.xml
TODO: Doplnit alebo nalinkovat obsah suboru idp-metadata.xml
Po reštarte jetty budú metadata dostupné na adrese https://demoisp.sanet.sk/idp/shibboleth. Metadata je potrebné validovať vo validátore: https://mdr.safeid.sk/saml-validator/
Persistentný identifikátor / eduPersonTargetedID
Identifikátor sa generuje pre každý pár používateľ-služba a slúži na ochranu súkromia používatela (služba zároveň vie, že sa jedná o rovnakého používateľa). Kedže sa pre každú sluzbu generuje iný identifikátor a tento identifikátor je nahodny reťazec, nie je jednoducho možne pre prevádzkovateľa služby používateľa identifikovať ale zároven to umožäuje zo strany služby ukladať rôzne personalizované nastavenia atď. V tom je hlavný rozdiel oproti identifikátoru eduPersonPrinciaplName
, ktorý má spravidla hodnotu login@domena
.
Podpora pre túto funkcionalitu nie je povinná, ale je doporučovaná. Podobný efekt je možné dosiahnuť používaním generovaného čísla namiesto loginu používateľa v eduPersonPrinciaplName
. Samorejme to stráca zmysel ak spolu s týmto identifikátorom posielame ďalšie údaje ako meno, mail atď.
Navyše niektoré z konfigurašnych krokov, ktoré budú potrebné pre jeho spravádzkovanie bude potrebné aj tak urobiž kvôli ukladaniu súhlasov s poskytovaním atribútov.
Pre ukladanie údajov je odporúčané použiť databázu MySQL (nie MariaDB).
MySQL
Nainštalovať repozitár od Oracle - MySQL server:
yum install https://repo.mysql.com//mysql80-community-release-el7-1.noarch.rpm yum update yum install mysql-community-server
Spustiť server:
systemctl enable mysqld systemctl startmysqld
Po spustení server vygeneruje heslo pre roota, ktoré sa nachádza v logu:
cat /var/log/mysqld.log | grep password
Spustíme procedúru pre zabezpečenie databazy, v rámci ktorej zmeníme heslo pre roota (pozor, mysql8 má štandardne aktívne dosť prísne požiadavky na zložitosť hesla).
Aby sa nám s DB ľahšie pracovalo môžeme uložiť prihlasovacie údaje do súboru .my.cnf
:
vim /root/.my.cnf
obsah súboru:
[client] user=root password="4T............1I"
Nastavíme oprávnenia pre súbor:
chmod go-rwx .my.cnf
Prihlásime sa do cmd clienta a spustíme SQL príkazy pre vytvorenie databázy a používateľa (nezabudneme na silné heslo):
mysql
SET NAMES 'utf8'; SET CHARACTER SET utf8; CHARSET utf8; CREATE DATABASE IF NOT EXISTS shibboleth CHARACTER SET=utf8; CREATE USER 'shibboleth'@'localhost' IDENTIFIED BY 'jeGYjU....hFf7S'; GRANT ALL ON shibboleth.* TO 'shibboleth'@'localhost'; FLUSH PRIVILEGES;
Vytvoríme novú tabuľku v datábaze shibboleth:
USE shibboleth; CREATE TABLE IF NOT EXISTS `shibpid` ( `localEntity` VARCHAR(255) NOT NULL, `peerEntity` VARCHAR(255) NOT NULL, `principalName` VARCHAR(255) NOT NULL DEFAULT '', `localId` VARCHAR(255) NOT NULL, `persistentId` VARCHAR(50) NOT NULL, `peerProvidedId` VARCHAR(255) DEFAULT NULL, `creationDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `deactivationDate` TIMESTAMP NULL DEFAULT NULL, PRIMARY KEY (localEntity, peerEntity, persistentId) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Doinštalujeme knižnice do Jetty:
http://tux.rainside.sk/apache//commons/dbcp/binaries/commons-dbcp2-2.5.0-bin.tar.gz http://tux.rainside.sk/apache//commons/pool/binaries/commons-pool2-2.6.0-bin.tar.gz https://search.maven.org/remotecontent?filepath=commons-logging/commons-logging-api/1.1/commons-logging-api-1.1.jar https://cdn.mysql.com//Downloads/Connector-J/mysql-connector-java-8.0.13.tar.gz
TODO: Momentalne to bezi so starsimi kniznicami:
https://search.maven.org/remotecontent?filepath=org/apache/commons/commons-dbcp2/2.1.1/commons-dbcp2-2.1.1.jar https://search.maven.org/remotecontent?filepath=org/apache/commons/commons-pool2/2.4.2/commons-pool2-2.4.2.jar
Keďže MySQL je v aktuálnej verzii 8, driver musí byť tieť “najnovší” mysql-connector-java-8.0.13.tar.gz
.
Archívy treba porozbaľovať a potom skopírovať súbory:
cp commons-dbcp2-2.5.0/commons-dbcp2-2.5.0.jar /opt/jetty/lib/ext/ cp commons-pool2-2.6.0/commons-pool2-2.6.0.jar /opt/jetty/lib/ext/ cp commons-logging-api-1.1.jar /opt/jetty/lib/ext/ cp mysql-connector-java-8.0.13/mysql-connector-java-8.0.13.jar /opt/jetty/lib/ext/
chown idp:idp /opt/jetty/lib/ext/*
Konfigurácia IdP
vim /opt/shibboleth-idp/conf/attribute-resolver.xml
Doplniť nový atribút:
<AttributeDefinition id="eduPersonTargetedID" xsi:type="SAML2NameID" nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"> <InputDataConnector ref="myStoredId" attributeNames="storedId"/> <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" encodeType="false"/> <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="eduPersonTargetedID" encodeType="false"/> </AttributeDefinition>
A nový data konektor:
<DataConnector id="myStoredId" xsi:type="StoredId" sourceAttributeID="uid" generatedAttributeID="storedId" salt="<Zadat vygenerovany SALT>" queryTimeout="0"> <InputAttributeDefinition ref="uid"/> <BeanManagedConnection>shibboleth.MySQLDataSource</BeanManagedConnection> </DataConnector>
Konfiguračný súbor uložíme.
Vygenerujeme salt pomocou príkazu:
openssl rand -base64 36 2>/dev/null
Vystup vyzerá napríklad takto:
LdudV6JOJDzQOaF/4a75mApxsIFf7LVbjdgG3ME3hh7saPJw
Dodefinujeme potrebné beany v global.xml
vim /opt/shibboleth-idp/conf/global.xml
<bean id="shibboleth.MySQLDataSource" class="org.apache.commons.dbcp2.BasicDataSource" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost:3306/shibboleth" p:username="shibboleth" p:password="<heslo pre MySQL pouzivatela shibboleth>" /> <bean id="shibboleth.JPAStorageService" class="org.opensaml.storage.impl.JPAStorageService" p:cleanupInterval="%{idp.storage.cleanupInterval:PT10M}" c:factory-ref="shibboleth.JPAStorageService.entityManagerFactory" /> <bean id="shibboleth.JPAStorageService.entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="packagesToScan" value="org.opensaml.storage.impl"/> <property name="dataSource" ref="shibboleth.MySQLDataSource"/> <property name="jpaVendorAdapter" ref="shibboleth.JPAStorageService.JPAVendorAdapter"/> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> </property> </bean> <bean id="shibboleth.JPAStorageService.JPAVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" p:generateDdl="true" p:database="MYSQL" p:databasePlatform="org.hibernate.dialect.MySQL5Dialect" />
Nový atribút zaradíme aj do konfigurácie filtrov attribute-filter.xml
. Keďže sa jedná o anonymný atribút, môžeme ho sprístupnovať všetkým.
vim /opt/shibboleth-idp/conf/attribute-filter.xml
<AttributeRule attributeID="eduPersonTargetedID"> <PermitValueRule xsi:type="ANY" /> </AttributeRule>
Upravíme súbor saml-nameid.properties
:
vi /opt/shibboleth-idp/conf/saml-nameid.properties
Doplníme potrebné atribúty (odkazy na beany a salt):
idp.persistentId.generator = shibboleth.StoredPersistentIdGenerator idp.persistentId.dataSource = shibboleth.MySQLDataSource idp.persistentId.sourceAttribute = uid idp.persistentId.salt = LdudV6JOJDzQOaF/4a75mApxsIFf7LVbjdgG3ME3hh7saPJw
Ďalej upravíme konfiguráciu v saml-nameid.xml
vim /opt/shibboleth-idp/conf/saml-nameid.xml
V sôbore odkomentujeme tento riadok:
<ref bean="shibboleth.SAML2PersistentGenerator" />
Ďalej upravíme súbor:
vim /opt/shibboleth-idp/conf/idp.properties
V súbore doplníme riadok:
idp.consent.StorageService = shibboleth.JPAStorageService
Ešte ostáva upraviť súbor subject-c14n.xml
:
vim /opt/shibboleth-idp/conf/c14n/subject-c14n.xml
V súbore odkomentujeme riadok:
<ref bean="c14n/SAML2Persistent" />
V metadatach budeme oznamovaž, že IdP podporuje persistentný identifikátor:
vim /opt/shibboleth-idp/metadata/idp-metadata.xml
Do elementu IDPSSODescriptor
pridáme element (napríklad za element <ArtifactResolutionService …>):
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
Vygenerujeme nový WAR súbor a reľtartujeme Jetty:
/opt/shibboleth-idp/bin/build.sh systemctl restart jetty
Úprava prihlasovacej stránky
TODO