Commit 0cecf43b authored by Marco Malavolti's avatar Marco Malavolti
Browse files

Fixed encoding and Web GUI

parent 7bc48f56
# HOWTO Install and Configure ECCS-2
* `sudo apt install python3 python3-pip chromium chromium-l10n git`
* `sudo apt install python3 python3-pip chromium chromium-l10n git libapache2-mod-wsgi python3-dev`
* `python3 -m pip install --user --upgrade pip virtualenv`
* `python3 -m venv eccs2venv`
* `source eccs2venv/bin/activate` (`deactivate` di exit Virtualenv)
......@@ -11,7 +11,7 @@
# API
* `/eccs/test` (Trivial Test)
* `/eccs/checks` (Should return the results of the last checks)
* `/eccs/checks` (Return the results of the last checks)
* `/eccs/checks?<parameter>=<value>`:
* `date=2020-02-20` (select date)
* `idp=Any%20words%20do%20you%20like%20url%20encoded`
......@@ -21,7 +21,10 @@
* 'No-eduGAIN-Metadata'
* 'Form-Invalid'
* 'Excluded'
* /eccs/eccsresults (Return the results of the last check ready for ECCS Gui)
# API Development Server
* `sudo apt install libapache2-mod-wsgi-py3 python3-dev`
* `sudo a2enmod wsgi`
* `cd ~/eccs2 ; ./api.py`
......@@ -88,7 +88,7 @@ class Checks(Resource):
idp = request.args['idp']
app.logger.info(idp)
fo = open(file_path, "r")
fo = open(file_path,"r",encoding="utf-8")
result = []
lines = fo.readlines()
......@@ -138,12 +138,180 @@ class Checks(Resource):
return jsonify(pp_json)
else:
return jsonify(result)
# Build Email Addresses Link for ECCS2 Web Gui
def buildEmailAddress(listContacts):
listCtcs = listContacts.split(",")
hrefList = []
for email in listCtcs:
hrefList.append("<a href='%s'>%s</a>" % (email,email.replace('mailto:', '')))
return hrefList
class EccsResults(Resource):
def get(self):
app.logger.info("Request 'EccsResults'")
file_path = "logs/eccs2_2020-03-01.log"
date = PurePath(file_path).parts[-1].split('_')[1].split('.')[0]
pretty = 0
status = None
idp = None
if 'date' in request.args:
app.logger.info("'date' parameter inserted")
file_path = "logs/eccs2_"+request.args['date']+".log"
date = request.args['date']
if 'pretty' in request.args:
app.logger.info("'pretty' parameter inserted")
pretty = request.args['pretty']
if 'status' in request.args:
app.logger.info("'status' parameter inserted")
status = request.args['status']
if 'idp' in request.args:
app.logger.info("'idp' parameter inserted")
idp = request.args['idp']
app.logger.info(idp)
fo = open(file_path,"r",encoding="utf-8")
result = []
lines = fo.readlines()
for line in lines:
# Line:
# IdP-DisplayName; check[0]
# IdP-entityID; check[1]
# IdP-RegAuth; check[2]
# IdP-tech-ctc-1,IdP-tech-ctc-2; check[3]
# IdP-supp-ctc-1,IdP-supp-ctc-2; check[4]
# Status; check[5]
# SP-entityID-1; check[6]
# SP-status-1; check[7]
# SP-entityID-2; check[8]
# SP-status-2 check[9]
check = line.split(";")
idp_displayname = check[0].rstrip("\n\r")
idp_entity_id = check[1].rstrip("\n\r")
idp_reg_auth = check[2].rstrip("\n\r")
idp_tech_ctcs = check[3].rstrip("\n\r")
idp_supp_ctcs = check[4].rstrip("\n\r")
idp_checks_status = check[5].rstrip("\n\r")
sp1_entity_id = check[6].rstrip("\n\r")
sp1_check_status = check[7].rstrip("\n\r")
sp2_entity_id = check[8].rstrip("\n\r")
sp2_check_status = check[9].rstrip("\n\r")
if (idp and status):
app.logger.info("Results for the idp '%s' with status '%s'" % (idp, status))
if (idp == idp_entity_id and status == idp_checks_status):
result.append(
{
'displayName' : idp_displayname,
'entityID' : idp_entity_id,
'registrationAuthority' : idp_reg_auth,
'contacts' : {
'technical' : buildEmailAddress(idp_tech_ctcs),
'support' : buildEmailAddress(idp_supp_ctcs),
},
'date' : date,
'sp1' : {
'entityID' : sp1_entity_id,
'status' : sp1_check_status
},
'sp2' : {
'entityID' : sp2_entity_id,
'status' : sp2_check_status
},
'status' : idp_checks_status
} )
elif (idp):
#app.logger.info(re.search(".*."+idp+".*.", idp_entity_id, re.IGNORECASE))
#app.logger.info(idp_entity_id))
app.logger.info("Results for IdP '%s'." % idp)
if (re.search(".*."+idp+".*.", idp_entity_id, re.IGNORECASE)):
result.append(
{
'displayName' : idp_displayname,
'entityID' : idp_entity_id,
'registrationAuthority' : idp_reg_auth,
'contacts' : {
'technical' : buildEmailAddress(idp_tech_ctcs),
'support' : buildEmailAddress(idp_supp_ctcs),
},
'date' : date,
'sp1' : {
'entityID' : sp1_entity_id,
'status' : sp1_check_status
},
'sp2' : {
'entityID' : sp2_entity_id,
'status' : sp2_check_status
},
'status' : idp_checks_status
} )
elif (status):
app.logger.info("Results for status '%s'." % status)
if (status == idp_checks_status):
result.append(
{
'displayName' : idp_displayname,
'entityID' : idp_entity_id,
'registrationAuthority' : idp_reg_auth,
'contacts' : {
'technical' : buildEmailAddress(idp_tech_ctcs),
'support' : buildEmailAddress(idp_supp_ctcs),
},
'date' : date,
'sp1' : {
'entityID' : sp1_entity_id,
'status' : sp1_check_status
},
'sp2' : {
'entityID' : sp2_entity_id,
'status' : sp2_check_status
},
'status' : idp_checks_status
} )
else:
app.logger.info("All checks.")
result.append(
{
'displayName' : idp_displayname,
'entityID' : idp_entity_id,
'registrationAuthority' : idp_reg_auth,
'contacts' : {
'technical' : buildEmailAddress(idp_tech_ctcs),
'support' : buildEmailAddress(idp_supp_ctcs),
},
'date' : date,
'sp1' : {
'entityID' : sp1_entity_id,
'status' : sp1_check_status
},
'sp2' : {
'entityID' : sp2_entity_id,
'status' : sp2_check_status
},
'status' : idp_checks_status
} )
if (pretty):
pp_json = dumps(result, indent=4, sort_keys=True)
return jsonify(pp_json)
else:
return jsonify(result)
api.add_resource(Test, '/eccs/test') # Route_1
api.add_resource(Checks, '/eccs/checks') # Route_2
api.add_resource(EccsResults, '/eccs/eccsresults') # Route_3
if __name__ == '__main__':
app.config['JSON_AS_ASCII'] = False
app.logger = getLogger("logs/eccs2api.log","INFO")
app.run(port='5002')
......@@ -11,15 +11,6 @@ import logging
Questo script funziona SOLO con SP aventi Embedded Discovery Service come DS.
"""
def logFile(idp,content):
path = idp+".txt"
f = open(path,'w')
f.write(content)
f.close()
def getIdpListFromUrl():
import certifi
import urllib3
......@@ -40,7 +31,7 @@ def getIdpListFromUrl():
def getIdpListFromFile():
import json
with open('list_eccs_idps-idem.txt') as f:
with open('list_eccs_idps-idem.txt','r',encoding='utf-8') as f:
json_data = json.loads(f.read())
return json_data
......@@ -71,15 +62,15 @@ def checkIdP(sp,idp,logger):
entities_blacklist = ['https://idp.eie.gr/idp/shibboleth','https://gn-vho.grnet.gr/idp/shibboleth','https://wtc.tu-chemnitz.de/shibboleth','https://wtc.tu-chemnitz.de/shibboleth','https://idp.fraunhofer.de/idp/shibboleth','https://login.hs-owl.de/nidp/saml2/metadata','https://idp.dfn-cert.de/idp/shibboleth']
if (idp['entityID'] in entities_blacklist):
logger.info("%s;%s;IdP excluded from checks")
logger.info("%s;%s;IdP excluded from checks" % (idp['entityID'],sp))
driver.close()
driver.quit()
return "Disabled"
return "DISABLED"
if (idp['registrationAuthority'] in federation_blacklist):
logger.info("%s;%s;Federation excluded from checks")
logger.info("%s;%s;Federation excluded from checks" % (idp['entityID'],sp))
driver.close()
driver.quit()
return "Disabled"
return "DISABLED"
# Open SP, select the IDP from the EDS and press 'Enter' to reach the IdP login page to check
try:
......@@ -151,11 +142,25 @@ def getLogger(filename,log_level="DEBUG",path="./"):
return logger
# Return a list of email address for a specific type of contact
def getIdPContacts(idp,contactType):
ctcList = []
for ctcType in idp['contacts']:
if (ctcType == contactType):
for ctc in idp['contacts'][contactType]:
ctcList.append(ctc['emailOrPhone']['EmailAddress'][0])
return ctcList
# MAIN
if __name__=="__main__":
eccs2log = getLogger("logs/eccs2_"+date.today().isoformat()+".log","INFO")
eccs2checksLog = getLogger("logs/eccs2checks_"+date.today().isoformat()+".log","INFO")
day = date.today().isoformat()
eccs2log = getLogger("logs/eccs2_"+day+".log","INFO")
eccs2checksLog = getLogger("logs/eccs2checks_"+day+".log","INFO")
sps = ["https://sp24-test.garr.it/secure", "https://attribute-viewer.aai.switch.ch/eds/"]
......@@ -167,11 +172,47 @@ if __name__=="__main__":
for sp in sps:
result.append(checkIdP(sp,idp,eccs2checksLog))
listTechContacts = getIdPContacts(idp,'technical')
listSuppContacts = getIdPContacts(idp,'support')
strTechContacts = ','.join(listTechContacts)
strSuppContacts = ','.join(listSuppContacts)
# If all checks are 'OK', than the IdP consuming correctly eduGAIN Metadata.
if (result[0] == result[1] == "OK"):
eccs2log.info("IdP '%s' results: OK" % (idp['entityID']))
# IdP-DisplayName;IdP-entityID;IdP-RegAuth;IdP-tech-ctc-1,IdP-tech-ctc-2;IdP-supp-ctc-1,IdP-supp-ctc-2;Status;SP-entityID-1;SP-status-1;SP-entityID-2;SP-status-2
eccs2log.info("%s;%s;%s;%s;%s;%s;%s;%s;%s;%s" % (
idp['displayname'].split(';')[1].split('==')[0],
idp['entityID'],
idp['registrationAuthority'],
strTechContacts,
strSuppContacts,
'OK',
sps[0],
result[0],
sps[1],
result[1]))
elif (result[0] == result[1] == "DISABLED"):
eccs2log.info("IdP '%s' results: DISABLED" % (idp['entityID']))
eccs2log.info("%s;%s;%s;%s;%s;%s;%s;%s;%s;%s" % (
idp['displayname'].split(';')[1].split('==')[0],
idp['entityID'],
idp['registrationAuthority'],
strTechContacts,
strSuppContacts,
'DISABLE',
sps[0],
result[0],
sps[1],
result[1]))
else:
eccs2log.info("IdP '%s' results: ERROR" % (idp['entityID']))
eccs2log.info("%s;%s;%s;%s;%s;%s;%s;%s;%s;%s" % (
idp['displayname'].split(';')[1].split('==')[0],
idp['entityID'],
idp['registrationAuthority'],
strTechContacts,
strSuppContacts,
'ERROR',
sps[0],
result[0],
sps[1],
result[1]))
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css"/>
<script type="text/javascript" src="script.js"></script>
<link href="style.css" rel="stylesheet" type="text/css" />
<meta charset=utf-8 />
<title>eduGAIN Connectivity Check Service 2</title>
</head>
<body>
<div class="container">
<table id="example" class="display" style="width:100%">
<thead>
<tr>
<th></th>
<th>DisplayName</th>
<th>EntityID</th>
<th>Registration Authority</th>
<th>Technical Contacts</th>
<th>Support Contacts</th>
<th>Date</th>
<th>Status</th>
</tr>
</thead>
</table>
</div>
</body>
</html>
/* Formatting function for row details - modify as you need */
function format ( d ) {
// `d` is the original data object for the row
return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
'<tr>'+
'<td>IdP DisplayName:</td>'+
'<td>'+d.displayName+'</td>'+
'<td></td>'+
'</tr>'+
'<tr>'+
'<td>Technical Contacts:</td>'+
'<td>'+d.contacts.technical+'</td>'+
'<td></td>'+
'</tr>'+
'<tr>'+
'<td>SP1:</td>'+
'<td>'+d.sp1.entityID+'</td>'+
'<td>'+d.sp1.status+'</td>'+
'</tr>'+
'<tr>'+
'<td>SP2:</td>'+
'<td>'+d.sp2.entityID+'</td>'+
'<td>'+d.sp2.status+'</td>'+
'</tr>'+
'</table>';
}
$(document).ready(function() {
var table = $('#example').DataTable( {
"ajax": {
"url": "data.json",
"dataSrc": ""
},
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{
"data": "displayName",
"defaultContent": ''
},
{ "data": "entityID" },
{ "data": "registrationAuthority" },
{
"data": "contacts.technical",
"defaultContent": ''
},
{
"data": "contacts.support",
"defaultContent": ''
},
{ "data": "date" },
{ "data": "status" }
],
"rowCallback": function( row, data, index ) {
if (data.status == "ERROR") {
$('td', row).css('background-color', 'Red');
}
if (data.status == "DISABLE") {
$('td', row).css('background-color', 'Grey');
}
if (data.status == "OK") {
$('td', row).css('background-color', 'Green');
}
},
"order": [[1, 'asc']]
} );
// Add event listener for opening and closing details
$('#example tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row( tr );
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child( format(row.data()) ).show();
tr.addClass('shown');
}
} );
} );
td.details-control {
background: url('./details_open.png') no-repeat center center;
cursor: pointer;
}
tr.shown td.details-control {
background: url('./details_close.png') no-repeat center center;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment