diff --git a/nspepi/README.md b/nspepi/README.md index ade0aaa..1de71e2 100644 --- a/nspepi/README.md +++ b/nspepi/README.md @@ -41,6 +41,18 @@ The following modules are the prerequisites for using these tools: - Ply module for Python - Switch.pm for Perl +If python3 is installed, then please create a symbolic link for python like "ln -s /usr/bin/pytho3 /usr/bin/python". + +Commands to install pip, ply and Switch.pm modules in CentOS: +sudo yum install -y perl-Switch +sudo yum install python-pip +sudo yum install python-ply + +Commands to install pip, ply and Switch.pm modules in Ubuntu: +sudo apt install libswitch-perl +sudo apt install python-ply +sudo apt install python-pip + ## Pre-validation tool for removed or deprecated features in Citrix ADC version 13.1 This is a pre-validation tool to check if any deprecated functionality that is removed from Citrix ADC 13.1 is still used in the configuration for your current release. If the validation result shows usage of a deprecated functionality, then before upgrading your appliance, you must first modify the configuration to the Citrix recommended alternative. You can modify the configuration either manually or using the NSPEPI tool. diff --git a/nspepi/check_invalid_config b/nspepi/check_invalid_config index 4d64f63..a7c80ef 100755 --- a/nspepi/check_invalid_config +++ b/nspepi/check_invalid_config @@ -27,35 +27,71 @@ if (!($python_module_list =~ m/\bply==/)) { my $number_args = $#ARGV + 1; -if ($number_args != 1) { - print "Usage: check_invalid_config \n"; +if ($number_args > 3) { + tool_usage(); exit; } +my($buildVersion) ="13.1"; +my @allowed_build_versions = ("13.1", "14.1"); + +if ($number_args == 3) { + if (uc($ARGV[1]) ne "-BUILDVERSION") { + tool_usage(); + exit; + } + $buildVersion = $ARGV[2]; + if (not grep(/^$buildVersion/, @allowed_build_versions)) { + print "Incorrect build version\n"; + exit; + } +} elsif ($number_args > 1) { + print "Incorrect parameters\n"; + tool_usage(); + exit; +} + my $config_file = $ARGV[0]; if (not -e $config_file) { print "No such file: $config_file\n"; exit; } +sub tool_usage() { + print "Usage: check_invalid_config -buildVersion \n"; +} + my($filename, $dir_path) = fileparse($config_file); my $dirname = dirname(__FILE__); -my $exit_status = system("python $dirname/nspepi2/config_check_main.py -f $config_file"); +my $exit_status = system("python $dirname/nspepi2/config_check_main.py -f $config_file -B $buildVersion"); if ($exit_status != 0) { print "Error in checking config file: $exit_status"; exit; } my $invalid_config_file = $dir_path."/issues_".$filename; +my $deprecated_config_file = $dir_path."deprecated_".$filename; # Checks whether any command is present in the file if (!(-z $invalid_config_file)) { - print "\nThe following configuration lines will get errors in 13.1 and both they and dependent configuration will be removed from the configuration:\n"; - system("cat $invalid_config_file"); - print "\nThe nspepi upgrade tool can be useful in converting your configuration - see the documentation at https://docs.citrix.com/en-us/citrix-adc/current-release/appexpert/policies-and-expressions/introduction-to-policies-and-exp/converting-policy-expressions-nspepi-tool.html.\n"; - print "\nNOTE: the nspepi tool doesn't convert the following configurations:\n\t1. SureConnect commands\n\t2. PriorityQueuing commands\n\t3. HTTP Denial of Service Protection commands\n\t4. Classic SSL commands\n\t5. HTMLInjection commands.\n"; + print "\nThe following configuration lines will get errors in ".$buildVersion." and both they and dependent configuration will be removed from the configuration:\n"; + system("cat $invalid_config_file"); + print "\nThe nspepi upgrade tool can be useful in converting your configuration - see the documentation at https://docs.citrix.com/en-us/citrix-adc/current-release/appexpert/policies-and-expressions/introduction-to-policies-and-exp/converting-policy-expressions-nspepi-tool.html.\n"; + print "\nNOTE: the nspepi tool doesn't convert the following configurations:\n\t1. SureConnect commands\n\t2. PriorityQueuing commands\n\t3. HTTP Denial of Service Protection commands\n\t4. Classic SSL commands\n\t5. HTMLInjection commands.\n"; + if (!(-z $deprecated_config_file)) { + print "\nNOTE: some deprecated commands have also been detected in the config file, please check ".$deprecated_config_file." file for the deprecated commands.\n"; + } else { + print "\nNOTE: No deprecated commands detected in the configuration.\n"; + } } else { - print "\nNo issue detected with the configuration.\n"; + if (!(-z $deprecated_config_file)) { + print "\nThe following configuration lines have been deprecated in ".$buildVersion." and will be removed in future releases:\n"; + system("tail -n 10 $deprecated_config_file"); + print "\nFor the complete deprecated commands, please see the output of ".$deprecated_config_file." file.\n"; + print "\nNo invalid config detected with the configuration.\n"; + } else { + print "\nNo invalid or deprecated config detected with the configuration.\n"; + } } print "\nUse pre-validation tool and nspepi tool available at https://github.com/citrix/ADC-scripts/tree/master/nspepi for the most complete and up-to-date version.\n" ### End check_invalid_config script diff --git a/nspepi/nspepi2/check_classic_configs.py b/nspepi/nspepi2/check_classic_configs.py index e8ea325..3de691c 100644 --- a/nspepi/nspepi2/check_classic_configs.py +++ b/nspepi/nspepi2/check_classic_configs.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright 2021-2022 Citrix Systems, Inc. All rights reserved. +# Copyright 2021-2023 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, # which accompany or are included with this software. @@ -17,11 +17,13 @@ def check_configs_init(): global policy_entities_names global classic_entities_names global named_expr + global build_version named_expr = {} policy_entities_names = set() classic_entities_names = set() # Register built-in named expressions. NamedExpression.register_built_in_named_exprs() + build_version = "13.1" def is_advanced_removed_expr_present(expr): @@ -135,7 +137,7 @@ def check_pos_expr(commandParseTree, pos, check_removed_expr = True): logging.error('Error in checking command : ' + str(commandParseTree)) elif converted_expr == "Invalid Expression": - commandParseTree.set_invalid() + commandParseTree.set_invalid() else: # converted_expr will have quotes and rule_expr will not have # quotes. Since we are comparing these 2 expressions, removing @@ -248,6 +250,7 @@ def check_policy(self, commandParseTree): return [commandParseTree] return [] else: + commandParseTree.set_invalid() return [commandParseTree] @common.register_for_cmd("bind", "cr", "vserver") @@ -267,6 +270,7 @@ def check_cr_vserver_bind(self, bind_parse_tree): if policy_type == class_name: # check for classic built-in policy. if policy_name in self.built_in_policies: + bind_parse_tree.set_invalid() return [bind_parse_tree] return [] @@ -311,6 +315,7 @@ class Patset(CheckConfig): def register_name(self, commandParseTree): Patset.register_policy_entity_name(commandParseTree) if commandParseTree.keyword_exists('indexType'): + commandParseTree.set_invalid() return [commandParseTree] return [] @@ -323,6 +328,7 @@ class Dataset(CheckConfig): def register_name(self, commandParseTree): Dataset.register_policy_entity_name(commandParseTree) if commandParseTree.keyword_exists('indexType'): + commandParseTree.set_invalid() return [commandParseTree] return [] @@ -334,11 +340,13 @@ class Patclass(CheckConfig): @common.register_for_cmd("add", "policy", "patclass") def check_add_patclass(self, commandParseTree): Patclass.register_policy_entity_name(commandParseTree) + commandParseTree.set_invalid() return [commandParseTree] @common.register_for_cmd("bind", "policy", "patclass") def check_bind_patclass(self, commandParseTree): Patclass.register_policy_entity_name(commandParseTree) + commandParseTree.set_invalid() return [commandParseTree] @@ -516,6 +524,10 @@ def check_policy_expr(self, 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") + .format(str(commandParseTree).strip())) return [] original_tree = copy.deepcopy(commandParseTree) @@ -530,10 +542,13 @@ 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") + .format(str(commandParseTree).strip())) else: NamedExpression.register_policy_entity_name(original_tree) - if is_advanced_removed_expr_present(expr_rule): - return [commandParseTree] + if is_advanced_removed_expr_present(expr_rule): + return [commandParseTree] return [] @@ -549,6 +564,7 @@ def check_spdy(self, commandParseTree): Syntax: """ if commandParseTree.keyword_exists('spdy'): + commandParseTree.set_invalid() return [commandParseTree] HTTPProfile.check_adv_expr_list(commandParseTree, ["clientIpHdrExpr"]) if commandParseTree.invalid: @@ -569,16 +585,18 @@ def check_cs_policy(self, commandParseTree): return [] if commandParseTree.keyword_exists('rule'): if commandParseTree.keyword_exists('domain'): + commandParseTree.set_invalid() return [commandParseTree] else: - original_cmd = copy.deepcopy(commandParseTree) commandParseTree = ContentSwitching \ .check_keyword_expr(commandParseTree, 'rule') if commandParseTree.invalid: - return [original_cmd] + return [commandParseTree] elif commandParseTree.keyword_exists('url'): + commandParseTree.set_invalid() return [commandParseTree] elif commandParseTree.keyword_exists('domain'): + commandParseTree.set_invalid() return [commandParseTree] return [] @@ -605,6 +623,7 @@ def set_cmp_parameter(self, cmp_param_tree): self._initial_cmp_parameter = \ cmp_param_tree.keyword_value("policyType")[0].value.lower() if self._initial_cmp_parameter == "classic": + cmp_param_tree.set_invalid() return [cmp_param_tree] return [] @@ -612,15 +631,15 @@ def set_cmp_parameter(self, cmp_param_tree): def set_cmp_policy(self, cmp_policy_tree): policy_name = cmp_policy_tree.positional_value(0).value if policy_name in self.built_in_policies: + cmp_policy_tree.set_invalid() return [cmp_policy_tree] return [] @common.register_for_cmd("add", "cmp", "policy") def check_cmp_policy(self, cmp_policy_tree): - original_cmd = copy.deepcopy(cmp_policy_tree) CheckConfig.check_keyword_expr(cmp_policy_tree, 'rule') if cmp_policy_tree.invalid: - return [original_cmd] + return [cmp_policy_tree] return [] @common.register_for_cmd("bind", "cmp", "global") @@ -631,10 +650,12 @@ def check_cmp_global_bind(self, bind_cmd_tree): # If state keyword is present then it is a # classic binding. if bind_cmd_tree.keyword_exists("state"): + bind_cmd_tree.set_invalid() return [bind_cmd_tree] policy_name = bind_cmd_tree.positional_value(0).value if policy_name in self.built_in_policies: + bind_cmd_tree.set_invalid() return [bind_cmd_tree] return [] @@ -650,6 +671,7 @@ def check_filter_action(self, action_parse_tree): """ Check Filter action """ + action_parse_tree.set_invalid() return [action_parse_tree] @common.register_for_cmd("add", "filter", "policy") @@ -657,6 +679,7 @@ def check_filter_policy(self, policy_parse_tree): """ Check Filter policy """ + policy_parse_tree.set_invalid() return [policy_parse_tree] @common.register_for_cmd("bind", "filter", "global") @@ -664,6 +687,7 @@ def check_filter_global_bindings(self, bind_parse_tree): """ Check Filter global binding """ + bind_parse_tree.set_invalid() return [bind_parse_tree] @common.register_for_cmd("add", "filter", "htmlinjectionvariable") @@ -675,6 +699,7 @@ def check_filter_htmlinjection_command(self, cmd_parse_tree): """ Check Filter HTMLInjection command """ + cmd_parse_tree.set_invalid() return [cmd_parse_tree] @@ -687,8 +712,10 @@ class Rewrite(CheckConfig): @common.register_for_cmd("add", "rewrite", "action") def check_rewrite_action(self, tree): if tree.keyword_exists('pattern'): + tree.set_invalid() return [tree] if tree.keyword_exists('bypassSafetyCheck'): + tree.set_invalid() return [tree] Rewrite.check_adv_expr_list(tree, [2, 3, "refineSearch"]) if tree.invalid: @@ -723,6 +750,7 @@ class SureConnect(CheckConfig): @common.register_for_cmd("add", "sc", "policy") @common.register_for_cmd("set", "sc", "parameter") def check_sc_policy(self, tree): + tree.set_invalid() return [tree] @@ -734,6 +762,7 @@ class PriorityQueuing(CheckConfig): @common.register_for_cmd("add", "pq", "policy") def check_sc_policy(self, tree): + tree.set_invalid() return [tree] @@ -744,7 +773,8 @@ class HDoSP(CheckConfig): """ @common.register_for_cmd("add", "dos", "policy") - def check_sc_policy(self, tree): + def check_dos_policy(self, tree): + tree.set_invalid() return [tree] @@ -757,11 +787,9 @@ class AdvExpression(CheckConfig): """ @common.register_for_cmd("add", "rewrite", "policy") - @common.register_for_cmd("add", "responder", "action") @common.register_for_cmd("add", "responder", "policy") @common.register_for_cmd("add", "cs", "vserver") @common.register_for_cmd("add", "videooptimization", "detectionpolicy") - @common.register_for_cmd("add", "videooptimization", "pacingpolicy") @common.register_for_cmd("add", "dns", "policy") @common.register_for_cmd("add", "cache", "selector") @common.register_for_cmd("add", "cs", "action") @@ -790,7 +818,6 @@ class AdvExpression(CheckConfig): @common.register_for_cmd("add", "ica", "policy") @common.register_for_cmd("add", "lb", "group") @common.register_for_cmd("add", "audit", "messageaction") - @common.register_for_cmd("add", "aaa", "preauthenticationpolicy") @common.register_for_cmd("add", "spillover", "policy") @common.register_for_cmd("add", "stream", "selector") @common.register_for_cmd("add","tm", "formSSOAction") @@ -798,30 +825,6 @@ class AdvExpression(CheckConfig): @common.register_for_cmd("add", "vpn", "sessionPolicy") @common.register_for_cmd("add", "vpn", "trafficAction") @common.register_for_cmd("add", "vpn", "vserver") - #TODO: This entry needs to be removed when Classic Syslog policy - # support is removed, and we've a separate function to check the - # command. - @common.register_for_cmd("add", "audit", "syslogPolicy") - #TODO: This entry needs to be removed when Classic Nslog policy - # support is removed, and we've a separate function to check the - # command. - @common.register_for_cmd("add", "audit", "nslogPolicy") - #TODO: This entry needs to be removed when Classic Authorization - # poicy support is removed, and we've a separate function - # to check the command. - @common.register_for_cmd("add", "authorization", "policy") - #TODO: This entry needs to be removed when Classic VPNTraffic policy - # support is removed, and we've a separate function to check the - # command. - @common.register_for_cmd("add", "vpn", "trafficPolicy") - #TODO: This entry needs to be removed when Classic TM sessionPolicy - # policy support is removed, and we've a separate function to check - # the command. - @common.register_for_cmd("add", "tm", "sessionPolicy") - #TODO: This entry needs to be removed when Classic tunnel trafficPolicy - # policy support is removed, and we've a separate function to check - # the command. - @common.register_for_cmd("add", "tunnel", "trafficPolicy") def check_advanced_expr(self, commandParseTree): """ Commands which allows ONLY advanced expressions should be registered for this method. @@ -837,7 +840,6 @@ def check_advanced_expr(self, commandParseTree): # If its a positional parameter, mention the position of the parameter. command_parameters_list = { "add rewrite policy": [1], - "add responder action": [2, "reasonPhrase", "headers"], "add responder policy": [1], "add cs vserver": ["Listenpolicy", "pushLabel"], "add videooptimization detectionpolicy": ["rule"], @@ -871,7 +873,6 @@ def check_advanced_expr(self, commandParseTree): "add ica policy": ["rule"], "add lb group": ["rule"], "add audit messageaction": [2], - "add aaa preauthenticationpolicy": [1], "add spillover policy": ["rule"], "add stream selector": [1, 2, 3, 4, 5], "add tm formssoaction": ["ssoSuccessRule"], @@ -879,30 +880,6 @@ def check_advanced_expr(self, commandParseTree): "add vpn sessionpolicy": [1], "add vpn trafficaction": ["userExpression", "passwdExpression"], "add vpn vserver": ["Listenpolicy"], - #TODO: This entry needs to be removed when Classic Syslog policy - # support is removed, and we've a separate function to check the - # command. - "add audit syslogpolicy": [1], - #TODO: This entry needs to be removed when Classic Nslog policy - # support is removed, and we've a separate function to check the - # command. - "add audit nslogpolicy": [1], - #TODO: This entry needs to be removed when Classic Authorization - # poicy support is removed, and we've a separate function - # to check the command. - "add authorization policy": [1], - #TODO: This entry needs to be removed when Classic VPNTraffic policy - # support is removed, and we've a separate function to check the - # command. - "add vpn trafficpolicy": [1], - #TODO: This entry needs to be removed when Classic TM sessionPolicy - # policy support is removed, and we've a separate function to check - # the command. - "add tm sessionpolicy": [1], - #TODO: This entry needs to be removed when Classic tunnel trafficPolicy - # policy support is removed, and we've a separate function to check - # the command. - "add tunnel trafficpolicy": [1], } command = " ".join(commandParseTree.get_command_type()).lower() @@ -911,3 +888,236 @@ def check_advanced_expr(self, commandParseTree): if commandParseTree.invalid: return [commandParseTree] return [] + + +@common.register_class_methods +class Deprecation(CheckConfig): + """ + Check the deprecated commands or parameters or expressions. + """ + + @common.register_for_cmd("add", "audit", "syslogPolicy") + @common.register_for_cmd("add", "audit", "nslogPolicy") + @common.register_for_cmd("add", "authorization", "policy") + @common.register_for_cmd("add", "vpn", "trafficPolicy") + @common.register_for_cmd("add", "tunnel", "trafficPolicy") + @common.register_for_cmd("add", "tm", "sessionPolicy") + def check_deprecated_classic_policy(self, commandParseTree): + """ + Check the policies which can still use the classic + expressions. + """ + rule_expr = commandParseTree.positional_value(1).value + 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") + .format(str(commandParseTree).strip())) + elif is_advanced_removed_expr_present(rule_expr): + commandParseTree.set_invalid() + return [commandParseTree] + return [] + + @common.register_for_cmd("add", "authentication", "certPolicy") + @common.register_for_cmd("add", "authentication", "negotiatePolicy") + @common.register_for_cmd("add", "authentication", "tacacsPolicy") + @common.register_for_cmd("add", "authentication", "samlPolicy") + @common.register_for_cmd("add", "authentication", "radiusPolicy") + @common.register_for_cmd("add", "authentication", "ldapPolicy") + @common.register_for_cmd("add", "authentication", "localPolicy") + @common.register_for_cmd("add", "authentication", "webAuthPolicy") + @common.register_for_cmd("add", "authentication", "dfaPolicy") + @common.register_for_cmd("add", "aaa", "preauthenticationpolicy") + 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") + .format(str(commandParseTree).strip())) + return [] + + @common.register_for_cmd("add", "ns", "trafficDomain") + def check_ns_traffic_domain(self, commandParseTree): + """ + Check the traffic domain command + """ + logging.warning(("[{}] command has been deprecated," + " please use the admin partition feature") + .format(str(commandParseTree).strip())) + return [] + + @common.register_for_cmd("set", "aaa", "preauthenticationparameter") + def check_aaa_preauth_params(self, commandParseTree): + """ + Rule filed of "set aaa preauthenticationparameter" + command is deprecated. + """ + if commandParseTree.keyword_exists('rule'): + logging.warning(("Client security expressions are deprecated" + " using this command [{}], please use the" + " the advanced authentication policy command") + .format(str(commandParseTree).strip())) + return [] + + @common.register_for_cmd("add", "vpn", "sessionAction") + def check_vpn_sessionaction(self, commandParseTree): + """ + clientSecurity filed of "add vpn sessionAction" + command is deprecated. + """ + if commandParseTree.keyword_exists('clientSecurity'): + logging.warning(("Client security expressions are deprecated" + " using this command [{}], please use the" + " the advanced authentication policy command") + .format(str(commandParseTree).strip())) + return [] + + @common.register_for_cmd("add", "vpn", "url") + def check_vpn_url(self, commandParseTree): + """ + SelfAuth SSO type is deprecated + """ + if commandParseTree.keyword_exists('ssotype'): + sso_type = commandParseTree.keyword_value("ssotype")[0].value.lower() + if sso_type is "selfauth": + logging.warning("Selfauth type has been deprecated" + " in command [{}]".format(str(commandParseTree).strip())) + return [] + + @common.register_for_cmd("add", "vpn", "portaltheme") + def check_vpn_portaltheme(self, commandParseTree): + """ + Default, X1, and Greenbubble portal themes are + deprecated + """ + 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": + logging.warning(("Default, GreenBubble and X1 themes" + " have been deprecated in command [{}]," + " please use RfWebUI theme or RfWebUI based custom theme") + .format(str(commandParseTree).strip())) + return [] + + @common.register_for_cmd("bind", "vpn", "vserver") + @common.register_for_cmd("bind", "vpn", "global") + def check_vpn_commands(self, commandParseTree): + """ + Default, X1, and Greenbubble portal themes are + deprecated + """ + 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": + logging.warning(("Default, GreenBubble and X1 themes" + " have been deprecated in command [{}]," + " please use RfWebUI theme or RfWebUI based custom theme") + .format(str(commandParseTree).strip())) + return [] + + @common.register_for_cmd("add", "dns", "action") + def check_dns_action(self, commandParseTree): + """ + Rewrite_response and DROP action types are + deprecated. + """ + action_type = commandParseTree.positional_value(1).value.lower() + 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.") + .format(str(commandParseTree).strip())) + elif action_type is "drop": + logging.warning(("Drop action type is deprecated in" + " command [{}], please use the Drop" + " action type under Responder feature.") + .format(str(commandParseTree).strip())) + return [] + + @common.register_for_cmd("enable", "ns", "feature") + def check_ns_feature(self, commandParseTree): + """ + SC, PQ, HDOSP, and CF features are deprecated. + """ + features_to_remove = ["SC", "PQ", "HDOSP", "CF"] + num_of_enabled_features = commandParseTree.get_number_of_params() + for inx in range(num_of_enabled_features): + feature_node = commandParseTree.positional_value(inx) + 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" + .format(str(commandParseTree).strip())) + break + return [] + + @common.register_for_cmd("add", "videooptimization", "pacingpolicy") + @common.register_for_cmd("add", "videooptimization", "pacingaction") + @common.register_for_cmd("add", "videooptimization", "pacingpolicylabel") + @common.register_for_cmd("bind", "videooptimization", "globalpacing") + @common.register_for_cmd("bind", "videooptimization", "pacingpolicylabel") + def check_deprecated_pacingcommands(self, commandParseTree): + """ + Check the videooptimization pacing commands + """ + if (commandParseTree.ot == "pacingpolicy"): + rule_expr = commandParseTree.keyword_value("rule")[0].value + if is_advanced_removed_expr_present(rule_expr): + commandParseTree.set_invalid() + return [commandParseTree] + + logging.warning(("[{}] command has been deprecated") + .format(str(commandParseTree).strip())) + return [] + + @common.register_for_cmd("add", "lsn", "appsattributes") + @common.register_for_cmd("add", "lsn", "appsprofile") + @common.register_for_cmd("add", "lsn", "client") + @common.register_for_cmd("add", "lsn", "group") + @common.register_for_cmd("add", "lsn", "httphdrlogprofile") + @common.register_for_cmd("add", "lsn", "ip6profile") + @common.register_for_cmd("add", "lsn", "logprofile") + @common.register_for_cmd("add", "lsn", "pool") + @common.register_for_cmd("add", "lsn", "rtspalgprofile") + @common.register_for_cmd("add", "lsn", "sipalgprofile") + @common.register_for_cmd("add", "lsn", "static") + @common.register_for_cmd("add", "lsn", "transportprofile") + @common.register_for_cmd("bind", "lsn", "appsprofile") + @common.register_for_cmd("bind", "lsn", "client") + @common.register_for_cmd("bind", "lsn", "group") + @common.register_for_cmd("bind", "lsn", "pool") + 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") + .format(str(commandParseTree).strip())) + return [] + + +@common.register_class_methods +class Responder(CheckConfig): + """ + Check responder commands + """ + + @common.register_for_cmd("add", "responder", "action") + def check_responder_action(self, commandParseTree): + """ + Check the responder action for the removed + advanced expressions and NOOP action type. + """ + Responder.check_adv_expr_list( + commandParseTree, [2, "reasonPhrase", "headers"]) + if commandParseTree.invalid: + return [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())) + return [] diff --git a/nspepi/nspepi2/config_check_main.py b/nspepi/nspepi2/config_check_main.py index 973060d..2850f9c 100755 --- a/nspepi/nspepi2/config_check_main.py +++ b/nspepi/nspepi2/config_check_main.py @@ -66,13 +66,10 @@ def setup_logging(log_file_name, file_log_level): console_log_handler = logging.StreamHandler() console_log_handler.setLevel(logging.INFO) # create formatters and add them to the handlers - fh_format = logging.Formatter('%(asctime)s: %(levelname)s - %(message)s') - ch_format = logging.Formatter('%(levelname)s - %(message)s') + fh_format = logging.Formatter('%(message)s') file_log_handler.setFormatter(fh_format) - console_log_handler.setFormatter(ch_format) # add the handlers to the logger logger.addHandler(file_log_handler) - logger.addHandler(console_log_handler) def output_line(line, outfile, verbose): @@ -132,7 +129,7 @@ def check_config_file(infile, outfile, verbose): def main(): desc = cleandoc( """ - Checks whether invalid config is present in input file + Checks whether invalid or deprecated config is present in input file """) arg_parser = argparse.ArgumentParser( prog="configCheck", @@ -147,6 +144,10 @@ def main(): arg_parser.add_argument( '-V', '--version', action='version', version='%(prog)s {}'.format(__version__)) + arg_parser.add_argument( + '-B', '--buildVersion', default='13.1', + help="Build version for which invalid or depreacted commands" + " need to check") try: args = arg_parser.parse_args() except IOError as e: @@ -155,7 +156,10 @@ def main(): conf_file_path = os.path.dirname(args.infile) conf_file_name = os.path.basename(args.infile) check_classic_configs.check_configs_init() + check_classic_configs.build_version = args.buildVersion new_path = os.path.join(conf_file_path, "issues_" + conf_file_name) + deprecated_file_name = os.path.join(conf_file_path, "deprecated_" + conf_file_name) + setup_logging(deprecated_file_name, logging.WARNING) with open(args.infile, 'r') as infile: with open(new_path, 'w') as outfile: check_config_file(infile, outfile, args.verbose) diff --git a/nspepi/nspepi2/convert_cli_commands.py b/nspepi/nspepi2/convert_cli_commands.py index ccb6ca6..9858981 100644 --- a/nspepi/nspepi2/convert_cli_commands.py +++ b/nspepi/nspepi2/convert_cli_commands.py @@ -1075,7 +1075,7 @@ class TMSession(ConvertConfig): # classic built-in policy and its corresponding advanced built-in policy. built_in_policies = { - "settmsessparams_pol": "SETTMSESSPARAMS_ADV_POL" + "SETTMSESSPARAMS_POL": "SETTMSESSPARAMS_ADV_POL" } def __init__(self): @@ -1134,10 +1134,10 @@ def convert_tmsession_entity_bind(self, commandParseTree, policy_name, # TM session policy can be bound to aaa user, aaa group and # Authentication vserver.In all these bind commands, keyword used # for policy is "policy" - lower_policy_name = policy_name.lower() - if lower_policy_name in self.built_in_policies: + upper_policy_name = policy_name.upper() + if upper_policy_name in self.built_in_policies: self.update_tree_arg(commandParseTree, "policy", - self.built_in_policies[lower_policy_name]) + self.built_in_policies[upper_policy_name]) return self.convert_entity_policy_bind( commandParseTree, commandParseTree, policy_name, policy_type, priority_arg, goto_arg) @@ -1157,14 +1157,14 @@ def convert_tm_global(self, commandParseTree): if (common.pols_binds.get_policy(policy_name).module != self.__class__.__name__): return [commandParseTree] - lower_policy_name = policy_name.lower() + upper_policy_name = policy_name.upper() priority_arg = "priority" goto_arg = "gotoPriorityExpression" module = self.__class__.__name__ # check for classic built-in policy - if lower_policy_name in self.built_in_policies: + if upper_policy_name in self.built_in_policies: self.update_tree_arg(commandParseTree, "policyName", - self.built_in_policies[lower_policy_name]) + self.built_in_policies[upper_policy_name]) return self.convert_global_bind(commandParseTree, commandParseTree, policy_name, module, priority_arg, goto_arg) @@ -2542,7 +2542,6 @@ class AdvExpression(ConvertConfig): @common.register_for_cmd("add", "ica", "policy") @common.register_for_cmd("add", "lb", "group") @common.register_for_cmd("add", "audit", "messageaction") - @common.register_for_cmd("add", "aaa", "preauthenticationpolicy") @common.register_for_cmd("add", "spillover", "policy") @common.register_for_cmd("add", "stream", "selector") @common.register_for_cmd("add","tm", "formSSOAction") @@ -2607,7 +2606,6 @@ def convert_advanced_expr(self, tree): "add ica policy": ["rule"], "add lb group": ["rule"], "add audit messageaction": [2], - "add aaa preauthenticationpolicy": [1], "add spillover policy": ["rule"], "add stream selector": [1, 2, 3, 4, 5], "add tm formssoaction": ["ssoSuccessRule"], @@ -2691,3 +2689,51 @@ def convert_policy(self, commandParseTree): "is not supported, please do the conversion " "manually").format(str(commandParseTree).strip())) return [commandParseTree] + + +@common.register_class_methods +class NSFeatures(ConvertConfig): + """ Handles enable ns feature command """ + + @common.register_for_cmd("enable", "ns", "feature") + def convert_ns_features(self, commandParseTree): + features_to_remove = ["SC", "PQ", "HDOSP", "CF"] + num_of_enabled_features = commandParseTree.get_number_of_params() + new_feature_command = CLICommand("enable", "ns", "feature") + is_rewrite_feature_enabled = False + is_responder_feature_enabled = False + is_appqoe_feature_enabled = False + enable_rw_responder_features = False + enable_appqoe_feature = False + for inx in range(num_of_enabled_features): + feature_node = commandParseTree.positional_value(inx) + feature_name = feature_node.value + if feature_name == "REWRITE": + is_rewrite_feature_enabled = True + elif feature_name == "RESPONDER": + is_responder_feature_enabled = True + elif feature_name == "AppQoE": + is_appqoe_feature_enabled = True + + if feature_name == "CF": + enable_rw_responder_features = True + elif feature_name in ["SC", "PQ", "HDOSP"]: + enable_appqoe_feature = True + + if feature_name not in features_to_remove: + new_feature_command.add_positional(feature_node) + + if enable_rw_responder_features: + if not is_rewrite_feature_enabled: + pos = CLIPositionalParameter("REWRITE") + new_feature_command.add_positional(pos) + + if not is_responder_feature_enabled: + pos = CLIPositionalParameter("RESPONDER") + new_feature_command.add_positional(pos) + + if enable_appqoe_feature and not is_appqoe_feature_enabled: + pos = CLIPositionalParameter("AppQoE") + new_feature_command.add_positional(pos) + + return [new_feature_command]