SimpleSAMLphp IdP

Z PIONIER.Id
Wersja z dnia 15:24, 23 lut 2023 autorstwa Mwolniewicz (dyskusja | edycje)
(różn.) ← poprzednia wersja | przejdź do aktualnej wersji (różn.) | następna wersja → (różn.)
Przejdź do nawigacji Przejdź do wyszukiwania

Wymagania wstępne

  • Aktywny serwis ntp
  • Serwer HTTP mający możliwość wykonywania skryptów PHP
  • PHP w werji >= 7.1.0
  • Rozszerzenia PHP:
    • date, dom, hash, libxml, openssl, pcre, SPL, zlib, json, mbstring, cURL
    • jeśli będziemy korzystać z bazy użytkowników LDAP: ldap
    • jeśli używamy bazy danych:
      • zawsze: PDO
      • database driver: (mysql, pgsql, ...)
      • opcjonalnie: session, memcache

Instalacja

Pobieramy najświeższą wersję SSP ze strony https://simplesamlphp.org/download

 wget -O /tmp/ssp.tgz https://simplesamlphp.org/download?latest
 cd /usr/local
 tar xvf /tmp/ssp.tgz

Dostosowanie konfiguracji serwera HTTP:

  • załóżmy, że nazwa naszego serwera to login.example.pl, serwer o tej nazwie należy skonfigurować jako wirtualny serwer https (port 443), zaleca się również realizację przekierowania adresu http://login.example.pl na https://login.example.pl, np:
 ServerName login.example.pl
 DocumentRoot /var/www/html
 RedirectMatch 301 ^/simplesaml(.*) https://login.example.pl/simplesaml$1


  • w konfiguracji serwera SSL podajemy klucz prywatny serwera (SSLCertificateKeyFile) oraz certyfikat serwera (SSLCertificateFile) i plik zawierający łańcuch certyfikatów wystawców (SSLCACertificateFile) - należy użyć znanego wystawcy certyfikatów, wymogi spełniają certyfikaty TCS, również tzw. wildcard (czyli wystawione dla nazwy *.example.pl)
  • dodajemy w sekcji wirtualnego hosta SSL
Alias /simplesaml /usr/local/simplesamlphp-1.19.0/www


  • nadajemy uprawnienia dla katalogu
 Order allow,deny
 Allow from all
 Require all granted

(niezbędne jest Require all granted)


Konfiguracja SimpleSAMLphp IdP

Opis konfiguracji jest dostępny na stronie Konfiguracja SimpleSAMLphp IdP

Plik konfiguracyjny config/config.php

'debug' => true,

oraz

'logging.level' => SimpleSAML_Logger::DEBUG,

Warto również ustawić

 'logging.handler' => 'file',

zamiast logowania via syslog

  • Pamiętamy o ustawieniu praw dostępu do katalogu log (zapis przez użytkownika serwera httpd).
  • Dostosowujemy inne zmienne konfiguracyjne:
    • auth.adminpassword - hasło administratora umożliwiające logowanie na stronie https://login.example.pl/simplesaml
    • secretsalt - poprzez wygenerowanie zmiennej losowej - jej wartość w wersji produkcyjnej należy zarchiwizować, by przy aktualizacjach zagwarantować stosowanie takiej samej
    • technicalcontact_name, technicalcontact_email
    • timezone - należy ustalić 'Europe/Warsaw'


    • enable.saml20-idp - wartość true oznacza, że instalacja pełni funkcję IdP
  • Ustawiamy filtry służące do przygotowania atrybutów:
    'authproc.idp' => array(
       30 => 'core:LanguageAdaptor',
       95 => array(
             'class' => 'core:TargetedID' , 'attributename' => 'eduPersonPrincipalName', 'nameId' => TRUE),
       98 => 'core:AttributeLimit',
       100 => array('class' => 'core:AttributeMap', 'name2oid'),
   ),
  • W pliku metadata/saml20-idp-hosted.php umieszczamy wykaz atrybutów, które IdP może wysłać
  'attributes' => array(
   'uid', 'commonName', 'sn', 'givenname', 'mail', 'eduPersonPrincipalName', 'eduPersonTargetedID'
  ),

Plik config/authsources.php

Zakładamy, że korzystamy z bazy LDAP do uwierzytelniania.Dostosowujemy sekcję po komentarzu Example of a LDAP authentication source - example-ldap, np:

'example-ldap' => array(
 'ldap:LDAP',
 'hostname' => 'localhost',
 'enable_tls' => FALSE,
 'debug' => FALSE,
 'timeout' => 0,
 'referrals' => TRUE,
 'attributes' => NULL, // NULL oznacza pobierz wszystkie atrybuty, można podać tablicę atrybutóœ
 'search.enable' => FALSE,
 'dnpattern' => 'uid=%username%,ou=users,dc=test-org,dc=pl',
 'search.base' => 'ou=users,dc=example,dc=pl',
 'search.attributes' => array('uid', 'mail'),
 'search.username' => 'cn=admin,dc=test-org,dc=pl',
 'search.password' => '1qaz2wsx',
),


Certyfikat stosowany do podpisywania/szyfrowania danych przekazywanych między IdP a SP

Przygotowujemy certyfikat tzw. self-signed

 openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out example.pl.pem -keyout example.pl.key

i umieszczamy klucz prywatny oraz certyfikat w katalogu cert

Uwaga! SimpleSAMLphp obsługuje wyłącznie certyfikaty RSA. Nie są wspierane certyfikaty DSA.


Plik metadata/saml20-idp-hosted.php

W pliku metadata/saml20-idp-hosted.php umieszcza się metadane IdP. Należy dostosować wpisy dotyczące certyfikatów:

'privatekey' => 'example.pl.key',
'certificate' => 'example.pl.pem',Wpis
 'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',

Wpis 'auth' musi wskazywać wybrane źródło uwierzytelniania, czyli np.

'auth' => 'example-ldap',Poza tym umieszczamy:
 'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',

Dodajemy ustawienie sposobu kodowania atrybutu eduPersonPrincipalName:

  'attributeencodings' => array( 'urn:oid:1.3.6.1.4.1.5923.1.1.1.10' => 'raw', ),

Powiązanie z bazą danych użytkowników IdP

Patrz Baza użytkowników IdP

Moduł metarefresh - pobieranie i odświeżanie metadanych

Moduł metarefresh służy do pobierania metadanych. Jeśli współpracuje z modułem cron, to za jego pomocą można regularne aktualizować metadane. Aby aktywować moduł, wykonujemy:

cd /usr/local/simplesamlphp-1.19.0
touch modules/metarefresh/enable

Aktywizujemy również moduł cron:

touch modules/cron/enableKopiujemy pliki konfiguracyjne tych dwóch modułów do katalogu config:
cp modules/cron/config-templates/module_cron.php config/
cp modules/metarefresh/config-templates/config-metarefresh.php config/

W pliku config/module_cron.php ustalamy stosowany tajny klucz (key):

'key' => '0oki8uh',

Aby metarefres regularnie pobierał metadane z określonych lokalizacji, należy dostosować plik config/config-metarefresh.php:

  • Usuwamy wpis:
 'kalmar' => array(.....),
  • Dodajemy wpis:
  'identyfikator_źródła_metadanych' => array(
      'cron'          => array('daily'),
      'sources'       => array(
          array(
           'src' => 'URL_źródła_metadanych',
           'validateFingerprint' => 'fingerprint_certyfikatu_podpisującego_metadane',
          ),
      ),
      'expireAfter' => 60*60*24*4, 
      'outputDir' => 'metadata/katalog_tego_źródła_metadanych/',
      'outputFormat' => 'flatfile',
  ),


Ładowanie metadanych usługodawców, z którymi ma współpracować IdP

Testowy Dostawca Usługi - PIONIER Test SP

Metadane testowego SP znajdują się pod adresem Testowy Dostawca Usługi. Metadane testowego SP w postaci "SimpleSAMLphp flat file format" umieszczmy w pliku ./metadata/saml20-sp-remote.php.

Metadane PIONIER.Id

Jeśli od razu chcemy włączyć dostęp do IdP ze wszystkich usług (SP) zarejestrowanych w eduGAIN, pomijamy poniższą instrukcję, przechodzimy do punktu Metadane PIONIER.Id-eduGAIN.IdP ma umożliwiać logowanie do federacyjnych usług zarejestrowanych w ramach PIONIER.Id. Metadane federacji PIONIER.Id są dostępne pod adresem https://aai.pionier.net.pl/pionierid.xml.IdP musi regularnie odświeżać te dane. W tym celu korzystamy z modułu metarefresh.

  • Modyfikujemy plik config/config-metarefresh.php - dodajemy dane potrzebne do pobierania metadanych PIONIER.Id:
  'pionierid' => array(
      'cron'          => array('daily'),
      'sources'       => array(
          array(
           'src' => 'https://aai.pionier.net.pl/pionierid.xml',
           'validateFingerprint' => '48:73:B2:14:DB:A1:48:E5:4B:F2:DA:4F:67:A5:67:E0:E1:B1:53:52',
          ),
      ),
      'expireAfter' => 60*60*24*4, 
      'outputDir' => 'metadata/pionierid/',
      'outputFormat' => 'flatfile',
  ),

(dostępna po zalogowaniu jako administrator), np.

00 12 * * * curl --silent "https://ssp-idp.uci.umk.pl/simplesaml/module.php/cron/cron.php?key=0oki8uh&tag=daily" > /dev/null 2>&1

Można również z tej strony uruchomić zadanie natychmiast przez kliknięcie "Run [daily]"

Zaplanowane zadanie odświeżania metadanych będzie realizowane w wyznaczonych godzinach.

  • W pliku config/config.php we wpisie metadata.sources dodajemy:
array('type' => 'flatfile', 'directory' => 'metadata/pionierid'),


Metadane PIONIER.Id-eduGAIN

Jeśli IdP ma umożliwiać logowanie do usług zewnętrznych, oferowanych w ramach projektu eduGAIN, np. http://foodl.org, to należy regularnie pobierać metadane eduGAIN przygotowane przez federację PIONIER.Id. Są one dostępne pod adresem https://aai.pionier.net.pl/pionierid-edugain-sp-feed.xml.Aby włączyć regularne pobieranie metadanych wykonujemy następujące kroki:

  • Dodajemy w pliku config/config-metarefresh.php wpis:
'edugain-sp' => array(
      'cron'          => array('hourly'),
      'sources'       => array(
          array(
                'src' => 'https://aai.pionier.net.pl/pionierid-edugain-sp-feed.xml',
                'validateFingerprint' => '48:73:B2:14:DB:A1:48:E5:4B:F2:DA:4F:67:A5:67:E0:E1:B1:53:52',
          ),
       ),
      'expireAfter' => 60*60*24*4, // Maximum 4 days cache time.
      'outputDir' => 'metadata/edugain-sp/',
      'outputFormat' => 'flatfile',
 ),
  • Tworzymy katalog metadata/edugain-sp/ z prawami zapisu dla użytkownika, pod którym pracuje httpd
  • Dodajemy do crontaba wpis wg tego co podaje strona

https://login.example.pl/simplesaml/module.php/cron/croninfo.php (dostępna po zalogowaniu jako administrator), np.

10 * * * * curl --silent "https://ssp-idp.uci.umk.pl/simplesaml/module.php/cron/cron.php?key=0oki8uh&tag=daily"> /dev/null 2>&1

Można również z tej strony uruchomić zadanie natychmiast przez kliknięcie "Run [hourly]"

  • Zaplanowane zadanie odświeżania metadanych będzie realizowane w wyznaczonych godzinach.

W pliku config/config.php we wpisie 'metadata.sources' należy dodać:

array('type' => 'flatfile', 'directory' => 'metadata/edugain-sp'),

Uwaga: metadane PIONIER.Id-eduGAIN zawierają metadane PIONIER.Id, należy więc wyłaczyć pobiernie metadanych PIONIER.Id, tj. wycofać zadanie icy pobierania z crontab i usunąć wpis wskazujący katalog metadata/pionierid z parameter metadata.sources w pliku config/config.php.

Włączenie modułu zgody na przekazywanie atrybutów

Aby dostawca tożsamości (IdP) wymuszał wyrażenie zgody na przekazanie atrybutów do aplikacji, musi zostać aktywowany moduł consent. W tym celu w konfiguracji głównej config/config.php, we wpisie authproc.idp odkomentowujemy:

90 => array(
 'class' => 'consent:Consent',
 'store' => 'consent:Cookie',
 'focus' => 'yes',
 'checked' => TRUE
),

Jeśli dane dotyczące zgody mają być przechowywane w bazie danych, to tworzymy w wybranej bazie tabelę:

CREATE TABLE consent (
   consent_date TIMESTAMP NOT NULL,
   usage_date TIMESTAMP NOT NULL,
   hashed_user_id VARCHAR(80) NOT NULL,
   service_id VARCHAR(255) NOT NULL,
   attribute VARCHAR(80) NOT NULL,
   UNIQUE (hashed_user_id, service_id)
);

i nadajemy uprawnienia użytkownikowi simplesaml/secreti w parametrze store zamiast 'consent:Cookie' podajemy

  array(
       'consent:Database', 
       'dsn' => 'mysql:host=localhost;dbname=consent',
       'username' => 'simplesaml',
       'password' => 'secret',
   ),

Przechowywanie identyfikatorów Persistent Id w bazie danych

Typowo identyfikatory Persistent Id są generowane każdorazowo przy korzystaniu z usługi. Ponieważ na ich wartość ma wpływ postać URL-i usługodawcy i dostawcy tożsamości, identyfikator użytkownika oraz liczba losowa (salt), która jest ustalana dla danej instalacji, wartość Persistent Id nie zmienia się dla danego dostawcy usługi i danego użytkownika. Aby zagwarantować trwałość tego identyfikatora pomiędzy instalacjami można użyć filtra o nazwie SQLPersistentId, który pozwala przechowywać identyfikatory w bazie danych (sqllite, mysql).W tym celu w głównej konfiguracji, tj. w pliku config/config.php zmieniamy wartość store.type na sql i definiujemy połączenie do bazy:

'store.type' => 'sql',
'store.sql.dsn' => 'mysql:host=localhost;dbname=ssp',
'store.sql.username' => 'ssp',
'store.sql.password' => 'zaqWSX12',Tworzymy bazę danych ssp:
create database ssp;

W pliku config/config.php we wpisie authproc.idp umieszczamy:

 1 => array(
       'class' => 'saml:SQLPersistentNameID',
       'attribute' => 'eduPersonPrincipalName',
       'AllowCreate' => "true"
 ),
 95 => array(
      'class' => 'saml:PersistentNameID2TargetedID' , 
      'attributename' => 'eduPersonTargetedID', 
      'nameId' => TRUE
 ),

Od tej chwili w bazie danych pojawią się trzy tabele. W tabeli simpleSAMLphp_saml_PersistentNameID będzie przechowywany persistent ID.

Testowanie SimpleSAMLphp IdP

Aby przetestować działanie IdP najlepiej skorzystać z testowego dostawcy https://aai.pionier.net.pl/test/attributes.php

Metadane tego usługodawcy zostały dodane do konfiguracji (patrz Testowy Dostawca Usługi - PIONIER Test SP).

Testowy dostawca MUSI OTRZYMAĆ METADANE IdP. W tym celu należy przekazać na adres admin@aai.pionier.net.pl URL metadanych, tj. https://login.example.pl/idp/shibboleth

Dostosowanie graficzne strony logowania

Szczegółowe wskazówki jak dostosować grafikę stron SimpleSAMLphp znajdują się tutaj

Współpraca SimpleSAMLphp z innymi niż LDAP źródłami uwierzytelniania

Bazy SQL

Moduł sqlauth:SQL umożliwia uwierzytelnianie przez bazy MySQL. W pliku config/authsources.php trzeba zdefiniować parametry połączenia do bazy, np.:

 
'via-sql' => array(
 'sqlauth:SQL',
 'dsn' => 'mysql:host=localhost;port=3306;dbname=allusers',
          'username' => 'admin',
          'password' => '0okmnji9',
          'query' => 'SELECT login,mail,eppn,displayname FROM users WHERE login=:username AND password=MD5(:password)',
 ),

Dokumentacja SimpleSAMLphp dotycząca użycia modułu sqlauth:SQL znajduje się na stronie https://simplesamlphp.org/docs/stable/sqlauth:sql.

Central Authentication Service (CAS)

W pakiecie SimpleSAMLphp jest dostępny moduł cas. Aby z niego korzystać, trzeba go aktywować:

cd /usr/local/simplesaml
touch modules/cas/enable

Następnie w pliku config/authsources.php umieszczamy konfigurację tego modułu, która:

  • wskazuje serwer CAS, sposób realizacji zalogowania, wylogowania i walidacji ticketów CAS,
  • wskazuje sposób pobierania atrybutów, moduł cas zakłada, że atrybuty są dostępnie via LDAP
 'example-cas' => array(
        'cas:CAS',
        'cas' => array(
          'login' => 'https://cas.example.pl/login',
          'validate' => 'https://cas.example.pl/validate',
          'logout' => 'https://cas.example.pl/logout'
        ),
        'ldap' => array(
          'servers' => 'ldap://localhost',
          'enable_tls' => false,
          'searchbase' => 'ou=users,dc=example,dc=pl',
          'searchattributes' => 'edupersonprincipalname',
          'attributes' => array('edupersonprincipalname','cn', 'mail','edupersonentitlement',  
              'sn', 'givenname', 'edupersonaffiliation', 'edupersonscopedaffiliation',   
              'preferredLanguage','displayname','uid'),
          'priv_user_dn' => 'cn=admin,dc=example,dc=pl',
          'priv_user_pw' => '1qazxsw2',
        ),
 ),

Dokumentacja SimpleSAMLphp dotycząca użycia modułu cas znajduje się na stronie https://simplesamlphp.org/docs/stable/cas:cas