cs:tech:idp:shibboleth

Shibboleth IdP

Tato sekce je rozdělena na dvě části – instalaci a konfiguraci. Samotná instalace je velmi triviální, zabere minimum času a rozdíly v ní jsou jen na úrovni vyplnění odpovídajícího entity ID apod. Konfigurace je již dost individuální v závislosti na tom, čeho chceme dosáhnout, zda-li používáme pro ověření uživatele LDAP server nebo Active Directory atd.


Instalace IdP

Zdrojové kódy Shibboleth IdP můžeme stáhnout ze stránky projektu a umístit do adresáře /opt/src anebo pomocí programu wget následujícím způsobem. Nezapomeneme ověřit SHA256 otisk a GPG podpis.

# Stažení zdrojového kódu Shibboleth IdP
mkdir -p /opt/src
cd /opt/src/
wget https://shibboleth.net/downloads/identity-provider/3.4.3/shibboleth-identity-provider-3.4.3.tar.gz \
     https://shibboleth.net/downloads/identity-provider/3.4.3/shibboleth-identity-provider-3.4.3.tar.gz.asc \
     https://shibboleth.net/downloads/identity-provider/3.4.3/shibboleth-identity-provider-3.4.3.tar.gz.sha256
 
# Kontrola SHA256 otisku
sha256sum -c shibboleth-identity-provider-3.4.3.tar.gz.sha256
 
# Kontrola GPG podpisu
# Nejprve importujeme klíč 07CEEB8B
#gpg --keyserver hkp://keys.gnupg.net --search-keys 07CEEB8B
# Nyní můžeme provést samotnou kontrolu
#gpg --verify shibboleth-identity-provider-3.4.3.tar.gz.asc

Nyní přistoupíme k samotné instalaci IdP.

# Instalace Shibboleth IdP
cd /opt/
tar -xzf src/shibboleth-identity-provider-3.4.3.tar.gz
cd shibboleth-identity-provider-3.4.3/
./bin/install.sh

Po spuštění instalačního skriptu:

  1. potvrdíme zdrojový instalační adresář,
  2. vyplníme hostname serveru (pokud není předvyplněn správně),
  3. potvrdíme entityID (případně upravíme na to stávající, které aktuálně používáme ve federaci [prosím, neměňte entityID, zbytečně si tím přiděláte problémy!]),
  4. zadáme scope organizace,
  5. vložíme dvě hesla, o která budeme požádáni (jako generátor lze použít unixovou utilitu pwgen).

Zde je vyobrazen průběh instalačního skriptu install.sh.

./bin/install.sh
Source (Distribution) Directory (press <enter> to accept default): [/opt/shibboleth-identity-provider-3.4.3]
 
Installation Directory: [/opt/shibboleth-idp]
 
