From 9df1d0344f01aa9bc06b6227772c5872dfbaa065 Mon Sep 17 00:00:00 2001 From: Ramaraja Date: Fri, 20 Nov 2015 04:08:02 -0800 Subject: [PATCH] Bandit fix for tmp directory usage and shell injection. Includes eval to literal_eval fix Change-Id: I275c6cf0c0bc9b2620d6278f3069aa16016ece67 --- cloudpulse/operator/ansible/ansible_runner.py | 23 +++++++-- .../ansible/openstack_config_reader.py | 2 +- .../testcase/file_check_test.py | 48 ++++++++++--------- .../testcase/generate_baseline.py | 11 +++-- .../testcase/ks_admin_token_check.py | 7 ++- .../testcase/mysql_tls_enable_test.py | 7 ++- .../testcase/remote_baseline.py | 2 +- .../testcase/remote_file_check.py | 30 ++++++------ .../testcase/tls_enable_test.py | 7 ++- 9 files changed, 79 insertions(+), 58 deletions(-) diff --git a/cloudpulse/operator/ansible/ansible_runner.py b/cloudpulse/operator/ansible/ansible_runner.py index c246b5a..5fbd073 100644 --- a/cloudpulse/operator/ansible/ansible_runner.py +++ b/cloudpulse/operator/ansible/ansible_runner.py @@ -17,11 +17,27 @@ from __future__ import print_function import ansible.constants as CONST import ansible.inventory import ansible.runner +import cloudpulse +from cloudpulse.scenario.plugins.security_pulse.util.\ + security_pulse_test_input import security_test_input_reader import json import os + +def get_temp_path(): + base_dir = os.path.dirname(cloudpulse.__file__) + try: + config_file = base_dir + '/scenario/plugins/security_pulse/config/' +\ + 'securityhealth_test_input.yaml' + input_reader = security_test_input_reader(config_file) + input_data = input_reader.process_security_input_file() + return input_data['global_data']['file_info_dir'] + except Exception: + print ("Exception while getting temp path..") + return "/var/sec_hc/" + CONST.HOST_KEY_CHECKING = False -TMP_LOCATION = "/tmp/sec_hc/" +TMP_LOCATION = get_temp_path() is_containerized = False @@ -56,10 +72,11 @@ class ansible_runner(object): out = self.execute(command, container_name=container_name) print (out) # remove the files from containers - self.execute("rm -rf /tmp/sec_hc/", container_name=container_name) + self.execute("rm -rf " + TMP_LOCATION, + container_name=container_name) if is_containerized: # remove the files from host - self.execute("rm -rf /tmp/sec_hc/") + self.execute("rm -rf " + TMP_LOCATION) return out def set_ansible_inventory(self, inv): diff --git a/cloudpulse/operator/ansible/openstack_config_reader.py b/cloudpulse/operator/ansible/openstack_config_reader.py index 4b03f7f..487d5c7 100644 --- a/cloudpulse/operator/ansible/openstack_config_reader.py +++ b/cloudpulse/operator/ansible/openstack_config_reader.py @@ -68,7 +68,7 @@ class os_cfg_reader(object): print ("NAGIOS RUNNING - %s" % (str(hostObj.isNagiosRunning()))) def generate_ansible_config(self, os_obj_list): - f = open('/tmp/sec_hc/ansible_hosts', 'w+') + f = open('/var/sec_hc/ansible_hosts', 'w+') for obj in os_obj_list: # print obj.getName() f.write('[' + obj.getName() + ']\n') diff --git a/cloudpulse/scenario/plugins/security_pulse/testcase/file_check_test.py b/cloudpulse/scenario/plugins/security_pulse/testcase/file_check_test.py index 62a9948..8fff62d 100644 --- a/cloudpulse/scenario/plugins/security_pulse/testcase/file_check_test.py +++ b/cloudpulse/scenario/plugins/security_pulse/testcase/file_check_test.py @@ -13,12 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. +import ast import cloudpulse from cloudpulse.operator.ansible.ansible_runner import ansible_runner import json import os - -TMP_LOCATION = "/tmp/sec_hc/" +import subprocess class SecurityFileCheck(object): @@ -46,18 +46,18 @@ class SecurityFileCheck(object): "remote_file_check.py", base_dir + "/scenario/plugins/security_pulse/testcase/" + "remote_filecredentials.py", - "/tmp/sec_hc/dir_list", - "/tmp/sec_hc/os_baseline"] + file_info_dir + "dir_list", + file_info_dir + "os_baseline"] def ConsolidateResults(flist, container_name=None): result = ans_runner.execute_cmd( "python " + - TMP_LOCATION + + file_info_dir + "remote_file_check.py ", file_list=flist, container_name=container_name) Result = ans_runner.get_parsed_ansible_output(result) final_status.append(Result[0]) - final_result.extend(eval(Result[1])) + final_result.extend(ast.literal_eval(Result[1])) final_msg.extend(Result[2]) for p in perform_on: @@ -65,7 +65,8 @@ class SecurityFileCheck(object): ans_runner = ansible_runner([obj]) if obj.getRole() == p: os_dir = input_params[p + '_dir'] - all_baseline = eval(open(baseline_file).read()) + all_baseline = ast.literal_eval( + open(baseline_file).read()) baseline = all_baseline[p] open( file_info_dir + @@ -82,7 +83,10 @@ class SecurityFileCheck(object): ConsolidateResults( flist, container_name=container) - os.system('rm ' + file_info_dir + 'dir_list ') + subprocess.call([ + 'rm', + file_info_dir + + 'dir_list']) else: os_dir_list = [] @@ -91,32 +95,32 @@ class SecurityFileCheck(object): self.createDirList(os_dir_list, file_info_dir) # flist.append("/tmp/sec_hc/dir_list") ConsolidateResults(flist) - os.system( - 'rm -rf ' + + subprocess.call([ + 'rm', '-rf', file_info_dir + - 'os_baseline ' + + 'os_baseline', file_info_dir + - 'output') - os.system( - 'rm ' + + 'output']) + subprocess.call([ + 'rm', file_info_dir + - 'dir_list ') + 'dir_list']) if 404 in final_status: return (404, final_result, final_msg) else: return (200, final_result, final_msg) except Exception as e: print ("exception in perform_file_permission_check is--", e) - os.system( - 'rm -rf ' + + subprocess.call([ + 'rm', '-rf', file_info_dir + - 'os_baseline ' + + 'os_baseline', file_info_dir + - 'output') - os.system( - 'rm ' + + 'output']) + subprocess.call([ + 'rm', file_info_dir + - 'dir_list ') + 'dir_list']) print ( "Exception occured in executing" + " perform_file_permission_check") diff --git a/cloudpulse/scenario/plugins/security_pulse/testcase/generate_baseline.py b/cloudpulse/scenario/plugins/security_pulse/testcase/generate_baseline.py index 93670f3..98b1ad7 100644 --- a/cloudpulse/scenario/plugins/security_pulse/testcase/generate_baseline.py +++ b/cloudpulse/scenario/plugins/security_pulse/testcase/generate_baseline.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import ast import cloudpulse from cloudpulse.operator.ansible.ansible_runner import ansible_runner from cloudpulse.operator.ansible import openstack_config_reader as os_cfg @@ -31,7 +32,7 @@ class BaseLine(object): openstack_host_list = oscfg_reader.get_host_list() baseline_data = {} for host in openstack_host_list: - f = open('/tmp/sec_hc/dir_list', 'w+') + f = open('/var/sec_hc/dir_list', 'w+') for dir_name in host.getDirList(): f.write(dir_name + '\n') f.close() @@ -41,11 +42,11 @@ class BaseLine(object): base_dir += '/scenario/plugins/security_pulse/testcase' flist = [base_dir + '/remote_baseline.py', base_dir + '/remote_filecredentials.py', - '/tmp/sec_hc/dir_list' + '/var/sec_hc/dir_list' ] results = ans_runner.execute_cmd( "python " + - '/tmp/sec_hc/' + + '/var/sec_hc/' + "remote_baseline.py ", file_list=flist) # for node in results['contacted'].keys(): @@ -53,10 +54,10 @@ class BaseLine(object): node = host.getIp() data = results['contacted'][node]['stdout'] - baseline_data.update({role: eval(data)}) + baseline_data.update({role: ast.literal_eval(data)}) print (baseline_data) formated_data = json.dumps(baseline_data, indent=4) - open('/tmp/sec_hc/os_allnode_baseline', + open('/var/sec_hc/os_allnode_baseline', 'w+').write(str(formated_data)) except Exception as e: print (e) diff --git a/cloudpulse/scenario/plugins/security_pulse/testcase/ks_admin_token_check.py b/cloudpulse/scenario/plugins/security_pulse/testcase/ks_admin_token_check.py index 95dfe4c..d7c87f8 100644 --- a/cloudpulse/scenario/plugins/security_pulse/testcase/ks_admin_token_check.py +++ b/cloudpulse/scenario/plugins/security_pulse/testcase/ks_admin_token_check.py @@ -18,8 +18,7 @@ import cloudpulse from cloudpulse.operator.ansible.ansible_runner import ansible_runner import json import os - -TMP_LOCATION = "/tmp/sec_hc/" +import subprocess class ks_admin_token_check(object): @@ -47,9 +46,9 @@ class ks_admin_token_check(object): container_name = input_params['input']['container_name'] result = ans_runner.execute_cmd( "python " + - TMP_LOCATION + + file_info_dir + "keystone_admin_token_check.py ", file_list=flist, container_name=container_name) Result = ans_runner.get_parsed_ansible_output(result) - os.system('rm -rf ' + file_info_dir + 'output') + subprocess.call(['rm', '-rf', file_info_dir + 'output']) return Result diff --git a/cloudpulse/scenario/plugins/security_pulse/testcase/mysql_tls_enable_test.py b/cloudpulse/scenario/plugins/security_pulse/testcase/mysql_tls_enable_test.py index 2b06376..acc0f9e 100644 --- a/cloudpulse/scenario/plugins/security_pulse/testcase/mysql_tls_enable_test.py +++ b/cloudpulse/scenario/plugins/security_pulse/testcase/mysql_tls_enable_test.py @@ -17,8 +17,7 @@ import cloudpulse from cloudpulse.operator.ansible.ansible_runner import ansible_runner import json import os - -TMP_LOCATION = "/tmp/sec_hc/" +import subprocess class mysql_tls_enablement_test(object): @@ -45,11 +44,11 @@ class mysql_tls_enablement_test(object): container_name = input_params['input']['container_name'] result = ans_runner.execute_cmd( "python " + - TMP_LOCATION + + file_info_dir + "remote_mysql_tls_enablement_check.py ", file_list=flist, container_name=container_name) Result = ans_runner.get_parsed_ansible_output(result) - os.system('rm -rf ' + file_info_dir + 'output') + subprocess.call(['rm', '-rf', file_info_dir + 'output']) return Result except Exception as msg: print ( diff --git a/cloudpulse/scenario/plugins/security_pulse/testcase/remote_baseline.py b/cloudpulse/scenario/plugins/security_pulse/testcase/remote_baseline.py index 3c7aa7c..ae9ddb5 100644 --- a/cloudpulse/scenario/plugins/security_pulse/testcase/remote_baseline.py +++ b/cloudpulse/scenario/plugins/security_pulse/testcase/remote_baseline.py @@ -52,7 +52,7 @@ class FileTraversal(object): if __name__ == '__main__': # LOG.info('Executing test') - file_dir = '/tmp/sec_hc/' + file_dir = '/var/sec_hc/' dirs = [] with open(file_dir + 'dir_list') as f: dirs = f.read().splitlines() diff --git a/cloudpulse/scenario/plugins/security_pulse/testcase/remote_file_check.py b/cloudpulse/scenario/plugins/security_pulse/testcase/remote_file_check.py index 290d159..eadd9a1 100644 --- a/cloudpulse/scenario/plugins/security_pulse/testcase/remote_file_check.py +++ b/cloudpulse/scenario/plugins/security_pulse/testcase/remote_file_check.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import ast import os import pwd import remote_filecredentials as filecredentials @@ -51,7 +52,8 @@ class FileCheck(object): 'mode': ins.getMode(), 'user': ins.getUser(), 'group': ins.getGroup()}}) - keystone_baseline = eval(open(file_dir + 'os_baseline').read()) + keystone_baseline = ast.literal_eval( + open(file_dir + 'os_baseline').read()) remote_mismatch = list(set(output.keys()). difference(keystone_baseline.keys())) baseline_mismatch = list(set(keystone_baseline.keys()). @@ -74,29 +76,29 @@ class FileCheck(object): ' in remote') msg = string.join(l, ', ') if msg: - temp = {'Test Case Name': key, 'Status': 'Fail'} - temp.update({'Message': msg}) + temp = {'test_case_name': key, 'Status': 'Fail'} + temp.update({'message': msg}) result.append(temp) if baseline_mismatch: for item in baseline_mismatch: msg = 'File not found in remote' - temp = {'Test Case Name': item, 'Status': 'Fail'} - temp.update({'Message': msg}) + temp = {'test_case_name': item, 'Status': 'Fail'} + temp.update({'message': msg}) result.append(temp) if remote_mismatch: for item in remote_mismatch: msg = 'New file found in remote' - temp = {'Test Case Name': item, 'Status': 'Fail'} - temp.update({'Message': msg}) + temp = {'test_case_name': item, 'Status': 'Fail'} + temp.update({'message': msg}) result.append(temp) if not result: overall_status = True final_result.update( {'OverallStatus': overall_status}) result = {} - result.update({'Test Case Name': 'File permission Check'}) - result.update({'Status': 'Pass'}) - result.update({'Message': 'No mismatch'}) + result.update({'test_case_name': 'File permission Check'}) + result.update({'status': 'Pass'}) + result.update({'message': 'No mismatch'}) final_result.update({'result': [result]}) print (final_result) return @@ -110,16 +112,16 @@ class FileCheck(object): final_result.update( {'OverallStatus': False}) result = {} - result.update({'Test Case Name': 'File permission Check'}) - result.update({'Status': 'Fail'}) + result.update({'test_case_name': 'File permission Check'}) + result.update({'status': 'Fail'}) result.update( - {'Message': 'Exception in file comparision' + str(e)}) + {'message': 'Exception in file comparision' + str(e)}) final_result.update({'result': [result]}) print (final_result) return if __name__ == '__main__': - file_dir = '/tmp/sec_hc/' + file_dir = '/var/sec_hc/' dirs = [] with open(file_dir + 'dir_list') as f: dirs = f.read().splitlines() diff --git a/cloudpulse/scenario/plugins/security_pulse/testcase/tls_enable_test.py b/cloudpulse/scenario/plugins/security_pulse/testcase/tls_enable_test.py index f390cc9..55613ad 100644 --- a/cloudpulse/scenario/plugins/security_pulse/testcase/tls_enable_test.py +++ b/cloudpulse/scenario/plugins/security_pulse/testcase/tls_enable_test.py @@ -17,8 +17,7 @@ import cloudpulse from cloudpulse.operator.ansible.ansible_runner import ansible_runner import json import os - -TMP_LOCATION = "/tmp/sec_hc/" +import subprocess class tls_enablement_test(object): @@ -45,9 +44,9 @@ class tls_enablement_test(object): container_name = input_params['input']['container_name'] result = ans_runner.execute_cmd( "python " + - TMP_LOCATION + + file_info_dir + "TLS_Enablement_Check.py ", file_list=flist, container_name=container_name) Result = ans_runner.get_parsed_ansible_output(result) - os.system('rm -rf ' + file_info_dir + 'output') + subprocess.call(['rm', '-rf', file_info_dir + 'output']) return Result