From dd9e8643b72497eecdb4c80dc64f161b1562033b Mon Sep 17 00:00:00 2001 From: SerenaFeng Date: Fri, 9 Sep 2016 16:50:48 +0800 Subject: [PATCH] Fix security issues of eval-s in testapi results from security audit show risks and recommendations to fix them JIRA: RELENG-144 Change-Id: If128cc3ae230150a912b581dfb1ded543d851eb5 Signed-off-by: SerenaFeng --- .../opnfv_testapi/dashboard/bottlenecks2Dashboard.py | 4 ++-- .../opnfv_testapi/dashboard/dashboard_utils.py | 10 ++++------ .../opnfv_testapi/dashboard/doctor2Dashboard.py | 4 ++-- .../opnfv_testapi/dashboard/functest2Dashboard.py | 4 ++-- .../opnfv_testapi/dashboard/promise2Dashboard.py | 7 ++----- .../opnfv_testapi/dashboard/yardstick2Dashboard.py | 5 ++--- .../result_collection_api/opnfv_testapi/resources/handlers.py | 5 +++-- .../opnfv_testapi/tests/unit/fake_pymongo.py | 4 ++++ .../opnfv_testapi/tests/unit/test_dashboard.py | 5 +++-- .../opnfv_testapi/tests/unit/test_fake_pymongo.py | 3 ++- .../opnfv_testapi/tests/unit/test_result.py | 2 +- .../update/templates/changes_in_mongodb.py | 3 ++- .../result_collection_api/update/templates/update_mongodb.py | 9 ++++++--- 13 files changed, 35 insertions(+), 30 deletions(-) diff --git a/utils/test/result_collection_api/opnfv_testapi/dashboard/bottlenecks2Dashboard.py b/utils/test/result_collection_api/opnfv_testapi/dashboard/bottlenecks2Dashboard.py index 2e106bec8..f5e3d9a6e 100755 --- a/utils/test/result_collection_api/opnfv_testapi/dashboard/bottlenecks2Dashboard.py +++ b/utils/test/result_collection_api/opnfv_testapi/dashboard/bottlenecks2Dashboard.py @@ -48,8 +48,8 @@ def format_bottlenecks_for_dashboard(case, results): then build the call to the specific method """ if check_bottlenecks_case_exist(case): - cmd = "format_" + case + "_for_dashboard(results)" - res = eval(cmd) + cmd = "format_" + case + "_for_dashboard" + res = globals()[cmd](results) else: res = [] print "Test cases not declared" diff --git a/utils/test/result_collection_api/opnfv_testapi/dashboard/dashboard_utils.py b/utils/test/result_collection_api/opnfv_testapi/dashboard/dashboard_utils.py index 121875d02..42c635846 100644 --- a/utils/test/result_collection_api/opnfv_testapi/dashboard/dashboard_utils.py +++ b/utils/test/result_collection_api/opnfv_testapi/dashboard/dashboard_utils.py @@ -14,7 +14,6 @@ # # v0.1: basic example # -import os import re import sys from functest2Dashboard import format_functest_for_dashboard, \ @@ -47,8 +46,8 @@ def check_dashboard_ready_project(test_project): def check_dashboard_ready_case(project, case): - cmd = "check_" + project + "_case_exist(case)" - return eval(cmd) + cmd = "check_" + project + "_case_exist" + return globals()[cmd](case) def get_dashboard_projects(): @@ -73,6 +72,5 @@ def get_dashboard_result(project, case, results=None): # project: project name # results: array of raw results pre-filterded # according to the parameters of the request - cmd = "format_" + project + "_for_dashboard(case,results)" - res = eval(cmd) - return res + cmd = "format_" + project + "_for_dashboard" + return globals()[cmd](case, results) diff --git a/utils/test/result_collection_api/opnfv_testapi/dashboard/doctor2Dashboard.py b/utils/test/result_collection_api/opnfv_testapi/dashboard/doctor2Dashboard.py index 38b23abb4..5b1f190a9 100644 --- a/utils/test/result_collection_api/opnfv_testapi/dashboard/doctor2Dashboard.py +++ b/utils/test/result_collection_api/opnfv_testapi/dashboard/doctor2Dashboard.py @@ -36,8 +36,8 @@ def format_doctor_for_dashboard(case, results): # note we add _case because testcase and project had the same name # TODO refactoring...looks fine at the beginning wit only 1 project # not very ugly now and clearly not optimized... - cmd = "format_" + case.replace('-','_') + "_case_for_dashboard(results)" - res = eval(cmd) + cmd = "format_" + case.replace('-','_') + "_case_for_dashboard" + res = globals()[cmd](results) else: res = [] return res diff --git a/utils/test/result_collection_api/opnfv_testapi/dashboard/functest2Dashboard.py b/utils/test/result_collection_api/opnfv_testapi/dashboard/functest2Dashboard.py index 86521b984..01697f73b 100644 --- a/utils/test/result_collection_api/opnfv_testapi/dashboard/functest2Dashboard.py +++ b/utils/test/result_collection_api/opnfv_testapi/dashboard/functest2Dashboard.py @@ -34,8 +34,8 @@ def format_functest_for_dashboard(case, results): then build the call to the specific method """ if check_functest_case_exist(case): - cmd = "format_" + case + "_for_dashboard(results)" - res = eval(cmd) + cmd = "format_" + case + "_for_dashboard" + res = globals()[cmd](results) else: res = [] print "Test cases not declared" diff --git a/utils/test/result_collection_api/opnfv_testapi/dashboard/promise2Dashboard.py b/utils/test/result_collection_api/opnfv_testapi/dashboard/promise2Dashboard.py index 84f43a7d1..c96341f6d 100644 --- a/utils/test/result_collection_api/opnfv_testapi/dashboard/promise2Dashboard.py +++ b/utils/test/result_collection_api/opnfv_testapi/dashboard/promise2Dashboard.py @@ -14,9 +14,6 @@ # a new method format__for_dashboard(results) # v0.1: basic example with methods for odl, Tempest, Rally and vPing # -import re -import datetime - def get_promise_cases(): """ @@ -36,8 +33,8 @@ def format_promise_for_dashboard(case, results): # note we add _case because testcase and project had the same name # TODO refactoring...looks fine at the beginning wit only 1 project # not very ugly now and clearly not optimized... - cmd = "format_" + case + "_case_for_dashboard(results)" - res = eval(cmd) + cmd = "format_" + case + "_case_for_dashboard" + res = globals()[cmd](results) else: res = [] print "Test cases not declared" diff --git a/utils/test/result_collection_api/opnfv_testapi/dashboard/yardstick2Dashboard.py b/utils/test/result_collection_api/opnfv_testapi/dashboard/yardstick2Dashboard.py index 4f022d5b9..4df4b5007 100644 --- a/utils/test/result_collection_api/opnfv_testapi/dashboard/yardstick2Dashboard.py +++ b/utils/test/result_collection_api/opnfv_testapi/dashboard/yardstick2Dashboard.py @@ -16,7 +16,6 @@ # Fio, Lmbench, Perf, Cyclictest. # - def get_yardstick_cases(): """ get the list of the supported test cases @@ -33,8 +32,8 @@ def format_yardstick_for_dashboard(case, results): then build the call to the specific method """ if check_yardstick_case_exist(case): - cmd = "format_" + case + "_for_dashboard(results)" - res = eval(cmd) + cmd = "format_" + case + "_for_dashboard" + res = globals()[cmd](results) else: res = [] print "Test cases not declared" diff --git a/utils/test/result_collection_api/opnfv_testapi/resources/handlers.py b/utils/test/result_collection_api/opnfv_testapi/resources/handlers.py index f98c35e8f..5059f5d77 100644 --- a/utils/test/result_collection_api/opnfv_testapi/resources/handlers.py +++ b/utils/test/result_collection_api/opnfv_testapi/resources/handlers.py @@ -23,8 +23,8 @@ import json from datetime import datetime -from tornado.web import RequestHandler, asynchronous, HTTPError from tornado import gen +from tornado.web import RequestHandler, asynchronous, HTTPError from models import CreateResponse from opnfv_testapi.common.constants import DEFAULT_REPRESENTATION, \ @@ -217,7 +217,8 @@ class GenericApiHandler(RequestHandler): return equal, query def _eval_db(self, table, method, *args, **kwargs): - return eval('self.db.%s.%s(*args, **kwargs)' % (table, method)) + exec_collection = self.db.__getattr__(table) + return exec_collection.__getattribute__(method)(*args, **kwargs) def _eval_db_find_one(self, query, table=None): if table is None: diff --git a/utils/test/result_collection_api/opnfv_testapi/tests/unit/fake_pymongo.py b/utils/test/result_collection_api/opnfv_testapi/tests/unit/fake_pymongo.py index 450969248..3dd87e603 100644 --- a/utils/test/result_collection_api/opnfv_testapi/tests/unit/fake_pymongo.py +++ b/utils/test/result_collection_api/opnfv_testapi/tests/unit/fake_pymongo.py @@ -181,6 +181,10 @@ class MemDb(object): self._check_keys(doc.get(key)) +def __getattr__(name): + return globals()[name] + + pods = MemDb() projects = MemDb() testcases = MemDb() diff --git a/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_dashboard.py b/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_dashboard.py index 8f729c0d0..27ec76385 100644 --- a/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_dashboard.py +++ b/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_dashboard.py @@ -8,9 +8,10 @@ ############################################################################## import unittest -from test_result import TestResultBase from opnfv_testapi.common.constants import HTTP_NOT_FOUND, HTTP_OK +from test_result import TestResultBase + class TestDashboardBase(TestResultBase): def setUp(self): @@ -63,7 +64,7 @@ class TestDashboardQuery(TestDashboardBase): if k == 'self' or k == 'uri': continue if v is None: - v = eval('self.' + k) + v = self.__getattribute__(k) if v != 'missing': uri += '{}={}&'.format(k, v) uri += 'pod={}&'.format(self.pod) diff --git a/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_fake_pymongo.py b/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_fake_pymongo.py index 9a1253e94..5f50ba867 100644 --- a/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_fake_pymongo.py +++ b/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_fake_pymongo.py @@ -115,7 +115,8 @@ class MyTest(AsyncHTTPTestCase): self.assertEqual(name_error, error) def _eval_pods_db(self, method, *args, **kwargs): - return eval('self.db.pods.%s(*args, **kwargs)' % method) + table_obj = vars(self.db)['pods'] + return table_obj.__getattribute__(method)(*args, **kwargs) if __name__ == '__main__': diff --git a/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_result.py b/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_result.py index eee06c6e5..8479b35cd 100644 --- a/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_result.py +++ b/utils/test/result_collection_api/opnfv_testapi/tests/unit/test_result.py @@ -305,7 +305,7 @@ class TestResultGet(TestResultBase): def _set_query(self, *args): def get_value(arg): - return eval('self.' + arg) \ + return self.__getattribute__(arg) \ if arg != 'trust_indicator' else self.trust_indicator.current uri = '' for arg in args: diff --git a/utils/test/result_collection_api/update/templates/changes_in_mongodb.py b/utils/test/result_collection_api/update/templates/changes_in_mongodb.py index 9744dd9fe..1a4d5a16f 100644 --- a/utils/test/result_collection_api/update/templates/changes_in_mongodb.py +++ b/utils/test/result_collection_api/update/templates/changes_in_mongodb.py @@ -45,6 +45,7 @@ docs_old2New = { # ({'case_name': 'ovno'}, {'case_name': 'ocl'}) # ] 'results': [ - ({'trust_indicator': 0}, {'trust_indicator': {'current': 0, 'histories': []}}) + ({'trust_indicator': 0}, + {'trust_indicator': {'current': 0, 'histories': []}}) ] } diff --git a/utils/test/result_collection_api/update/templates/update_mongodb.py b/utils/test/result_collection_api/update/templates/update_mongodb.py index b1e378dd7..ba4334aa3 100644 --- a/utils/test/result_collection_api/update/templates/update_mongodb.py +++ b/utils/test/result_collection_api/update/templates/update_mongodb.py @@ -10,7 +10,8 @@ import argparse from pymongo import MongoClient -from changes_in_mongodb import collections_old2New, fields_old2New, docs_old2New +from changes_in_mongodb import collections_old2New, \ + fields_old2New, docs_old2New from utils import main, parse_mongodb_url parser = argparse.ArgumentParser(description='Update MongoDBs') @@ -54,11 +55,13 @@ def change_docs(a_dict): def eval_db(method, *args, **kwargs): - return eval('db.%s(*args, **kwargs)' % method) + exec_db = db.__getattribute__(method) + return exec_db(*args, **kwargs) def eval_collection(collection, method, *args, **kwargs): - return eval('db.%s.%s(*args, **kwargs)' % (collection, method)) + exec_collection = db.__getattr__(collection) + return exec_collection.__getattribute__(method)(*args, **kwargs) def collection_update(a_dict, operator): -- 2.16.6