1#!/usr/bin/env python 2#coding=utf-8 3 4# 5# Copyright (c) 2023-2024 Huawei Device Co., Ltd. 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19import os 20import json 21 22from .base_rule import BaseRule 23 24 25class CmdRule(BaseRule): 26 RULE_NAME = "NO-Config-Cmds-In-Init" 27 28 def __init__(self, mgr, args): 29 super().__init__(mgr, args) 30 self._cmds = {} 31 self._start_modes = {} 32 self._boot_list = {} 33 self._condition_list = {} 34 self._start_cmd_list = {} 35 36 def __check__(self): 37 return self.check_config_cmd() 38 39 def check_config_cmd(self): 40 passed = True 41 self._parse_while_list() 42 cfg_parser = self.get_mgr().get_parser_by_name('config_parser') 43 self._get_json_service() 44 45 start_passed = self._check_start_cmd(cfg_parser) 46 secon_passed = self._check_selinux(cfg_parser) 47 cmd_passed = self._check_cmdline_in_parser(cfg_parser) 48 start_mode_passed = self._check_service(cfg_parser) 49 passed = start_passed and secon_passed and cmd_passed and start_mode_passed 50 return passed 51 52 def _get_json_service(self): 53 for _, start_mode in enumerate(self._start_modes): 54 if start_mode.get("start-mode") == "boot": 55 self._boot_list = start_mode.get("service") 56 elif start_mode.get("start-mode") == "condition": 57 self._condition_list = start_mode.get("service") 58 pass 59 60 def _get_start_cmds(self, parser): 61 lists = {} 62 for cmd in parser._cmds: 63 if cmd["name"] == "start": 64 lists[cmd["content"]] = cmd["fileId"] 65 pass 66 return lists 67 68 def _parse_while_list(self): 69 white_lists = self.get_white_lists()[0] 70 for key, item in white_lists.items(): 71 if key == "cmds": 72 self._cmds = item 73 if key == "start-modes": 74 self._start_modes = item 75 if key == "start-cmd": 76 self._start_cmd_list = item 77 78 def _check_condition_start_mode(self, cmd_list, service_name, passed): 79 if service_name in self._condition_list and service_name in cmd_list: 80 pass 81 else: 82 self.warn("\'%s\' cannot be started in conditional mode" % service_name) 83 return passed 84 85 86 def _check_service(self, parser): 87 boot_passed = True 88 condition_passed = True 89 start_cmd_list = self._get_start_cmds(parser).keys() 90 for key, item in parser._services.items(): 91 if item.get("start_mode") == "boot": 92 if key not in self._boot_list: 93 self.warn("\'%s\' cannot be started in boot mode" % key) 94 elif item.get("on_demand") is not True and item.get("start_mode") == "condition": 95 condition_passed = self._check_condition_start_mode(start_cmd_list, key, condition_passed) 96 return boot_passed and condition_passed 97 98 def _check_file_id_in_cmds(self, cmdlist, cmdline): 99 file_id_list = set() 100 for _, cmd in enumerate(cmdlist): 101 if cmdline == cmd["name"]: 102 file_id_list.add(cmd["fileId"]) 103 return file_id_list 104 105 def _check_cmdline_in_parser(self, parser): 106 passed = True 107 cmdline = [] 108 file_id_list = set() 109 parser_cmds = parser._cmds 110 111 for cmd in self._cmds: 112 cmdline = cmd["cmd"] 113 file_id_list = self._check_file_id_in_cmds(parser_cmds, cmdline) 114 file_lists = cmd["location"] 115 for key, item in parser._files.items(): 116 if item["fileId"] in file_id_list and key not in file_lists: 117 output = "\'{}\' is timeout command, in {}".format(cmd["cmd"], key) 118 self.error("%s" % str(output)) 119 passed = False 120 file_id_list.clear() 121 return passed 122 123 def _check_selinux(self, parser): 124 if parser._selinux != 'enforcing': 125 self.warn("selinux status is %s" % parser._selinux) 126 return True 127 128 passed = True 129 for key, item in parser._services.items(): 130 if item.get("secon") == "": 131 output_str = "%s \'secon\' is empty" % key 132 self.error("%s" % str(output_str)) 133 passed = False 134 return passed 135 136 def _check_start_cmd(self, parser): 137 passed = True 138 start_cmd_list = self._get_start_cmds(parser) 139 for cmd, file_id in start_cmd_list.items(): 140 if cmd in list(self._start_cmd_list): 141 pass 142 else: 143 for key, item in parser._files.items(): 144 if item["fileId"] == file_id: 145 log_str = "{} is not in start cmd list. path:{}".format(cmd, item["file_name"]) 146 self.warn("%s" % log_str) 147 passed = False 148 pass 149 return passed 150