From 4dec233f07223ec8ac45d0e0799e3ffbe477411f Mon Sep 17 00:00:00 2001 From: Vishal John Varghese <72516017+VishalJohnVarghese1996@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:33:41 +0530 Subject: [PATCH 1/3] Add files via upload --- nspepi/nspepi2/check_classic_configs.py | 80 +++--- nspepi/nspepi2/check_classic_expr.py | 6 +- nspepi/nspepi2/cli_lex.py | 20 +- nspepi/nspepi2/convert_classic_expr.py | 26 +- nspepi/nspepi2/convert_cli_commands.py | 314 ++++++++--------------- nspepi/nspepi2/convert_cmp_cmd.py | 26 +- nspepi/nspepi2/convert_filter_command.py | 224 ++++++++-------- nspepi/nspepi2/convert_lb_cmd.py | 10 +- nspepi/nspepi2/nspepi_common.py | 7 +- nspepi/nspepi2/nspepi_helper | 66 ++--- nspepi/nspepi2/nspepi_main.py | 21 +- nspepi/nspepi2/nspepi_parse_tree.py | 13 - nspepi/nspepi2/pi_lex.py | 4 +- 13 files changed, 328 insertions(+), 489 deletions(-) diff --git a/nspepi/nspepi2/check_classic_configs.py b/nspepi/nspepi2/check_classic_configs.py index b7f73c9..02c3f69 100644 --- a/nspepi/nspepi2/check_classic_configs.py +++ b/nspepi/nspepi2/check_classic_configs.py @@ -134,8 +134,8 @@ def check_pos_expr(commandParseTree, pos, check_removed_expr = True): rule_expr = rule_node.value converted_expr = check_classic_expr.check_classic_expr(rule_expr) if converted_expr is None: - logging.error('Error in checking command : ' + - str(commandParseTree)) + logging.error(('Error in checking command : [{}]').format(str(commandParseTree))) + elif converted_expr == "Invalid Expression": commandParseTree.set_invalid() else: @@ -168,8 +168,7 @@ def check_keyword_expr(commandParseTree, keywordName): rule_expr = rule_node[0].value converted_expr = check_classic_expr.check_classic_expr(rule_expr) if converted_expr is None: - logging.error('Error in checking command : ' + - str(commandParseTree)) + logging.error(('Error in checking command : [{}]').format(str(commandParseTree))) elif converted_expr == "Invalid Expression": commandParseTree.set_invalid() else: @@ -519,14 +518,14 @@ def check_policy_expr(self, commandParseTree): " and shouldn't be name of another policy entity" "; words reserved for policy use may not be used;" " underscores will be substituted for any invalid" - " characters in corresponding advanced name") - .format(expr_name)) + " characters in corresponding advanced name : [{}]") + .format(expr_name, str(commandParseTree))) if commandParseTree.keyword_exists('clientSecurityMessage'): NamedExpression.register_classic_entity_name(commandParseTree) logging.warning(("Client security expressions are deprecated" - " using this command [{}], please use the" - " the advanced authentication policy command") + " using this command, please use the" + " the advanced authentication policy command. : [{}]") .format(str(commandParseTree).strip())) return [] @@ -542,8 +541,8 @@ def check_policy_expr(self, commandParseTree): """ NamedExpression.register_policy_entity_name(commandParseTree) NamedExpression.register_classic_entity_name(original_tree) - logging.warning(("Classic expression has been deprecated in" - " command [{}], please use the advanced expression") + logging.warning(("Classic expression has been deprecated in the" + " following command, please use the advanced expression : [{}]") .format(str(commandParseTree).strip())) else: NamedExpression.register_policy_entity_name(original_tree) @@ -911,7 +910,7 @@ def check_deprecated_classic_policy(self, commandParseTree): commandParseTree = Deprecation.check_pos_expr(commandParseTree, 1, False) if commandParseTree.invalid: logging.warning(("Classic expression in the rule field has been deprecated" - " for command [{}], please use the advanced expression") + " for the following command, please use the advanced expression : [{}]") .format(str(commandParseTree).strip())) elif is_advanced_removed_expr_present(rule_expr): commandParseTree.set_invalid() @@ -932,8 +931,8 @@ def check_authentication_commands(self, commandParseTree): """ Check the Authentication commands which have been deprecated """ - logging.warning(("[{}] command has been deprecated," - " please use the advanced authentication policy command") + logging.warning(("Following command has been deprecated," + " please use the advanced authentication policy command : [{}]") .format(str(commandParseTree).strip())) return [] @@ -942,8 +941,8 @@ def check_ns_traffic_domain(self, commandParseTree): """ Check the traffic domain command """ - logging.warning(("[{}] command has been deprecated," - " please use the admin partition feature") + logging.warning(("Command has been deprecated," + " please use the admin partition feature. : [{}]") .format(str(commandParseTree).strip())) return [] @@ -955,8 +954,8 @@ def check_aaa_preauth_params(self, commandParseTree): """ if commandParseTree.keyword_exists('rule'): logging.warning(("Client security expressions are deprecated" - " using this command [{}], please use the" - " the advanced authentication policy command") + " using this command, please use the" + " the advanced authentication policy command : [{}]") .format(str(commandParseTree).strip())) return [] @@ -968,8 +967,8 @@ def check_vpn_sessionaction(self, commandParseTree): """ if commandParseTree.keyword_exists('clientSecurity'): logging.warning(("Client security expressions are deprecated" - " using this command [{}], please use the" - " the advanced authentication policy command") + " using this command, please use the" + " the advanced authentication policy command : [{}]") .format(str(commandParseTree).strip())) return [] @@ -980,9 +979,9 @@ def check_vpn_url(self, commandParseTree): """ if commandParseTree.keyword_exists('ssotype'): sso_type = commandParseTree.keyword_value("ssotype")[0].value.lower() - if sso_type == "selfauth": + if sso_type is "selfauth": logging.warning("Selfauth type has been deprecated" - " in command [{}]".format(str(commandParseTree).strip())) + " in command : [{}]".format(str(commandParseTree).strip())) return [] @common.register_for_cmd("add", "vpn", "portaltheme") @@ -993,11 +992,11 @@ def check_vpn_portaltheme(self, commandParseTree): """ if commandParseTree.keyword_exists('basetheme'): base_theme = commandParseTree.keyword_value("basetheme")[0].value - if base_theme == "Default" or base_theme == "X1" \ - or base_theme == "Greenbubble": + if base_theme is "Default" or base_theme is "X1" \ + or base_theme is "Greenbubble": logging.warning(("Default, GreenBubble and X1 themes" - " have been deprecated in command [{}]," - " please use RfWebUI theme or RfWebUI based custom theme") + " have been deprecated in the command," + " please use RfWebUI theme or RfWebUI based custom theme : [{}]") .format(str(commandParseTree).strip())) return [] @@ -1010,11 +1009,11 @@ def check_vpn_commands(self, commandParseTree): """ if commandParseTree.keyword_exists('portaltheme'): base_theme = commandParseTree.keyword_value("portaltheme")[0].value - if base_theme == "Default" or base_theme == "X1" \ - or base_theme == "Greenbubble": + if base_theme is "Default" or base_theme is "X1" \ + or base_theme is "Greenbubble": logging.warning(("Default, GreenBubble and X1 themes" - " have been deprecated in command [{}]," - " please use RfWebUI theme or RfWebUI based custom theme") + " have been deprecated in the command," + " please use RfWebUI theme or RfWebUI based custom theme : [{}]") .format(str(commandParseTree).strip())) return [] @@ -1025,15 +1024,15 @@ def check_dns_action(self, commandParseTree): deprecated. """ action_type = commandParseTree.positional_value(1).value.lower() - if action_type == "rewrite_response": + if action_type is "rewrite_response": logging.warning(("Rewrite_Response action type is deprecated in" - " command [{}], please use the replace_dns_answer_section" - " action type under Rewrite feature.") + " the command, please use the replace_dns_answer_section" + " action type under Rewrite feature. : [{}]") .format(str(commandParseTree).strip())) - elif action_type == "drop": + elif action_type is "drop": logging.warning(("Drop action type is deprecated in" - " command [{}], please use the Drop" - " action type under Responder feature.") + " the command, please use the Drop" + " action type under Responder feature. : [{}]") .format(str(commandParseTree).strip())) return [] @@ -1049,8 +1048,8 @@ def check_ns_feature(self, commandParseTree): feature_name = feature_node.value if feature_name in features_to_remove: logging.warning("SC, PQ, HDOSP, and CF features" - " have been deprecated in command [{}], please" - " use the APPQOE, REWRITE, and RESPONDER features" + " have been deprecated in the command, please" + " use the APPQOE, REWRITE, and RESPONDER features : [{}]" .format(str(commandParseTree).strip())) break return [] @@ -1070,7 +1069,7 @@ def check_deprecated_pacingcommands(self, commandParseTree): commandParseTree.set_invalid() return [commandParseTree] - logging.warning(("[{}] command has been deprecated") + logging.warning(("Command has been deprecated : [{}]") .format(str(commandParseTree).strip())) return [] @@ -1090,13 +1089,12 @@ def check_deprecated_pacingcommands(self, commandParseTree): @common.register_for_cmd("bind", "lsn", "client") @common.register_for_cmd("bind", "lsn", "group") @common.register_for_cmd("bind", "lsn", "pool") - @common.register_for_cmd("set", "lsn", "parameter") def check_lsn_commands(self, commandParseTree): """ Check the Authentication commands which have been deprecated """ if (int(build_version.split(".")[0]) > 13): - logging.warning(("[{}] command has been deprecated") + logging.warning(("Command has been deprecated : [{}]") .format(str(commandParseTree).strip())) return [] @@ -1120,5 +1118,5 @@ def check_responder_action(self, commandParseTree): action_type = commandParseTree.positional_value(1).value.lower() if action_type is "noop": logging.warning("NOOP action type has been deprecated" - " for command [{}]".format(str(commandParseTree).strip())) + " for the command : [{}]".format(str(commandParseTree).strip())) return [] diff --git a/nspepi/nspepi2/check_classic_expr.py b/nspepi/nspepi2/check_classic_expr.py index 53635d7..d9867b4 100644 --- a/nspepi/nspepi2/check_classic_expr.py +++ b/nspepi/nspepi2/check_classic_expr.py @@ -26,10 +26,8 @@ def check_classic_expr(classic_expr): of the converted string, so remove that character.""" nspepi_tool_output = nspepi_tool_output.rstrip() except subprocess.CalledProcessError as exc: - # Log the command which is failing - logging.error(exc) - # Log the error message - logging.error(exc.output) + # Log the command which is failing and also the error message + logging.error(exc.output + " : [" + exc + "]") return None nspepi_tool_output = nspepi_tool_output.decode() if nspepi_tool_output.startswith('ERROR:'): diff --git a/nspepi/nspepi2/cli_lex.py b/nspepi/nspepi2/cli_lex.py index 7e39e38..60b6a6c 100644 --- a/nspepi/nspepi2/cli_lex.py +++ b/nspepi/nspepi2/cli_lex.py @@ -176,8 +176,7 @@ def token(self): else: self.advance_token(self._length) token_type = "ERROR" - logging.error("Data: {}".format(self._data)) - logging.error("Unbalanced closed parenthesis") + logging.error("Unbalanced closed parenthesis : [{}]".format(self._data)) break elif self._data[self._lex_pos] == "\\": # backslashes are escapes inside quotes @@ -187,9 +186,7 @@ def token(self): self.advance_and_append_token( self._data[self._lex_pos]) token_type = "ERROR" - logging.error("Data: {}".format(self._data)) - logging.error("Blackslashes inside quotes are " - "followed by end of the command") + logging.error("Blackslashes inside quotes are followed by end of the command : [{}]".format(self._data)) break if self._data[self._lex_pos + 1] == 't': self.advance_and_append_token('\t', 2) @@ -211,8 +208,7 @@ def token(self): if state in "\"'" or parenthesis_counter > 0: # error token for not matching with any rule token_type = "ERROR" - logging.error("Data: {}".format(self._data)) - logging.error("Unbalanced parenthesis or quotes") + logging.error("Unbalanced parenthesis or quotes : [{}]".format(self._data)) next_token = LexToken(token_type, self._token_value, 1, self._lex_pos - 1) return next_token @@ -333,9 +329,7 @@ def adv_expr_token(self): self.advance_and_append_token( self._data[self._lex_pos]) token_type = "ERROR" - logging.error("Data: {}".format(self._data)) - logging.error("Blackslashes inside quotes are " - "followed by end of the expression") + logging.error("Blackslashes inside quotes are followed by end of the expression : [{}]".format(self._data)) break if self._data[self._lex_pos + 1] == 't': self.advance_and_append_token('\t', 2) @@ -357,13 +351,11 @@ def adv_expr_token(self): if state in "\"'": # error token for not matching with any rule token_type = "ERROR" - logging.error("Data: {}".format(self._data)) - logging.error("Unbalanced quotes") + logging.error("Unbalanced quotes : [{}]".format(self._data)) elif state == "REGEX": # error token for not matching with any rule token_type = "ERROR" - logging.error("Data: {}".format(self._data)) - logging.error("Unterminated regex") + logging.error("Unterminated regex : [{}]".format(self._data)) next_token = LexToken(token_type, self._token_value, 1, self._lex_pos - 1) return next_token diff --git a/nspepi/nspepi2/convert_classic_expr.py b/nspepi/nspepi2/convert_classic_expr.py index d3cafd4..eb11aee 100644 --- a/nspepi/nspepi2/convert_classic_expr.py +++ b/nspepi/nspepi2/convert_classic_expr.py @@ -37,7 +37,7 @@ r'(S\.CACHE_CONTROL)|(S\.TXID)|(S\.MEDIA))\b', re.IGNORECASE) -def convert_classic_expr(classic_expr, ignore_csec_expr = False): +def convert_classic_expr(classic_expr): tree_obj = CLIParseTreeNode() info_msg = 'INFO: Expression is not converted' + \ ' - most likely it is a valid advanced expression' @@ -53,23 +53,15 @@ def convert_classic_expr(classic_expr, ignore_csec_expr = False): of the converted string, so remove that character.""" nspepi_tool_output = nspepi_tool_output.rstrip() except subprocess.CalledProcessError as exc: - # Log the command which is failing - logging.error(exc) - # Log the error message - logging.error(exc.output) + # Log the command which is failing and also the reason + logging.error(str(exc) + " : [" + str(exc.output) + "]") return None nspepi_tool_output = nspepi_tool_output.decode() if nspepi_tool_output.startswith('ERROR:'): """Handles the error returned by old nspepi tool""" - csec_error_msg = 'Conversion of client ' + \ - 'security expression is not supported' - if (ignore_csec_expr and (csec_error_msg in \ - nspepi_tool_output)): - return "Ignoring Client security Expression" - else: - logging.error(nspepi_tool_output) - return None + logging.error(nspepi_tool_output) + return None elif nspepi_tool_output.endswith(info_msg): """old nspepi tool didn't convert the expression, so return input expression""" @@ -102,7 +94,7 @@ def convert_adv_expr(advanced_expr): body_expr_without_arg = is_body_expr_without_arg_present(advanced_expr) if body_expr_without_arg: logging.error("Body size needs to process is not present " - "in HTTP.REQ.BODY expression, please privoide the body size.") + "in HTTP.REQ.BODY expression, please provide the body size. : [{}]".format(advanced_expr)) return None advanced_expr = convert_q_s_expr(advanced_expr) return convert_sys_eval_classic_expr(advanced_expr) @@ -169,7 +161,7 @@ def convert_sys_eval_classic_expr(advanced_expr): classic_exp_info = PILex.get_pi_string( advanced_expr[arg_start_index:]) if classic_exp_info is None: - logging.error("Error in converting expression: {}".format( + logging.error("Error in converting expression : [{}]".format( original_expr)) return None classic_expr = classic_exp_info[0] @@ -184,7 +176,7 @@ def convert_sys_eval_classic_expr(advanced_expr): sys_end_index += 1 if (sys_end_index >= advanced_expr_length or advanced_expr[sys_end_index] != ')'): - logging.error("Error in converting expression: {}".format( + logging.error("Error in converting expression : [{}]".format( original_expr)) return None converted_expr = convert_classic_expr(classic_expr) @@ -192,7 +184,7 @@ def convert_sys_eval_classic_expr(advanced_expr): # Result from convert_classic_expr will have enclosing quotes. converted_expr = cli_commands.remove_quotes(converted_expr) if converted_expr is None or converted_expr == classic_expr: - logging.error("Error in converting expression: {}".format( + logging.error("Error in converting expression: [{}]".format( original_expr)) return None # Converted expression should be enclosed in braces because diff --git a/nspepi/nspepi2/convert_cli_commands.py b/nspepi/nspepi2/convert_cli_commands.py index 2db3727..f8f7bbb 100644 --- a/nspepi/nspepi2/convert_cli_commands.py +++ b/nspepi/nspepi2/convert_cli_commands.py @@ -96,10 +96,9 @@ def get_classic_expr_list(expr): token_value = str(next_token) token_value_len = len(token_value) is_classic_expr = False - lower_token_value = token_value.lower() - if lower_token_value in NamedExpression.built_in_named_expr: + if token_value in NamedExpression.built_in_named_expr: # Checking for built-in classic Named expression. - adv_expr_name = NamedExpression.built_in_named_expr[lower_token_value] + adv_expr_name = NamedExpression.built_in_named_expr[token_value] lower_adv_expr_name = adv_expr_name.lower() if lower_adv_expr_name in policy_entities_names: is_classic_expr = True @@ -151,8 +150,8 @@ def print_csec_error_message(expr_list): """ for expr_name in expr_list: if not NamedExpression.csec_expr_list[expr_name]["error_displayed"]: - logging.error(("Conversion of clientSecurityMessage based expression [{}] " - "is not supported, please do the conversion manually.") + logging.error(("Conversion of clientSecurityMessage based expression " + "is not supported, please do the conversion manually. : [{}]") .format(str(NamedExpression.csec_expr_list[expr_name]["tree"]).strip())) NamedExpression.csec_expr_list[expr_name]["error_displayed"] = True @@ -183,7 +182,7 @@ def replace_named_expr(rule_expr): return converted_expr @staticmethod - def convert_pos_expr(commandParseTree, pos, ignore_csec_expr = False): + def convert_pos_expr(commandParseTree, pos): """ Convert the expression present at a given position commandParseTree - the parse tree to modify @@ -196,19 +195,16 @@ def convert_pos_expr(commandParseTree, pos, ignore_csec_expr = False): csec_expr_info = has_client_security_expressions(rule_expr) if csec_expr_info[0]: print_csec_error_message(csec_expr_info[1]) - logging.error('Error in converting command : ' + - str(commandParseTree).strp()) + logging.error('Error in converting command : [' + + str(commandParseTree).strp() + ']') return commandParseTree - converted_expr = convert_classic_expr.convert_classic_expr(rule_expr, ignore_csec_expr) + converted_expr = convert_classic_expr.convert_classic_expr(rule_expr) if converted_expr is None: - logging.error('Error in converting command : ' + - str(commandParseTree).strip()) + logging.error('Error in converting command : [' + + str(commandParseTree).strip() + ']') converted_expr = rule_expr else: - if (converted_expr == "Ignoring Client security Expression"): - commandParseTree.set_has_csec_expr() - return commandParseTree # converted_expr will have quotes and rule_expr will not have # quotes. Since we are comparing these 2 expressions, removing # quotes from converted_expr. @@ -240,14 +236,14 @@ def convert_keyword_expr(commandParseTree, keywordName): csec_expr_info = has_client_security_expressions(rule_expr) if csec_expr_info[0]: print_csec_error_message(csec_expr_info[1]) - logging.error('Error in converting command : ' + - str(commandParseTree).strip()) + logging.error('Error in converting command : [' + + str(commandParseTree).strip() + ']') return commandParseTree converted_expr = convert_classic_expr.convert_classic_expr(rule_expr) if converted_expr is None: - logging.error('Error in converting command : ' + - str(commandParseTree).strip()) + logging.error('Error in converting command : [' + + str(commandParseTree).strip() + ']') converted_expr = rule_expr else: # converted_expr will have quotes and rule_expr will not have @@ -286,8 +282,8 @@ def convert_adv_expr_list(tree, param_list): continue converted_expr = convert_classic_expr.convert_adv_expr(adv_expr) if converted_expr is None: - logging.error('Error in converting command : ' + - str(original_tree).strip()) + logging.error('Error in converting command : [' + + str(original_tree).strip() + ']') return original_tree else: converted_expr = remove_quotes(converted_expr) @@ -763,10 +759,10 @@ def reprioritize_binds(self, binds): self.update_tree_arg(bind_info.parse_tree, bind_info.bind_arg_goto, new_goto) elif goto.upper() not in ("NEXT", "END", "USE_INVOCATION_RESULT"): - logging.error("gotoPriorityExpression in {} uses an" + logging.error("gotoPriorityExpression in this CLI command uses an" " expression. Since the priorities for this" " bindpoint have been renumbered, this" - " expression will need to be modified manually." + " expression will need to be modified manually. : [{}]" "".format(str(bind_info.parse_tree))) return new_binds @@ -792,10 +788,11 @@ def reprioritize_and_emit_global_binds(self): " converted as [{}]. If the command is required" " please take a backup because comments are not" " saved in ns.conf after triggering" - "'save ns config'.{}" + "'save ns config'.{} : [{}]" "".format(bind_info.orig_cmd.strip(), str(bind_info.parse_tree).strip(), - common.CMD_MOD_ERR_MSG)) + common.CMD_MOD_ERR_MSG, + bind_info.orig_cmd.strip())) bind_cmd_trees.append( "# {}".format(str(bind_info.parse_tree))) else: @@ -863,10 +860,11 @@ def reprioritize_and_emit_4_level_dict(self, bind_dict): " required please take a backup because" " comments are not saved in ns.conf" " after triggering 'save ns config'." - "{}".format( + "{} : [{}]".format( bind_info.orig_cmd.strip(), str(bind_info.parse_tree).strip(), - common.CMD_MOD_ERR_MSG)) + common.CMD_MOD_ERR_MSG, + bind_info.orig_cmd.strip())) bind_cmd_trees.append( "# {}".format(str(bind_info.parse_tree))) else: @@ -1214,7 +1212,7 @@ def convert_tunnel_global(self, commandParseTree): " with the advanced configuration, so if we convert this" " config then functionality will change. If command is" " required please take a backup because comments will" - " not be saved in ns.conf after triggering 'save ns config': {}"). + " not be saved in ns.conf after triggering 'save ns config' : [{}]"). format(str(commandParseTree).strip()) ) return ['#' + str(commandParseTree)] @@ -1459,7 +1457,7 @@ def convert_appfw_global_bind(self, commandParseTree): " with the advanced configuration, so if we convert this" " config then functionality will change. If command is" " required please take a backup because comments will" - " not be saved in ns.conf after triggering 'save ns config': {}"). + " not be saved in ns.conf after triggering 'save ns config' : [{}]"). format(str(commandParseTree).strip())) return ['#' + str(commandParseTree)] @@ -1591,7 +1589,7 @@ def register_name(self, commandParseTree): """ logging.error(("HTTP callout name {} is conflicting with" " named expression entity name, please resolve" - " the conflict.").format(callout_name)) + " the conflict. : [{}]").format(callout_name, str(commandParseTree))) else: HTTP_CALLOUT.register_policy_entity_name(commandParseTree) commandParseTree = HTTP_CALLOUT.convert_adv_expr_list( @@ -1744,6 +1742,18 @@ def convert_policy(self, commandParseTree): expr_rule = commandParseTree.positional_value(1).value lower_expr_name = expr_name.lower() named_expr[lower_expr_name] = expr_rule + if (((lower_expr_name in reserved_word_list) or + (re.match('^[a-z_][a-z0-9_]*$', lower_expr_name) is None) or + (lower_expr_name in policy_entities_names))): + logging.error(("Expression name {} is invalid for advanced " + "expression: names must begin with an ASCII " + "alphabetic character or underscore and must " + "contain only ASCII alphanumerics or underscores" + " and shouldn't be name of another policy entity" + "; words reserved for policy use may not be used;" + " underscores will be substituted for any invalid" + " characters in corresponding advanced name : [{}]") + .format(expr_name, commandParseTree)) if commandParseTree.keyword_exists('clientSecurityMessage'): NamedExpression.csec_expr_list[lower_expr_name] = {} @@ -1760,21 +1770,6 @@ def convert_policy(self, commandParseTree): NamedExpression.register_classic_entity_name(commandParseTree) return [commandParseTree] - if ((lower_expr_name in reserved_word_list) or - (re.match('^[a-z_][a-z0-9_]*$', lower_expr_name) is None)): - logging.error(("Expression name {} is invalid for advanced " - "expression: names must begin with an ASCII " - "alphabetic character or underscore and must " - "contain only ASCII alphanumerics or underscores" - " and shouldn't be name of another policy entity" - "; words reserved for policy use may not be used;" - " underscores will be substituted for any invalid" - " characters in corresponding advanced name") - .format(expr_name)) - - if (lower_expr_name in policy_entities_names): - logging.error("Name {} is already in use".format(expr_name)) - original_tree = copy.deepcopy(commandParseTree) """Convert classic named expression to advanced Syntax: @@ -1783,7 +1778,7 @@ def convert_policy(self, commandParseTree): add policy expression """ commandParseTree = NamedExpression \ - .convert_pos_expr(commandParseTree, 1, True) + .convert_pos_expr(commandParseTree, 1) if commandParseTree.adv_upgraded: tree_list = [commandParseTree] @@ -1811,11 +1806,6 @@ def convert_policy(self, commandParseTree): tree_list.append(commandParseTree) NamedExpression.register_policy_entity_name(commandParseTree) NamedExpression.register_classic_entity_name(original_tree) - elif commandParseTree.has_csec_expr: - NamedExpression.csec_expr_list[lower_expr_name] = {} - NamedExpression.csec_expr_list[lower_expr_name]["tree"] = original_tree - NamedExpression.csec_expr_list[lower_expr_name]["error_displayed"] = False - NamedExpression.register_classic_entity_name(original_tree) else: NamedExpression.register_policy_entity_name(original_tree) return tree_list @@ -1972,8 +1962,8 @@ def convert_policy(self, commandParseTree): converted_expr = convert_classic_expr.convert_classic_expr( rule_expr) if converted_expr is None: - logging.error('Error in converting command : ' + - str(commandParseTree).strip()) + logging.error('Error in converting command : [' + + str(commandParseTree).strip() + ']') return [commandParseTree] converted_expr = converted_expr.strip('"') domain_name = commandParseTree.keyword_value('domain')[0] \ @@ -2137,35 +2127,6 @@ def convert_cs_bind_command(self, commandParseTree): # CS policies without action issue. if cs_vserver_name not in self._cs_policy_binding_info: self._cs_policy_binding_info[cs_vserver_name] = [] - - if commandParseTree.keyword_exists("targetLBVserver"): - vserver_name = commandParseTree.keyword_value( - "targetLBVserver")[0].value - else: - vserver_name = commandParseTree.positional_value(1).value - - if "vserver_bind_info" not in self._policy_bind_info[policy_name]: - vserver_bind_info = {} - vserver_bind_info["multiple_bindings"] = False - vserver_bind_info["multiple_target_vservers"] = False - vserver_bind_info["diff_case_search"] = False - ci_search = cs_vserver_name in self._cs_vserver_info_ci - vserver_bind_info["case_insensitive"] = ci_search - vserver_bind_info["target_vservers"] = vserver_name - self._policy_bind_info[policy_name]["vserver_bind_info"] = \ - vserver_bind_info - else: - vserver_bind_info = self._policy_bind_info[policy_name]["vserver_bind_info"] - vserver_bind_info["multiple_bindings"] = True - - if vserver_bind_info["target_vservers"] != vserver_name: - vserver_bind_info["multiple_target_vservers"] = True - - if vserver_bind_info["diff_case_search"] is False: - ci_search = cs_vserver_name in self._cs_vserver_info_ci - if vserver_bind_info["case_insensitive"] != ci_search: - vserver_bind_info["diff_case_search"] = True - self._cs_policy_binding_info[cs_vserver_name].append( commandParseTree) return [] @@ -2203,11 +2164,6 @@ def convert_cs_policy_entity_bind( It will be either positional index or keyword name. Returns converted list of parse trees. """ - # If no classic CS policy is configured, then no need - # to process the bindings. - if not self._classic_policy_exists: - return [commandParseTree] - policy_type = self.__class__.__name__ if policy_name in self._policy_bind_info: cs_vserver_name = commandParseTree.positional_value(0).value @@ -2215,23 +2171,6 @@ def convert_cs_policy_entity_bind( # CS policies without action issue. if cs_vserver_name not in self._cs_policy_binding_info: self._cs_policy_binding_info[cs_vserver_name] = [] - - vserver_name = commandParseTree.keyword_value("policyName")[1].value - if "vserver_bind_info" not in self._policy_bind_info[policy_name]: - vserver_bind_info = {} - vserver_bind_info["multiple_bindings"] = False - vserver_bind_info["multiple_target_vservers"] = False - vserver_bind_info["diff_case_search"] = False - vserver_bind_info["target_vservers"] = vserver_name - self._policy_bind_info[policy_name]["vserver_bind_info"] = \ - vserver_bind_info - else: - vserver_bind_info = self._policy_bind_info[policy_name]["vserver_bind_info"] - vserver_bind_info["multiple_bindings"] = True - - if vserver_bind_info["target_vservers"] != vserver_name: - vserver_bind_info["multiple_target_vservers"] = True - self._cs_policy_binding_info[cs_vserver_name].append( commandParseTree) return [] @@ -2292,36 +2231,31 @@ def get_converted_cmds(self): "bind cr vserver"): vserver_name = bind_tree.keyword_value( "policyName")[1].value - + new_policy_name = "nspepi_adv_" + policy_name + '_' + \ + vserver_name set_ci_rule = False + # If CS vserver is configured with caseSensitive + # parameter set to OFF and policy is configured + # with URL parameter, then add '_ci' suffix in the + # new policy name and rule of that policy should + # do case-insensitive search. if (is_cs_vserver and (cs_cr_vserver_name in self._cs_vserver_info_ci) and - (policy_name in self._policy_url_info)): + (policy_name in self._policy_url_info)): + new_policy_name += '_ci' set_ci_rule = True - - vserver_bind_info = self._policy_bind_info[policy_name]["vserver_bind_info"] - need_new_policy = False - need_new_action = False - - if vserver_bind_info["multiple_bindings"]: - need_new_action = True - if vserver_bind_info["multiple_target_vservers"]: - need_new_policy = True - elif vserver_bind_info["diff_case_search"]: - if set_ci_rule: - need_new_policy = True - - if need_new_action: - action_name = "nspepi_adv_cs_act_" + vserver_name - truncated_act_name = action_name + truncated_pol_name = new_policy_name + action_name = "nspepi_adv_cs_act_" + vserver_name + truncated_act_name = action_name + if new_policy_name not in newly_added_policy_names: if action_name not in newly_added_action_names: # Create new action action_tree = CLICommand("add", "cs", "action") # Check action name length. Max allowed length is 127 if len(action_name) > 127: truncated_act_name, overlength_action_counter = \ - self.truncate_name(action_name, - overlength_action_names, - overlength_action_counter) + self.truncate_name(action_name, + overlength_action_names, + overlength_action_counter) pos = CLIPositionalParameter(truncated_act_name) action_tree.add_positional(pos) vserver_key = CLIKeywordParameter(CLIKeywordName( @@ -2335,80 +2269,54 @@ def get_converted_cmds(self): # Get truncated name if truncated. if action_name in overlength_action_names: truncated_act_name = overlength_action_names[ - action_name] - - if need_new_policy: - new_policy_name = "nspepi_adv_" + policy_name + '_' + \ - vserver_name - # If CS vserver is configured with caseSensitive - # parameter set to OFF and policy is configured - # with URL parameter, then add '_ci' suffix in the - # new policy name and rule of that policy should - # do case-insensitive search. - if set_ci_rule: - new_policy_name += '_ci' + action_name] + # Create new policy with [policy_name]_[vserver_name] as + # as name and bind to newly created action + # cs_act_[vserver_name] + new_policy = copy.deepcopy(policy_tree) + # Max length of policy name allowed is 127. truncated_pol_name = new_policy_name - if new_policy_name not in newly_added_policy_names: - # Create new policy with [policy_name]_[vserver_name] as - # as name and bind to newly created action - # cs_act_[vserver_name] - new_policy = copy.deepcopy(policy_tree) - # Max length of policy name allowed is 127. - truncated_pol_name = new_policy_name - if len(new_policy_name) > 127: - truncated_pol_name, overlength_policy_counter = \ - self.truncate_name(new_policy_name, - overlength_policy_names, - overlength_policy_counter) - self.update_tree_arg(new_policy, 0, truncated_pol_name) - if set_ci_rule: - rule_node = new_policy.keyword_value('rule') - rule_node[0].set_value(self._policy_url_info[policy_name], True) - action_key = CLIKeywordParameter(CLIKeywordName("action")) - action_key.add_value(truncated_act_name) - new_policy.add_keyword(action_key) - # Remove the devno so that multiple lines - # don't have the same devno. - if new_policy.keyword_exists('devno'): - new_policy.remove_keyword('devno') - newly_added_policy_names.append(new_policy_name) - pol_list.append(new_policy) - else: - # When policy is already added. - # Get truncated policy name if truncated. - if new_policy_name in overlength_policy_names: - truncated_pol_name = overlength_policy_names[ - new_policy_name] - # Remove targetLBVserver from bind command and update policy - # name to newly added policy name. - self.update_tree_arg(bind_tree, "policyName", - truncated_pol_name) - else: + if len(new_policy_name) > 127: + truncated_pol_name, overlength_policy_counter = \ + self.truncate_name(new_policy_name, + overlength_policy_names, + overlength_policy_counter) + self.update_tree_arg(new_policy, 0, truncated_pol_name) if set_ci_rule: - rule_node = policy_tree.keyword_value('rule') + rule_node = new_policy.keyword_value('rule') rule_node[0].set_value(self._policy_url_info[policy_name], True) - if need_new_action: - action_key = CLIKeywordParameter(CLIKeywordName("action")) - action_key.add_value(truncated_act_name) - policy_tree.add_keyword(action_key) - - if policy_tree not in pol_list: - pol_list.append(policy_tree) - - if need_new_action: - if ((' '.join(bind_tree.get_command_type())).lower() == - "bind cs vserver"): - if bind_tree.keyword_exists("targetLBVserver"): - bind_tree.remove_keyword("targetLBVserver") - else: - bind_tree.remove_positional(1) - elif ((' '.join(bind_tree.get_command_type())).lower() == - "bind cr vserver"): - # In bind cr vserver command, vserver name exists in - # following way: - # bind cr vserver -policyName - # - bind_tree.remove_keyword_value("policyName", 1) + action_key = CLIKeywordParameter(CLIKeywordName("action")) + action_key.add_value(truncated_act_name) + new_policy.add_keyword(action_key) + # Remove the devno so that multiple lines + # don't have the same devno. + if new_policy.keyword_exists('devno'): + new_policy.remove_keyword('devno') + newly_added_policy_names.append(new_policy_name) + pol_list.append(new_policy) + else: + # When policy is already added. + # Get truncated policy name if truncated. + if new_policy_name in overlength_policy_names: + truncated_pol_name = overlength_policy_names[ + new_policy_name] + # Remove targetLBVserver from bind command and update policy + # name to newly added policy name. + self.update_tree_arg(bind_tree, "policyName", + truncated_pol_name) + if ((' '.join(bind_tree.get_command_type())).lower() == + "bind cs vserver"): + if bind_tree.keyword_exists("targetLBVserver"): + bind_tree.remove_keyword("targetLBVserver") + else: + bind_tree.remove_positional(1) + elif ((' '.join(bind_tree.get_command_type())).lower() == + "bind cr vserver"): + # In bind cr vserver command, vserver name exists in + # following way: + # bind cr vserver -policyName + # + bind_tree.remove_keyword_value("policyName", 1) if cs_cr_vserver_name not in cs_cr_vserver_bindings: cs_cr_vserver_bindings[cs_cr_vserver_name] = [[], [], [], [], []] @@ -2738,9 +2646,9 @@ def convert_policy(self, commandParseTree): original_tree = copy.deepcopy(commandParseTree) convertedParseTree = SSL.convert_keyword_expr(commandParseTree, 'rule') if convertedParseTree.upgraded: - logging.error(("Classic SSL policy [{}] is not working from 10.1 release, " + logging.error(("Classic SSL policy is not working from 10.1 release, " "please remove the classic SSL policy configuration " - "from the config file").format(str(original_tree).strip())) + "from the config file : [{}]").format(str(original_tree).strip())) return [original_tree] return [commandParseTree] @@ -2753,9 +2661,9 @@ class SureConnect(ConvertConfig): @common.register_for_cmd("add", "sc", "policy") @common.register_for_cmd("set", "sc", "parameter") def convert_policy(self, commandParseTree): - logging.error(("SureConnect feature command [{}] conversion " + logging.error(("SureConnect feature command conversion " "is not supported, please do the conversion " - "manually").format(str(commandParseTree).strip())) + "manually : [{}]").format(str(commandParseTree).strip())) return [commandParseTree] @@ -2766,9 +2674,9 @@ class PriorityQueuing(ConvertConfig): """ @common.register_for_cmd("add", "pq", "policy") def convert_policy(self, commandParseTree): - logging.error(("PriorityQueuing feature command [{}] conversion " + logging.error(("PriorityQueuing feature command conversion " "is not supported, please do the conversion " - "manually").format(str(commandParseTree).strip())) + "manually : [{}]").format(str(commandParseTree).strip())) return [commandParseTree] @@ -2779,9 +2687,9 @@ class HDoSP(ConvertConfig): """ @common.register_for_cmd("add", "dos", "policy") def convert_policy(self, commandParseTree): - logging.error(("HDoSP feature command [{}] conversion " + logging.error(("HDoSP feature command conversion " "is not supported, please do the conversion " - "manually").format(str(commandParseTree).strip())) + "manually : [{}]").format(str(commandParseTree).strip())) return [commandParseTree] diff --git a/nspepi/nspepi2/convert_cmp_cmd.py b/nspepi/nspepi2/convert_cmp_cmd.py index 2936010..203f738 100644 --- a/nspepi/nspepi2/convert_cmp_cmd.py +++ b/nspepi/nspepi2/convert_cmp_cmd.py @@ -33,14 +33,6 @@ class CMP(cli_cmds.ConvertConfig): "ns_nocmp_xml_ie": "ns_adv_nocmp_xml_ie" } - builtin_adv_policies_bind_info = { - "ns_adv_nocmp_xml_ie": ["8700", "END"], - "ns_adv_nocmp_mozilla_47": ["8800", "END"], - "ns_adv_cmp_mscss": ["8900", "END"], - "ns_adv_cmp_msapp": ["9000", "END"], - "ns_adv_cmp_content_type": ["10000", "END"], - } - def __init__(self): """ Information about CMP commands. @@ -208,22 +200,12 @@ def convert_cmp_global_bind(self, bind_cmd_tree): " with the advanced configuration, so if we convert this" " config then functionality will change. If command is" " required please take a backup because comments will" - " not be saved in ns.conf after triggering 'save ns config': {}"). + " not be saved in ns.conf after triggering 'save ns config' : [{}]"). format(str(bind_cmd_tree).strip()) ) return ["#" + str(bind_cmd_tree)] policy_name = bind_cmd_tree.positional_value(0).value - # Ignore the default advanced bindings - if policy_name in self.builtin_adv_policies_bind_info: - policy_info = self.builtin_adv_policies_bind_info[policy_name] - priority = bind_cmd_tree.keyword_value("priority")[0].value - next_prio_expr = bind_cmd_tree.keyword_value( - "gotoPriorityExpression")[0].value - if ((policy_info[0] == priority) and - (policy_info[1] == next_prio_expr)): - return [bind_cmd_tree] - self.replace_builtin_policy(bind_cmd_tree, policy_name, 0) bind_point = "" self.update_bind_info(bind_cmd_tree, bind_point) @@ -373,7 +355,7 @@ def check_functionality(self): " Now classic policies are converted to advanced. " "This will change the functionality. CMP policy bindings " "are commented out. Modify the bindings of CMP policies " - "manually.").format(bind_point) + "manually. : [{}]").format(bind_point, bind_point) ) conflict_exists = True elif self._cmp_bind_info[global_bind_point][ @@ -386,7 +368,7 @@ def check_functionality(self): "converted to advanced. This will change the " "functionality. CMP policy bindings are commented out. " "Modify the bindings of CMP policies " - "manually.").format(bind_point) + "manually. : [{}]").format(bind_point, bind_point) ) conflict_exists = True return conflict_exists @@ -562,4 +544,4 @@ def get_cmp_policy_bindings(self): tree_list += self.convert_entity_policy_bind( tree, tree, policy_name, policy_type, priority_arg, goto_arg) - return tree_list + return tree_list \ No newline at end of file diff --git a/nspepi/nspepi2/convert_filter_command.py b/nspepi/nspepi2/convert_filter_command.py index 6fc4d30..106367d 100644 --- a/nspepi/nspepi2/convert_filter_command.py +++ b/nspepi/nspepi2/convert_filter_command.py @@ -190,6 +190,18 @@ bind rewrite global pol2 NEXT -type RES_DEFAULT bind vserver -policyName pol1 [-priority ]) -gotoPriorityExpression NEXT -TYPE REQUEST bind vserver -policyName pol2 [-priority ]) -gotoPriorityExpression NEXT -TYPE RESPONSE + +# Remove this comment line at the time of transforming actionType FORWARD +---INPUT FORWARD ACTIONTYPE--- +add filter action act1 FORWARD serviceName +add filter policy pol1 -rule "ns_true" -reqAction act1 +bind filter global pol1 [-priority ]) +bind vserver -policyName pol1 [-priority ]) +---CONVERTED RESULT--- +add filter action act1 FORWARD serviceName +add filter policy pol1 -rule "ns_true" -reqAction act1 +bind filter global pol1 [-priority ]) +bind vserver -policyName pol1 [-priority ]) ''' import re @@ -242,12 +254,7 @@ def __init__(self): ("reset", ["reset"]), ("drop", ["drop"])]) self._converted_pol_param = OrderedDict() self._policy_command = [] - self._htmlInjection = OrderedDict() - self._htmlInjection["action"] = [] - self._htmlInjection["policy"] = [] - self._forward = OrderedDict() - self._forward["action"] = [] - self._forward["policy"] = [] + self._htmlInjection = [] self._bind_tree_rw = [] self._bind_tree_resp = [] self._policylabel_name = [] @@ -256,7 +263,11 @@ def __init__(self): self.overlength_policy_counter = 0 self.overlength_policylabel_names = {} self.overlength_policylabel_counter = 0 - + ''' + # TODO - This should be uncommented at the time of + # transformation for FORWARD actionType. + self._vserverName_list = set([]) + ''' @common.register_for_cmd("add", "filter", "action") def convert_filter_action(self, action_parse_tree): """ @@ -290,10 +301,9 @@ def convert_filter_action(self, action_parse_tree): # Store actionType and actionName actionName = original_cmd.positional_value( 0).value - lower_actionName = actionName.lower() if action_type not in self._actionTypeName: self._actionTypeName[action_type] = [] - self._actionTypeName[action_type].append(lower_actionName) + self._actionTypeName[action_type].append(actionName) if (action_type == "add"): """ @@ -350,13 +360,13 @@ def convert_filter_action(self, action_parse_tree): # rewrite_action_response: action which has HTTP.RES.XX # action_parse_tree: action which has HTTP.REQ.XX + # Save action name in a list which is used to + # identify an action command + if actionName not in self._action_command: + self._action_command[actionName] = [] rewrite_action_response = copy.deepcopy( action_parse_tree) if match_value.group(1) in Filter_variable: - # Save action name in a list which is used to - # identify an action command - if lower_actionName not in self._action_command: - self._action_command[lower_actionName] = [] # Add a new rewrite action of different name whose # stringBuildExpr should be expression of # RESPONSE side @@ -379,23 +389,16 @@ def convert_filter_action(self, action_parse_tree): action_parse_tree.set_upgraded() # Store actionName, and converted command - self._action_command[lower_actionName].append( + self._action_command[actionName].append( action_parse_tree) - self._action_command[lower_actionName].append( + self._action_command[actionName].append( rewrite_action_response) # Store actionType and actionName self._actionTypeName[action_type].append( rewrite_action_response.positional_value( - 0).value.lower()) + 0).value) return [] - else: - logging.error( - "Conversion of HTMLInjection variable in " - "command [{}] is not supported in this tool." - "".format(str(original_cmd).strip())) - return [action_parse_tree] - else: # Prebody/postbody value indicates that this config is # being used for HTMLinjection feature, and conversion @@ -403,15 +406,14 @@ def convert_filter_action(self, action_parse_tree): # the input command as the output. # Remove action name from stored dictionary. - self._actionTypeName[action_type].remove(lower_actionName) + self._actionTypeName[action_type].remove(actionName) # Store list of corresponding action names - self._htmlInjection["action"].append(actionName) + self._htmlInjection.append(actionName) action_parse_tree_list = [original_cmd] logging.error( - "Conversion of HTMLInjection feature related" - " command [{}] is not supported in this tool." - "".format(str(original_cmd).strip())) + "Conversion of [{}] not supported in this tool. : [{}]" + "".format(str(original_cmd).strip(), str(original_cmd).strip())) elif (action_type == "corrupt"): """ Transformation for filter action of CORRUPT as actionType @@ -439,8 +441,8 @@ def convert_filter_action(self, action_parse_tree): """ # Save action name in a list which is used to # identify an action command - if lower_actionName not in self._action_command: - self._action_command[lower_actionName] = [] + if actionName not in self._action_command: + self._action_command[actionName] = [] # A. Parse tree for advance command with responder feature responder_action = CLICommand("add", "responder", "action") action_name = CLIPositionalParameter(actionName) @@ -529,13 +531,12 @@ def convert_filter_action(self, action_parse_tree): rewrite_action.set_upgraded() # Store actionName, and converted command - self._action_command[lower_actionName].append(responder_action) - self._action_command[lower_actionName].append(rewrite_action) - + self._action_command[actionName].append(responder_action) + self._action_command[actionName].append(rewrite_action) # Store actionType and actionName self._actionTypeName[action_type].append(str( - rewrite_action.positional_value(0).value.lower())) + rewrite_action.positional_value(0).value)) return [] elif (action_type == "drop") or (action_type == "reset"): """ Transformation for classicAction DROP/RESET actionType @@ -550,14 +551,59 @@ def convert_filter_action(self, action_parse_tree): # identify an action command return [] elif action_type == "forward": + """Transformation for filter action command of FORWARD as + actionType, LBvserver is created and bound to the existing + service via VserverCreation function and LBvserver Name is + fetched and used in transformed command of feature group CS + vs_kw - key for targetLBVserver + lb_name - new lb vserver to be used by cs action """ - Conversion of FORWARD action type - """ + ''' + # TODO - there are issues with FORWARD actionType in binding, + # so we won't currently enable conversions for filter of + # FORWARD actionType. + service = original_cmd.positional_value(2).value + lb_name = "nspepi_lb_vserver_" + service + action_parse_tree = CLICommand("add", "cs", "action") + action_name = CLIPositionalParameter(actionName) + action_parse_tree.add_positional(action_name) + vs_kw = CLIKeywordParameter(CLIKeywordName("targetLBVserver")) + vs_kw.add_value(lb_name) + action_parse_tree.add_keyword(vs_kw) + action_parse_tree.set_upgraded() + if lb_name in self._vserverName_list: + # If vserverName already exists in the list + # then just output the transformed action + self._vserverName_list.add(lb_name) + action_parse_tree_list = [action_parse_tree] + else: + # If vserverName not in the list + # then output- add vserver, bind vserver and + # transformed action + self._vserverName_list.add(lb_name) + + # Add LB Vserver with name nspepi_lb_vserver_ + vserver = CLICommand("add", "lb", "vserver") + vs_name = CLIPositionalParameter(lb_name) + vs_type = CLIPositionalParameter("http") + vserver.add_positional_list([vs_name, vs_type]) + vserver.set_upgraded() + + # Bind LB Vserver with Service Name which is available in + # classic action command + bindVserver = CLICommand("bind", "lb", "vserver") + bind_vs_name = CLIPositionalParameter(str(vs_name)) + bind_service_name = CLIPositionalParameter(service) + bindVserver.add_positional_list([ + bind_vs_name, bind_service_name]) + bindVserver.set_upgraded() + action_parse_tree_list = [ + vserver, bindVserver, action_parse_tree] + ''' action_parse_tree_list = [original_cmd] - self._forward["action"].append(actionName) logging.error( - "Conversion of FORWARD action type related command" - " [{}] not supported in this tool".format(str(original_cmd).strip())) + "Conversion of [{}] not supported in this tool. : [{}]" + "".format(str(original_cmd).strip(), str(original_cmd).strip())) else: """ @@ -568,7 +614,7 @@ def convert_filter_action(self, action_parse_tree): action_parse_tree_list = [original_cmd] logging.error( 'Error in converting original command since' + - ' CLI context of filter feature is invalid: ' + + ' CLI context of filter feature is invalid : ' + '[{}]'.format(str(original_cmd))) return action_parse_tree_list @@ -605,23 +651,11 @@ def convert_filter_policy(self, policy_parse_tree): converted_pol_cmd, policy_action_key, orig_action_name = self.new_policy( policy_parse_tree, policyName) policy_action = orig_action_name.lower() - if policy_action in self._htmlInjection["action"]: + if policy_action in self._htmlInjection: # Return input for those policies which are calling actions # having value as prebody or postbody Since they belong to # html injection family - logging.error( - "Conversion of HTMLInjection feature reated command [{}]" - "not supported in this tool.".format(str(original_cmd).strip())) - self._htmlInjection["policy"].append(policyName) - return [original_cmd] - - if policy_action in self._forward["action"]: - logging.error( - "Conversion of FORWARD action type related command [{}]" - "not supported in this tool.".format(str(original_cmd).strip())) - self._forward["policy"].append(policyName) - return [original_cmd] - + return self.return_original_input(original_cmd, pol_obj) for dict_key, dict_value in self._actionTypeName.items(): """ Extract key and value from stored _actionTypeName dictionary through action convertion """ @@ -672,10 +706,27 @@ def convert_filter_policy(self, policy_parse_tree): elif (dict_key == "forward"): """ If input policy calls the action which points to the action for FORWARD """ - logging.error( - "Conversion of FORWARD action type command [{}]" - "not supported in this tool.".format(str(original_cmd).strip())) - return [original_cmd] + # TODO - This should be uncommented at the time of + # transformation for FORWARD actionType. + """ + converted_pol_cmd = CLICommand("add", "cs", "policy") + policy_name = CLIPositionalParameter(policyName) + converted_pol_cmd.add_positional(policy_name) + rule = CLIKeywordParameter(CLIKeywordName("rule")) + rule.add_value(advanced_expr) + converted_pol_cmd.add_keyword(rule) + action_key = CLIKeywordParameter(CLIKeywordName("action")) + action_key.add_value(action_name) + converted_pol_cmd.add_keyword(action_key) + """ + # TODO - put it outside at the time of transformation for + # FORWARD actionType and return converted output. + + # To store policy name and tuple of reqAction key name and + # original module + return self.return_original_input(original_cmd, pol_obj) + else: + return self.return_original_input(original_cmd, pol_obj) # Changing the module name to converted module name pol_obj.module = self.__class__.__name__ @@ -717,6 +768,16 @@ def new_policy(self, policy_parse_tree, policyName): converted_pol_cmd.set_upgraded() return converted_pol_cmd, policy_action_key, policy_action + def return_original_input(self, original_cmd, pol_obj): + """ Return original input """ + logging.error( + "Conversion of [{}] not supported in this tool. : [{}]" + "".format(str(original_cmd).strip(), str(original_cmd).strip())) + # Setting policy type to advanced to avoid conversion + # during bind command + pol_obj.policy_type = "advanced" + return [original_cmd] + @common.register_for_bind(["LB", "ContentSwitching", "CacheRedirection"]) def convert_filter_vserver_bindings( self, bind_parse_tree, policy_name, priority_arg, goto_arg): @@ -734,19 +795,6 @@ def convert_filter_vserver_bindings( if policy_type == "advanced": # Return same if policy_type is marked advanced return [bind_parse_tree] - - if policy_name in self._forward["policy"]: - logging.error( - "Conversion of FORWARD action type related command [{}]" - "not supported in this tool.".format(str(bind_parse_tree).strip())) - return [bind_parse_tree] - - if policy_name in self._htmlInjection["policy"]: - logging.error( - "Conversion of HTMLInjection feature related command [{}]" - "not supported in this tool.".format(str(bind_parse_tree).strip())) - return [bind_parse_tree] - vs_name = bind_parse_tree.positional_value(0).value.lower() if cli_cmds.vserver_protocol_dict[vs_name] not in ("HTTP", "SSL"): logging.error("Filter policy doesn't work with the non-http protocol" @@ -754,7 +802,7 @@ def convert_filter_vserver_bindings( " policy to the non-http vserver, then either the" " config will fail or the functionality will change," " so please review and remove such config" - " command [{}].".format(str(bind_parse_tree).strip())) + " command : [{}]".format(str(bind_parse_tree).strip())) return ['#' + str(bind_parse_tree)] flow_type = ("RESPONSE" if (self._converted_pol_param[ policy_name][0] == "resAction") else "REQUEST") @@ -795,24 +843,11 @@ def convert_filter_global_bindings(self, bind_parse_tree): " with the advanced configuration, so if we convert this" " config then functionality will change. If command is" " required please take a backup because comments will" - " not be saved in ns.conf after triggering 'save ns config': {}"). + " not be saved in ns.conf after triggering 'save ns config' : [{}]"). format(str(bind_parse_tree).strip()) ) return ["#" + str(bind_parse_tree)] policy_name = bind_parse_tree.positional_value(0).value - - if policy_name in self._forward["policy"]: - logging.error( - "Conversion of FORWARD action type related command [{}]" - "not supported in this tool.".format(str(bind_parse_tree).strip())) - return [bind_parse_tree] - - if policy_name in self._htmlInjection["policy"]: - logging.error( - "Conversion of HTMLInjection feature related command [{}]" - "not supported in this tool.".format(str(bind_parse_tree).strip())) - return [bind_parse_tree] - policy_type = common.pols_binds.policies[policy_name].policy_type if policy_type == "advanced": # Return input if policy_type is marked with "advanced" @@ -843,19 +878,6 @@ def convert_filter_global_bindings(self, bind_parse_tree): self._bind_tree_rw.append(bind_parse_tree) return [] - @common.register_for_cmd("add", "filter", "htmlinjectionvariable") - @common.register_for_cmd("set", "filter", "htmlinjectionvariable") - @common.register_for_cmd("set", "filter", "htmlinjectionparameter") - @common.register_for_cmd("set", "filter", "prebodyInjection") - @common.register_for_cmd("set", "filter", "postbodyInjection") - def convert_filter_htmlinjection_command(self, commandParseTree): - """ - Handling Filter HTMLInjection command - """ - logging.error("Conversion of HTMLInjection feature" - " related command [{}] is not supported".format(str(commandParseTree).strip())) - return [commandParseTree] - @common.register_for_final_call def get_converted_cmds(self): """ @@ -961,7 +983,7 @@ def return_bind_cmd_error(self, cmd): logging.error("In ns.conf, existing advanced feature policies's bind commands have" " gotoPriorityExpression as END/USE_INVOCATION_RESULT for HTTP/S." " Priorities and gotoPriorityExpression will need to" - " be added modified/added manually in [{}].".format(str(cmd).strip())) + " be added modified/added manually. : [{}]".format(str(cmd).strip())) bind_cmd = '#' + str(cmd) return bind_cmd @@ -1046,7 +1068,7 @@ def add_policy_invoke_policylabel(self, label_name, vserver_name, the policylabel label_name - rewrite policy label name vserver_name - vserver name in which filter policy is bound - vserver_group - vserver group: lb, cs or cr + vserver_group - vserver group: lb, cs or cr is_req_flow_type - True if binding is for request side, otherwise False """ diff --git a/nspepi/nspepi2/convert_lb_cmd.py b/nspepi/nspepi2/convert_lb_cmd.py index 927c18e..af88c97 100644 --- a/nspepi/nspepi2/convert_lb_cmd.py +++ b/nspepi/nspepi2/convert_lb_cmd.py @@ -128,7 +128,7 @@ def convert_lb_rule(self, add_lbvserver_parse_tree): # CONTENTS exists but not a simple expression. # Throw error and don't convert. logging.error(("-rule in the following command has to be " - "converted manually: {}").format( + "converted manually : [{}]").format( str(add_lbvserver_parse_tree).strip())) return [add_lbvserver_parse_tree] @@ -169,10 +169,10 @@ def convert_lb_rule(self, add_lbvserver_parse_tree): "format. This will result in functionality " "change when rule is used for persistenceType" " or lbMethod. To aviod the functionality " - "change, {} command is modified by removing " - "the following keywords: {}.").format( - str(original_tree).strip(), - ", ".join(removed_keywords))) + "change, command is modified by removing " + "the following keywords : {} : [{}]").format( + ", ".join(removed_keywords), + str(original_tree).strip())) return [add_lbvserver_parse_tree] def search_pattern(self, rule, index, found_expr_list): diff --git a/nspepi/nspepi2/nspepi_common.py b/nspepi/nspepi2/nspepi_common.py index ac48618..74850dc 100644 --- a/nspepi/nspepi2/nspepi_common.py +++ b/nspepi/nspepi2/nspepi_common.py @@ -21,8 +21,7 @@ import nspepi_parse_tree -currentfile = os.path.abspath(inspect.getfile(inspect.currentframe())) -currentdir = os.path.dirname(currentfile) +currentdir = os.path.dirname(os.path.abspath(__file__)) parentdir = os.path.dirname(currentdir) sys.path.insert(0, parentdir) @@ -935,9 +934,9 @@ def do_priority_analysis_for_all_users_groups(self, user_list, group_list): for v in weights.values(): same_weight_group_set = set([o.entity_name for o in v]) if len(same_weight_group_set) > 1: - logging.error("Groups: {} having the same weight and bindings" + logging.error("Groups having the same weight and bindings" " have no defined ordering in Advanced Policy" - " evaluation.".format( + " evaluation. : {}".format( ", ".join(sorted(same_weight_group_set)))) res.update(v) logging.debug("do_priority_analysis_for_all_users_groups(): ") diff --git a/nspepi/nspepi2/nspepi_helper b/nspepi/nspepi2/nspepi_helper index 41b84e7..d373292 100755 --- a/nspepi/nspepi2/nspepi_helper +++ b/nspepi/nspepi2/nspepi_helper @@ -158,11 +158,11 @@ my %EXPR_LIST=( # List of classic expressions that are not convertable my @CSEC_BLOCKED_LIST=( - 'CLIENT\.APPLICATION', - 'CLIENT\.FILE', - 'CLIENT\.OS', - 'CLIENT\.REG', - 'CLIENT\.SVC', + 'CLIENT.APPLICATION', + 'CLIENT.FILE', + 'CLIENT.OS', + 'CLIENT.REG', + 'CLIENT.SVC', 'f_5_TrendMicroOfficeScan_7_3', 'f_5_sygate_5_6', 'f_5_zonealarm_6_5', @@ -180,15 +180,15 @@ my @CSEC_BLOCKED_LIST=( ); my @FILE_BLOCKED_LIST=( - 'FS\.COMMAND', - 'FS\.DIR', - 'FS\.DOMAIN', - 'FS\.FILE', - 'FS\.PATH', - 'FS\.SERVER', - 'FS\.SERVERIP', - 'FS\.SERVICE', - 'FS\.USER', + 'FS.COMMAND', + 'FS.DIR', + 'FS.DOMAIN', + 'FS.FILE', + 'FS.PATH', + 'FS.SERVER', + 'FS.SERVERIP', + 'FS.SERVICE', + 'FS.USER', ); my @BLOCKED_LIST=( @@ -305,7 +305,7 @@ sub convertExpression } # Check for client security expression expressions foreach (@CSEC_BLOCKED_LIST) { - if ($expression =~ /\b$_/i) { + if ($expression =~ /$_/i) { print_it($LFILE,"$line\n"); err_handle $ERR_CSEC_BLOCKED_MSG; return; @@ -313,7 +313,7 @@ sub convertExpression } # Check for file system based expression expressions foreach (@FILE_BLOCKED_LIST) { - if ($expression =~ /\b$_/i) { + if ($expression =~ /$_/i) { print_it($LFILE,"$line\n"); err_handle $ERR_FILE_BLOCKED_MSG; return; @@ -321,7 +321,7 @@ sub convertExpression } # Check for blocked expressions foreach (@BLOCKED_LIST) { - if ($expression =~ /\b$_/i) { + if ($expression =~ /$_/i) { my $err_msg = "Conversion of $_ expression is not supported"; print_it($LFILE,"$line\n"); err_handle $err_msg; @@ -814,38 +814,12 @@ sub identifyExpressions my $OPERATOR=$1; $expr_params=$2; my $ARG = extractArgument(); - if ($ARG =~ /^\S{3}\, (\d{1,2}) (\S{3}) (\d{4}) (\d{2}):(\d{2}):(\d{2}) (\S{3})$/) { - # Handling RFC822 format: Tue, 05 Nov 1994 08:12:31 GMT + if ($ARG =~ /^\S{3}\, (\d{2}) (\S{3}) (\d{4}) (\d{2}):(\d{2}):(\d{2}) (\S{3})$/) { $ARG = "$7 $3 $2 $1 $4h $5m $6s"; parseNumericOperator($OPERATOR,$ARG); return; - } elsif ($ARG =~ /^\S{3}\, (\d{1,2})-(\S{3})-(\d{4}) (\d{2}):(\d{2}):(\d{2}) (\S{3})$/) { - # Handling cookie format: Tue, 05-Nov-1994 08:12:31 GMT - $ARG = "$7 $3 $2 $1 $4h $5m $6s"; - parseNumericOperator($OPERATOR,$ARG); - return; - } elsif ($ARG =~ /^\S{3} (\S{3}) (\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4}) (\S{3})$/) { - # Handling asctime format: Tue Nov 4 08:12:31 1994 GMT - $ARG = "$7 $6 $1 $2 $3h $4m $5s"; - parseNumericOperator($OPERATOR,$ARG); - return; - } elsif ($ARG =~ /^\S{3} (\S{3}) (\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/) { - # Handling asctime format: Tue Nov 4 08:12:31 1994 GMT - $ARG = "GMT $6 $1 $2 $3h $4m $5s"; - parseNumericOperator($OPERATOR,$ARG); - return; - } elsif ($ARG =~ /^\S{5,8}\, (\d{1,2})-(\S{3})-(\d{2}) (\d{2}):(\d{2}):(\d{2}) (\S{3})$/) { - # Handling RFC850 format: Tuesday, 05-Nov-94 08:12:31 GMT - my $year = int($3); - if ($year > 70) { - $year = 1900 + $year; - } else { - $year = 2000 + $year; - } - $ARG = "GMT $year $2 $1 $5h $5m $6s"; - parseNumericOperator($OPERATOR,$ARG); - return; - } else { + } + else { err_handle $ERR_OPERATOR_MSG; return; } diff --git a/nspepi/nspepi2/nspepi_main.py b/nspepi/nspepi2/nspepi_main.py index 6f3cdd6..09331da 100755 --- a/nspepi/nspepi2/nspepi_main.py +++ b/nspepi/nspepi2/nspepi_main.py @@ -38,7 +38,6 @@ file_log_handler = None console_log_handler = None debug_log_handler = None -error_log_handler = None def create_file_log_handler(file_name, log_level): """ @@ -62,13 +61,12 @@ def create_file_log_handler(file_name, log_level): file_handler.setFormatter(fh_format) return file_handler -def setup_logging(log_file_name, file_log_level, error_file_name, debug_file_name, console_output_needed): +def setup_logging(log_file_name, file_log_level, debug_file_name, console_output_needed): """ Sets up logging for the program. Args: log_file_name: The name of the log file - error_file_name: The name of the error log file file_log_level: The level of logs to put in log_file_name file debug_file_name: The name of the debug log file console_output_needed: True if logs need to be seen on console @@ -76,22 +74,17 @@ def setup_logging(log_file_name, file_log_level, error_file_name, debug_file_nam global file_log_handler global console_log_handler global debug_log_handler - global error_log_handler # create logger logger = logging.getLogger() logger.setLevel(logging.DEBUG) # if called multiple times, remove existing handlers logger.removeHandler(file_log_handler) logger.removeHandler(console_log_handler) - logger.removeHandler(console_log_handler) - logger.removeHandler(error_log_handler) + logger.removeHandler(debug_log_handler) # create file handler file_log_handler = create_file_log_handler(log_file_name, file_log_level) # add the handlers to the logger logger.addHandler(file_log_handler) - if error_file_name: - error_log_handler = create_file_log_handler(error_file_name, logging.ERROR) - logger.addHandler(error_log_handler) if debug_file_name: debug_log_handler = create_file_log_handler(debug_file_name, logging.DEBUG) logger.addHandler(debug_log_handler) @@ -226,10 +219,9 @@ def main(): arg_parser.add_argument( '-V', '--version', action='version', version='%(prog)s {}'.format(__version__)) - arg_parser.add_argument('-E', '--newErrorFileName', action="store_true", - help=argparse.SUPPRESS) try: args = arg_parser.parse_args() + print(args) except IOError as e: exit(str(e)) # obtain logging parameters and setup logging @@ -239,11 +231,10 @@ def main(): conf_file_path = os.path.dirname(args.infile) conf_file_name = os.path.basename(args.infile) log_file_name = os.path.join(conf_file_path, 'warn_' + conf_file_name) - err_file_name = os.path.join(conf_file_path, 'error_' + conf_file_name) if args.newErrorFileName else None debug_file_name = os.path.join(conf_file_path, 'debug_' + conf_file_name) if args.debug else None # For -v and -e options, logs will be seen on console and warn file. # For other options, logs will only be in warn file and not on console. - setup_logging(log_file_name, logging.WARNING, err_file_name, debug_file_name, args.verbose or args.expression is not None) + setup_logging(log_file_name, logging.WARNING, debug_file_name, args.verbose or args.expression is not None) convert_cli_commands.convert_cli_init() # convert classic policy expression if given as an argument if args.expression is not None: @@ -271,9 +262,6 @@ def main(): with open(args.infile, 'r') as infile: with open(new_path, 'w') as outfile: convert_config_file(infile, outfile, args.verbose) - if err_file_name: - if os.path.getsize(err_file_name) == 0: - os.remove(err_file_name) if os.path.getsize(log_file_name) == 0: error_warn_msg = ".\nConversion is successful, no error or warning is generated." os.remove(log_file_name) @@ -284,7 +272,6 @@ def main(): + conf_file_name + error_warn_msg) if args.debug: print("Check debug_" + conf_file_name + " file for debug logs.") - print("\nUse nspepi tool available at https://github.com/citrix/ADC-scripts/tree/master/nspepi for the most complete and up-to-date version.") if __name__ == '__main__': diff --git a/nspepi/nspepi2/nspepi_parse_tree.py b/nspepi/nspepi2/nspepi_parse_tree.py index 4591242..8ce3c69 100644 --- a/nspepi/nspepi2/nspepi_parse_tree.py +++ b/nspepi/nspepi2/nspepi_parse_tree.py @@ -110,7 +110,6 @@ def __init__(self, op, group, ot): policy is advanced but need to set upgrade flag after conversion. adv_upgraded should be used in such cases instead of upgraded. invalid - Indicates whether the command is invalid in 13.1 release. - has_csec_expr - Indicates that command has client security expression original_line - the text of the line that was parsed lineno - the line number (starting with 1) that the command occurs on op - the op-code for the command @@ -120,7 +119,6 @@ def __init__(self, op, group, ot): self._upgraded = True self._adv_upgraded = True self._invalid = False - self._has_csec_expr = False self._original_line = "" self._lineno = 0 self._op = op @@ -211,17 +209,6 @@ def set_invalid(self): def invalid(self): return self._invalid - def set_has_csec_expr(self): - """ - Flags that this command has - Client security expression. - """ - self._has_csec_expr = True - - @property - def has_csec_expr(self): - return self._has_csec_expr - def add_positional(self, positional_param): """ Adds a positional parameter at the end of the parameters. positional_param - the node containing the value of the parameter diff --git a/nspepi/nspepi2/pi_lex.py b/nspepi/nspepi2/pi_lex.py index 0875a7f..367f9cf 100644 --- a/nspepi/nspepi2/pi_lex.py +++ b/nspepi/nspepi2/pi_lex.py @@ -58,7 +58,7 @@ def get_pi_string(expr): hex_digits = int(hex_digits, 16) if hex_digits > 127: logging.error("Invalid hex value is used. Maximum " - "hex value allowed is 7f.") + "hex value allowed is 7f. : [{}]".format(expr)) return None value += chr(hex_digits) else: @@ -73,7 +73,7 @@ def get_pi_string(expr): oct_digits = int(oct_digits, 8) if oct_digits > 127: logging.error("Invalid octal value is used. Maximum " - "octal value allowed is 177.") + "octal value allowed is 177. : [{}]".format(expr)) return None value += chr(oct_digits) else: From 5ee1b0028ebdae9d6e82e34fc4c43d98cd136ab2 Mon Sep 17 00:00:00 2001 From: Vishal John Varghese <72516017+VishalJohnVarghese1996@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:03:03 +0000 Subject: [PATCH 2/3] Code corrections --- nspepi/nspepi2/check_classic_configs.py | 15 +- nspepi/nspepi2/convert_classic_expr.py | 10 +- nspepi/nspepi2/convert_cli_commands.py | 241 ++++++++++++++++------- nspepi/nspepi2/convert_cmp_cmd.py | 17 ++ nspepi/nspepi2/convert_filter_command.py | 203 +++++++++---------- nspepi/nspepi2/nspepi_helper | 66 +++++-- nspepi/nspepi2/nspepi_main.py | 19 +- nspepi/nspepi2/nspepi_parse_tree.py | 13 ++ 8 files changed, 366 insertions(+), 218 deletions(-) diff --git a/nspepi/nspepi2/check_classic_configs.py b/nspepi/nspepi2/check_classic_configs.py index 02c3f69..e97ec33 100644 --- a/nspepi/nspepi2/check_classic_configs.py +++ b/nspepi/nspepi2/check_classic_configs.py @@ -979,7 +979,7 @@ def check_vpn_url(self, commandParseTree): """ if commandParseTree.keyword_exists('ssotype'): sso_type = commandParseTree.keyword_value("ssotype")[0].value.lower() - if sso_type is "selfauth": + if sso_type == "selfauth": logging.warning("Selfauth type has been deprecated" " in command : [{}]".format(str(commandParseTree).strip())) return [] @@ -992,8 +992,8 @@ def check_vpn_portaltheme(self, commandParseTree): """ if commandParseTree.keyword_exists('basetheme'): base_theme = commandParseTree.keyword_value("basetheme")[0].value - if base_theme is "Default" or base_theme is "X1" \ - or base_theme is "Greenbubble": + if base_theme == "Default" or base_theme == "X1" \ + or base_theme == "Greenbubble": logging.warning(("Default, GreenBubble and X1 themes" " have been deprecated in the command," " please use RfWebUI theme or RfWebUI based custom theme : [{}]") @@ -1009,8 +1009,8 @@ def check_vpn_commands(self, commandParseTree): """ if commandParseTree.keyword_exists('portaltheme'): base_theme = commandParseTree.keyword_value("portaltheme")[0].value - if base_theme is "Default" or base_theme is "X1" \ - or base_theme is "Greenbubble": + if base_theme == "Default" or base_theme == "X1" \ + or base_theme == "Greenbubble": logging.warning(("Default, GreenBubble and X1 themes" " have been deprecated in the command," " please use RfWebUI theme or RfWebUI based custom theme : [{}]") @@ -1024,12 +1024,12 @@ def check_dns_action(self, commandParseTree): deprecated. """ action_type = commandParseTree.positional_value(1).value.lower() - if action_type is "rewrite_response": + if action_type == "rewrite_response": logging.warning(("Rewrite_Response action type is deprecated in" " the command, please use the replace_dns_answer_section" " action type under Rewrite feature. : [{}]") .format(str(commandParseTree).strip())) - elif action_type is "drop": + elif action_type == "drop": logging.warning(("Drop action type is deprecated in" " the command, please use the Drop" " action type under Responder feature. : [{}]") @@ -1089,6 +1089,7 @@ def check_deprecated_pacingcommands(self, commandParseTree): @common.register_for_cmd("bind", "lsn", "client") @common.register_for_cmd("bind", "lsn", "group") @common.register_for_cmd("bind", "lsn", "pool") + @common.register_for_cmd("set", "lsn", "parameter") def check_lsn_commands(self, commandParseTree): """ Check the Authentication commands which have been deprecated diff --git a/nspepi/nspepi2/convert_classic_expr.py b/nspepi/nspepi2/convert_classic_expr.py index eb11aee..1c48e65 100644 --- a/nspepi/nspepi2/convert_classic_expr.py +++ b/nspepi/nspepi2/convert_classic_expr.py @@ -37,7 +37,7 @@ r'(S\.CACHE_CONTROL)|(S\.TXID)|(S\.MEDIA))\b', re.IGNORECASE) -def convert_classic_expr(classic_expr): +def convert_classic_expr(classic_expr, ignore_csec_expr = False): tree_obj = CLIParseTreeNode() info_msg = 'INFO: Expression is not converted' + \ ' - most likely it is a valid advanced expression' @@ -60,6 +60,14 @@ def convert_classic_expr(classic_expr): if nspepi_tool_output.startswith('ERROR:'): """Handles the error returned by old nspepi tool""" + csec_error_msg = 'Conversion of client ' + \ + 'security expression is not supported' + if (ignore_csec_expr and (csec_error_msg in \ + nspepi_tool_output)): + return "Ignoring Client security Expression" + else: + logging.error(nspepi_tool_output) + return None logging.error(nspepi_tool_output) return None elif nspepi_tool_output.endswith(info_msg): diff --git a/nspepi/nspepi2/convert_cli_commands.py b/nspepi/nspepi2/convert_cli_commands.py index f8f7bbb..070056e 100644 --- a/nspepi/nspepi2/convert_cli_commands.py +++ b/nspepi/nspepi2/convert_cli_commands.py @@ -96,9 +96,10 @@ def get_classic_expr_list(expr): token_value = str(next_token) token_value_len = len(token_value) is_classic_expr = False - if token_value in NamedExpression.built_in_named_expr: + lower_token_value = token_value.lower() + if lower_token_value in NamedExpression.built_in_named_expr: # Checking for built-in classic Named expression. - adv_expr_name = NamedExpression.built_in_named_expr[token_value] + adv_expr_name = NamedExpression.built_in_named_expr[lower_token_value] lower_adv_expr_name = adv_expr_name.lower() if lower_adv_expr_name in policy_entities_names: is_classic_expr = True @@ -182,7 +183,7 @@ def replace_named_expr(rule_expr): return converted_expr @staticmethod - def convert_pos_expr(commandParseTree, pos): + def convert_pos_expr(commandParseTree, pos, ignore_csec_expr = False): """ Convert the expression present at a given position commandParseTree - the parse tree to modify @@ -199,7 +200,7 @@ def convert_pos_expr(commandParseTree, pos): str(commandParseTree).strp() + ']') return commandParseTree - converted_expr = convert_classic_expr.convert_classic_expr(rule_expr) + converted_expr = convert_classic_expr.convert_classic_expr(rule_expr, ignore_csec_expr) if converted_expr is None: logging.error('Error in converting command : [' + str(commandParseTree).strip() + ']') @@ -1742,18 +1743,6 @@ def convert_policy(self, commandParseTree): expr_rule = commandParseTree.positional_value(1).value lower_expr_name = expr_name.lower() named_expr[lower_expr_name] = expr_rule - if (((lower_expr_name in reserved_word_list) or - (re.match('^[a-z_][a-z0-9_]*$', lower_expr_name) is None) or - (lower_expr_name in policy_entities_names))): - logging.error(("Expression name {} is invalid for advanced " - "expression: names must begin with an ASCII " - "alphabetic character or underscore and must " - "contain only ASCII alphanumerics or underscores" - " and shouldn't be name of another policy entity" - "; words reserved for policy use may not be used;" - " underscores will be substituted for any invalid" - " characters in corresponding advanced name : [{}]") - .format(expr_name, commandParseTree)) if commandParseTree.keyword_exists('clientSecurityMessage'): NamedExpression.csec_expr_list[lower_expr_name] = {} @@ -1769,6 +1758,21 @@ def convert_policy(self, commandParseTree): NamedExpression.csec_expr_list[lower_expr_name]["error_displayed"] = False NamedExpression.register_classic_entity_name(commandParseTree) return [commandParseTree] + + if ((lower_expr_name in reserved_word_list) or + (re.match('^[a-z_][a-z0-9_]*$', lower_expr_name) is None)): + logging.error(("Expression name {} is invalid for advanced " + "expression: names must begin with an ASCII " + "alphabetic character or underscore and must " + "contain only ASCII alphanumerics or underscores" + " and shouldn't be name of another policy entity" + "; words reserved for policy use may not be used;" + " underscores will be substituted for any invalid" + " characters in corresponding advanced name") + .format(expr_name)) + + if (lower_expr_name in policy_entities_names): + logging.error("Name {} is already in use".format(expr_name)) original_tree = copy.deepcopy(commandParseTree) """Convert classic named expression to advanced @@ -1778,7 +1782,7 @@ def convert_policy(self, commandParseTree): add policy expression """ commandParseTree = NamedExpression \ - .convert_pos_expr(commandParseTree, 1) + .convert_pos_expr(commandParseTree, 1, True) if commandParseTree.adv_upgraded: tree_list = [commandParseTree] @@ -1806,6 +1810,11 @@ def convert_policy(self, commandParseTree): tree_list.append(commandParseTree) NamedExpression.register_policy_entity_name(commandParseTree) NamedExpression.register_classic_entity_name(original_tree) + elif commandParseTree.has_csec_expr: + NamedExpression.csec_expr_list[lower_expr_name] = {} + NamedExpression.csec_expr_list[lower_expr_name]["tree"] = original_tree + NamedExpression.csec_expr_list[lower_expr_name]["error_displayed"] = False + NamedExpression.register_classic_entity_name(original_tree) else: NamedExpression.register_policy_entity_name(original_tree) return tree_list @@ -2127,6 +2136,35 @@ def convert_cs_bind_command(self, commandParseTree): # CS policies without action issue. if cs_vserver_name not in self._cs_policy_binding_info: self._cs_policy_binding_info[cs_vserver_name] = [] + + if commandParseTree.keyword_exists("targetLBVserver"): + vserver_name = commandParseTree.keyword_value( + "targetLBVserver")[0].value + else: + vserver_name = commandParseTree.positional_value(1).value + + if "vserver_bind_info" not in self._policy_bind_info[policy_name]: + vserver_bind_info = {} + vserver_bind_info["multiple_bindings"] = False + vserver_bind_info["multiple_target_vservers"] = False + vserver_bind_info["diff_case_search"] = False + ci_search = cs_vserver_name in self._cs_vserver_info_ci + vserver_bind_info["case_insensitive"] = ci_search + vserver_bind_info["target_vservers"] = vserver_name + self._policy_bind_info[policy_name]["vserver_bind_info"] = \ + vserver_bind_info + else: + vserver_bind_info = self._policy_bind_info[policy_name]["vserver_bind_info"] + vserver_bind_info["multiple_bindings"] = True + + if vserver_bind_info["target_vservers"] != vserver_name: + vserver_bind_info["multiple_target_vservers"] = True + + if vserver_bind_info["diff_case_search"] is False: + ci_search = cs_vserver_name in self._cs_vserver_info_ci + if vserver_bind_info["case_insensitive"] != ci_search: + vserver_bind_info["diff_case_search"] = True + self._cs_policy_binding_info[cs_vserver_name].append( commandParseTree) return [] @@ -2164,6 +2202,11 @@ def convert_cs_policy_entity_bind( It will be either positional index or keyword name. Returns converted list of parse trees. """ + # If no classic CS policy is configured, then no need + # to process the bindings. + if not self._classic_policy_exists: + return [commandParseTree] + policy_type = self.__class__.__name__ if policy_name in self._policy_bind_info: cs_vserver_name = commandParseTree.positional_value(0).value @@ -2171,6 +2214,23 @@ def convert_cs_policy_entity_bind( # CS policies without action issue. if cs_vserver_name not in self._cs_policy_binding_info: self._cs_policy_binding_info[cs_vserver_name] = [] + + vserver_name = commandParseTree.keyword_value("policyName")[1].value + if "vserver_bind_info" not in self._policy_bind_info[policy_name]: + vserver_bind_info = {} + vserver_bind_info["multiple_bindings"] = False + vserver_bind_info["multiple_target_vservers"] = False + vserver_bind_info["diff_case_search"] = False + vserver_bind_info["target_vservers"] = vserver_name + self._policy_bind_info[policy_name]["vserver_bind_info"] = \ + vserver_bind_info + else: + vserver_bind_info = self._policy_bind_info[policy_name]["vserver_bind_info"] + vserver_bind_info["multiple_bindings"] = True + + if vserver_bind_info["target_vservers"] != vserver_name: + vserver_bind_info["multiple_target_vservers"] = True + self._cs_policy_binding_info[cs_vserver_name].append( commandParseTree) return [] @@ -2231,22 +2291,28 @@ def get_converted_cmds(self): "bind cr vserver"): vserver_name = bind_tree.keyword_value( "policyName")[1].value - new_policy_name = "nspepi_adv_" + policy_name + '_' + \ - vserver_name + set_ci_rule = False - # If CS vserver is configured with caseSensitive - # parameter set to OFF and policy is configured - # with URL parameter, then add '_ci' suffix in the - # new policy name and rule of that policy should - # do case-insensitive search. + if (is_cs_vserver and (cs_cr_vserver_name in self._cs_vserver_info_ci) and (policy_name in self._policy_url_info)): - new_policy_name += '_ci' set_ci_rule = True - truncated_pol_name = new_policy_name - action_name = "nspepi_adv_cs_act_" + vserver_name - truncated_act_name = action_name - if new_policy_name not in newly_added_policy_names: + + vserver_bind_info = self._policy_bind_info[policy_name]["vserver_bind_info"] + need_new_policy = False + need_new_action = False + + if vserver_bind_info["multiple_bindings"]: + need_new_action = True + if vserver_bind_info["multiple_target_vservers"]: + need_new_policy = True + elif vserver_bind_info["diff_case_search"]: + if set_ci_rule: + need_new_policy = True + + if need_new_action: + action_name = "nspepi_adv_cs_act_" + vserver_name + truncated_act_name = action_name if action_name not in newly_added_action_names: # Create new action action_tree = CLICommand("add", "cs", "action") @@ -2254,8 +2320,8 @@ def get_converted_cmds(self): if len(action_name) > 127: truncated_act_name, overlength_action_counter = \ self.truncate_name(action_name, - overlength_action_names, - overlength_action_counter) + overlength_action_names, + overlength_action_counter) pos = CLIPositionalParameter(truncated_act_name) action_tree.add_positional(pos) vserver_key = CLIKeywordParameter(CLIKeywordName( @@ -2270,53 +2336,78 @@ def get_converted_cmds(self): if action_name in overlength_action_names: truncated_act_name = overlength_action_names[ action_name] - # Create new policy with [policy_name]_[vserver_name] as - # as name and bind to newly created action - # cs_act_[vserver_name] - new_policy = copy.deepcopy(policy_tree) - # Max length of policy name allowed is 127. + if need_new_policy: + new_policy_name = "nspepi_adv_" + policy_name + '_' + \ + vserver_name + # If CS vserver is configured with caseSensitive + # parameter set to OFF and policy is configured + # with URL parameter, then add '_ci' suffix in the + # new policy name and rule of that policy should + # do case-insensitive search. + if set_ci_rule: + new_policy_name += '_ci' truncated_pol_name = new_policy_name - if len(new_policy_name) > 127: - truncated_pol_name, overlength_policy_counter = \ - self.truncate_name(new_policy_name, - overlength_policy_names, - overlength_policy_counter) - self.update_tree_arg(new_policy, 0, truncated_pol_name) + if new_policy_name not in newly_added_policy_names: + # Create new policy with [policy_name]_[vserver_name] as + # as name and bind to newly created action + # cs_act_[vserver_name] + new_policy = copy.deepcopy(policy_tree) + # Max length of policy name allowed is 127. + truncated_pol_name = new_policy_name + if len(new_policy_name) > 127: + truncated_pol_name, overlength_policy_counter = \ + self.truncate_name(new_policy_name, + overlength_policy_names, + overlength_policy_counter) + self.update_tree_arg(new_policy, 0, truncated_pol_name) + if set_ci_rule: + rule_node = new_policy.keyword_value('rule') + rule_node[0].set_value(self._policy_url_info[policy_name], True) + action_key = CLIKeywordParameter(CLIKeywordName("action")) + action_key.add_value(truncated_act_name) + new_policy.add_keyword(action_key) + # Remove the devno so that multiple lines + # don't have the same devno. + if new_policy.keyword_exists('devno'): + new_policy.remove_keyword('devno') + newly_added_policy_names.append(new_policy_name) + pol_list.append(new_policy) + else: + # When policy is already added. + # Get truncated policy name if truncated. + if new_policy_name in overlength_policy_names: + truncated_pol_name = overlength_policy_names[ + new_policy_name] + # Remove targetLBVserver from bind command and update policy + # name to newly added policy name. + self.update_tree_arg(bind_tree, "policyName", + truncated_pol_name) + else: if set_ci_rule: - rule_node = new_policy.keyword_value('rule') + rule_node = policy_tree.keyword_value('rule') rule_node[0].set_value(self._policy_url_info[policy_name], True) - action_key = CLIKeywordParameter(CLIKeywordName("action")) - action_key.add_value(truncated_act_name) - new_policy.add_keyword(action_key) - # Remove the devno so that multiple lines - # don't have the same devno. - if new_policy.keyword_exists('devno'): - new_policy.remove_keyword('devno') - newly_added_policy_names.append(new_policy_name) - pol_list.append(new_policy) - else: - # When policy is already added. - # Get truncated policy name if truncated. - if new_policy_name in overlength_policy_names: - truncated_pol_name = overlength_policy_names[ - new_policy_name] - # Remove targetLBVserver from bind command and update policy - # name to newly added policy name. - self.update_tree_arg(bind_tree, "policyName", - truncated_pol_name) - if ((' '.join(bind_tree.get_command_type())).lower() == - "bind cs vserver"): - if bind_tree.keyword_exists("targetLBVserver"): - bind_tree.remove_keyword("targetLBVserver") - else: - bind_tree.remove_positional(1) - elif ((' '.join(bind_tree.get_command_type())).lower() == - "bind cr vserver"): - # In bind cr vserver command, vserver name exists in - # following way: - # bind cr vserver -policyName - # - bind_tree.remove_keyword_value("policyName", 1) + if need_new_action: + action_key = CLIKeywordParameter(CLIKeywordName("action")) + action_key.add_value(truncated_act_name) + policy_tree.add_keyword(action_key) + + if policy_tree not in pol_list: + pol_list.append(policy_tree) + + if need_new_action: + if ((' '.join(bind_tree.get_command_type())).lower() == + "bind cs vserver"): + if bind_tree.keyword_exists("targetLBVserver"): + bind_tree.remove_keyword("targetLBVserver") + else: + bind_tree.remove_positional(1) + elif ((' '.join(bind_tree.get_command_type())).lower() == + "bind cr vserver"): + # In bind cr vserver command, vserver name exists in + # following way: + # bind cr vserver -policyName + # + bind_tree.remove_keyword_value("policyName", 1) if cs_cr_vserver_name not in cs_cr_vserver_bindings: cs_cr_vserver_bindings[cs_cr_vserver_name] = [[], [], [], [], []] diff --git a/nspepi/nspepi2/convert_cmp_cmd.py b/nspepi/nspepi2/convert_cmp_cmd.py index 203f738..7760744 100644 --- a/nspepi/nspepi2/convert_cmp_cmd.py +++ b/nspepi/nspepi2/convert_cmp_cmd.py @@ -33,6 +33,14 @@ class CMP(cli_cmds.ConvertConfig): "ns_nocmp_xml_ie": "ns_adv_nocmp_xml_ie" } + builtin_adv_policies_bind_info = { + "ns_adv_nocmp_xml_ie": ["8700", "END"], + "ns_adv_nocmp_mozilla_47": ["8800", "END"], + "ns_adv_cmp_mscss": ["8900", "END"], + "ns_adv_cmp_msapp": ["9000", "END"], + "ns_adv_cmp_content_type": ["10000", "END"], + } + def __init__(self): """ Information about CMP commands. @@ -206,6 +214,15 @@ def convert_cmp_global_bind(self, bind_cmd_tree): return ["#" + str(bind_cmd_tree)] policy_name = bind_cmd_tree.positional_value(0).value + # Ignore the default advanced bindings + if policy_name in self.builtin_adv_policies_bind_info: + policy_info = self.builtin_adv_policies_bind_info[policy_name] + priority = bind_cmd_tree.keyword_value("priority")[0].value + next_prio_expr = bind_cmd_tree.keyword_value( + "gotoPriorityExpression")[0].value + if ((policy_info[0] == priority) and + (policy_info[1] == next_prio_expr)): + return [bind_cmd_tree] self.replace_builtin_policy(bind_cmd_tree, policy_name, 0) bind_point = "" self.update_bind_info(bind_cmd_tree, bind_point) diff --git a/nspepi/nspepi2/convert_filter_command.py b/nspepi/nspepi2/convert_filter_command.py index 106367d..d911417 100644 --- a/nspepi/nspepi2/convert_filter_command.py +++ b/nspepi/nspepi2/convert_filter_command.py @@ -191,17 +191,6 @@ bind vserver -policyName pol1 [-priority ]) -gotoPriorityExpression NEXT -TYPE REQUEST bind vserver -policyName pol2 [-priority ]) -gotoPriorityExpression NEXT -TYPE RESPONSE -# Remove this comment line at the time of transforming actionType FORWARD ----INPUT FORWARD ACTIONTYPE--- -add filter action act1 FORWARD serviceName -add filter policy pol1 -rule "ns_true" -reqAction act1 -bind filter global pol1 [-priority ]) -bind vserver -policyName pol1 [-priority ]) ----CONVERTED RESULT--- -add filter action act1 FORWARD serviceName -add filter policy pol1 -rule "ns_true" -reqAction act1 -bind filter global pol1 [-priority ]) -bind vserver -policyName pol1 [-priority ]) ''' import re @@ -254,7 +243,12 @@ def __init__(self): ("reset", ["reset"]), ("drop", ["drop"])]) self._converted_pol_param = OrderedDict() self._policy_command = [] - self._htmlInjection = [] + self._htmlInjection = OrderedDict() + self._htmlInjection["action"] = [] + self._htmlInjection["policy"] = [] + self._forward = OrderedDict() + self._forward["action"] = [] + self._forward["policy"] = [] self._bind_tree_rw = [] self._bind_tree_resp = [] self._policylabel_name = [] @@ -263,11 +257,7 @@ def __init__(self): self.overlength_policy_counter = 0 self.overlength_policylabel_names = {} self.overlength_policylabel_counter = 0 - ''' - # TODO - This should be uncommented at the time of - # transformation for FORWARD actionType. - self._vserverName_list = set([]) - ''' + @common.register_for_cmd("add", "filter", "action") def convert_filter_action(self, action_parse_tree): """ @@ -301,9 +291,10 @@ def convert_filter_action(self, action_parse_tree): # Store actionType and actionName actionName = original_cmd.positional_value( 0).value + lower_actionName = actionName.lower() if action_type not in self._actionTypeName: self._actionTypeName[action_type] = [] - self._actionTypeName[action_type].append(actionName) + self._actionTypeName[action_type].append(lower_actionName) if (action_type == "add"): """ @@ -360,13 +351,13 @@ def convert_filter_action(self, action_parse_tree): # rewrite_action_response: action which has HTTP.RES.XX # action_parse_tree: action which has HTTP.REQ.XX - # Save action name in a list which is used to - # identify an action command - if actionName not in self._action_command: - self._action_command[actionName] = [] rewrite_action_response = copy.deepcopy( action_parse_tree) if match_value.group(1) in Filter_variable: + # Save action name in a list which is used to + # identify an action command + if lower_actionName not in self._action_command: + self._action_command[lower_actionName] = [] # Add a new rewrite action of different name whose # stringBuildExpr should be expression of # RESPONSE side @@ -389,16 +380,23 @@ def convert_filter_action(self, action_parse_tree): action_parse_tree.set_upgraded() # Store actionName, and converted command - self._action_command[actionName].append( + self._action_command[lower_actionName].append( action_parse_tree) - self._action_command[actionName].append( + self._action_command[lower_actionName].append( rewrite_action_response) # Store actionType and actionName self._actionTypeName[action_type].append( rewrite_action_response.positional_value( - 0).value) + 0).value.lower()) return [] + else: + logging.error( + "Conversion of HTMLInjection variable in " + "command [{}] is not supported in this tool." + "".format(str(original_cmd).strip())) + return [action_parse_tree] + else: # Prebody/postbody value indicates that this config is # being used for HTMLinjection feature, and conversion @@ -406,10 +404,10 @@ def convert_filter_action(self, action_parse_tree): # the input command as the output. # Remove action name from stored dictionary. - self._actionTypeName[action_type].remove(actionName) + self._actionTypeName[action_type].remove(lower_actionName) # Store list of corresponding action names - self._htmlInjection.append(actionName) + self._htmlInjection["action"].append(actionName) action_parse_tree_list = [original_cmd] logging.error( "Conversion of [{}] not supported in this tool. : [{}]" @@ -441,8 +439,8 @@ def convert_filter_action(self, action_parse_tree): """ # Save action name in a list which is used to # identify an action command - if actionName not in self._action_command: - self._action_command[actionName] = [] + if lower_actionName not in self._action_command: + self._action_command[lower_actionName] = [] # A. Parse tree for advance command with responder feature responder_action = CLICommand("add", "responder", "action") action_name = CLIPositionalParameter(actionName) @@ -531,12 +529,12 @@ def convert_filter_action(self, action_parse_tree): rewrite_action.set_upgraded() # Store actionName, and converted command - self._action_command[actionName].append(responder_action) - self._action_command[actionName].append(rewrite_action) + self._action_command[lower_actionName].append(responder_action) + self._action_command[lower_actionName].append(rewrite_action) # Store actionType and actionName self._actionTypeName[action_type].append(str( - rewrite_action.positional_value(0).value)) + rewrite_action.positional_value(0).value.lower())) return [] elif (action_type == "drop") or (action_type == "reset"): """ Transformation for classicAction DROP/RESET actionType @@ -551,56 +549,11 @@ def convert_filter_action(self, action_parse_tree): # identify an action command return [] elif action_type == "forward": - """Transformation for filter action command of FORWARD as - actionType, LBvserver is created and bound to the existing - service via VserverCreation function and LBvserver Name is - fetched and used in transformed command of feature group CS - vs_kw - key for targetLBVserver - lb_name - new lb vserver to be used by cs action """ - ''' - # TODO - there are issues with FORWARD actionType in binding, - # so we won't currently enable conversions for filter of - # FORWARD actionType. - service = original_cmd.positional_value(2).value - lb_name = "nspepi_lb_vserver_" + service - action_parse_tree = CLICommand("add", "cs", "action") - action_name = CLIPositionalParameter(actionName) - action_parse_tree.add_positional(action_name) - vs_kw = CLIKeywordParameter(CLIKeywordName("targetLBVserver")) - vs_kw.add_value(lb_name) - action_parse_tree.add_keyword(vs_kw) - action_parse_tree.set_upgraded() - if lb_name in self._vserverName_list: - # If vserverName already exists in the list - # then just output the transformed action - self._vserverName_list.add(lb_name) - action_parse_tree_list = [action_parse_tree] - else: - # If vserverName not in the list - # then output- add vserver, bind vserver and - # transformed action - self._vserverName_list.add(lb_name) - - # Add LB Vserver with name nspepi_lb_vserver_ - vserver = CLICommand("add", "lb", "vserver") - vs_name = CLIPositionalParameter(lb_name) - vs_type = CLIPositionalParameter("http") - vserver.add_positional_list([vs_name, vs_type]) - vserver.set_upgraded() - - # Bind LB Vserver with Service Name which is available in - # classic action command - bindVserver = CLICommand("bind", "lb", "vserver") - bind_vs_name = CLIPositionalParameter(str(vs_name)) - bind_service_name = CLIPositionalParameter(service) - bindVserver.add_positional_list([ - bind_vs_name, bind_service_name]) - bindVserver.set_upgraded() - action_parse_tree_list = [ - vserver, bindVserver, action_parse_tree] - ''' + Conversion of FORWARD action type + """ action_parse_tree_list = [original_cmd] + self._forward["action"].append(actionName) logging.error( "Conversion of [{}] not supported in this tool. : [{}]" "".format(str(original_cmd).strip(), str(original_cmd).strip())) @@ -651,11 +604,23 @@ def convert_filter_policy(self, policy_parse_tree): converted_pol_cmd, policy_action_key, orig_action_name = self.new_policy( policy_parse_tree, policyName) policy_action = orig_action_name.lower() - if policy_action in self._htmlInjection: + if policy_action in self._htmlInjection["action"]: # Return input for those policies which are calling actions # having value as prebody or postbody Since they belong to # html injection family - return self.return_original_input(original_cmd, pol_obj) + logging.error( + "Conversion of HTMLInjection feature reated command [{}]" + "not supported in this tool.".format(str(original_cmd).strip())) + self._htmlInjection["policy"].append(policyName) + return [original_cmd] + + if policy_action in self._forward["action"]: + logging.error( + "Conversion of FORWARD action type related command [{}]" + "not supported in this tool.".format(str(original_cmd).strip())) + self._forward["policy"].append(policyName) + return [original_cmd] + for dict_key, dict_value in self._actionTypeName.items(): """ Extract key and value from stored _actionTypeName dictionary through action convertion """ @@ -706,27 +671,10 @@ def convert_filter_policy(self, policy_parse_tree): elif (dict_key == "forward"): """ If input policy calls the action which points to the action for FORWARD """ - # TODO - This should be uncommented at the time of - # transformation for FORWARD actionType. - """ - converted_pol_cmd = CLICommand("add", "cs", "policy") - policy_name = CLIPositionalParameter(policyName) - converted_pol_cmd.add_positional(policy_name) - rule = CLIKeywordParameter(CLIKeywordName("rule")) - rule.add_value(advanced_expr) - converted_pol_cmd.add_keyword(rule) - action_key = CLIKeywordParameter(CLIKeywordName("action")) - action_key.add_value(action_name) - converted_pol_cmd.add_keyword(action_key) - """ - # TODO - put it outside at the time of transformation for - # FORWARD actionType and return converted output. - - # To store policy name and tuple of reqAction key name and - # original module - return self.return_original_input(original_cmd, pol_obj) - else: - return self.return_original_input(original_cmd, pol_obj) + logging.error( + "Conversion of FORWARD action type command [{}]" + "not supported in this tool.".format(str(original_cmd).strip())) + return [original_cmd] # Changing the module name to converted module name pol_obj.module = self.__class__.__name__ @@ -768,16 +716,6 @@ def new_policy(self, policy_parse_tree, policyName): converted_pol_cmd.set_upgraded() return converted_pol_cmd, policy_action_key, policy_action - def return_original_input(self, original_cmd, pol_obj): - """ Return original input """ - logging.error( - "Conversion of [{}] not supported in this tool. : [{}]" - "".format(str(original_cmd).strip(), str(original_cmd).strip())) - # Setting policy type to advanced to avoid conversion - # during bind command - pol_obj.policy_type = "advanced" - return [original_cmd] - @common.register_for_bind(["LB", "ContentSwitching", "CacheRedirection"]) def convert_filter_vserver_bindings( self, bind_parse_tree, policy_name, priority_arg, goto_arg): @@ -795,6 +733,19 @@ def convert_filter_vserver_bindings( if policy_type == "advanced": # Return same if policy_type is marked advanced return [bind_parse_tree] + + if policy_name in self._forward["policy"]: + logging.error( + "Conversion of FORWARD action type related command [{}]" + "not supported in this tool.".format(str(bind_parse_tree).strip())) + return [bind_parse_tree] + + if policy_name in self._htmlInjection["policy"]: + logging.error( + "Conversion of HTMLInjection feature related command [{}]" + "not supported in this tool.".format(str(bind_parse_tree).strip())) + return [bind_parse_tree] + vs_name = bind_parse_tree.positional_value(0).value.lower() if cli_cmds.vserver_protocol_dict[vs_name] not in ("HTTP", "SSL"): logging.error("Filter policy doesn't work with the non-http protocol" @@ -848,6 +799,19 @@ def convert_filter_global_bindings(self, bind_parse_tree): ) return ["#" + str(bind_parse_tree)] policy_name = bind_parse_tree.positional_value(0).value + + if policy_name in self._forward["policy"]: + logging.error( + "Conversion of FORWARD action type related command [{}]" + "not supported in this tool.".format(str(bind_parse_tree).strip())) + return [bind_parse_tree] + + if policy_name in self._htmlInjection["policy"]: + logging.error( + "Conversion of HTMLInjection feature related command [{}]" + "not supported in this tool.".format(str(bind_parse_tree).strip())) + return [bind_parse_tree] + policy_type = common.pols_binds.policies[policy_name].policy_type if policy_type == "advanced": # Return input if policy_type is marked with "advanced" @@ -878,6 +842,19 @@ def convert_filter_global_bindings(self, bind_parse_tree): self._bind_tree_rw.append(bind_parse_tree) return [] + @common.register_for_cmd("add", "filter", "htmlinjectionvariable") + @common.register_for_cmd("set", "filter", "htmlinjectionvariable") + @common.register_for_cmd("set", "filter", "htmlinjectionparameter") + @common.register_for_cmd("set", "filter", "prebodyInjection") + @common.register_for_cmd("set", "filter", "postbodyInjection") + def convert_filter_htmlinjection_command(self, commandParseTree): + """ + Handling Filter HTMLInjection command + """ + logging.error("Conversion of HTMLInjection feature" + " related command [{}] is not supported".format(str(commandParseTree).strip())) + return [commandParseTree] + @common.register_for_final_call def get_converted_cmds(self): """ diff --git a/nspepi/nspepi2/nspepi_helper b/nspepi/nspepi2/nspepi_helper index d373292..41b84e7 100755 --- a/nspepi/nspepi2/nspepi_helper +++ b/nspepi/nspepi2/nspepi_helper @@ -158,11 +158,11 @@ my %EXPR_LIST=( # List of classic expressions that are not convertable my @CSEC_BLOCKED_LIST=( - 'CLIENT.APPLICATION', - 'CLIENT.FILE', - 'CLIENT.OS', - 'CLIENT.REG', - 'CLIENT.SVC', + 'CLIENT\.APPLICATION', + 'CLIENT\.FILE', + 'CLIENT\.OS', + 'CLIENT\.REG', + 'CLIENT\.SVC', 'f_5_TrendMicroOfficeScan_7_3', 'f_5_sygate_5_6', 'f_5_zonealarm_6_5', @@ -180,15 +180,15 @@ my @CSEC_BLOCKED_LIST=( ); my @FILE_BLOCKED_LIST=( - 'FS.COMMAND', - 'FS.DIR', - 'FS.DOMAIN', - 'FS.FILE', - 'FS.PATH', - 'FS.SERVER', - 'FS.SERVERIP', - 'FS.SERVICE', - 'FS.USER', + 'FS\.COMMAND', + 'FS\.DIR', + 'FS\.DOMAIN', + 'FS\.FILE', + 'FS\.PATH', + 'FS\.SERVER', + 'FS\.SERVERIP', + 'FS\.SERVICE', + 'FS\.USER', ); my @BLOCKED_LIST=( @@ -305,7 +305,7 @@ sub convertExpression } # Check for client security expression expressions foreach (@CSEC_BLOCKED_LIST) { - if ($expression =~ /$_/i) { + if ($expression =~ /\b$_/i) { print_it($LFILE,"$line\n"); err_handle $ERR_CSEC_BLOCKED_MSG; return; @@ -313,7 +313,7 @@ sub convertExpression } # Check for file system based expression expressions foreach (@FILE_BLOCKED_LIST) { - if ($expression =~ /$_/i) { + if ($expression =~ /\b$_/i) { print_it($LFILE,"$line\n"); err_handle $ERR_FILE_BLOCKED_MSG; return; @@ -321,7 +321,7 @@ sub convertExpression } # Check for blocked expressions foreach (@BLOCKED_LIST) { - if ($expression =~ /$_/i) { + if ($expression =~ /\b$_/i) { my $err_msg = "Conversion of $_ expression is not supported"; print_it($LFILE,"$line\n"); err_handle $err_msg; @@ -814,12 +814,38 @@ sub identifyExpressions my $OPERATOR=$1; $expr_params=$2; my $ARG = extractArgument(); - if ($ARG =~ /^\S{3}\, (\d{2}) (\S{3}) (\d{4}) (\d{2}):(\d{2}):(\d{2}) (\S{3})$/) { + if ($ARG =~ /^\S{3}\, (\d{1,2}) (\S{3}) (\d{4}) (\d{2}):(\d{2}):(\d{2}) (\S{3})$/) { + # Handling RFC822 format: Tue, 05 Nov 1994 08:12:31 GMT $ARG = "$7 $3 $2 $1 $4h $5m $6s"; parseNumericOperator($OPERATOR,$ARG); return; - } - else { + } elsif ($ARG =~ /^\S{3}\, (\d{1,2})-(\S{3})-(\d{4}) (\d{2}):(\d{2}):(\d{2}) (\S{3})$/) { + # Handling cookie format: Tue, 05-Nov-1994 08:12:31 GMT + $ARG = "$7 $3 $2 $1 $4h $5m $6s"; + parseNumericOperator($OPERATOR,$ARG); + return; + } elsif ($ARG =~ /^\S{3} (\S{3}) (\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4}) (\S{3})$/) { + # Handling asctime format: Tue Nov 4 08:12:31 1994 GMT + $ARG = "$7 $6 $1 $2 $3h $4m $5s"; + parseNumericOperator($OPERATOR,$ARG); + return; + } elsif ($ARG =~ /^\S{3} (\S{3}) (\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/) { + # Handling asctime format: Tue Nov 4 08:12:31 1994 GMT + $ARG = "GMT $6 $1 $2 $3h $4m $5s"; + parseNumericOperator($OPERATOR,$ARG); + return; + } elsif ($ARG =~ /^\S{5,8}\, (\d{1,2})-(\S{3})-(\d{2}) (\d{2}):(\d{2}):(\d{2}) (\S{3})$/) { + # Handling RFC850 format: Tuesday, 05-Nov-94 08:12:31 GMT + my $year = int($3); + if ($year > 70) { + $year = 1900 + $year; + } else { + $year = 2000 + $year; + } + $ARG = "GMT $year $2 $1 $5h $5m $6s"; + parseNumericOperator($OPERATOR,$ARG); + return; + } else { err_handle $ERR_OPERATOR_MSG; return; } diff --git a/nspepi/nspepi2/nspepi_main.py b/nspepi/nspepi2/nspepi_main.py index 09331da..1c28da8 100755 --- a/nspepi/nspepi2/nspepi_main.py +++ b/nspepi/nspepi2/nspepi_main.py @@ -38,6 +38,7 @@ file_log_handler = None console_log_handler = None debug_log_handler = None +error_log_handler = None def create_file_log_handler(file_name, log_level): """ @@ -61,12 +62,13 @@ def create_file_log_handler(file_name, log_level): file_handler.setFormatter(fh_format) return file_handler -def setup_logging(log_file_name, file_log_level, debug_file_name, console_output_needed): +def setup_logging(log_file_name, file_log_level, error_file_name, debug_file_name, console_output_needed): """ Sets up logging for the program. Args: log_file_name: The name of the log file + error_file_name: The name of the error log file file_log_level: The level of logs to put in log_file_name file debug_file_name: The name of the debug log file console_output_needed: True if logs need to be seen on console @@ -74,17 +76,22 @@ def setup_logging(log_file_name, file_log_level, debug_file_name, console_output global file_log_handler global console_log_handler global debug_log_handler + global error_log_handler # create logger logger = logging.getLogger() logger.setLevel(logging.DEBUG) # if called multiple times, remove existing handlers logger.removeHandler(file_log_handler) logger.removeHandler(console_log_handler) - logger.removeHandler(debug_log_handler) + logger.removeHandler(console_log_handler) + logger.removeHandler(error_log_handler) # create file handler file_log_handler = create_file_log_handler(log_file_name, file_log_level) # add the handlers to the logger logger.addHandler(file_log_handler) + if error_file_name: + error_log_handler = create_file_log_handler(error_file_name, logging.ERROR) + logger.addHandler(error_log_handler) if debug_file_name: debug_log_handler = create_file_log_handler(debug_file_name, logging.DEBUG) logger.addHandler(debug_log_handler) @@ -219,6 +226,8 @@ def main(): arg_parser.add_argument( '-V', '--version', action='version', version='%(prog)s {}'.format(__version__)) + arg_parser.add_argument('-E', '--newErrorFileName', action="store_true", + help=argparse.SUPPRESS) try: args = arg_parser.parse_args() print(args) @@ -231,9 +240,11 @@ def main(): conf_file_path = os.path.dirname(args.infile) conf_file_name = os.path.basename(args.infile) log_file_name = os.path.join(conf_file_path, 'warn_' + conf_file_name) + err_file_name = os.path.join(conf_file_path, 'error_' + conf_file_name) if args.newErrorFileName else None debug_file_name = os.path.join(conf_file_path, 'debug_' + conf_file_name) if args.debug else None # For -v and -e options, logs will be seen on console and warn file. # For other options, logs will only be in warn file and not on console. + setup_logging(log_file_name, logging.WARNING, err_file_name, debug_file_name, args.verbose or args.expression is not None) setup_logging(log_file_name, logging.WARNING, debug_file_name, args.verbose or args.expression is not None) convert_cli_commands.convert_cli_init() # convert classic policy expression if given as an argument @@ -262,6 +273,9 @@ def main(): with open(args.infile, 'r') as infile: with open(new_path, 'w') as outfile: convert_config_file(infile, outfile, args.verbose) + if err_file_name: + if os.path.getsize(err_file_name) == 0: + os.remove(err_file_name) if os.path.getsize(log_file_name) == 0: error_warn_msg = ".\nConversion is successful, no error or warning is generated." os.remove(log_file_name) @@ -272,6 +286,7 @@ def main(): + conf_file_name + error_warn_msg) if args.debug: print("Check debug_" + conf_file_name + " file for debug logs.") + print("\nUse nspepi tool available at https://github.com/citrix/ADC-scripts/tree/master/nspepi for the most complete and up-to-date version.") if __name__ == '__main__': diff --git a/nspepi/nspepi2/nspepi_parse_tree.py b/nspepi/nspepi2/nspepi_parse_tree.py index 8ce3c69..432f2cd 100644 --- a/nspepi/nspepi2/nspepi_parse_tree.py +++ b/nspepi/nspepi2/nspepi_parse_tree.py @@ -110,6 +110,7 @@ def __init__(self, op, group, ot): policy is advanced but need to set upgrade flag after conversion. adv_upgraded should be used in such cases instead of upgraded. invalid - Indicates whether the command is invalid in 13.1 release. + has_csec_expr - Indicates that command has client security expression original_line - the text of the line that was parsed lineno - the line number (starting with 1) that the command occurs on op - the op-code for the command @@ -119,6 +120,7 @@ def __init__(self, op, group, ot): self._upgraded = True self._adv_upgraded = True self._invalid = False + self._has_csec_expr = False self._original_line = "" self._lineno = 0 self._op = op @@ -208,6 +210,17 @@ def set_invalid(self): @property def invalid(self): return self._invalid + + def set_has_csec_expr(self): + """ + Flags that this command has + Client security expression. + """ + self._has_csec_expr = True + + @property + def has_csec_expr(self): + return self._has_csec_expr def add_positional(self, positional_param): """ Adds a positional parameter at the end of the parameters. From 86576416a0d736061c31fc49df28504fe1eb119e Mon Sep 17 00:00:00 2001 From: Vishal John Varghese <72516017+VishalJohnVarghese1996@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:10:00 +0000 Subject: [PATCH 3/3] Code Changes --- nspepi/nspepi2/convert_classic_expr.py | 2 -- nspepi/nspepi2/convert_cli_commands.py | 4 ++-- nspepi/nspepi2/nspepi_main.py | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/nspepi/nspepi2/convert_classic_expr.py b/nspepi/nspepi2/convert_classic_expr.py index 1c48e65..9f4c5de 100644 --- a/nspepi/nspepi2/convert_classic_expr.py +++ b/nspepi/nspepi2/convert_classic_expr.py @@ -68,8 +68,6 @@ def convert_classic_expr(classic_expr, ignore_csec_expr = False): else: logging.error(nspepi_tool_output) return None - logging.error(nspepi_tool_output) - return None elif nspepi_tool_output.endswith(info_msg): """old nspepi tool didn't convert the expression, so return input expression""" diff --git a/nspepi/nspepi2/convert_cli_commands.py b/nspepi/nspepi2/convert_cli_commands.py index 070056e..1c77122 100644 --- a/nspepi/nspepi2/convert_cli_commands.py +++ b/nspepi/nspepi2/convert_cli_commands.py @@ -2335,8 +2335,8 @@ def get_converted_cmds(self): # Get truncated name if truncated. if action_name in overlength_action_names: truncated_act_name = overlength_action_names[ - action_name] - if need_new_policy: + action_name] + if need_new_policy: new_policy_name = "nspepi_adv_" + policy_name + '_' + \ vserver_name # If CS vserver is configured with caseSensitive diff --git a/nspepi/nspepi2/nspepi_main.py b/nspepi/nspepi2/nspepi_main.py index 1c28da8..6f3cdd6 100755 --- a/nspepi/nspepi2/nspepi_main.py +++ b/nspepi/nspepi2/nspepi_main.py @@ -230,7 +230,6 @@ def main(): help=argparse.SUPPRESS) try: args = arg_parser.parse_args() - print(args) except IOError as e: exit(str(e)) # obtain logging parameters and setup logging @@ -245,7 +244,6 @@ def main(): # For -v and -e options, logs will be seen on console and warn file. # For other options, logs will only be in warn file and not on console. setup_logging(log_file_name, logging.WARNING, err_file_name, debug_file_name, args.verbose or args.expression is not None) - setup_logging(log_file_name, logging.WARNING, debug_file_name, args.verbose or args.expression is not None) convert_cli_commands.convert_cli_init() # convert classic policy expression if given as an argument if args.expression is not None: