Shibboleth EDS¶
DOC: https://shibboleth.atlassian.net/wiki/spaces/EDS10/overview
1. Setup folder¶
Create the folder to obtain the JSON file from the JSON Web Token (JWT):
2. Retrieve IDEM Public key¶
Retrieve the public key needed to decode:
sudo wget "https://mdx.idem.garr.it/idem-mdx-service-pubkey.pem" -O /opt/idem_jwt_to_json/idem-mdx-service-pubkey.pem
and check the validity:
-
SHA1:
sudo openssl rsa -pubin -in /opt/idem_jwt_to_json/idem-mdx-service-pubkey.pem -pubout -outform DER | openssl sha1 -c
will give:
((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_json/idem-mdx-service-pubkey.pem -pubout -outform DER | openssl md5 -c
will give:
((stdin)= 84:5f:69:99:c5:f6:bb:e6:5f:ff:32:39:9a:a6:bb:85)
3. Install the needed Python modules¶
-
Python >= 3.9:
-
sudo apt-get install python3-pip
-
sudo pip install pyjwt pyjwt[crypto] pem requests
-
-
Python >= 3.11:
sudo apt-get install python3-jwt python3-requests python3-pem
4. Download the JWT decoding file¶
Retrieve the decodeToken.py
file in the /opt/idem_jwt_to_json
folder:
-
cd /opt/idem_jwt_to_json
-
sudo wget https://mdx.idem.garr.it/decodeToken.py
-
sudo chmod +x decodeToken.py
which contains the following code block:
#!/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. [OPTIONAL] Create a custom JSON¶
5.1. Retrieve the eds-filter.py
file in the /opt/idem_jwt_to_json
folder:
-
cd /opt/idem_jwt_to_json
-
sudo wget https://mdx.idem.garr.it/eds-filter.py
-
sudo chmod +x eds-filter.py
which contains the following code block:
#!/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. Create a file called entity_ids.txt
in the
/opt/idem_jwt_to_json
folder, containing the list of entityIDs of the organizations you want to filter.
For example:
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. Create a cronjob to update JSON files¶
Create eds-refresh
file:
and, depending on the Metadata and the DocumentRoot
used (default: /var/www/html
),
add the following jobs:
-
IDEM Production Federation (complete):
-
eduGAIN + IDEM Interfederation (complete):
*/30 * * * * /opt/idem_jwt_to_json/decodeToken.py -j https://mdx.idem.garr.it/edugain2idem-token -o /var/www/html/edugain2idem-eds.json -k /opt/idem_jwt_to_json/idem-mdx-service-pubkey.pem > /opt/idem_jwt_to_json/jwt_to_json.log 2>&1
version without logos ( (complete):
-
IDEM Test Federation (complete):
-
IDEM Production Federation (custom):
*/30 * * * * /opt/idem_jwt_to_json/decodeToken.py -j https://mdx.idem.garr.it/idem-token -o /opt/idem_jwt_to_json/idem-eds.json -k /opt/idem_jwt_to_json/idem-mdx-service-pubkey.pem > /opt/idem_jwt_to_json/jwt_to_json.log 2>&1 */30 * * * * /opt/idem_jwt_to_json/eds-filter.py -i /opt/idem_jwt_to_json/idem-eds.json -o /var/www/html/custom-eds.json -e /opt/idem_jwt_to_json/entity_ids.txt > /opt/idem_jwt_to_json/eds-filter.log 2>&1
-
eduGAIN + IDEM Interfederation (custom):
*/30 * * * * /opt/idem_jwt_to_json/decodeToken.py -j https://mdx.idem.garr.it/edugain2idem-token -o /opt/idem_jwt_to_json/edugain2idem-eds.json -k /opt/idem_jwt_to_json/idem-mdx-service-pubkey.pem > /opt/idem_jwt_to_json/jwt_to_json.log 2>&1 */30 * * * * /opt/idem_jwt_to_json/eds-filter.py -i /opt/idem_jwt_to_json/edugain2idem-eds.json -o /var/www/html/custom-eds.json -e /opt/idem_jwt_to_json/entity_ids.txt > /opt/idem_jwt_to_json/eds-filter.log 2>&1
-
IDEM Test Federation (custom):
*/30 * * * * /opt/idem_jwt_to_json/decodeToken.py -j https://mdx.idem.garr.it/idem-test-token -o /opt/idem_jwt_to_json/idem-test-eds.json -k /opt/idem_jwt_to_json/idem-mdx-service-pubkey.pem > /opt/idem_jwt_to_json/jwt_to_json.log 2>&1 */30 * * * * /opt/idem_jwt_to_json/eds-filter.py -i /opt/idem_jwt_to_json/idem-test-eds.json -o /var/www/html/custom-eds.json -e /opt/idem_jwt_to_json/entity_ids.txt > /opt/idem_jwt_to_json/eds-filter.log 2>&1
7. Configure EDS¶
Modify the EDS configuration:
by changing the value of this.dataSource
with the appropriate value chosen from:
- IDEM Test Federation:
/idem-test-eds.json
- IDEM Federation:
/idem-eds.json
- eduGAIN:
/edugain2idem-eds.json
- Custom JSON:
/custom-eds.json
Warning: The value of this.dataSource
is the URL of the source of
the data feed of IdPs to the Discovery Service. This feed MUST be at the same
location as the DS itself and so it is usual for the protocol and host part of
the URL (https://example.org
) to be dropped. The data source is a JSON file.
The schema of this file is defined in EDSDetails