diff --git a/api.py b/api.py index 1425fec76333ac8c85e422ad7aee8e302cdf83a4..30d690a3dd1e922c7a62a051604bad05711aa5a2 100755 --- a/api.py +++ b/api.py @@ -143,8 +143,15 @@ class EccsResults(Resource): elif (reg_auth and status): if (reg_auth == aux['registrationAuthority'] and status == aux['status']): if (simple): - auxSimple = getSimpleDict(aux) - results.append(auxSimple) + auxsimple = getsimpledict(aux) + results.append(auxsimple) + else: + results.append(aux) + elif (reg_auth and check_result): + if (reg_auth == aux['registrationAuthority'] and (check_result == aux['sp1']['checkResult'] or check_result == aux['sp2']['checkResult'])): + if (simple): + auxsimple = getsimpledict(aux) + results.append(auxsimple) else: results.append(aux) elif (idp): diff --git a/eccs2.py b/eccs2.py index 0777b840ee666be95f67af11c1e929a34db71345..83e7abaa843c9c4163ed4d63c8470a9e1fac4a92 100755 --- a/eccs2.py +++ b/eccs2.py @@ -36,7 +36,7 @@ def store_eccs_result(idp,sp,check_results,idp_status,test): if (test): sys.stdout.write("\nECCS2:") - sys.stdout.write('{"displayName":"%s","entityID":"%s","registrationAuthority":"%s","contacts":{"technical":"%s","support":"%s"},"status":"%s","sp1":{"wayflessUrl":"%s","checkTime":"%s","httpCode":"%s","checkResult":"%s"},"sp2":{"wayflessUrl":"%s","checkTime":"%s","httpCode":"%s","checkResult":"%s"}}\n' % ( + sys.stdout.write('{"displayName":"%s","entityID":"%s","registrationAuthority":"%s","contacts":{"technical":"%s","support":"%s"},"status":"%s","sp1":{"wayflessUrl":"%s","checkTime":"%s","checkResult":"%s"},"sp2":{"wayflessUrl":"%s","checkTime":"%s","checkResult":"%s"}}\n' % ( get_display_name(idp['displayname']), # IdP-DisplayName idp['entityID'], # IdP-entityID idp['registrationAuthority'], # IdP-RegAuth @@ -45,18 +45,16 @@ def store_eccs_result(idp,sp,check_results,idp_status,test): idp_status, # IdP-ECCS-Status check_results[0][1], # SP-wayfless-url-1 check_results[0][2], # SP-check-time-1 - check_results[0][3], # SP-http-code-1 - check_results[0][4], # SP-check-result-1 + check_results[0][3], # SP-check-result-1 check_results[1][1], # SP-wayfless-url-2 check_results[1][2], # SP-check-time-2 - check_results[1][3], # SP-http-code-2 - check_results[1][4])) # SP-check-result-2 + check_results[1][3])) # SP-check-result-2 else: - # IdP-DisplayName;IdP-entityID;IdP-RegAuth;IdP-tech-ctc-1,IdP-tech-ctc-2;IdP-supp-ctc-1,IdP-supp-ctc-2;IdP-ECCS-Status;SP-wayfless-url-1;SP-check-time-1;SP-http-code-1;SP-result-1;SP-wayfless-url-2;SP-check-time-2;SP-http-code-2;SP-result-2 + # IdP-DisplayName;IdP-entityID;IdP-RegAuth;IdP-tech-ctc-1,IdP-tech-ctc-2;IdP-supp-ctc-1,IdP-supp-ctc-2;IdP-ECCS-Status;SP-wayfless-url-1;SP-check-time-1;SP-result-1;SP-wayfless-url-2;SP-check-time-2;SP-result-2 with open(f"{e2p.ECCS2OUTPUTDIR}/{e2p.ECCS2RESULTSLOG}", 'a') as f: try: - f.write('{"displayName":"%s","entityID":"%s","registrationAuthority":"%s","contacts":{"technical":"%s","support":"%s"},"status":"%s","sp1":{"wayflessUrl":"%s","checkTime":"%s","httpCode":"%s","checkResult":"%s"},"sp2":{"wayflessUrl":"%s","checkTime":"%s","httpCode":"%s","checkResult":"%s"}}\n' % ( + f.write('{"displayName":"%s","entityID":"%s","registrationAuthority":"%s","contacts":{"technical":"%s","support":"%s"},"status":"%s","sp1":{"wayflessUrl":"%s","checkTime":"%s","checkResult":"%s"},"sp2":{"wayflessUrl":"%s","checkTime":"%s","checkResult":"%s"}}\n' % ( get_display_name(idp['displayname']), # IdP-DisplayName idp['entityID'], # IdP-entityID idp['registrationAuthority'], # IdP-RegAuth @@ -65,12 +63,10 @@ def store_eccs_result(idp,sp,check_results,idp_status,test): idp_status, # IdP-ECCS-Status check_results[0][1], # SP-wayfless-url-1 check_results[0][2], # SP-check-time-1 - check_results[0][3], # SP-http-code-1 - check_results[0][4], # SP-check-result-1 + check_results[0][3], # SP-check-result-1 check_results[1][1], # SP-wayfless-url-2 check_results[1][2], # SP-check-time-2 - check_results[1][3], # SP-http-code-2 - check_results[1][4] # SP-check-result-2 + check_results[1][3] # SP-check-result-2 ) ) except IOError: @@ -89,10 +85,10 @@ def check(idp,test): sys.exit(1) if (len(check_results) == len(e2p.ECCS2SPS)): - check_result_sp1 = check_results[0][4] - check_result_sp2 = check_results[1][4] - check_result_weberr1 = check_results[0][5] - check_result_weberr2 = check_results[1][5] + check_result_sp1 = check_results[0][3] + check_result_sp2 = check_results[1][3] + check_result_weberr1 = check_results[0][4] + check_result_weberr2 = check_results[1][4] # If all checks are 'OK', than the IdP consuming correctly eduGAIN Metadata. if (check_result_sp1 == check_result_sp2 == "OK"): diff --git a/utils.py b/utils.py index 85369330aa7272c0e796ec21e00c7c7a9e0a522d..00e51ce8bfd8a305b63f7f83c3ac33b375ee7e1a 100644 --- a/utils.py +++ b/utils.py @@ -13,7 +13,7 @@ import time import eccs2properties as e2p from selenium import webdriver -from selenium.common.exceptions import WebDriverException,TimeoutException +from selenium.common.exceptions import WebDriverException,TimeoutException,NoSuchElementException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC @@ -190,6 +190,13 @@ def get_driver_selenium(idp=None,sp=None,debugSelenium=False): driver = webdriver.Chrome(e2p.PATHCHROMEDRIVER, options=chrome_options) return driver +def follow_all_nested_iframes(driver): + try: + while (driver.find_element(By.XPATH,'//iframe')): + driver.switch_to.frame(0) + except NoSuchElementException: + return driver.page_source + # ECCS2 Check made by Selenium def check_idp_response_selenium(sp,idp,test): @@ -204,21 +211,18 @@ def check_idp_response_selenium(sp,idp,test): idps_disabled_dict = e2p.IDPS_DISABLED_DICT webdriver_error = 0 # No WebDriver Error - # SELENIUM CONSTANTS - http_code = "NULL" - # Handle Disabled Idps/Federations if (idp['registrationAuthority'] in federations_disabled_dict.keys()): check_time = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S') + 'Z' page_source = federations_disabled_dict[idp['registrationAuthority']] store_page_source(page_source,idp,sp,test) - return (idp['entityID'],wayfless_url,check_time,"NULL","DISABLED",webdriver_error) + return (idp['entityID'],wayfless_url,check_time,"DISABLED",webdriver_error) if (idp['entityID'] in idps_disabled_dict.keys()): check_time = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S') + 'Z' page_source = idps_disabled_dict[idp['entityID']] store_page_source(page_source,idp,sp,test) - return (idp['entityID'],wayfless_url,check_time,"NULL","DISABLED",webdriver_error) + return (idp['entityID'],wayfless_url,check_time,"DISABLED",webdriver_error) # Robots + SSL Check try: @@ -236,41 +240,21 @@ def check_idp_response_selenium(sp,idp,test): if (test): page_source = f"\nAn SSL Error occurred while opening https://{fqdn_idp}/robots.txt:\n\n{e}\n\nCheck it on SSL Labs: https://www.ssllabs.com/ssltest/analyze.html?d={fqdn_idp}" else: page_source = f"<h1>SSL ERROR</h1><h2>An SSL error occurred for the server {fqdn_idp}:</h2><p>{e}</p><p>Check it on SSL Labs: <a href='https://www.ssllabs.com/ssltest/analyze.html?d={fqdn_idp}'>Click Here</a></p>" store_page_source(page_source,idp,sp,test) - return (idp['entityID'],wayfless_url,check_time,"(failed)","SSL-Error",webdriver_error) + return (idp['entityID'],wayfless_url,check_time,"SSL-Error",webdriver_error) # Do not consider any other Exception except: pass - ''' - except requests.exceptions.ConnectionError as e: - if (test): page_source = f"\nA Connection error occurred while opening https://{fqdn_idp}/robots.txt:\n\n{e}" - else: page_source = f"<h1>CONNECTION ERROR:</h1><h2>A Connection error occurred while opening <a href='https://{fqdn_idp}/robots.txt'>https://{fqdn_idp}/robots.txt</a>:</h2><p>{e}</p>" - store_page_source(page_source,idp,sp,test) - return (idp['entityID'],wayfless_url,check_time,"(failed)","Connection-Error",webdriver_error) - - except requests.exceptions.Timeout as e: - if (test): page_source = f"\nThe request timed out while trying to connect to the remote server '{fqdn_idp}':\n\n{e}" - else: page_source = f"<h1>CONNECTION TIMEOUT</h1><h2>The request timed out while opening <a href='https://{fqdn_idp}/robots.txt'>https://{fqdn_idp}/robots.txt</a>:</h2><p>{e}</p>" - store_page_source(page_source,idp,sp,test) - return (idp['entityID'],wayfless_url,check_time,"(failed)","Connection-Error",webdriver_error) - - except requests.exceptions.TooManyRedirects as e: - if (test): page_source = f"\nToo many redirects occurred while opening: https://{fqdn_idp}/robots.txt:\n\n{e}" - else: page_source = f"<h1>TOO MANY REDIRECTS</h1><h2>Too many redirects occurred while opening: <a href='https://{fqdn_idp}/robots.txt'>https://{fqdn_idp}/robots.txt</a>:</h2><p>{e}</p>" - store_page_source(page_source,idp,sp,test) - return (idp['entityID'],wayfless_url,check_time,"(failed)","Connection-Error",webdriver_error) - ''' - if (robots): check_time = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S') + 'Z' p = re.compile('^User-Agent:\sECCS\sDisallow:\s\/\s*$', re.MULTILINE) m = p.search(robots.text) if (m): - page_source = "IdP excluded from check by robots.txt" + page_source = "<h1>IdP excluded from check by robots.txt</h1>" store_page_source(page_source,idp,sp,test) - return (idp['entityID'],wayfless_url,check_time,"NULL","DISABLED",webdriver_error) + return (idp['entityID'],wayfless_url,check_time,"DISABLED",webdriver_error) try: # WebDriver MUST be instanced here to avoid problems with SESSION @@ -290,79 +274,69 @@ def check_idp_response_selenium(sp,idp,test): metadata_not_found = re.search(e2p.METADATAPATTERN,driver.page_source, re.I) if (metadata_not_found): - if (test): pgsrc = f"\n[PAGE_SOURCE]\n{page_source}\n[WAYFLESS URL]{wayfless_url} - METADATA NOT FOUND" + if (test): pgsrc = f"\n[PAGE_SOURCE]\n{driver.page_source}\n[WAYFLESS URL]{wayfless_url} - METADATA NOT FOUND" else: pgsrc = driver.page_source stored = store_page_source(pgsrc,idp,sp,test) if (stored): - return (idp['entityID'],wayfless_url,check_time,http_code,"No-eduGAIN-Metadata",webdriver_error) + return (idp['entityID'],wayfless_url,check_time,"No-eduGAIN-Metadata",webdriver_error) - # If meet <iframe> load it + # If meet <iframe> follow all iframes if ('<iframe' in driver.page_source): - seq = driver.find_elements_by_tag_name('iframe') - - #switching between the iframes based on index - - for index in range(len(seq)): - driver.switch_to_default_content - iframe = driver.find_elements_by_tag_name('iframe')[index] - driver.switch_to.frame(iframe) - - # and search the <input type="password"> tag - if (EC.presence_of_element_located((By.XPATH,'//input[@type="password"]'))): - break # input password found + follow_all_nested_iframes(driver) - driver.switch_to.default_content + WebDriverWait(driver, e2p.ECCS2SELENIUMPAGELOADTIMEOUT).until( + EC.presence_of_element_located((By.XPATH,'//input[@type="password"]')) + ) - # else search only the <input type="password"> tag - else: - WebDriverWait(driver, e2p.ECCS2SELENIUMPAGELOADTIMEOUT).until( - EC.presence_of_element_located((By.XPATH,'//input[@type="password"]')) - ) - - page_source = driver.page_source - - if (test): pgsrc = f"\n[WAYFLESS URL]{wayfless_url} - OK" - else: pgsrc = page_source + if (test): pgsrc = f"\n[WAYFLESS_URL]\n{wayfless_url} - OK" + else: pgsrc = driver.page_source stored = store_page_source(pgsrc,idp,sp,test) if (stored): - return (idp['entityID'],wayfless_url,check_time,http_code,"OK",webdriver_error) + return (idp['entityID'],wayfless_url,check_time,"OK",webdriver_error) + except TimeoutException as e: - page_source = driver.page_source + metadata_not_found = re.search(e2p.METADATAPATTERN,driver.page_source, re.I) - if (test): - sys.stdout.write(f"\nPAGE_SOURCE: {page_source}") + try: + input_password_found = driver.find_element(By.XPATH,'//input[@type="password"]') + + except NoSuchElementException as e: + # This IF is for those IdP that doesn't consuming the eduGAIN metadata and reaching Timeout + if (metadata_not_found): + if (test): pgsrc = f"\n[PAGE_SOURCE]\n{driver.page_source}\n[WAYFLESS URL]{wayfless_url} - METADATA NOT FOUND" + else: pgsrc = driver.page_source + stored = store_page_source(pgsrc,idp,sp,test) + if (stored): + return (idp['entityID'],wayfless_url,check_time,"No-eduGAIN-Metadata",webdriver_error) + elif(driver.page_source != "<html><head></head><body></body></html>"): + if (test): pgsrc = f"\n[PAGE_SOURCE]\n{driver.page_source}\nInvalid-Form: No valid login form found in {e2p.ECCS2SELENIUMPAGELOADTIMEOUT} seconds" + else: pgsrc = f"<h1>Invalid Form: no valid login form found in {e2p.ECCS2SELENIUMPAGELOADTIMEOUT} seconds</h1><h2>PAGE SOURCE:</h2><br/>{driver.page_source}" + stored = store_page_source(pgsrc,idp,sp,test) + if (stored): + return (idp['entityID'],wayfless_url,check_time,"Invalid-Form",webdriver_error) + else: + if (test): pgsrc = f"\n[PAGE_SOURCE]\n{driver.page_source}\nTimeout: No valid login form loaded in {e2p.ECCS2SELENIUMPAGELOADTIMEOUT} seconds." + else: pgsrc = f"<h1>Timeout - No valid login form found in {e2p.ECCS2SELENIUMPAGELOADTIMEOUT} seconds.</h1><h2>PAGE SOURCE:</h2><br/>{driver.page_source}" + stored = store_page_source(pgsrc,idp,sp,test) + if (stored): + return (idp['entityID'],wayfless_url,check_time,"Timeout",webdriver_error) + + except e: + if (test): pgsrc = f"\n[PAGE_SOURCE]\n{driver.page_source}\nTimeout: No valid login form loaded in {e2p.ECCS2SELENIUMPAGELOADTIMEOUT} seconds." + else: pgsrc = driver.page_source + stored = store_page_source(f"<h1>Timeout - No valid login form found in {e2p.ECCS2SELENIUMPAGELOADTIMEOUT} seconds.</h1><br/><p>{pgsrc}</p>",idp,sp,test) + if (stored): + return (idp['entityID'],wayfless_url,check_time,"Timeout",webdriver_error) - metadata_not_found = re.search(e2p.METADATAPATTERN,page_source, re.I) - # This IF is for those IdP that doesn't consuming the eduGAIN metadata and reaching Timeout - if (metadata_not_found): - if (test): pgsrc = f"\n[PAGE_SOURCE]\n{page_source}\n[WAYFLESS URL]{wayfless_url} - METADATA NOT FOUND" - else: pgsrc = page_source - stored = store_page_source(pgsrc,idp,sp,test) - if (stored): - return (idp['entityID'],wayfless_url,check_time,http_code,"No-eduGAIN-Metadata",webdriver_error) - # This IF is for those IdP that reaching out Timeout without any contents on their source page - elif(page_source == "<html><head></head><body></body></html>"): - if (test): pgsrc = f"\nTimeout: No valid login form loaded in {e2p.ECCS2SELENIUMPAGELOADTIMEOUT} seconds" - else: pgsrc = page_source - stored = store_page_source(f"<h1>Timeout - No valid login form loaded into {e2p.ECCS2SELENIUMPAGELOADTIMEOUT} seconds.",idp,sp,test) - if (stored): - return (idp['entityID'],wayfless_url,check_time,"(failed)","Timeout",webdriver_error) + # <input type="password"> found # This IF is for those IdPs that Timeout is caused by an image or other that do now prevent the Login process. - elif (EC.presence_of_element_located((By.XPATH,'//input[@type="password"]'))): - if (test): pgsrc = f"\n[WAYFLESS URL]{wayfless_url} - Timeout but OK" - else: pgsrc = page_source - stored = store_page_source(pgsrc,idp,sp,test) - if (stored): - return (idp['entityID'],wayfless_url,check_time,http_code,"OK",webdriver_error) - # Final else is for all the other cases - else: - if (test): pgsrc = f"\nInvalid-Form: No valid login form found in {e2p.ECCS2SELENIUMPAGELOADTIMEOUT} seconds" - else: pgsrc = page_source - stored = store_page_source(pgsrc,idp,sp,test) - if (stored): - return (idp['entityID'],wayfless_url,check_time,"(failed)","Invalid-Form",webdriver_error) + if (test): pgsrc = f"\n[PAGE_SOURCE]\n{driver.page_source} - Timeout but OK" + else: pgsrc = driver.page_source + stored = store_page_source(pgsrc,idp,sp,test) + if (stored): + return (idp['entityID'],wayfless_url,check_time,"OK",webdriver_error) except WebDriverException as e: error = e.__dict__['msg'].split('(')[0].rstrip() @@ -371,7 +345,7 @@ def check_idp_response_selenium(sp,idp,test): webdriver_error = 1 stored = store_page_source(pgsrc,idp,sp,test) if (stored): - return (idp['entityID'],wayfless_url,check_time,"(failed)","Connection-Error",webdriver_error) + return (idp['entityID'],wayfless_url,check_time,"Connection-Error",webdriver_error) finally: driver.quit()