diff --git a/README.md b/README.md index bec1d9acbf4ba6b68dfe175ecd5c76b9eab6fbc9..b439f28a6f264639bcf99f704c286a311efb9329 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # HOWTO Install and Configure ECCS-2 -* `sudo apt install mysql-server python3-pip` -* `pip3 install mysql-connector certifi selenium urllib3` +* `sudo apt install python3-pip chromium chromium-l10n git` +* `pip3 install certifi selenium urllib3 flask flask-jsonpify flask-restful` +* `cd /opt ; git clone https://github.com/malavolti/eccs2.git` +* `cd /opt/eccs2 ; ./eccs2.py` -# Create and configure the ECCS-2 database +# Create and configure the ECCS-2 database (not used now) * `sudo mysql` * `CREATE DATABASE eccs2db;` * `CREATE USER 'eccs2user'@'localhost' IDENTIFIED BY '<password>';` @@ -11,3 +13,20 @@ * `SHOW GRANTS FOR 'eccs2user'@'localhost';` * `FLUSH PRIVILEGES;` +# API + +* `/eccs/test` (Trivial Test) +* `/eccs/checks` (Should 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` + * `status=` + * 'OK' + * 'TIMEOUT' + * 'No-eduGAIN-Metadata' + * 'Form-Invalid' + * 'Excluded' + +# API Development Server + +* `cd /opt/eccs2 ; ./api.py` diff --git a/api.py b/api.py index d8b152fde47a9c7a13bc8b3738751a8dec405a57..fd9b51a86bd4da047f9aef293da13a8582788354 100755 --- a/api.py +++ b/api.py @@ -2,11 +2,12 @@ from flask import Flask, request from flask_restful import Resource, Api -from json import dumps +from json import dumps, loads from flask import jsonify from pathlib import PurePath import logging from logging.handlers import RotatingFileHandler +import re app = Flask(__name__) api = Api(app) @@ -43,56 +44,81 @@ class Test(Resource): app.logger.info("Test Superato!") return {'test':'It Works!'} -class AllChecks(Resource): +class Checks(Resource): def get(self): - app.logger.info("Richiesta 'AllChecks'") + app.logger.info("Richiesta 'Checks'") + file_path = "logs/eccs2checks_2020-02-19.log" - fo = open(file_path, "r") - result = [] date = PurePath(file_path).parts[-1].split('_')[1].split('.')[0] - lines = fo.readlines() + pretty = 0 + status = None + idp = None + + if 'date' in request.args: + app.logger.info("Parametro 'date' inserito") + file_path = "logs/eccs2checks_"+request.args['date']+".log" + date = request.args['date'] + if 'pretty' in request.args: + app.logger.info("Parametro 'pretty' inserito") + pretty = request.args['pretty'] + if 'status' in request.args: + app.logger.info("Parametro 'status' inserito") + status = request.args['status'] + if 'idp' in request.args: + app.logger.info("Parametro 'idp' inserito") + idp = request.args['idp'] + app.logger.info(idp) - for line in lines: - check = line.split(";") - idp = check[0] - sp = check[1] - check_result = check[2] - result.append( { 'sp' : sp, - 'idp' : idp, - 'check_result' : check_result.rstrip("\n\r"), - 'date': date - } ) - - return jsonify(result) - - -class ChecksByStatus(Resource): - def get(self,status): - file_path = "logs/eccs2checks_2020-02-19.log" fo = open(file_path, "r") result = [] - date = PurePath(file_path).parts[-1].split('_')[1].split('.')[0] lines = fo.readlines() - + for line in lines: - check_status = line.split(';')[2].rstrip("\n\r") - if (status == check_status): - check = line.split(";") - idp = check[0] - sp = check[1] - check_result = check[2] - result.append( { 'sp' : sp, - 'idp' : idp, - 'check_result' : check_result.rstrip("\n\r"), + check = line.split(";") + + check_idp = check[0] + check_sp = check[1] + check_status = check[2].rstrip("\n\r") + + if (idp and status): + if (idp == check_idp and status == check_status): + result.append( { 'sp' : check_sp, + 'idp' : check_idp, + 'status' : check_status, + 'date': date + } ) + elif (idp): + #app.logger.info(re.search(".*."+idp+".*.", check_idp, re.IGNORECASE)) + #app.logger.info(check_idp)) + if (re.search(".*."+idp+".*.", check_idp, re.IGNORECASE)): + result.append( { 'sp' : check_sp, + 'idp' : check_idp, + 'status' : check_status, + 'date': date + } ) + elif (status): + if (status == check_status): + result.append( { 'sp' : check_sp, + 'idp' : check_idp, + 'status' : check_status, + 'date': date + } ) + else: + result.append( { 'sp' : check_sp, + 'idp' : check_idp, + 'status' : check_status, 'date': date } ) - - return jsonify(result) - + + 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(AllChecks, '/eccs/checks/all') # Route_2 -api.add_resource(ChecksByStatus, '/eccs/checks/<status>') # Route_3 +api.add_resource(Checks, '/eccs/checks') # Route_2 if __name__ == '__main__': diff --git a/eccs2.py b/eccs2.py index 8148dd8ec973c82750e8b9f8e1d1f5331da2d61d..aec9c25a920b19f245cc824912f1b77b76e16e97 100755 --- a/eccs2.py +++ b/eccs2.py @@ -43,15 +43,17 @@ def getIdPs(): idp_list = [] for idp in idp_dict: - idp_list.append(idp['entityID']) + idp_list.append(idp['displayname'].split(';')[1].split('==')[0]) return idp_list -def checkIdP(driver,sp,idp,logger): +def checkIdP(sp,idp,logger): import re - # Apro la URL contenente il Discovery Service, inserisco l'idp e vado alla pagina di login + driver = setup() + + # Open SP, select the IDP from the EDS and press 'Enter' to reach the IdP login page to check try: driver.get(sp) driver.find_element_by_id("idpSelectInput").send_keys(idp + Keys.ENTER) @@ -63,6 +65,7 @@ def checkIdP(driver,sp,idp,logger): pass except TimeoutException as e: logger.info("%s;%s;TIMEOUT" % (idp,sp)) + driver.close() return "TIMEOUT" pattern_metadata = "Unable.to.locate(\sissuer.in|).metadata(\sfor|)|no.metadata.found|profile.is.not.configured.for.relying.party|Cannot.locate.entity|fail.to.load.unknown.provider|does.not.recognise.the.service|unable.to.load.provider|Nous.n'avons.pas.pu.(charg|charger).le.fournisseur.de service|Metadata.not.found|application.you.have.accessed.is.not.registered.for.use.with.this.service|Message.did.not.meet.security.requirements" @@ -76,29 +79,34 @@ def checkIdP(driver,sp,idp,logger): if(metadata_not_found): logger.info("%s;%s;No-eduGAIN-Metadata" % (idp,sp)) + driver.close() return "No-eduGAIN-Metadata" elif not username_found and not password_found: logger.info("%s;%s;Invalid-Form" % (idp,sp)) + driver.close() return "Invalid Form" else: logger.info("%s;%s;OK" % (idp,sp)) + driver.close() return "OK" +# Setup Chromium Webdriver def setup(): chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--headless') chrome_options.add_argument('--no-sandbox') - driver = webdriver.Chrome('chromedriver', chrome_options=chrome_options, service_args=['--verbose', '--log-path=./selenium_chromedriver.log']) +# driver = webdriver.Chrome('chromedriver', chrome_options=chrome_options, service_args=['--verbose', '--log-path=./selenium_chromedriver.log']) + driver = webdriver.Chrome('chromedriver', chrome_options=chrome_options) - # Configuro i timeout + # Configure timeouts driver.set_page_load_timeout(45) driver.set_script_timeout(45) return driver -# Use logger to produce files consumed by ECCS-2 +# Use logger to produce files consumed by ECCS-2 API def getLogger(filename,log_level="DEBUG",path="./"): logger = logging.getLogger(filename) @@ -126,35 +134,37 @@ def getLogger(filename,log_level="DEBUG",path="./"): return logger - +# MAIN if __name__=="__main__": eccs2log = getLogger("logs/eccs2_"+date.today().isoformat()+".log","INFO") eccs2checksLog = getLogger("logs/eccs2checks_"+date.today().isoformat()+".log","INFO") - driver = setup() - sps = ["https://sp24-test.garr.it/secure", "https://attribute-viewer.aai.switch.ch/eds/"] - listIdPs = [ - 'https://garr-idp-prod.irccs.garr.it', - 'https://idp.hec.gov.pk/idp/shibboleth', - 'https://login.itsak.gr/idp/shibboleth', - 'https://idp.eastdurham.ac.uk/openathens', - 'https://idp-lib.nwafu.edu.cn/idp/shibboleth', - ] - - #listIdPs = getIdPs() +# listIdPsTest = [ +# 'University of Utah', +# 'Nanjing Agriculture University', +# 'Fujian Normal University', +# 'SUIBE', +# 'Zuyd Hogeschool', +# 'Sur University College', +# 'https://idp.hec.gov.pk/idp/shibboleth', +# 'https://login.itsak.gr/idp/shibboleth', +# 'https://idp.eastdurham.ac.uk/openathens', +# 'https://idp-lib.nwafu.edu.cn/idp/shibboleth', +# ] + + listIdPs = getIdPs() for idp in listIdPs: result = [] for sp in sps: - result.append(checkIdP(driver,sp,idp,eccs2checksLog)) + result.append(checkIdP(sp,idp,eccs2checksLog)) - # se tutti e 2 i check sono andati bene, allora l'IdP รจ OK, altrimenti no. + # If all checks are 'OK', than the IdP consuming correctly eduGAIN Metadata. if (result[0] == result[1] == "OK"): eccs2log.info("IdP '%s' results into: OK" % (idp)) else: eccs2log.info("IdP '%s' results into: NOT OK" % (idp)) - driver.close()