Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

Shibboleth IdP - wersja 4

Z MAN-HA wiki


Niezbędne komponenty dodatkowe

Instalacja Shibboleth IdP 4.X

Bieżącą stabilną wersją jest V4.1.2

Pobieramy pakiet Shibboleth IdP z repozytorium https://shibboleth.net/downloads/identity-provider/latest/, np. pobranie wersji 4.1.2:

cd /opt/
wget https://shibboleth.net/downloads/identity-provider/latest/shibboleth-identity-provider-4.1.2.tar.gz
tar zxfv shibboleth-identity-provider-4.1.2.tar.gz

Pobieramy wymienione w poprzedniej sekcji pakiety mysql, commons*, HikariCP.

Tworzymy katalog /opt/shibboleth-idp/edit-webapp/, a w nim podkatalog WEB-INF/lib/, w którym umieszczamy pliki jar pobranych pakietów dodatkowych.

W podkatalogu messages/ dystrybucji umieszczamy pliki z wersją polską komunikatów. Tłumaczenia są do pobrania wg linku na stronie https://wiki.shibboleth.net/confluence/display/IDP4/MessagesTranslation.

Uruchamiamy instalację pakietu:

./bin/install.sh 

Wskazujemy parametry instalacyjne:

Source (Distribution) Directory: [/opt/shibboleth-identity-provider-4.1.2] podajemy katalog dystrybucji
Installation Directory: [/opt/shibboleth-idp] podajemy katalog instalacji
Hostname: [host.example.pl] idp.example.pl podajemy nazwę serwera
SAML EntityID: [1] zatwierdzamy nazwę SAML tworzonego elementu 
Attribute Scope: [example.pl] example.pl podajemy dla jakiej domeny będzie działał IdP
TLS Private Key Password: podajemy hasło klucza prywatnego
Re-enter password: ponownie wprowadzamy powyższe hasło
Cookie Encryption Key Password: podajemy hasło do szyfrowania cookies
Re-enter password: ponownie wprowadzamy powyższe hasło

W czasie instalacji tworzony jest katalog instalacyjny, kopiowana jest konfiguracja domyślna, w katalogu katalog /opt/shibboleth-idp/credentials/ umieszczane są wygenerowane klucze podpisujący i szyfrujący oraz magazyn typu JCEKS zabezpieczający cookies. Powstaje również plik aplikacji idp.war. Klucz podpisujący (pliki idp-signing.*) jest stosowany do podpisywania odpowiedzi wysyłanych przez IdP, klucza szyfrującego (pliki idp-encryption.*) IdP używa do zaszyfrowania danych przekazywanych w odpowiedzi.

Jeżeli pojawi się potrzeba dodania do  pliku aplikacji dodatkowych biblioteki, dodanych w katalogu '/opt/shibboleth-idp/edit-webapp/'WEB-INF/lib/, czy zmieniane są pliki zawierające tłumaczenia, należy ponowić utworzenie aplikacji.

cd /opt/shibboleth-idp/
./bin/build.sh

Instalacja Jetty

Oprogramowanie IdP MUSI być udostępniane za pomocą bezpiecznego połączenia SSL/TLS, czyli poprzez protokół https. Serwer udostępniający IdP musi być chroniony certyfikatem wystawionym przez urząd, któremu użytkownik będzie mógł ufać, czyli np. certyfikatem TCS. Certyfikat serwera musi zostać przekształcony do odpowiedniej postaci.

Dokładne informacje na temat przygotowania serwera obsługującego aplikację znajdują się na stronie Instalacja Jetty.

Konfiguracja Shibboleth IdP 4.X

Pliki konfiguracyjne Shibboleth 4 IdP są umieszczone w katalogu /opt/shibboleth-idp/conf. W katalogu /opt/shibboleth-idp/credentials znajdują się certyfikaty, klucze i inne dane związane z uwierzytelnianiem. W katalogu /opt/shibboleth-idp/metadata lokalizowane są metadane SAML. Na stronie https://wiki.shibboleth.net/confluence/display/IDP4/Configuration#Configuration-InstallationLayout została opisana rola poszczególnych podkatalogów w drzewie instalacji Shibboleth.

Dostosowanie plików konfiguracyjnych

Najistotniejsze ustawienia są umieszczone w plikach typu properties. Drugą formą konfiguracji są pliki w formacie XML. Podstawowe pliki konfiguracyjne to:

idp.properties

W tym pliku podczas instalacji są wpisywane ścieżki do certyfikatów, hasła do plików z kluczami, nazwa IdP itp. Podczas pierwszego uruchomienia IdP nie są potrzebne żadne zmiany w tym plik. Zmiany będą potrzebne np. przy ustalaniu zasad działania modułu wyrażania zgody na przekazanie atrybutów.

relying-party.xml

Plik ten zawiera definicje sposobu działania IdP, ustala wspierane profile oraz umożliwia zrządzanie ustawieniami w ramach profili.Modyfikacje pliku mogą być potrzebne w przypadku, gdy np. w odniesieniu do konkretnych dostawców usług rezygnujemy z pytania o zgodę na przekazywanie atrybutów.

metadata-providers.xml

Plik ten zawiera konfigurację metadanych, z których korzysta IdP. W pliku, w postaci komentarzy, są podane przykłady użycia podstawowych metod definicji metadanych. Domyślnie w pliku nie są umieszczone żadne wskazania metadanych.Szczegółowy opis możliwości w zakresie konfiguracji źródeł metadanych znajduje się na stroniehttps://wiki.shibboleth.net/confluence/display/IDP4/MetadataConfiguration.

Aby sprawdzić działanie serwera dostawcy tożsamości (IdP) z aplikacją testową PIONIER.Id należy dodać w tym pliku:

<!-- PIONIER.Id Test SP -->
<MetadataProvider id="TESTSP" xsi:type="FileBackedHTTPMetadataProvider"
  metadataURL="https://aai.pionier.net.pl/test/module.php/saml/sp/metadata.php/default-sp"
  backingFile="/opt/shibboleth-idp/metadata/testsp.xml">
</MetadataProvider>
<!-- PIONIER.Id Test SP -->

Aby IdP współpracował ze wszystkimi SP zarejestrowanymi w eduGAIN dodajemy:

 
<MetadataProvider id="eduGAINSP" xsi:type="FileBackedHTTPMetadataProvider"
  metadataURL="http://aai.pionier.net.pl/pionierid-edugain-sp-feed.xml"
  backingFile="/opt/shibboleth-idp/metadata/pionierid-edugain-sp-feed.xml">
 <MetadataFilter xsi:type="SignatureValidation" certificateFile="${idp.home}/credentials/pionier-signer.pem"/>
</MetadataProvider>

a w pliku opt/shibboleth-idp/credentials/pionier-signer.pem umieszczamy zawartość pobraną z adresu https://aai.pionier.net.pl/PIONIER.Id.pem

Shibboleth IdP domyślnie odświeża wszystkie metadane co 3 godziny.

saml-nameid.properties

W tym pliku są ustalane zasady generowania identyfikatora NameID. Domyślną postacią identyfikatora jest urn:oasis:names:tc:SAML:2.0:nameid-format:transient. Ten plik wymaga dostosowania, by IdP tworzył identyfikator typu persistent i zapisywał go do bazy danych:

idp.persistentId.sourceAttribute = eduPersonPrincipalName
idp.persistentId.encoding = BASE32
idp.persistentId.generator = shibboleth.StoredPersistentIdGenerator
idp.persistentId.dataSource = nazwa_zrodla_danych
idp.persistentId.salt = wartość_losowa_używana_do_wyliczenia_persistentId

Parametr idp.persistentId.generator ustala, że identyfikator persistenId ma być generowany za pomocą klasy umożliwiającej zapamiętanie tego identyfikatora. Parametr idp.persistentId.dataSource wskazuje nazwę magazynu do przechowywania identyfikatorów, sposób obsługi tego magazynu jest definiowany w pliku konfiguracyjnym global.xml lub saml-nameid.xml . Parametr idp.persistentId.sourceAttribute zawiera atrybut używany do wyliczania wartości persistentId.

saml-nameid.xml

W pliku są definiowane działania w celu wygenerowania identyfikatora persistentId. Należy odkomentować bean="shibboleth.SAML2PersistentGenerator", tak by blok o id="shibboleth.SAML2NameIDGenerators" był następujący:

 <util:list id="shibboleth.SAML2NameIDGenerators">
        <ref bean="shibboleth.SAML2TransientGenerator" />
        <ref bean="shibboleth.SAML2PersistentGenerator" />
    </util:list>
global.xml

Jest to plik, w którym umieszczane są potrzebne definicje komponentów Javy zw. beans, np. w celu wskazania dedykowanych rozwiązań przechowywania danych.W tym pliku dodajemy definicję źródła podanego w ustawieniu w pliku saml-nameid.properties:

idp.persistentId.dataSource = nazwa_zrodla_danych
<bean id="nazwa_zrodla_danych" class="org.apache.commons.dbcp2.BasicDataSource"
    p:driverClassName="com.mysql.cj.jdbc.Driver"
    p:url="jdbc:mysql://localhost:3306/shibboleth"
    p:username="użytkownik"
    p:password="hasło użytkownika"
    p:maxIdle="5"
    p:maxWaitMillis="15000"
    p:testOnBorrow="true"
    p:validationQuery="select 1"
    p:validationQueryTimeout="5" />
</beans>

shibboleth.StoredPersistentIdGenerator używa tablicy shibpid we wskazanej powyżej bazie danych do zapisywania identyfikatorów. Należy stworzyć tablicę:

CREATE TABLE shibpid (
  `localEntity` varchar(255) NOT NULL,
  `peerEntity` varchar(255) NOT NULL,
  `persistentId` varchar(50) NOT NULL,
  `principalName` varchar(50) NOT NULL,
  `localId` varchar(50) NOT NULL,
  `peerProvidedId` varchar(50) 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;

Również w pliku global.xml jest deklarowane miejsce przechowywania dodatkowych danych IdP, np. danych sesyjnych, m.in na potrzeby obsługi wylogowania. Definicja obszaru bazy danych na dane IdP wygląda następująco:

<!-- DB-independent Configuration -->
 
<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=""/>
      <property name="dataSource" ref="shibboleth.JPAStorageService.DataSource"/>
      <property name="jpaVendorAdapter" ref="shibboleth.JPAStorageService.JPAVendorAdapter"/>
      <property name="jpaDialect">
         <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
      </property>
</bean>
 
<!-- DB-dependent Configuration -->
 
<bean id="shibboleth.JPAStorageService.JPAVendorAdapter" 
      class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
      <property name="database" value="MYSQL" />
</bean>
 
<!-- Bean to store IdP data unrelated with persistent identifiers on 'shibboleth' database -->
<bean id="shibboleth.JPAStorageService.DataSource"
      class="com.zaxxer.hikari.HikariDataSource" destroy-method="close" lazy-init="true"
      p:driverClassName="com.mysql.cj.jdbc.Driver"
      p:jdbcUrl="jdbc:mysql://localhost:3306/shibboleth"
      p:username="użytkownik"
      p:password="hasło użytkownika" />
attribute-resolver.xml

W tym pliku jest ustalany sposób tworzenia atrybutów oraz ich kodowania przed wysłaniem.Plik ten zmienił się w porównaniu do v.3.Atrybuty są definiowane w blokach AttributeDefinition, np.

   
<AttributeDefinition id="eduPersonPrincipalName" xsi:type="Scoped" scope="%{idp.scope}">
   <InputAttributeDefinition ref="uid" />
</AttributeDefinition>
<AttributeDefinition xsi:type="Simple" id="mail">
   <InputDataConnector ref="myLDAP" attributeNames="mail"/>
</AttributeDefinition>

Pierwsza z powyższych definicji ustala, że atrybut eduPersonPrincipalName, który jest w schemacie eduPerson traktowany jako identyfikator użytkownika, powstaje na bazie atrybutu uid i jest atrybutem typu Scoped, co oznacza, że powstaje poprzez dodanie do wartości atrybutu uid domeny zadeklarowanej w pliku idp.properties jako idp.scope.

Druga definicja precyzuje zasady otrzymania atrybutu mail - jest pobierany z bazy wskazanej w elemencie ref (tu myLDAP).

Na potrzeby generowania przez IdP stałych identyfikatorów związanych z konkretnym dostawcą usługi (SP), należy zdefiniować atrybut edupersonTargetedID, np. jako atrybut powiązany z tzw. trwałym identyfikatorem:

<AttributeDefinition xsi:type="SAML2NameID" 
                     nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
                     id="eduPersonTargetedID">
    <InputDataConnector ref="StoredId" attributeNames="persistentID" />
</AttributeDefinition>

Źródłem tego atrybutu jest baza wskazana jako StoredId

Powiązania atrybutów z bazą danych są definiowane w elementach , np.

 
<DataConnector id="myLDAP" xsi:type="LDAPDirectory"
        ldapURL="ldap://localhost"
        baseDN="ou=users,dc=test-org,dc=pl"
        principal="cn=admin,dc=test-org,dc=pl"
        principalCredential="hasło użytkownika admin">
        <FilterTemplate>
            <![CDATA[
                (uid=$requestContext.principalName)
            ]]>
        </FilterTemplate>
</DataConnector>

Z kolei w elemencie o identyfikatorze StoredId wskazujemy parametry bazy danych służącej do przechowywania tego identyfikatora , np.:

<DataConnector id="StoredId" xsi:type="StoredId"
        generatedAttributeID="persistentID"
        salt="%{idp.persistentId.salt}"
        queryTimeout="0">
   <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}" />
   <BeanManagedConnection>%{idp.persistentId.dataSource}</BeanManagedConnection>
</DataConnector>

Powyższa definicja ustala źródłowy atrybut, nazwę wygenerowanego atrybutu oraz powiązania z bazą danych (poprzez definicję idp.persistentId.dataSource.

Aby aplikacja Shibboleth IdP obsługiwała atrybuty SCHAC, należy pamiętać o umieszczeniu definicji tych atrybutów, np.

    <AttributeDefinition xsi:type="Simple" id="schacHomeOrganization">
           <InputDataConnector ref="myLDAP" attributeNames="schacHomeOrganization"/>
    </AttributeDefinition>
    <AttributeDefinition xsi:type="Simple" id="schacHomeOrganizationType">
           <InputDataConnector ref="myLDAP" attributeNames="schacHomeOrganizationType"/>
    </AttributeDefinition>
    <AttributeDefinition xsi:type="Simple" id="schacPersonalUniqueCode">
           <InputDataConnector ref="myLDAP" attributeNames="schacPersonalUniqueCode"/>
    </AttributeDefinition>

Jeśli chcemy, by dostawca tożsamości przekazywał statyczną wartość określonego atrybutu, np. atrybutu schacHomeOrganization, w którym oczekiwana jest nazwa domenowa instytucji, czy atrybutu schacHomeOrganizationType, w którym oczekiwany jest typ instytucji, warto skorzystać z funkcjonalności [StaticDataConnector]. Definiujemy odpowiednie atrybuty wskazując staticAttributes jako źródło danych:

    <AttributeDefinition xsi:type="Simple" id="schacHomeOrganizationType">
           <InputDataConnector ref="staticAttributes" attributeNames="schacHomeOrganizationType"/>
    </AttributeDefinition>
    <AttributeDefinition xsi:type="Simple" id="schacPersonalUniqueCode">
           <InputDataConnector ref="myLDAP" attributeNames="schacPersonalUniqueCode"/>
    </AttributeDefinition>

a na końcu pliku attribute-resolver.xml dodajemy:

<DataConnector  id="staticAttributes"  xsi:type="Static" >
    <Attribute id="schacHomeOrganization">
        <Value>domena.instytucji.pl</Value>
     </Attribute>
     <Attribute id = "schacHomeOrganizationType" >
        <Value>urn:schac:homeOrganizationType:pl:university</Value>
     </Attribute>
    </DataConnector>
attribute-filter.xml

Zawiera ustalenia dotyczące filtrowania atrybutów na podstawie nazw atrybutów, ich wartości. Umożliwia precyzyjną kontrolę dostępu poprzez wskazanie dozwolonych odbiorców atrybutów.

IdP powinien przekazywać każdemu dostawcy usługi takie atrybuty jak transientId, persistentId, edupersonTargetedID:

 
<AttributeFilterPolicy id="releaseTransientIdToAnyone">
   <PolicyRequirementRule xsi:type="ANY"/>
   <AttributeRule attributeID="transientId">
     <PermitValueRule xsi:type="ANY"/>
   </AttributeRule>
</AttributeFilterPolicy
 
<AttributeFilterPolicy id="releasePersistentIdToAnyone">
   <PolicyRequirementRule xsi:type="ANY"/>
   <AttributeRule attributeID="persistentId">
     <PermitValueRule xsi:type="ANY" />
   </AttributeRule>
</AttributeFilterPolicy>
 
<AttributeFilterPolicy id="releasePermanentIdToAnyone">
   <PolicyRequirementRule xsi:type="ANY"/>
   <AttributeRule attributeID="eduPersonTargetedID">
     <PermitValueRule xsi:type="ANY"/>
   </AttributeRule>
</AttributeFilterPolicy>

Jeśli IdP ma przekazywać konkretne atrybuty określonemu SP, to można umieścić poniższą regułę:

<AttributeFilterPolicy id="releaseeduPersonEntitlementtosp12example">
        <PolicyRequirementRule xsi:type="OR">
            <Rule xsi:type="AttributeRequesterString"
                        value="" />
            <Rule xsi:type="AttributeRequesterString"
                        value="https://sp2.example.pl" />
        </PolicyRequirementRule>
        <AttributeRule attributeID="eduPersonEntitlement">
            <PermitValueRule xsi:type="ANY" />
        </AttributeRule>
</AttributeFilterPolicy>

która ustala, że atrybut eduPersonEntitlement będzie przekazywany do usług https://sp1.example.pl i https://sp2.example.pl.

Dostawcy tożsamości zarejestrowani w PIONIER.Id mogą deklarować akceptowanie Geant Code of Conduct (http://www.geant.net/uri/dataprotection-code-of-conduct/v1) oraz stosowanie zasad research and scholarship (http://refeds.org/category/research-and-scholarship). Odpowiadają za to poniższe reguły:

 
    <AttributeFilterPolicy id="releaseToCoC">
        <PolicyRequirementRule xsi:type="EntityAttributeExactMatch"
            attributeName="http://macedir.org/entity-category"
            attributeValue="http://www.geant.net/uri/dataprotection-code-of-conduct/v1"/>
        <AttributeRule attributeID="displayName">
            <PermitValueRule xsi:type="MappedAttributeInMetadata" onlyIfRequired="true"/>
        </AttributeRule>
        <AttributeRule attributeID="sn">
            <PermitValueRule xsi:type="MappedAttributeInMetadata" onlyIfRequired="true"/>
        </AttributeRule>
        <AttributeRule attributeID="mail">
            <PermitValueRule xsi:type="MappedAttributeInMetadata" onlyIfRequired="true"/>
        </AttributeRule>
        <AttributeRule attributeID="eduPersonPrincipalName">
            <PermitValueRule xsi:type="MappedAttributeInMetadata" onlyIfRequired="true"/>
        </AttributeRule>
        <AttributeRule attributeID="eduPersonScopedAffiliation">
            <PermitValueRule xsi:type="MappedAttributeInMetadata" onlyIfRequired="true"/>
        </AttributeRule>
    </AttributeFilterPolicy>
 
    <AttributeFilterPolicy id="releaseToRRandS">
        <PolicyRequirementRule xsi:type="EntityAttributeExactMatch"
            attributeName="http://macedir.org/entity-category"
            attributeValue="http://refeds.org/category/research-and-scholarship"/>
        <AttributeRule attributeID="displayName">
            <PermitValueRule xsi:type="ANY"/>
        </AttributeRule>
        <AttributeRule attributeID="sn">
            <PermitValueRule xsi:type="ANY"/>
        </AttributeRule>
        <AttributeRule attributeID="givenName">
            <PermitValueRule xsi:type="ANY"/>
        </AttributeRule>
        <AttributeRule attributeID="mail">
            <PermitValueRule xsi:type="ANY"/>
        </AttributeRule>
        <AttributeRule attributeID="eduPersonPrincipalName">
            <PermitValueRule xsi:type="ANY"/>
        </AttributeRule>
        <AttributeRule attributeID="eduPersonScopedAffiliation">
            <PermitValueRule xsi:type="ANY"/>
        </AttributeRule>
        <AttributeRule attributeID="schacPersonalUniqueCode">
            <PermitValueRule xsi:type="AND">
              <Rule xsi:type="AttributeInMetadata" onlyIfRequired="true"/>
              <Rule xsi:type="ValueRegex" regex="^urn:schac:personalUniqueCode:int:esi:.*$" />
            </PermitValueRule>
        </AttributeRule>
        <AttributeRule attributeID="schacHomeOrganization">
          <PermitValueRule xsi:type="AttributeInMetadata" onlyIfRequired="false"/>
        </AttributeRule>
    </AttributeFilterPolicy>

Jeśli IdP obsługuje Office365, należy również dodać reguły:

  <AttributeFilterPolicy id="PolicyForWindowsAzureAD">
        <PolicyRequirementRule xsi:type="Requester" value="" />
        <AttributeRule attributeID="UserId">
                <PermitValueRule xsi:type="ANY"/>
        </AttributeRule>
        <AttributeRule attributeID="ImmutableID">
          <PermitValueRule xsi:type="ANY"/>
        </AttributeRule>
        <AttributeRule attributeID="transientId">
          <DenyValueRule xsi:type="ANY"/>
        </AttributeRule>
    </AttributeFilterPolicy>

Na potrzeby sprawdzenia działania IdP z testowym dostawcą usługi PIONIER.Id dodajemy:

 
<AttributeFilterPolicy id="PolicyForMyTestSP">
        <PolicyRequirementRule xsi:type="Requester" value="" />
        <AttributeRule attributeID="email">
          <PermitValueRule xsi:type="ANY"/>
        </AttributeRule>
        <AttributeRule attributeID="eduPersonPrincipalName">
          <PermitValueRule xsi:type="ANY" />
        </AttributeRule>
        <AttributeRule attributeID="transientId">
          <DenyValueRule xsi:type="ANY"/>
        </AttributeRule>
    </AttributeFilterPolicy>

W federacji PIONIER.Id będę rejestrowani dostawcy usług spoza eduGAIN i nie wspierający Geant Code of Conduct czy Research & Scholarship. W takich przypadkach po stronie IdP może być potrzebne dodanie filtra specyficznego dla danego dostawcy.

W części Dodawanie filtrów nowych usługodawców Shibboleth IdP są prezentowane filtry dla usługodawców PIONIER.Id.

Rejestr atrybutów: conf/attributes/default-rules.xml, conf/attributes/custom/

W pliku /opt/shibboleth-idp/conf/attributes/default-rules.xml zdefiniowane są zasady transkodowania atrybutów. Domyślne reguły definiowane są w plikach:

inetOrgPerson.xml
eduPerson.xml
eduCourse.xml
samlSubject.xml
Dodanie niestandardowych reguł - obsługa eduPersonTargetedID

W katalogu /opt /shibboleth-idp/conf/attributes/custom można umieścić własne reguły, dotyczące danej instalacji. W celu zapewnienia transkodowania atrybutu eduPersonTargetedID należy w tym katalogu umieścić plik eduPersonTargetedID.properties o zawartości (pobierz plik eduPersonTargetedID.properties)

<?xml version="1.0" encoding="UTF-8"?>
id=eduPersonTargetedID
transcoder=SAML2XMLObjectTranscoder
saml2.name=urn:oid:1.3.6.1.4.1.5923.1.1.1.10
displayName.en=Opaque per-service identifier
displayName.pl=Anonimowy identyfikator us\u0142ugi
description.en=Opaque per-service identifier
description.pl=Anonimowy identyfikator us\u0142ugi
saml1.encodeType=false

Po restarcie aplikacji jetty zostanie wczytana nowa konfiguracja.

Dodanie obsługi atrybutów SCHema for ACademia (SCHAC)

Korzystanie ze schematu SCHAC jest niezbędne jeśli dostawca tożsamości chce korzystać z europejskich usług związanych z mobilnością studentów: https://wiki.geant.org/display/SM/MyAcademicID+Project

Wymagania dotyczące niezbędnych atrybutów są opisane na stronie: https://wiki.aai.pionier.net.pl/index.php?title=Federacja:ESI. Należy pobrać plik zawierający definicję transkodowania atrybutów SCHAC schac.xml i umieścić w katalogu /opt/shibboleth-idp/conf/attributes/.W pliku /opt/shibboleth-idp/conf/attributes/default-rules.xml należy dodać wiersz (najlepiej jako kolejny wiersz za ostatnią linią import:

<import resource="schac.xml" />

Po restarcie aplikacji jetty zostanie wczytana nowa konfiguracja.

Zgoda użytkownika na przekazanie atrybutów

Jeżeli instalacja wersji 4.1.0 jest nowa, tzn. nie jest aktualizacją z niższej wersji, w której była aktywa zgoda na przekazywanie atrybutów niezbędne jest włączenie modułu idp.intercept.Consent.Polecenie

/opt/shibboleth-idp/bin/module.sh

pokazuje listę modułów oraz ich stanów (ENABLED/DISABLED)Polecenie

/opt/shibboleth-idp/bin/module.sh -e idp.intercept.Consent

ustala stan ENABLED dla modułu idp.intercept.Consent

W pliku /opt/shibboleth-idp/conf/intercept/consent-intercept-config.xml są definiowane dodatkowe ustawienia związane z modułem zgody. W tym pliku m.in. można zgodnie z obowiązującą na uczelni polityką, umieszczać atrybuty, które są umieszczane na tzw. whitelist lub blacklist podczas działania modułu wyrażania zgody.

Pliki /opt/shibboleth-idp/views/intercept/attribute-release.vm i /opt/shibboleth-idp/views/intercept/terms-of-use.vm są plikami wzorcowymi dla stron związanych z udzielaniem zgody na przekazanie atrybutów.

Aby zgoda była aktywna w odniesieniu do dowolnego dostawcy usługi, pliku konfiguracyjnym '/opt/shibboleth-idp/conf/relying-party-xml, w bloku bean o id="shibboleth.DefaultRelyingParty" modyfikujemy wiersz dotyczący SAML2.SSO:

<bean parent="SAML2.SSO" p:postAuthenticationFlows="attribute-release" />

Podstawowe ustawienia związane z wyrażaniem zgody są umieszczone w pliku idp.properties.Własności te mają nazwy zaczynające się od id.consent..Domyślnie informacje o wyrażonej zgodzie są przechowywane w pliku w podkatalogu logs instalacji Shibboleth. Zaleca się jednak takie skonfigurowanie IdP, by informacja o zgodzie była przechowywana w bazie danych. W tym celu w pliku idp.properties umieszczamy:

idp.consent.StorageService = shibboleth.JPAStorageService
idp.consent.attribute-release.userStorageKey = shibboleth.consent.PrincipalConsentStorageKey
idp.consent.userStorageKeyAttribute = eduPersonPrincipalName
idp.consent.maxStoredRecords = -1

Moduł zgody korzysta z ustawień dot. shibboleth.JPAStorage w pliku konfiguracyjnym global.xml.

Z kolei w bazie danych tworzymy tablicę StorageRecords do przechowywania m.in. zgód.

CREATE TABLE `StorageRecords` (
  `context` varchar(255) NOT NULL,
  `id` varchar(255) NOT NULL,
  `expires` bigint(20) DEFAULT NULL,
  `value` longtext NOT NULL,
  `version` bigint(20) NOT NULL,
  `creationDate` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`context`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Ustawienia w pliku idp.properties decydują o dodatkowych możliwościach w zakresie wyrażania zgody, np.

  • idp.consent.allowDoNotRemember - ustala że po wydaniu zgody przy kolejnych logowaniach nie jest prezentowana prośba o wyrażenie zgody, o ile nie uległy zmianie informacje podlegające zgodzie, domyślnie true
  • idp.consent.allowGlobal - opcja powodująca, że jedną z możliwości na liście decyzji jest zgoda na przekazywanie atrybutów do wszystkich dostawców usług, domyślnie true czyli opcja jest włączona
  • idp.consent.allowPerAttribute - opcja dająca możliwość wyączenia zgody dla konkretnego atrybutu (przez skasowanie zaznaczenia przy tym atrybucie) - domyślnie false
Wyłączenie zgody dla określonych dostawców usług (SP)

Jeśli dla określonego dostawcy usługi nie ma być wyświetlany formularz wyrażenia zgody, to w pliku relaying-party.xml w bloku ... należy dodać:

<bean parent="RelyingPartyByName" c:relyingPartyIds="nazwa usługi SP (entityId)">
            <property name="profileConfigurations">
   <list>
    <bean parent="SAML2.SSO" />
   </list>
 </property>
</bean>

Definicja metody uwierzytelnienia

Domyślną metodą uwierzytelnienia jest baza LDAP oraz para nazwa użytkownika i hasło. Polecenie:

/opt/shibboleth-idp/bin/module.shpokazuje w wynikach:
Module: idp.authn.Password [ENABLED]

Definicja źródła uwierzytelniania jest umieszczona w pliku konfiguracyjnym ldap.properties, w parametrachidp.authn.LDAP.ldapURL, idp.authn.LDAP.useStartTLS, idp.authn.LDAP.useSSL, idp.authn.LDAP.returnAttributes,idp.authn.LDAP.baseDN,idp.authn.LDAP.userFilter,idp.authn.LDAP.bindDN,idp.authn.LDAP.bindDNCredential.

Bardziej zaawansowane ustawienia są umieszczane w authn/ldap-authn-config.xml. Włączenie innego trybu, np. gdy dostawca tożsamości korzysta z CAS-a wymaga aktywizacji odpowiedniego modułu, np.:

/opt/shibboleth-idp/bin/module.sh -t idp.authn.RemoteUser

Integracja Shibboleth IdP z logowaniem CAS

Za pomocą pluginu shib-cas-auth

Jedną z metod integracji Shibboleth IdP z logowaniem via CAS jest użycie pluginu shib-cas-auth.

Plugin dostępny jest na stronie https://github.com/Unicon/shib-cas-authn.

Bieżącą wersję należy pobrać ze strony (np. via przycisk "Clone or Download" i dalej Download ZIP lub używając polecenia git) i rozpakowujemy.

W katalogu z rozpakowanym pluginem wykonujemy polecenie

./gradlew clean build

Do katalogu /opt/shibboleth-idp/edit-webapp/WEB-LIB/lib kopiujemy dwa pliki jar:

  • shib-cas-authenticator-4.0.0.jar
  • cas-client-core-3.6.0.jar (znajduje się w podkatalogu build/dist-tmp/edit-webapp/WEB-INF/lib/ rozpakowanego plugina)

Do katalogu /opt/shibboleth-idp/edit-webapp/ kopiujemy IDP_HOME/edit-webapp/no-conversation-state.jsp z katalogu rozpakowanego plugina.

Włączamy moduł idp.authn.external:

/opt/shibboleth-idp/bin/module.sh -e idp.authn.External

co powoduje utworzenie pliku /opt/shibboleth-idp/conf/authn/external-authn-config.xml. W tym pliku modyfikujemy ustawienie w bloku beana o id shibboleth.authn.External.externalAuthnPath (

<bean id="shibboleth.authn.External.externalAuthnPath" class="java.lang.String"
        c:_0="contextRelative:Authn/External" />

W pliku konfiguracyjnym conf/idp.properties dodajemy/modyfikujemy ustawienia:

idp.authn.flows = External
# wskazanie serwera CAS oraz strony logowania CAS
shibcas.casServerUrlPrefix = https://cassserver.example.edu/cas
shibcas.casServerLoginUrl = ${shibcas.casServerUrlPrefix}/login
# wskazanie serwera Shibboleth
shibcas.serverName = https://shibserver.example.edu

W katalogu instalacji Shibboleth IdP /opt/shibboleth-idp wykonujemy:

bin/build.sh

Utworzona nowa aplikacja idp.war będzie zintegrowana z logowaniem CAS.

Przy użyciu funkcjonalności SAML proxy do innego dostawcy tożsamości

Jeśli serwer CAS wspiera protokół SAML i jest przygotowany do działania jako dostawca tożsamości SAML2, można skorzystać z funkcjonalności umożliwiającej przekazanie zleceń SAML-owych do kolejnego dostawcy. W tej sytuacji Shibboleth IdP proxujący zlecenie występuje w roli usługodawcy (SP), natomiast serwer CAS staje się dostawcą tożsamości.Na stronach:

opisano szczegółowo konfigurację Shibboleth IdP.Niezbędnym elementem jest zapewnienie, by oba IdP (Shibboleth i CAS) używały wspólnego atrybutu powiązanego z użytkownikiem. Chodzi o to by serwer CAS pełniący rolę dostawcy tożsamości w ramach pozytywnej odpowiedzi na uwierzytelnienie przekazał do Shibboleth IdP atrybut identyfikujący użytkownika, za pomocą którego Shibboleth IdP realizuje etap powiązania dodatkowych atrybutów z użytkownikiem (attribute resolution). W celu zapewnienia funkcjonalności SAML proxy należy:

  • W metadanych po stronie Shibboleth IdP umieścić metadane serwera CAS (w roli IdP, czyli zawierające IDPSSODescriptor.
  • W metadanych po stronie CAS umieścić metadane Shibboleth IdP (w roli SP, czyli zawierające SPSSODescriptor). Domyślne metadane nie zawierają definicji tej roli, trzeba samodzielnie dodać blok o postaci:
 <!-- New SP block -->
    <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
 
        <KeyDescriptor use="signing">
            <ds:KeyInfo>
                <ds:X509Data>
                    <ds:X509Certificate>
                    ...Signing Certificate from IdP...
                    </ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </KeyDescriptor>
        <KeyDescriptor use="encryption">
            <ds:KeyInfo>
                <ds:X509Data>
                    <ds:X509Certificate>
                    ...Encryption Certificate from IdP...
                    </ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </KeyDescriptor>
 
    <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://idp.example.ac.uk/idp/profile/Authn/SAML2/POST/SSO" index="0"/>
</SPSSODescriptor>

W konfiguracji Shibboleth IdP trzeba wykonać następujące zmiany:

  • Aktywować uwierzytelnienie SAML - w tym celu w pliku /opt/shibboleth-idp/conf/authn/saml-authn-config.xml należy odkomentować bean shibboleth.authn.SAML.discoveryFunction i zedytować wartość target:
<bean id="shibboleth.authn.SAML.discoveryFunction" parent="shibboleth.Functions.Constant"
            c:target="https://adres_serwera_CAS/idp" />
  • W pliku /opt/shibboleth-idp/conf/idp.properties ustawić wartość SAML przy rodzaju uwierzytelnienia
idp.authn.flows=SAML
  • Zaktualizować plik /opt/shibboleth-idp/conf/attribute-filter.xml, by zawierał definicję wspólnego atrybutu, np. zakładając, że CAS przekazuje do Shibboleth IdP atrybut uid:
<AttributeFilterPolicy id="proxy">
    <PolicyRequirementRule xsi:type="Issuer" value="" />
    <AttributeRule attributeID="uid" permitAny="true" />
</AttributeFilterPolicy>
  • Zaktualizować plik /opt/shibboleth-idp/conf/attribute-resolver.xml, by umożliwić obsługę atrybutu odebranego z CAS:
<AttributeDefinition id="proxied-uid" xsi:type="SubjectDerivedAttribute"
        forCanonicalization="true"
        principalAttributeName="uid" />
  • Zaktualizować plik /opt/shibboleth-idp/conf/c14n/attribute-sourced-subject-c14n-config.xml, by aktywne były bloki:
<util:list id="shibboleth.c14n.attribute.AttributesToResolve">
 <value>proxied-uid</value>
</util:list>
<util:list id="shibboleth.c14n.attribute.AttributeSourceIds">
 <value>proxied-uid</value>
</util:list>

Po restarcie Shibboleth IdP powinno działać logowanie via CAS w funkcji proxy SAML.

Internacjonalizacja/lokalizacja Shibboleth IdP

Shibboleth IdP obsługuje natywnie wszystkie języki, dla których przygotowano odpowiedni zestaw komunikatów. Domyślnie w podkatalogu messages w katalogu instalacyjnym (/opt/shibboleth-idp/) pojawia się plik messages.properties.

Aby w aplikacji pojawiały się polskie napisy, należy w tym samym katalogu umieścić plik messages_pl.properties.

Plik pobieramy wg wskazówek na stronie https://wiki.shibboleth.net/confluence/display/IDP4/MessagesTranslation z serwisu Zenata.

Konfiguracja wylogowania

Aby były obsługiwane zlecenia LogoutRequest należy w pliku konfiguracyjnym idp.properties zmienić domyślne ustawienia kilku własności:

  • ustawić magazyn sesji użytkownika po stronie serwera (domyślnie jest to realizowane po stronie klienta), w tym celu umieszczamy
idp.session.StorageService = shibboleth.JPAStorageService
  • uaktywnić własności związane z przechowywaniem sesji:
idp.session.trackSPSessions = true
idp.session.secondaryServiceIndex = true 

Przechowywanie sesji wymaga również konfiguracji magazynu danych. Jeżeli podczas przygotowania obsługi wyrażania zgody (patrz Zgoda użytkownika na przekazanie atrybutów) ustalono przechowywanie zgody w tablicy StorageRecords, to konfiguracja wylogowania jest już zakończona, w przeciwnym razie należy zdefiniować w pliku conf/global.xml magazyn shibboleth.JPAStorageService tak jak opisano tutaj.

Dostosowanie metadanych dostawcy tożsamości

W czasie instalacji dostawcy tożsamości w pliku /opt/shibboleth-idp/metadata/idp-metadata.xml są umieszczane metadane IdP. Plik ten wymaga dostosowania przed przekazaniem go do administratorów federacji PIONIER.Id.Poniżej zamieszczamy opis zmian:

  • usunąć wszelkie komentarze typu This is example metadata only itp.
  • usunąć z elementu EntityDescriptor atrybut validuntil
  • odkomentować blok mdui:UIInfo i umieścić w nim elementy dot. danego IdP, wg opisu na stronie https://wiki.aai.pionier.net.pl/index.php/Federacja:Metadane w sekcji Informacji dodatkowe - rozszerzenie MDUI
  • wyrzucić zakomentowane wiersze
<!--
<ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://......:8443/idp/profile/SAML1/SOAP/ArtifactResolution" index="1"/>
-->
 
<!--
<SingleSignOnService Binding="urn:mace:shibboleth:1.0:profiles:AuthnRequest" Location="https://....../idp/profile/Shibboleth/SSO"/>
-->
  • odkomentować blok zawierający trzy elementy SingleLogoutService
  • odkomentować cały blok zawierający element AttributeAuthorityDescriptor, usunąć w nim wiersz
<!--
<ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://......:8443/idp/profile/SAML1/SOAP/ArtifactResolution" index="1"/>
-->

Reinstalacja Shibboleth IdP

Jeśli jest potrzebne przebudowa głównego pliku aplikacji idp.war, po dokonaniu zmian w dystrybucji (np. dodanie pliku bliblioteki jar, zmiana jakiegoś pliku wzorcowego (.vm), czy stylu (.css) wykonujemy w katalogu dystrybucji Shibboleth IdP:

./bin/build.sh

i zatwierdzamy katalog. Upewniamy się, że nowy plik idp.war został umieśczony w katalogu instalacji Shibboleth IdP, np./opt/shibboleth-idp/war.

Restartujemy usługę.

Aktualizacja wersji Shibboleth IdP

Aktualizację wersji Shibboleth 4.X realizujemy następująco:

  • pobieramy nową wersję i rozpakowujemy
  • w katalogu dystrybucji dodajemy wszystkie potrzebne pliki jar - zgodnie z opisem w punkcie
  • wykonujemy
./bin/install.sh
  • zatwierdzamy katalog dystrybucji, a jako katalog instalacji podajemy ten sam katalog, w którym jest zainstalowana poprzednia wersja Shibboleth /opt/shibboleth-idp/

Ponieważ katalog już istnieje nie będą wgrywane pliki konfiguracyjne, powstanie nowy plik idp.war.

Dodawanie filtrów nowych usługodawców Shibboleth IdP

Jeśli nowa usługa wymaga specyficznej konfiguracji zasad dostarczania atrybutów, należy dodać nowy filtr w pliku attribute-filter.xml.

Poniżej wykaz usług zarejestrowanych w PIONIER.Id wymagających specyficznej konfiguracji:


Atlases Pathology Images http://atlases.muni.cz

 
<AttributeFilterPolicy id="ATLASES">
      <PolicyRequirementRule xsi:type="Requester" value="" />
      <AttributeRule attributeID="mail">
          <PermitValueRule xsi:type="ANY"/>
      </AttributeRule>
      <AttributeRule attributeID="eduPersonPrincipalName">
          <PermitValueRule xsi:type="ANY"/>
      </AttributeRule>
    </AttributeFilterPolicy>