Hostname: [localhost.localdomain]
whoami-dev.cesnet.cz
SAML EntityID: [https://whoami-dev.cesnet.cz/idp/shibboleth]
 
Attribute Scope: [localdomain]
cesnet.cz
Backchannel PKCS12 Password: 
Re-enter password: 
Cookie Encryption Key Password: 
Re-enter password: 
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 = whoami-dev.cesnet.cz URI = https://whoami-dev.cesnet.cz/idp/shibboleth ...
...done
Creating Encryption Key, CN = whoami-dev.cesnet.cz URI = https://whoami-dev.cesnet.cz/idp/shibboleth ...
...done
Creating Backchannel keystore, CN = whoami-dev.cesnet.cz URI = https://whoami-dev.cesnet.cz/idp/shibboleth ...
...done
Creating cookie encryption key files...
...done
Rebuilding /opt/shibboleth-idp/war/idp.war ...
...done
 
BUILD SUCCESSFUL
Total time: 30 seconds

Změníme vlastníka a skupinu pro adresáře /opt/shibboleth-idp a /opt/shibboleth-identity-provider-3.*:

# Změna práv k adresářům Shibbolethu (jako uživatel root)
chown -R idp:idp /opt/shibboleth-id*

Restartujeme Jetty, čímž dosáhneme nahrání servletu s Shibboleth IdP:

# Restart Jetty pro nahrání Shibboleth IdP WAR
systemctl restart jetty

Nyní můžeme vyzkoušet, zda-li Shibboleth IdP běží (je potřeba, aby Jetty běželo na HTTP/port 80, jinak je nutno použít parametr -u a zadat URL adresu, kam má být dotaz směřován – výchozí je http://localhost/idp):

# Zobrazení statusu IdP
cd /opt/shibboleth-idp/
./bin/status.sh

Pokud vše proběhlo bez problémů, uvidíte následující výstup:

### Operating Environment Information
operating_system: Linux
operating_system_version: 4.9.0-6-amd64
operating_system_architecture: amd64
jdk_version: 1.8.0_181
available_cores: 1
used_memory: 291 MB
maximum_memory: 957 MB

### Identity Provider Information
idp_version: 3.4.3
start_time: 2019-01-29T13:19:08+01:00
current_time: 2019-01-30T10:12:48+01:00
uptime: 75219793 ms

service: shibboleth.LoggingService
last successful reload attempt: 2019-01-29T12:15:36Z
last reload attempt: 2019-01-29T12:15:36Z

service: shibboleth.ReloadableAccessControlService
last successful reload attempt: 2019-01-29T12:15:46Z
last reload attempt: 2019-01-29T12:15:46Z

service: shibboleth.MetadataResolverService
last successful reload attempt: 2019-01-29T12:15:43Z
last reload attempt: 2019-01-29T12:15:43Z

service: shibboleth.RelyingPartyResolverService
last successful reload attempt: 2019-01-29T12:15:42Z
last reload attempt: 2019-01-29T12:15:42Z

service: shibboleth.NameIdentifierGenerationService
last successful reload attempt: 2019-01-29T12:15:42Z
last reload attempt: 2019-01-29T12:15:42Z

service: shibboleth.AttributeResolverService
last successful reload attempt: 2019-01-29T12:15:39Z
last reload attempt: 2019-01-29T12:15:39Z

	DataConnector staticAttributes: has never failed

service: shibboleth.AttributeFilterService
last successful reload attempt: 2019-01-29T12:15:39Z
last reload attempt: 2019-01-29T12:15:39Z

Můžete také zkusit ze svého počítače přístoupit na URL adresu s IdP: https://HOSTNAME/idp. Nicméně neuvidíte nic zajímavého:

Konfigurace IdP

Samotná konfigurace IdP může být velmi různorodá vzhledem k požadovaným vlastnostem a chování. Zde bude uvedeno elementární nastavení, které je dostatečným mustrem pro další odladění pro potřeby Vaší organizace.

Popis konfigurace je psán lineárně, proto tedy, prosím, nepřeskakujte jednotlivé části.

Veškeré úpravy budeme provádět pod neprivilegovaným uživatelským účtem idp, takže se na něj přepneme. Pouze pro restart Jetty potřebujeme mít rootovská práva.

# Přepnutí se na uživatele idp
su - idp

V případě, že budeme restartovat nějakou službu Shibboleth IdP serveru pod neprivilegovaným uživatelem a dostaneme chybu ERROR: JAVA_HOME environment variable is not set., nadefinujeme před příkazem proměnnou JAVA_HOME odkazující do adresáře, kde je nainstalované OpenJDK:

JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre /opt/shibboleth-idp/bin/reload-service.sh -id shibboleth.ReloadableAccessControlService

conf/idp.properties

V tomto základním konfiguračním souboru odkomentujeme proměnnou idp.cookie.secure a nastavíme na true. Bližší informace můžete vyčíst v dokumentaci.

# Úpravy konfiguračního souboru idp.properties
vi /opt/shibboleth-idp/conf/idp.properties
idp.cookie.secure = true

Následně restartujeme Jetty.

# Spustíme jako uživatel root
systemctl restart jetty

conf/access-control.xml

V tomto souboru lze nastavit IP adresy (anebo rozsahy IP adres), které mají mít přístup k diagnostické stránce (https://SERVER/idp/status) a dalším administrativním funkcionalitám, jako znovunačtení určitého konfiguračního soboru po zadání speciální URL adresy a podobně.

Doporučuji, abyste zde povolili přístup pouze z nezbytně nutných IP adres.

# Úpravy konfiguračního souboru access-control.xml
vi /opt/shibboleth-idp/conf/access-control.xml

V příkladu přidáme IPv4 adresu 192.0.2.100/32 a IPv6 adresu 2001:db8::dead:cafe/128. Adresy musí být zadány včetně síťové masky!

p:allowedRanges="#{ {'127.0.0.1/32', '::1/128', '192.0.2.100/32', '2001:db8::dead:cafe/128'} }"

Necháme načíst novou konfiguraci:

# Znovunačtení konfigurace ACL
cd /opt/shibboleth-idp
./bin/reload-service.sh -id shibboleth.ReloadableAccessControlService

Nyní, pokud z počítače s danou IP adresou přistoupíte na adresu https://SERVER/idp/status, zobrazí se Vám informace o systému, které můžete z konzole získat po spuštění příkazu /opt/shibboleth-idp/bin/status.sh.

conf/ldap.properties

V Shibboleth IdP 2.x se používala autentikace JAAS, stejně jako tomu bylo na školení. Nicméně, ač je to v Shibboleth IdP 3.x stále podporované, je to ve většině případů zbytečnost. Pokud tedy JAAS opravdu nepotřebujete, doporučuji nepoužívat.

V souboru conf/ldap.properties se nastavuje konektor do LDAP serveru, pomocí něhož budeme získávat uživatelské atributy.

# Úpravy konfiguračního souboru ldap.properties
vi /opt/shibboleth-idp/conf/ldap.properties

Důležité jsou především následující volby:

idp.authn.LDAP.authenticator     = bindSearchAuthenticator
idp.authn.LDAP.ldapURL           = ldaps://ldap1.example.org:636 \
                                   ldaps://ldap2.example.org:636
idp.authn.LDAP.useStartTLS       = false
idp.authn.LDAP.useSSL            = true
idp.authn.LDAP.sslConfig         = certificateTrust
idp.authn.LDAP.trustCertificates = %{idp.home}/credentials/ldap-server.crt
idp.authn.LDAP.baseDN            = ou=people,dc=example,dc=org
idp.authn.LDAP.subtreeSearch     = true
idp.authn.LDAP.bindDN            = uid=shibboleth,ou=users,dc=example,dc=org
idp.authn.LDAP.bindDNCredential  = nejakeheslo

První konfigurační parametr idp.authn.LDAP.authenticator určuje, jak se bude přistupovat k LDAP serveru. Výchozí (zakomentovaná) hodnota je anonSearchAuthenticator, takže se k LDAPu přistupuje anonymně. Pokud však chcete, aby se dotazování LDAP serveru provádělo až po přihlášení, je potřeba nastavit volbu na hodnotu bindSearchAuthenticator.

Volba idp.authn.LDAP.ldapURL určuje, ke kterému LDAP serveru se bude Shibboleth připojovat. Ve výše uvedeném příkladu to jsou LDAP servery ldap1.example.org a ldap2.example.org a připojovat se k nim budeme pomocí zabezpečeného SSL na stadardním portu 636.

Poznámka k ldapURL: V ldapURL nesmíme uvést koncové lomítko, např. ldaps://ldap1.example.org:636/, jinak nebude Shibboleth fungovat a v logu najdeme java.lang.NumberFormatException: For input string: „636/“.

Konfigurační volby idp.authn.LDAP.useStartTLS a idp.authn.LDAP.useSSL říkají, že namísto TLS budeme používat SSL. Následující volba idp.authn.LDAP.trustCertificates udává cestu ke kořenovému certifikátu CA, která vydala SSL certifikát pro LDAP servery ldap1.example.org a ldap2.example.org. Je nutné nezapomenout nakopírovat tento soubor na odpovídající místo a nastavit odpovídající práva, aby tento soubor mohl číst neprivilegovaný uživatel idp.

Volba idp.authn.LDAP.baseDN určuje tzv. „base DN“ v LDAPu. Volby idp.authn.LDAP.bindDN a idp.authn.LDAP.bindDNCredential určují uživatelské jméno a heslo, které se použije při přístupu k LDAP serveru pro získání uživatelských atributů.

conf/metadata-providers.xml

V konfiguračním souboru conf/metadata-providers.xml se nastavují zdroje metadat. V následujícím příkladu je jako zdroj metadat použita produkční federace eduID.cz, testovací federace czTestFed, která se hodí pro testovací účely, pokud připojujete nové IdP (případně SP), a mezinárodní federace eduGAIN. Metadata se stáhnou a lokálně uloží.

# Úpravy konfiguračního souboru metadata-providers.xml
vi /opt/shibboleth-idp/conf/metadata-providers.xml
<!-- eduID.cz -->
<MetadataProvider
    id="eduidcz-metadata"
    xsi:type="FileBackedHTTPMetadataProvider"
    backingFile="%{idp.home}/metadata/eduidcz.xml"
    metadataURL="https://metadata.eduid.cz/entities/eduid+sp"
    maxRefreshDelay="PT15M">
    <MetadataFilter
        xsi:type="SignatureValidation"
        requireSignedRoot="true"
        certificateFile="%{idp.home}/credentials/metadata.eduid.cz.crt.pem" />
</MetadataProvider>
 
<!-- czTestFed -->
<MetadataProvider
    id="cztestfed-metadata"
    xsi:type="FileBackedHTTPMetadataProvider"
    backingFile="%{idp.home}/metadata/cztestfed.xml"
    metadataURL="https://metadata.eduid.cz/entities/cztestfed"
    maxRefreshDelay="PT15M">
    <MetadataFilter
        xsi:type="SignatureValidation"
        requireSignedRoot="true"
        certificateFile="%{idp.home}/credentials/metadata.eduid.cz.crt.pem" />
</MetadataProvider>
 
<!-- eduGAIN -->
<MetadataProvider
    id="edugain-metadata"
    xsi:type="FileBackedHTTPMetadataProvider"
    backingFile="%{idp.home}/metadata/edugain.xml"
    metadataURL="https://metadata.eduid.cz/entities/edugain+sp"
    maxRefreshDelay="PT15M">
    <MetadataFilter
        xsi:type="SignatureValidation"
        requireSignedRoot="true"
        certificateFile="%{idp.home}/credentials/metadata.eduid.cz.crt.pem" />
</MetadataProvider>

Blok kódu výše, tedy element <MetadataProvider> se všemi atributy, je nutné umístit do elementu <MetadataProvider> v konfiguračním souboru metadata-providers.xml! Sice to působí podivně, ale bez toho nebude XML dokument validní a konfigurace nebude fungovat.

Význam atributů elementu <MetadataProvider> je následující:

  • id – identifikátor poskytovatele metadat (využit pro logování apod.),
  • xsi:type – určuje typ pluginu použitého pro čtení metadat,
  • backingFile – určuje soubor, kam se metadata lokálně uloží,
  • metadataURL – zdrojová adresa metadat,
  • maxRefreshDelay – aktulizace metadat každých 15 minut.

Metadata federací eduID.cz, czTestFed i eduGAIN jsou podepsána. Důrazně doporučujeme tedy jejich autenticitu ověřovat pomocí kontroly podpisu. Veřejný klíč je k dispozici na adrese https://www.eduid.cz/docs/eduid/metadata/metadata.eduid.cz.crt.pem. Stáhněte ho a uložte do adresáře /opt/shibboleth-idp/credentials.

# Stažení veřejného klíče metadata.eduid.cz.crt.pem
wget -P /opt/shibboleth-idp/credentials https://www.eduid.cz/docs/eduid/metadata/metadata.eduid.cz.crt.pem

Restartujeme službu pro načtení federačních metadat:

# Znovunačtení konfigurace metadat
cd /opt/shibboleth-idp
./bin/reload-service.sh -id shibboleth.MetadataResolverService

V adresáři /opt/shibboleth-idp/metadata se můžeme přesvědčit, že se federační metadata stáhla a uložila:

# Zobrazení stažených metadat
ls -1 metadata/
# Výpis stažených metadat
cztestfed.xml
edugain.xml
eduidcz.xml
idp-metadata.xml

Poznámka k metadatům

Stahujete-li na své IdP metadata produkční federace eduID.cz i testovací federace czTestFed, počítejte s tím, že při vyhodnocování filtrů (konfigurační soubor attribute-filter.xml) pro uvolňování atributů (Attribute Release Policy, ARP) může dojít k nepříjemnostem.

Je-li nějaká služba (SP) v obou federacích, které chcete uvolňovat atributy na základě entityID, pak se budou atributy uvolňovat v závislosti na tom, která metadata máte v konfiguračním souboru metadata-providers.xml uvedena dříve. Jsou-li to metadata federace eduID.cz, služba dostane atributy jako byste k ní přistopovali VŽDY přes federaci eduID.cz, i kdybyste se hlásili prostřednictvím czTestFedu.

Pokud Vám výše uvedené není jasné, uveďte jednoduše metadata federace eduID.cz v metadata-providers.xml před metadata federace czTestFed (jako je uvedeno v příkladu výše) a po odladění konfigurace a přesunu IdP do eduID.cz přestaňte stahovat metadata czTestFedu a odstraňte své IdP z této federace v JAGGERu. Podobně to platí i pro eduGAIN. Pokud si jste jistí, že eduGAIN nepotřebujete, nemusíte metadata eduGAINu stahovat. V drtivé většině případů metadata eduGAINu opravdu chcete.

conf/attribute-resolver.xml

Jelikož budeme mnohé uživatelské atributy získávat z LDAP serveru, jako základ tohoto konfiguračního souboru (attribute-resolver.xml) použijeme předpřipravený soubor attribute-resolver-ldap.xml, který obsahuje ukázkový LDAP konektor. Původní konfigurační soubor attribute-resolver.xml můžeme s klidem přepsat, nebudeme ho již potřebovat a pokud náhodou ano, najdeme ho v adresáři /opt/shibboleth-idp/dist/conf/, stejně tak jako původní konfigurační soubor attribute-resolver-ldap.xml.

Chcete-li se inspirovat, podívejte se na attribute-resolver.xml, který používáme na CESNETu. Obsahuje i skriptované atributy, u nichž se můžete inspirovat. Avšak důrazně doporučuji, abyste tento soubor slepě nepoužívali, protože mnohé atributy očekávají další úpravy v konfiguračních souborech. Je to však užitečný vzor.

Pro konfigurační soubor attribute-resolver.xml doporučuji začít s výchozím konfiguračním souborem, postupujte následovně:

# Připravení konfiguračního souboru attribute-resolver.xml
cd /opt/shibboleth-idp/conf
mv attribute-resolver-ldap.xml attribute-resolver.xml
vi attribute-resolver.xml

Následující atributy budeme získávat z LDAP serveru. U atributu eduPersonPrincipalName není třeba nastavovat „scope“, jelikož se bere hodnota z konfiguračního souboru idp.properties, kam se „scope“ zadává po spuštění instalačního skriptu Shibboleth IdP.

Atribut eduPersonPrincipalName se generuje z hodnoty atributu uid, který má ve své definici dependencyOnly=„true“, což znamená, že se hodnota uid atributu samostatně neuvolňuje, je definován je pro použití v jiných atributech. Atribut uid byste v rámci federace identit nikdy neměli používat. Toto nastavení (dependencyOnly=„true“) lze samozřejmě použít i u dalších atributů podobných vlastností — atribut používá se jako vstup pro jiné atributy, ale samostatně se nikdy neuvolňuje.

Definice atributů je následující:

<!-- authMail -->
<AttributeDefinition id="authMail" xsi:type="Simple">
    <InputDataConnector ref="myLDAP" attributeNames="authorisedMail"/>
    <DisplayName xml:lang="cs">Autorizovaný/é e-mail/y</DisplayName>
    <DisplayName xml:lang="en">Authorized email(s)</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:oid:1.2.840.113549.1.9.1" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.2.840.113549.1.9.1" friendlyName="mail" encodeType="false"/>
</AttributeDefinition>
 
<!-- cn -->
<AttributeDefinition id="cn" xsi:type="Simple">
    <InputDataConnector ref="myLDAP" attributeNames="cn"/>
    <DisplayName xml:lang="cs">Celé jméno</DisplayName>
    <DisplayName xml:lang="en">Full name</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:cn" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.3" friendlyName="cn" encodeType="false"/>
</AttributeDefinition>
 
<!-- commonNameASCII -->
<AttributeDefinition id="commonNameASCII" xsi:type="Simple">
    <InputDataConnector ref="myLDAP" attributeNames="cn;lang-en"/>
    <DisplayName xml:lang="cs">Celé jméno bez diakritiky</DisplayName>
    <DisplayName xml:lang="en">Full name without diacritics</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="http://eduid.cz/attributes/commonName#ASCII" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="http://eduid.cz/attributes/commonName#ASCII" friendlyName="commonNameASCII" encodeType="false"/>
</AttributeDefinition>
 
<!-- displayName -->
<AttributeDefinition id="displayName" xsi:type="Simple">
    <InputAttributeDefinition ref="cn" />
    <DisplayName xml:lang="cs">Zobrazované jméno</DisplayName>
    <DisplayName xml:lang="en">Display name</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:displayName" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.16.840.1.113730.3.1.241" friendlyName="displayName" encodeType="false"/>
</AttributeDefinition>
 
<!-- eduPersonEntitlement -->
<AttributeDefinition id="eduPersonEntitlement" xsi:type="Simple">
    <InputDataConnector ref="staticAttributes" attributeNames="eduPersonEntitlement"/>
    <DisplayName xml:lang="cs">Oprávnění pro některé služby</DisplayName>
    <DisplayName xml:lang="en">Permissions for specific services</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonEntitlement" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7" friendlyName="eduPersonEntitlement" encodeType="false"/>
</AttributeDefinition>
 
<!-- eduPersonPrincipalName -->
<AttributeDefinition id="eduPersonPrincipalName" xsi:type="Scoped" scope="%{idp.scope}">
    <InputDataConnector ref="myLDAP" attributeNames="uid"/>
    <DisplayName xml:lang="cs">Jednoznačný identifikátor</DisplayName>
    <DisplayName xml:lang="en">Unique identifier</DisplayName>
    <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonPrincipalName" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" friendlyName="eduPersonPrincipalName" encodeType="false"/>
</AttributeDefinition>
 
<!-- eduPersonUniqueId -->
<AttributeDefinition id="eduPersonUniqueId" xsi:type="Scoped" scope="%{idp.scope}">
    <InputDataConnector ref="myLDAP" attributeNames="tcsPersonalID"/>
    <DisplayName xml:lang="cs">Jednoznačný neměnný identifikátor s doménou</DisplayName>
    <DisplayName xml:lang="en">Unique persistent scoped identifier</DisplayName>
    <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.13" friendlyName="eduPersonUniqueId" encodeType="false"/>
</AttributeDefinition>
 
<!-- eduPersonScopedAffiliation -->
<AttributeDefinition id="eduPersonScopedAffiliation" xsi:type="Scoped" scope="%{idp.scope}">
    <InputAttributeDefinition ref="eduPersonAffiliation"/>
    <DisplayName xml:lang="cs">Role v rámci organizace</DisplayName>
    <DisplayName xml:lang="en">Role(s) in organization</DisplayName>
    <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" friendlyName="eduPersonScopedAffiliation" encodeType="false"/>
</AttributeDefinition>
 
<!-- givenName -->
<AttributeDefinition id="givenName" xsi:type="Simple">
    <InputDataConnector ref="myLDAP" attributeNames="givenName"/>
    <DisplayName xml:lang="cs">Křestní jméno</DisplayName>
    <DisplayName xml:lang="en">First name</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:givenName" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.42" friendlyName="givenName" encodeType="false"/>
</AttributeDefinition>
 
<!-- mail -->
<AttributeDefinition id="mail" xsi:type="Simple">
    <InputDataConnector ref="myLDAP" attributeNames="mail"/>
    <DisplayName xml:lang="cs">E-mail/y</DisplayName>
    <DisplayName xml:lang="en">Email(s)</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:mail" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.3" friendlyName="mail" encodeType="false"/>
</AttributeDefinition>
 
<!-- sn -->
<AttributeDefinition id="sn" xsi:type="Simple">
    <InputDataConnector ref="myLDAP" attributeNames="sn"/>
    <DisplayName xml:lang="cs">Příjmení</DisplayName>
    <DisplayName xml:lang="en">Last name</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:sn" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.4" friendlyName="sn" encodeType="false"/>
</AttributeDefinition>
 
<!-- uid -->
<AttributeDefinition id="uid" xsi:type="Simple" dependencyOnly="true">
    <InputDataConnector ref="myLDAP" attributeNames="uid"/>
    <DisplayName xml:lang="cs">Uživatelské jméno</DisplayName>
    <DisplayName xml:lang="en">Username</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:uid" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.1" friendlyName="uid" encodeType="false"/>
</AttributeDefinition>
 
<!-- unstructuredName -->
<AttributeDefinition id="unstructuredName" xsi:type="Simple">
    <InputDataConnector ref="myLDAP" attributeNames="tcsPersonalID"/>
    <DisplayName xml:lang="cs">Jednoznačný neměnný identifikátor</DisplayName>
    <DisplayName xml:lang="en">Unique persistent identifier</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:oid:1.2.840.113549.1.9.2" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.2.840.113549.1.9.2" friendlyName="unstructuredName" encodeType="false"/>
</AttributeDefinition>

Některé atributy, jako např. cn anebo commonNameASCII můžete snadno generovat, pokud je nemáte v LDAP/AD serveru.

Atributy eduPersonAffiliation (příslušnost k organizaci), o (název organizace) a schacHomeOrganization mají definice statické. Jsou to hodnoty, které jsou pro všechny naše uživatele stejné, takže je nemá smysl mít uložené v LDAP serveru, i když to není samozřejmě zakázané. Využití statických hodnot atributů se hodí, proto malá ukázka:

<!-- eduPersonAffiliation -->
<AttributeDefinition id="eduPersonAffiliation" xsi:type="Simple" dependencyOnly="true">
    <InputDataConnector ref="staticAttributes" attributeNames="eduPersonAffiliation"/>
    <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonAffiliation" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1" friendlyName="eduPersonAffiliation" encodeType="false"/>
</AttributeDefinition>
 
<!-- o -->
<AttributeDefinition id="o" xsi:type="Simple" >
    <InputDataConnector ref="staticAttributes" attributeNames="o"/>
    <DisplayName xml:lang="cs">Domovská organizace</DisplayName>
    <DisplayName xml:lang="en">Home organization name</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:o" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.10" friendlyName="o" encodeType="false"/>
</AttributeDefinition>
 
<!-- schacHomeOrganization -->
<AttributeDefinition id="schacHomeOrganization" xsi:type="Simple" >
    <InputDataConnector ref="staticAttributes" attributeNames="schacHomeOrganization"/>
    <DisplayName xml:lang="cs">Doména domovské organizace</DisplayName>
    <DisplayName xml:lang="en">Home organization domain</DisplayName>
    <AttributeEncoder xsi:type="SAML1String" name="urn:oid:1.3.6.1.4.1.25178.1.2.9" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.25178.1.2.9" friendlyName="schacHomeOrganization" encodeType="false"/>
</AttributeDefinition>

Atributy, které jsou pro každého uživatele jiné (jako jméno a příjmení) získáváme z LDAP konektoru nazvaného myLDAP. Všechny potřebné informace ohledně LDAP serveru, uživatelském jménu a heslu atd. jsme již vyplnili v souboru conf/ldap.properties.

Atributy, jež jsou pro všechny uživatele stejné, budeme získávat ze statického datového konektoru následovně:

<!-- Static Data Connector -->
<DataConnector id="staticAttributes" xsi:type="Static">
 
    <Attribute id="eduPersonAffiliation">
        <Value>affiliate</Value>
    </Attribute>
 
    <Attribute id="o">
        <Value>EXAMPLE, s. r. o.</Value>
    </Attribute>
 
    <Attribute id="schacHomeOrganization">
        <Value>%{idp.scope}</Value>
    </Attribute>
 
</DataConnector>

conf/attribute-filter.xml

Mít definované atributy nestačí. Ještě je totiž potřeba nadefinovat, které atributy budeme vydávat a komu je budeme vydávat. To se nastavuje v konfiguračním souboru conf/attribute-filter.xml.

Doporučujeme uvolňovat atributy pomocí následujícího předdefinovaného souboru attribute-filter.xml:

wget -O /opt/shibboleth-idp/conf/attribute-filter.xml https://www.eduid.cz/_media/cs/tech/idp/attribute-filter.xml

Chcete-li si uvolňování atributů nastavit dle svého, můžete:

# Úpravy konfiguračního souboru attribute-filter.xml
vi /opt/shibboleth-idp/conf/attribute-filter.xml

Vydávání atributů můžeme nastavit pro:

  • explicitně nedefinovanou službu (jinými slovy „pro kohokoliv“),
  • skupinu služeb s pomocí groupID,
  • konkrétní službu s pomocí entityID.

Pomocí následujícího kódu povolíme uvolňování atributů givenName (křestní jméno), sn (příjmení), cn (křestní jméno a příjmení) a o (název organizace) libovolné službě z federace:

<!-- Tyto atributy uvolnit všem -->
<AttributeFilterPolicy id="anyone">
 
    <PolicyRequirementRule xsi:type="ANY"/>
 
    <AttributeRule attributeID="cn">
        <PermitValueRule xsi:type="ANY"/>
    </AttributeRule>
 
    <AttributeRule attributeID="givenName">
        <PermitValueRule xsi:type="ANY"/>
    </AttributeRule>
 
    <AttributeRule attributeID="o">
        <PermitValueRule xsi:type="ANY"/>
    </AttributeRule>
 
    <AttributeRule attributeID="sn">
        <PermitValueRule xsi:type="ANY"/>
    </AttributeRule>
 
</AttributeFilterPolicy>

Následujícím nastavením zajistíme vydávání atributů givenName, sn, cn, o a schacHomeOrganization všem službám ve federaci eduID.cz – přesněji jde o služby, které jsou ve skupině entit označené hodnotou https://eduid.cz/metadata.

<!-- Uvolnit všem v eduID.cz -->
<AttributeFilterPolicy id="eduidcz">
 
    <PolicyRequirementRule xsi:type="InEntityGroup" groupID="https://eduid.cz/metadata"/>
 
    <AttributeRule attributeID="givenName">
        <PermitValueRule xsi:type="ANY"/>
    </AttributeRule>
 
    <AttributeRule attributeID="sn">
        <PermitValueRule xsi:type="ANY"/>
    </AttributeRule>
 
    <AttributeRule attributeID="cn">
        <PermitValueRule xsi:type="ANY"/>
    </AttributeRule>
 
    <AttributeRule attributeID="o">
        <PermitValueRule xsi:type="ANY"/>
    </AttributeRule>
 
    <AttributeRule attributeID="schacHomeOrganization">
        <PermitValueRule xsi:type="ANY"/>
    </AttributeRule>
 
</AttributeFilterPolicy>

Poslední ukázkou je nastavení, kdy můžeme vydávat atributy konkrétní službě na základě jejího entityID. V tomto případě služba s hodnotou entityID https://www.mojesluzba.org bude od našeho IdP získávat atributy givenName, sn, cn, o, schacHomeOrganization, PersonPrincipalName, uid a mail, tedy všechny, které jsme výše definovali.

<!-- Uvolnit službě s entityID https://www.mojesluzba.org -->
<AttributeFilterPolicy id="mojesluzbaorg">
 
    <PolicyRequirementRule xsi:type="Requester" value="https://www.mojesluzba.org" />
 
    <AttributeRule attributeID="eduPersonPrincipalName">
        <PermitValueRule xsi:type="ANY" />
    </AttributeRule>
 
    <AttributeRule attributeID="uid">
        <PermitValueRule xsi:type="ANY" />
    </AttributeRule>
 
    <AttributeRule attributeID="givenName">
        <PermitValueRule xsi:type="ANY" />
    </AttributeRule>
 
    <AttributeRule attributeID="sn">
        <PermitValueRule xsi:type="ANY" />
    </AttributeRule>
 
    <AttributeRule attributeID="cn">
        <PermitValueRule xsi:type="ANY" />
    </AttributeRule>
 
    <AttributeRule attributeID="organizationName">
        <PermitValueRule xsi:type="ANY" />
    </AttributeRule>
 
    <AttributeRule attributeID="schacHomeOrganization">
        <PermitValueRule xsi:type="ANY" />
    </AttributeRule>
 
    <AttributeRule attributeID="mail">
        <PermitValueRule xsi:type="ANY" />
    </AttributeRule>
 
</AttributeFilterPolicy>

metadata/idp-metadata.xml

Soubor metadata/idp-metadata.xml obsahuje metadata IdP, která je potřeba po instalaci doplnit o další informace jako například doplňující informace <UIInfo>, které se zapisují do „rozšíření“ (element <Extensions>), např. za <Scope>:

# Úpravy konfiguračního souboru idp-metadata.xml
vi /opt/shibboleth-idp/metadata/idp-metadata.xml
<Extensions>
    <shibmd:Scope regexp="false">example.org</shibmd:Scope>
    <mdui:UIInfo>
        <mdui:DisplayName xml:lang="en">ORGANIZATION</mdui:DisplayName>
        <mdui:DisplayName xml:lang="cs">ORGANIZACE</mdui:DisplayName>
        <mdui:Description xml:lang="en">Identity Provider for ORGANIZATION employees.</mdui:Description>
        <mdui:Description xml:lang="cs">Identity Provider pro zaměstnance ORGANIZACE.</mdui:Description>
        <mdui:InformationURL xml:lang="en">http://www.example.org/en/</mdui:InformationURL>
        <mdui:InformationURL xml:lang="cs">http://www.example.org/cs/</mdui:InformationURL>
        <mdui:Logo height="200" width="200">https://img.example.org/logo-200.gif</mdui:Logo>
        <mdui:Logo height="400" width="400">https://img.example.org/logo-400.gif</mdui:Logo>
    </mdui:UIInfo>
</Extensions>

Dále je nutno doplnit název organizace v elementu <Organization> (patří do elementu <EntityDescriptor> za element </AttributeAuthorityDescriptor>):

<Organization>
    <OrganizationName xml:lang="en">Organization</OrganizationName>
    <OrganizationName xml:lang="cs">Organizace</OrganizationName>
    <OrganizationDisplayName xml:lang="en">ORGANIZATION</OrganizationDisplayName>
    <OrganizationDisplayName xml:lang="cs">ORGANIZACE</OrganizationDisplayName>
    <OrganizationURL xml:lang="en">http://www.example.org/en/</OrganizationURL>
    <OrganizationURL xml:lang="cs">http://www.example.org/cs/</OrganizationURL>
</Organization>

Chybět nesmí ani kontaktní osoby v elementu <ContactPerson> (opět v elementu <EntityDescriptor> za element <Organization>):

<ContactPerson contactType="technical">
    <GivenName>Jméno</GivenName>
    <SurName>Příjmení</SurName>
    <EmailAddress>mailto:jmeno.prijmeni@example.org</EmailAddress>
</ContactPerson>

eduGAIN

Kromě služeb ve federaci eduID.cz je možné zpřístupnit uživatelům i služby mezinárodní federace eduGAIN. K tomu je potřeba, aby bylo IdP exportováno do metadat eduGAINu, což se zajistí následující úpravou souboru metadata/idp-metadata.xml.

Pozor! Následující kód je třeba umístit následujícím způsobem. Nejprve je element <EntityDescriptor>, pak následuje element <Extensions> a v něm jsou elementy <RepublishRequest> a <RepublishTarget>. Nepatří tedy do elementu <Extensions> umístěného v elementu <IDPSSODescriptor>!

<EntityDescriptor>
 
    <Extensions>
        <!-- eduGAIN -->
        <eduidmd:RepublishRequest xmlns:eduidmd="http://eduid.cz/schema/metadata/1.0">
            <eduidmd:RepublishTarget>http://edugain.org/</eduidmd:RepublishTarget>
        </eduidmd:RepublishRequest>
    </Extensions>
 
</EntityDescriptor>

Kompletní metadata IdP pro sdružení CESNET si můžete prohlédnout na adrese https://whoami.cesnet.cz/idp/shibboleth.

Persistentní identifikátor / eduPersonTargetedID

Persistentní identifikátor, jehož hodnota se posílá v atributu eduPersonTargetedID, není v Shibboleth IdP ve výchozím stavu zapnutý, ale je potřeba jeho podporu zapnout a nakonfigurovat.

Podporu persistentního identifikátoru sice striktně nevyžadujeme, ale důrazně doporučujeme. Už jen z toho důvodu, že konfigurační kroky spojené se zprovozněním persistentních identifikátorů se z velké části překrývají s konfigurací potřebnou pro ukládání souhlasu s vydáváním atributů.

Jelikož je dokumentace k persistentnímu identifikátoru poměrně rozsáhlá, je uvedena na samostatné stránce.

Přizpůsobení vzhledu přihlašovací stránky

Výchozí přihlašovací stránka vypadá následujícím způsobem.

Výchozí vzhled přihlašovací stránky.

Její vzhled je možno upravit do vzhledu podobnému stránkám naší organizace. Veškeré úpravy se provádí v adresáři /opt/shibboleth-idp/edit-webapp/, jehož obsah se při aktualizaci Shibboleth IdP, narozdíl od adresáře /opt/shibboleth-idp/webapp/, nepřepisuje.

Po úpravách v adresáři /opt/shibboleth-idp/edit-webapp/ vygenerujeme nový idp.war. Po zadání následujících příkazů je třeba potvrdit cílový adresář s instalací Shibboleth IdP.

# Vygenerování nového idp.war
cd /opt/shibboleth-idp
./bin/build.sh
# Průběh generování nového idp.war
Installation Directory: [/opt/shibboleth-idp]
 
Rebuilding /opt/shibboleth-idp/war/idp.war ...
...done
 
BUILD SUCCESSFUL
Total time: 3 seconds

Přidání metadat do federace

Přidání metadat do federace záleží na tom, do které federace se chceme připojit. Testovací federace czTestFed již používá (ve zkušebním režimu) webové rozhraní pro správu metadat s názvem JAGGER. Produkční Česká akademická federace identit eduID.cz zatím používá starý způsob správy metadat.

Postup registrace metadat pro:

Spuštění a otestování

Nyní, když máme vše nakonfigurováno, můžeme spustit Jetty, v němž Shibboleth poběží, pokud jsme to ještě neudělali:

# Spuštění Jetty, pokud ještě neběží
systemctl start jetty

V případě, že nám Jetty již běží, ale dělali jsme nějaké úpravy v konfiguraci Shibbolethu a nerestartovali jsme příslušnou službu Shibbolethu, restartujeme Jetty. Restartovat Jetty však neuškodí v žádném případě. Naopak otestujeme, zda je všechno korektně nastaveno:

# Restartování Jetty
systemctl restart jetty

Zbývá již jen otestovat funkčnost právě nainstalovaného a nakonfigurováného IdP. V závislosti na tom, do které federace jsme připojení, můžeme vyzkoušet následující stránky:

Na výše uvedených stránkách po přihlášení účtem u své domovské organizace uvidíme seznam atributů, které testovací služba (SP) obdržela od našeho IdP. Pokud nějaký uživatelský atribut není v seznamu uveden, IdP tento atribut (minimálně pro tuto službu) neuvolňuje anebo není v IdP vůbec definován.

Last modified:: 2019/02/22 12:35