Vai al contenuto

SimpleSAMLphp EDS

1. Setup cartella

Crea una cartella per ricavare il file JSON dal JSON Web Token (JWT) fornito dalla federazione:

sudo mkdir /opt/idem_jwt_to_php

2. Scaricare la chiave pubblica di IDEM

Scarica la chiave pubblica necessaria per la decodifica:

sudo wget "https://mdx.idem.garr.it/idem-mdx-service-pubkey.pem" -O /opt/idem_jwt_to_php/idem-mdx-service-pubkey.pem

e controllane la validità:

  • SHA1:

    sudo openssl rsa -pubin -in /opt/idem_jwt_to_php/idem-mdx-service-pubkey.pem -pubout -outform DER | openssl sha1 -c
    

    deve restituire:

    ((stdin)= 30:75:93:37:d0:05:55:19:9f:76:e1:5a:73:db:45:7f:5e:66:11:4b)

  • MD5:

    sudo openssl rsa -pubin -in /opt/idem_jwt_to_php/idem-mdx-service-pubkey.pem -pubout -outform DER | openssl md5 -c
    

    deve restituire:

    ((stdin)= 84:5f:69:99:c5:f6:bb:e6:5f:ff:32:39:9a:a6:bb:85)

3. Installazione moduli Python necessari per la decodifica

  • Python >= 3.9:

    • bash sudo apt-get install python3-pip

    • bash sudo pip install pyjwt pyjwt[crypto] pem requests

  • Python >= 3.11:

    • bash sudo apt-get install python3-jwt python3-requests python3-pem

4. Scaricare il file per la decodifica del JWT

Scarica il file decodeToken.py nella cartella /opt/idem_jwt_to_php:

  • cd /opt/idem_jwt_to_php

  • sudo wget https://mdx.idem.garr.it/decodeToken.py

  • sudo chmod +x decodeToken.py

che contiene il seguente blocco di codice:

#!/usr/bin/env python3

import jwt
import json
import pem
import sys, getopt
import requests

def main(argv):
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'j:o:k:hd', ['jwt=','output=','publickey=','help','debug' ])
    except getopt.GetoptError as err:
        print (str(err))
        print ("Usage: ./decodeToken.py -j <jwt_inputurl> -o <output_path> -k <publickey_path>")
        print ("The JSON file will be put in the output directory")
        sys.exit(2)

    inputurl = None
    outputpath = None
    publickey = None

    for opt, arg in opts:
        if opt in ('-h', '--help'):
            print ("Usage: ./decodeToken.py -j <jwt_inputurl> -o <output_path> -k <publickey_path>")
            print ("The JSON file will be put in the output directory")
            sys.exit()
        elif opt in ('-j', '--jwt'):
            inputurl = arg
        elif opt in ('-o', '--output'):
            outputpath = arg
        elif opt in ('-k', '--publickey'):
            publickey = arg
        elif opt == '-d':
            global _debug
            _debug = 1
        else:
            print ("Usage: ./decodeToken.py -j <jwt_inputurl> -o <output_path> -k <publickey_path>")
            print ("The JSON file will be put in the output directory")
            sys.exit()

    if inputurl == None:
        print ("Token file is missing!n")
        print ("Usage: ./decodeToken.py -j <jwt_inputurl> -o <output_path> -k <publickey_path>")
        sys.exit()

    if outputpath == None:
        print ("Output path is missing!n")
        print ("Usage: ./decodeToken.py -j <jwt_inputurl> -o <output_path> -k <publickey_path>")
        sys.exit()

    if publickey == None:
        print ("Public Key path is missing!n")
        print ("Usage: ./decodeToken.py -j <jwt_inputurl> -o <output_path> -k <publickey_path>")
        sys.exit()

    with open(publickey, 'r') as rsa_pubkey:
        pubkey = rsa_pubkey.read()

    jwt_token = requests.get(inputurl, allow_redirects=True)
    token = jwt_token.content
    decode = jwt.decode(token, pubkey, algorithms=["RS256"])

    x = decode["data"]
    json_decoded = json.dumps(x, indent = 4, ensure_ascii=False)

    result_path = open(outputpath, "w", encoding="utf-8")
    result_path.write(json_decoded)
    result_path.close()

if __name__ == "__main__":
    main(sys.argv[1:])

5. [OPZIONALE] Creazione di un JSON custom

