|
14 | 14 |
|
15 | 15 | # Python
|
16 | 16 | import re
|
| 17 | +import logging |
17 | 18 |
|
18 | 19 | # Metaparser
|
19 | 20 | from genie.metaparser import MetaParser
|
|
23 | 24 | # import parser utils
|
24 | 25 | from genie.libs.parser.utils.common import Common
|
25 | 26 |
|
| 27 | +log = logging.getLogger(__name__) |
| 28 | + |
26 | 29 | # =================================================
|
27 | 30 | # Schema for:
|
28 | 31 | # * 'show run policy-map {name}'
|
@@ -2751,7 +2754,9 @@ class ShowRunningConfigAAAUsernameSchema(MetaParser):
|
2751 | 2754 | Optional('common_criteria_policy'): str,
|
2752 | 2755 | Optional('view'): str,
|
2753 | 2756 | Optional('type'): str,
|
| 2757 | + Optional('autocommand'): str, |
2754 | 2758 | Optional('onetime'): bool,
|
| 2759 | + Optional('nopassword'): bool, |
2755 | 2760 | Optional('secret'): {
|
2756 | 2761 | Optional('type'): int,
|
2757 | 2762 | Optional('secret'): str,
|
@@ -2897,139 +2902,135 @@ def cli(self, output=None):
|
2897 | 2902 | else:
|
2898 | 2903 | out = output
|
2899 | 2904 |
|
2900 |
| - # username testuser password 0 lab |
2901 |
| - p1 = re.compile(r'^username +(?P<username>\S+) +password +(?P<type>\d) +(?P<password>.*)$') |
| 2905 | + # NOTE: All of the following regular expressions should be anchored to |
| 2906 | + # the begining of the line ('^'). As each is used the line will be |
| 2907 | + # shortened. Think of this as popping arguments (and their parameters) |
| 2908 | + # off of a stack (the front of the line). |
| 2909 | + # |
| 2910 | + # There are some arguments that cannot have any subsequent arguments. |
| 2911 | + # These are: |
| 2912 | + # 1) password |
| 2913 | + # 2) secret |
| 2914 | + # 3) autocommand |
| 2915 | + # These arguments shall also match the end of the line ('$'). |
| 2916 | + # |
| 2917 | + # All arguments that are not matched to the end of the line shall match |
| 2918 | + # an optional trailing space (' ?'). |
| 2919 | + |
| 2920 | + # username testuser |
| 2921 | + username_cmd = re.compile(r'^username (?P<username>\S+) ?') |
2902 | 2922 |
|
2903 |
| - # username testuser common-criteria-policy Test-CC password 0 password |
2904 |
| - p2 = re.compile( |
2905 |
| - r'^username +(?P<username>\S+) +common-criteria-policy +(?P<common_criteria_policy>.*) ' |
2906 |
| - r'+password +(?P<type>\d) +(?P<password>.*)$') |
| 2923 | + # common-criteria-policy Test-CC |
| 2924 | + common_criteria_policy = re.compile(r'^common-criteria-policy (?P<common_criteria_policy>\S+) ?') |
2907 | 2925 |
|
2908 |
| - # username testuser secret 9 $9$A2OfV.30kNlIhE$ZEJQIT6aUj.TfCzqGQr.h4AmjQd/bWikQaGRlaLv0nQ |
2909 |
| - p3 = re.compile(r'^username +(?P<username>\S+) +secret +(?P<type>\d) +(?P<secret>.*)$') |
| 2926 | + # secret 9 $9$A2OfV.30kNlIhE$ZEJQIT6aUj.TfCzqGQr.h4AmjQd/bWikQaGRlaLv0nQ |
| 2927 | + secret = re.compile(r'^secret (?P<type>\d) (?P<secret>.*)$') |
2910 | 2928 |
|
2911 |
| - # username testuser one-time secret 9 $9$AuJ8xgW8aBBuF.$HyAzLk.3ILFsKrEvd4YjaAHbtonVMLikXw2pnrlkYJY |
2912 |
| - p4 = re.compile( |
2913 |
| - r'^username +(?P<username>\S+) +one-time +(?P<Onetime>)\s*secret +(?P<type>\d+) +(?P<secret>.*)$') |
| 2929 | + # privilege 15 |
| 2930 | + privilege = re.compile(r'^privilege (?P<privilege>\d+) ?') |
2914 | 2931 |
|
2915 |
| - # username testuser privilege 15 password 0 lab |
2916 |
| - p5 = re.compile( |
2917 |
| - r'^username +(?P<username>\S+) +privilege +(?P<privilege>\d+) +password +(?P<type>\d) +(?P<password>.*)$') |
| 2932 | + # one-time |
| 2933 | + onetime = re.compile(r'^one-time ?') |
2918 | 2934 |
|
2919 |
| - # username testuser common-criteria-policy Test-CC secret 9 $9$7K9qbCZMJa2Vuk$6bS3.Bv7AkBXhTHpTH9V9fhMnJCQe1a9O7xBWHtOKo. |
2920 |
| - p6 = re.compile( |
2921 |
| - r'^username +(?P<username>\S+) +common-criteria-policy +(?P<common_criteria_policy>.*) ' |
2922 |
| - r'+secret +(?P<type>\d) +(?P<secret>.*)$') |
| 2935 | + # nopassword |
| 2936 | + nopassword = re.compile(r'^nopassword ?') |
2923 | 2937 |
|
2924 |
| - # username testuser one-time password 0 password |
2925 |
| - p7 = re.compile( |
2926 |
| - r'^username +(?P<username>\S+) +one-time +(?P<Onetime>)\s*password +(?P<type>\d) +(?P<password>.*)$') |
| 2938 | + # password 0 lab |
| 2939 | + password = re.compile(r'^password (?P<type>\d) (?P<password>.*)$') |
2927 | 2940 |
|
2928 |
| - # username developer privilege 15 secret 9 $9$oNguEA9um9vRx.$MsDk0DOy1rzBjKAcySWdNjoKcA7GetG9YNnKOs8S67A |
2929 |
| - p8 = re.compile(r'^username +(?P<username>\S+) +privilege +(?P<privilege>\d+) +secret +(?P<secret_type>\d+) +(?P<secret>\S+)$') |
| 2941 | + # autocommand show ip bgp summary |
| 2942 | + autocommand = re.compile(r'^autocommand (?P<autocommand>.*)$') |
2930 | 2943 |
|
2931 | 2944 | # Initial return dictionary
|
2932 | 2945 | ret_dict = {}
|
2933 | 2946 |
|
2934 | 2947 | for line in out.splitlines():
|
2935 | 2948 | line = line.strip()
|
2936 | 2949 |
|
2937 |
| - # username testuser password 0 lab |
2938 |
| - m = p1.match(line) |
2939 |
| - if m: |
2940 |
| - group = m.groupdict() |
2941 |
| - username = group['username'] |
2942 |
| - users_dict = ret_dict.setdefault('username', {}).setdefault(username, {}) |
2943 |
| - pass_dict = users_dict.setdefault('password', {}) |
2944 |
| - pass_dict['type'] = int(group['type']) |
2945 |
| - pass_dict['password'] = group['password'] |
| 2950 | + # username testuser |
| 2951 | + m = username_cmd.match(line) |
| 2952 | + if not m: |
| 2953 | + # CLAIM: This is not a line with a 'username' command. |
2946 | 2954 | continue
|
2947 | 2955 |
|
2948 |
| - # username testuser common-criteria-policy Test-CC password 0 password |
2949 |
| - m = p2.match(line) |
2950 |
| - if m: |
2951 |
| - group = m.groupdict() |
2952 |
| - username = group['username'] |
2953 |
| - users_dict = ret_dict.setdefault('username', {}).setdefault(username, {}) |
2954 |
| - users_dict['common_criteria_policy'] = group['common_criteria_policy'] |
2955 |
| - pass_dict = users_dict.setdefault('password', {}) |
2956 |
| - pass_dict['type'] = int(group['type']) |
2957 |
| - pass_dict['password'] = group['password'] |
2958 |
| - continue |
| 2956 | + # CLAIM: this is a username line |
| 2957 | + # GOAL: extract the specified username and switch to that |
| 2958 | + # sub-dictionary: |
| 2959 | + group = m.groupdict() |
| 2960 | + username = group['username'] |
| 2961 | + users_dict = ret_dict.setdefault('username', {}).setdefault(username, {}) |
2959 | 2962 |
|
2960 |
| - # username testuser secret 9 $9$A2OfV.30kNlIhE$ZEJQIT6aUj.TfCzqGQr.h4AmjQd/bWikQaGRlaLv0nQ |
2961 |
| - m = p3.match(line) |
2962 |
| - if m: |
2963 |
| - group = m.groupdict() |
2964 |
| - username = group['username'] |
2965 |
| - users_dict = ret_dict.setdefault('username', {}).setdefault(username, {}) |
2966 |
| - secret_dict = users_dict.setdefault('secret', {}) |
2967 |
| - secret_dict['type'] = int(group['type']) |
2968 |
| - secret_dict['secret'] = group['secret'] |
2969 |
| - continue |
| 2963 | + # GOAL: remove the matched portion from the begining of the line |
| 2964 | + # so that we can match the subsequent argument (if any): |
| 2965 | + line = line[m.end():] |
2970 | 2966 |
|
2971 |
| - # username testuser one-time secret 9 $9$AuJ8xgW8aBBuF.$HyAzLk.3ILFsKrEvd4YjaAHbtonVMLikXw2pnrlkYJY |
2972 |
| - m = p4.match(line) |
2973 |
| - if m: |
2974 |
| - group = m.groupdict() |
2975 |
| - username = group['username'] |
2976 |
| - users_dict = ret_dict.setdefault('username', {}).setdefault(username, {}) |
2977 |
| - users_dict['onetime'] = True |
2978 |
| - secret_dict = users_dict.setdefault('secret', {}) |
2979 |
| - secret_dict['type'] = int(group['type']) |
2980 |
| - secret_dict['secret'] = group['secret'] |
2981 |
| - continue |
| 2967 | + while line: |
| 2968 | + # GOAL: parse through the line an argument at a time, |
| 2969 | + # shortening the line as we go. |
2982 | 2970 |
|
2983 |
| - # username testuser privilege 15 password 0 lab |
2984 |
| - m = p5.match(line) |
2985 |
| - if m: |
2986 |
| - group = m.groupdict() |
2987 |
| - username = group['username'] |
2988 |
| - users_dict = ret_dict.setdefault('username', {}).setdefault(username, {}) |
2989 |
| - users_dict['privilege'] = int(group['privilege']) |
2990 |
| - pass_dict = users_dict.setdefault('password', {}) |
2991 |
| - pass_dict['type'] = int(group['type']) |
2992 |
| - pass_dict['password'] = group['password'] |
2993 |
| - continue |
| 2971 | + # GOAL: match the 'common-criteria-policy' option and return its parameter |
| 2972 | + # Sample: "common-criteria-policy MyPolicy" |
| 2973 | + if m := common_criteria_policy.match(line): |
| 2974 | + group = m.groupdict() |
| 2975 | + users_dict['common_criteria_policy'] = group['common_criteria_policy'] |
| 2976 | + line = line[m.end():] |
| 2977 | + continue |
2994 | 2978 |
|
2995 |
| - # username testuser common-criteria-policy Test-CC secret 9 $9$7K9qbCZMJa2Vuk$6bS3.Bv7AkBXhTHpTH9V9fhMnJCQe1a9O7xBWHtOKo. |
2996 |
| - m = p6.match(line) |
2997 |
| - if m: |
2998 |
| - group = m.groupdict() |
2999 |
| - username = group['username'] |
3000 |
| - users_dict = ret_dict.setdefault('username', {}).setdefault(username, {}) |
3001 |
| - users_dict['common_criteria_policy'] = group['common_criteria_policy'] |
3002 |
| - secret_dict = users_dict.setdefault('secret', {}) |
3003 |
| - secret_dict['type'] = int(group['type']) |
3004 |
| - secret_dict['secret'] = group['secret'] |
3005 |
| - continue |
| 2979 | + # GOAL: match the 'privilege' option and return its parameter |
| 2980 | + # Sample: "privilege 15" |
| 2981 | + if m := privilege.match(line): |
| 2982 | + group = m.groupdict() |
| 2983 | + users_dict['privilege'] = int(group['privilege']) |
| 2984 | + line = line[m.end():] |
| 2985 | + continue |
3006 | 2986 |
|
3007 |
| - # username testuser one-time password 0 password |
3008 |
| - m = p7.match(line) |
3009 |
| - if m: |
3010 |
| - group = m.groupdict() |
3011 |
| - username = group['username'] |
3012 |
| - users_dict = ret_dict.setdefault('username', {}).setdefault(username, {}) |
3013 |
| - users_dict['onetime'] = True |
3014 |
| - pass_dict = users_dict.setdefault('password', {}) |
3015 |
| - pass_dict['type'] = int(group['type']) |
3016 |
| - pass_dict['password'] = group['password'] |
3017 |
| - continue |
| 2987 | + # GOAL: match the 'secret' option and return its parameters ('type' and 'secret') |
| 2988 | + # Sample: "secret 9 $9$oNguEA9um9vRx.$MsDk0DOy1rzBjKAcySWdNjoKcA7GetG9YNnKOs8S67A" |
| 2989 | + if m := secret.match(line): |
| 2990 | + group = m.groupdict() |
| 2991 | + pass_dict = users_dict.setdefault('secret', {}) |
| 2992 | + pass_dict['type'] = int(group['type']) |
| 2993 | + pass_dict['secret'] = group['secret'] |
| 2994 | + line = line[m.end():] |
| 2995 | + continue |
3018 | 2996 |
|
3019 |
| - # username developer privilege 15 secret 9 $9$oNguEA9um9vRx.$MsDk0DOy1rzBjKAcySWdNjoKcA7GetG9YNnKOs8S67A |
3020 |
| - m = p8.match(line) |
3021 |
| - if m: |
3022 |
| - group = m.groupdict() |
3023 |
| - user_dict = ret_dict.setdefault('username', {}).setdefault(group['username'], {}) |
3024 |
| - user_dict.update({ |
3025 |
| - 'privilege': int(group['privilege']), |
3026 |
| - }) |
| 2997 | + # GOAL: match the 'onetime' flag |
| 2998 | + # Sample: "onetime" |
| 2999 | + if m := onetime.match(line): |
| 3000 | + group = m.groupdict() |
| 3001 | + users_dict['onetime'] = True |
| 3002 | + line = line[m.end():] |
| 3003 | + continue |
3027 | 3004 |
|
3028 |
| - secret_dict = user_dict.setdefault('secret', {}) |
3029 |
| - secret_dict.update({ |
3030 |
| - 'type': int(group['secret_type']), |
3031 |
| - 'secret': group['secret'] |
3032 |
| - }) |
| 3005 | + # GOAL: match the 'nopassword' flag |
| 3006 | + # Sample: "nopassword" |
| 3007 | + if m := nopassword.match(line): |
| 3008 | + group = m.groupdict() |
| 3009 | + users_dict['nopassword'] = True |
| 3010 | + line = line[m.end():] |
| 3011 | + continue |
| 3012 | + |
| 3013 | + # GOAL: match the 'autocommand' option and return all subsequent text |
| 3014 | + # Sample: "autocommand show ip bgp summary" |
| 3015 | + if m := autocommand.match(line): |
| 3016 | + group = m.groupdict() |
| 3017 | + users_dict['autocommand'] = group['autocommand'] |
| 3018 | + line = line[m.end():] |
| 3019 | + continue |
| 3020 | + |
| 3021 | + # GOAL: match the 'password' option and return its parameters ('type' and 'password') |
| 3022 | + # Sample: "password 0 lab" |
| 3023 | + if m := password.match(line): |
| 3024 | + group = m.groupdict() |
| 3025 | + pass_dict = users_dict.setdefault('password', {}) |
| 3026 | + pass_dict['type'] = int(group['type']) |
| 3027 | + pass_dict['password'] = group['password'] |
| 3028 | + line = line[m.end():] |
| 3029 | + continue |
| 3030 | + |
| 3031 | + # CLAIM: There is an unhandled argument. |
| 3032 | + log.warning(f"Unhandled argument in parser 'show running-config aaa username': {line}") |
| 3033 | + break |
3033 | 3034 |
|
3034 | 3035 | return ret_dict
|
3035 | 3036 |
|
|
0 commit comments