5.1. Scarica il file eds-filter.py nella cartella /opt/idem_jwt_to_php:

  • cd /opt/idem_jwt_to_php

  • sudo wget https://mdx.idem.garr.it/eds-filter.py

  • sudo chmod +x eds-filter.py

che contiene il seguente blocco di codice:

#!/usr/bin/env python3

import json
import getopt
import sys

def main(argv):
    input_file = ''
    output_file = ''
    entity_ids_file = ''

    try:
        opts, args = getopt.getopt(argv, "hi:o:e:", ["input=", "output=", "entityids="])
    except getopt.GetoptError:
        print('Usage: filter_json.py -i <input_file> -o <output_file> -e <entity_ids_file>')
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print('Usage: filter_json.py -i <input_file> -o <output_file> -e <entity_ids_file>')
            sys.exit()
        elif opt in ("-i", "--input"):
            input_file = arg
        elif opt in ("-o", "--output"):
            output_file = arg
        elif opt in ("-e", "--entityids"):
            entity_ids_file = arg

    if not input_file or not output_file or not entity_ids_file:
        print('Usage: filter_json.py -i <input_file> -o <output_file> -e <entity_ids_file>')
        sys.exit(2)

    # Leggi gli entityID dal file di testo
    with open(entity_ids_file, 'r', encoding='utf-8') as f:
        entity_ids_to_keep = [line.strip() for line in f]

    # Leggi il file JSON
    with open(input_file, 'r', encoding='utf-8') as file:
        data = json.load(file)

    # Filtra le entry mantenendo solo quelle con entityID presenti nella lista
    filtered_data = [entry for entry in data if entry['entityID'] in entity_ids_to_keep]

    # Scrivi i dati filtrati in un nuovo file JSON
    with open(output_file, 'w', encoding='utf-8') as file:
        json.dump(filtered_data, file, ensure_ascii=False, indent=4)

    print(f"Il file JSON è stato filtrato e salvato come '{output_file}'")

if __name__ == "__main__":
    main(sys.argv[1:])

5.2. Crea un file entity_ids.txt nella cartella /opt/idem_jwt_to_php contenente la lista degli entityID delle organizzazioni che si vogliono filtrare. Ad esempio:

https://idp.example.01.it/idp/shibboleth
https://idp.example.02.it/idp/shibboleth
http://idp.example.03.it/simplesaml/saml2/idp/metadata.php

6. Scaricare lo script per la conversione JSON -> PHP

Scarica lo script per la conversione del file JSON in PHP:

  • cd /opt/idem_jwt_to_php

  • sudo wget https://mdx.idem.garr.it/json_to_php_converter.php

  • sudo chmod +x json_to_php_converter.php

che contiene il seguente blocco di codice:

<?php
$jsondata = file_get_contents('/opt/idem_jwt_to_php/edugain2idem-eds.json');

if (!empty($jsondata)) {
    $entities = json_decode($jsondata, true);
    $text = '';
    $displaynames = '';

    foreach ($entities as $entity => $entityMetadata) {

        // remove the unused elements of json
        unset($entityMetadata['Logos']);

        $entityMetadata['entityid'] = $entityMetadata['entityID'];
        unset($entityMetadata['entityID']);

        $displaynames = $entityMetadata['DisplayNames'];
        unset($entityMetadata['DisplayNames']);

        if (!empty($displaynames)) {
                $entityMetadata['name'] = array();

                foreach ($displaynames as $displayname => $entityName) {

                        $entityMetadata['name'][$entityName['lang']] = $entityName['value'];

                }
        }
        $text .= '$metadata['.var_export($entityMetadata['entityid'], true).'] ='.
                var_export($entityMetadata, true).";n";

        $entities = $text;
    }
}

$file = '/var/simplesamlphp/metadata/saml20-idp-remote.php';
file_put_contents($file,"<?phpn");
file_put_contents($file, print_r($entities, true),FILE_APPEND);
?>

e modifica il valore di file_get_contents dipendentemente dal flusso utilizzato:

  • Federazione IDEM di Test: /opt/idem_jwt_to_php/idem-test-eds.json
  • Federazione IDEM di Produzione: /opt/idem_jwt_to_php/idem-eds.json
  • Interfederazione eduGAIN + IDEM: /opt/idem_jwt_to_php/edugain2idem-eds.json
  • Custom JSON: /opt/idem_jwt_to_php/custom-eds.json

7. Creazione cronjob per aggiornare i file JSON

Crea il file eds-refresh:

vim /etc/cron.d/eds-refresh

e aggiungi, dipendentemente dal flusso utilizzato, i seguenti jobs:

  • Federazione IDEM di Produzione (completo):

    */30 * * * * root  /opt/idem_jwt_to_php/decodeToken.py -j https://mdx.idem.garr.it/idem-token -o /opt/idem_jwt_to_php/idem-eds.json -k /opt/idem_jwt_to_php/idem-mdx-service-pubkey.pem > /opt/idem_jwt_to_php/jwt_to_php.log 2>&1
    
    */30 * * * * root  /usr/bin/php /opt/idem_jwt_to_php/json_to_php_converter.php
    
  • Interfederazione eduGAIN + IDEM (completo):

    */30 * * * * root  /opt/idem_jwt_to_php/decodeToken.py -j https://mdx.idem.garr.it/edugain2idem-token -o /opt/idem_jwt_to_php/edugain2idem-eds.json -k /opt/idem_jwt_to_php/idem-mdx-service-pubkey.pem > /opt/idem_jwt_to_php/jwt_to_php.log 2>&1
    
    */30 * * * * root  /usr/bin/php /opt/idem_jwt_to_php/json_to_php_converter.php
    
  • Federazione IDEM di Test (completo):

    */30 * * * * root  /opt/idem_jwt_to_php/decodeToken.py -j https://mdx.idem.garr.it/idem-test-token -o /opt/idem_jwt_to_php/idem-test-eds.json -k /opt/idem_jwt_to_php/idem-mdx-service-pubkey.pem > /opt/idem_jwt_to_php/jwt_to_php.log 2>&1
    
    */30 * * * * root  /usr/bin/php /opt/idem_jwt_to_php/json_to_php_converter.php
    
  • Federazione IDEM di Produzione (custom):

    */30 * * * * root  /opt/idem_jwt_to_php/decodeToken.py -j https://mdx.idem.garr.it/idem-token -o /opt/idem_jwt_to_php/idem-eds.json -k /opt/idem_jwt_to_php/idem-mdx-service-pubkey.pem > /opt/idem_jwt_to_php/jwt_to_php.log 2>&1
    
    */30 * * * * root  /opt/idem_jwt_to_php/eds-filter.py -i /opt/idem_jwt_to_php/idem-eds.json -o /opt/idem_jwt_to_php/custom-eds.json -e /opt/idem_jwt_to_php/entity_ids.txt > /opt/idem_jwt_to_php/eds-filter.log 2>&1 
    
    */30 * * * * root  /usr/bin/php /opt/idem_jwt_to_php/json_to_php_converter.php
    
  • Interfederazione eduGAIN + IDEM (custom):

    */30 * * * * root  /opt/idem_jwt_to_php/decodeToken.py -j https://mdx.idem.garr.it/edugain2idem-token -o /opt/idem_jwt_to_php/edugain2idem-eds.json -k /opt/idem_jwt_to_php/idem-mdx-service-pubkey.pem > /opt/idem_jwt_to_php/jwt_to_php.log 2>&1
    
    */30 * * * * root  /opt/idem_jwt_to_php/eds-filter.py -i /opt/idem_jwt_to_php/edugain2idem-eds.json -o /opt/idem_jwt_to_php/custom-eds.json -e /opt/idem_jwt_to_php/entity_ids.txt > /opt/idem_jwt_to_php/eds-filter.log 2>&1 
    
    */30 * * * * root  /usr/bin/php /opt/idem_jwt_to_php/json_to_php_converter.php
    
  • Federazione IDEM di Test (custom):

    */30 * * * * root  /opt/idem_jwt_to_php/decodeToken.py -j https://mdx.idem.garr.it/idem-test-token -o /opt/idem_jwt_to_php/idem-test-eds.json -k /opt/idem_jwt_to_php/idem-mdx-service-pubkey.pem > /opt/idem_jwt_to_php/jwt_to_php.log 2>&1
    
    */30 * * * * root  /opt/idem_jwt_to_php/eds-filter.py -i /opt/idem_jwt_to_php/idem-test-eds.json -o /opt/idem_jwt_to_php/custom-eds.json -e /opt/idem_jwt_to_php/entity_ids.txt > /opt/idem_jwt_to_php/eds-filter.log 2>&1 
    
    */30 * * * * root  /usr/bin/php /opt/idem_jwt_to_php/json_to_php_converter.php