carlmontanari / scrapli

Fast, flexible, sync/async, Python 3.7+ screen scraping client specifically for network devices
https://carlmontanari.github.io/scrapli/
MIT License
575 stars 59 forks source link

Timeout error in IOSXE if prompt contains parenthesis #291

Closed laherre closed 1 year ago

laherre commented 1 year ago

Trying to connect a cisco ios device withouth privileged level, depending device prompt, I get timeout error:

8HE2> 

Works ok

27N2(2960_PoE)>

Get timeout error.

Code used:

oneeq =  {
            'host': 'ip',
            'auth_username': 'user',
            'auth_password': 'pass',
            'default_desired_privilege_level': 'exec',
            "auth_strict_key": False,
            "transport": "asyncssh",
            "driver": AsyncIOSXEDriver            
        }
...
async def _fetch_data(self,device):
        driver = device.pop("driver")
        async with driver(**device) as conn:
            responses = await conn.send_commands(["show version", ]) 
            return responses
...

But It works if I define my own PrivilegeLevel with pattern including "(" and ")" :

...
'default_desired_privilege_level': 'miexec',
'privilege_levels': {
    'miexec': (
        PrivilegeLevel(
            pattern=r"^[\w.\-@/:()]{1,63}>$",
            name="miexec",
            previous_priv="",
            deescalate="",
            escalate="",
            escalate_auth=False,
            escalate_prompt="",
        )
    ),
},
...

(please sorry my english and really thanks for your work)

carlmontanari commented 1 year ago

👋 hey there, thanks for raising this!

do you know what platforms the ( and ) are supported in the hostname on?

Id have to go look more but I worry that a pattern like that may overlap w/ config modes of varying flavors (like somehost(config) and some host(tacacs+config) (or something like that)).

basically all of these would need to not be compromised and id want to know which platform(s) this hostname stuff is allowed in before changing anything.

so, worst case this is a "not broke wont fix" and you can handle it like you already have done, but if it seems like this is something we should support (due to it being broadly supported in iosxe devices) we can look at updating the core pattern(s).

carlmontanari commented 1 year ago

ah update. this works on my old 3560cx but it complains about illegal characters... so if thats the same for most places id say "not broke wont fix" and you can support it yourself. but still open to having my mind changed there :)

C3560CX#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
C3560CX(config)#hostname a(foo)
% Hostname contains one or more illegal characters.

a(foo)(config)#
mickyhale commented 1 year ago

Thought this was interesting because I was doing some work with a client that uses parentheses in some of their hostnames and so I wrote my own. Something like this would pass your tests:

PRIVS = {
    "exec": (
        PrivilegeLevel(
            pattern=r"^[\w.\-@/:()]{1,63}>$",
            name="exec",
            previous_priv="",
            deescalate="",
            escalate="",
            escalate_auth=False,
            escalate_prompt="",
        )
    ),
    "privilege_exec": (
        PrivilegeLevel(
            pattern=r"^[\w.\-@/:()]{1,63}#$",
            name="privilege_exec",
            previous_priv="exec",
            deescalate="disable",
            escalate="enable",
            escalate_auth=True,
            escalate_prompt=r"^(?:enable\s){0,1}password:\s?$",
            not_contains=["(conf", "(ipsec", "tcl)"],
        )
    ),
    "configuration": (
        PrivilegeLevel(
            pattern=r"^[\w.\-@/:()]{1,63}(?=(\((?:conf|ipse)[\w.\-@/:+]{0,28}\)#))",
            name="configuration",
            previous_priv="privilege_exec",
            deescalate="end",
            escalate="configure terminal",
            escalate_auth=False,
            escalate_prompt="",
            not_contains=["tcl)"],
        )
    ),
    "tclsh": (
        PrivilegeLevel(
            pattern=r"^([\w.\-@/+>:()]+\(tcl\)[>#]|\+>)$",
            name="tclsh",
            previous_priv="privilege_exec",
            deescalate="tclquit",
            escalate="tclsh",
            escalate_auth=False,
            escalate_prompt="",
        )
    ),
}

Tested on the following (a bit redundant, but you get the idea):

@pytest.mark.parametrize(
    "priv_pattern",
    [
        ("exec", "csr1000v>"),
        ("exec", "csr1000v(lab)>"),
        ("privilege_exec", "csr1000v#"),
        ("privilege_exec", "csr1000v(lab)#"),
        ("privilege_exec", "csr_1000v#"),
        ("privilege_exec", "csr_1000v(lab)#"),
        ("configuration", "csr1000v(config)#"),
        ("configuration", "csr1000v(lab)(config)#"),
        ("configuration", "csr1000v(conf-ssh-pubkey-data)#"),
        ("configuration", "csr1000v(lab)(conf-ssh-pubkey-data)#"),
        ("configuration", "csr1000v(conf-isa-prof)#"),
        ("configuration", "csr1000v(lab)(conf-isa-prof)#"),
        ("configuration", "csr1000v(config-sg-tacacs+)#"),
        ("configuration", "csr1000v(lab)(config-sg-tacacs+)#"),
        ("configuration", "819HGW(ipsec-profile)#"),
        ("configuration", "819HGW(lab)(ipsec-profile)#"),
        ("tclsh", "819HGW(tcl)#"),
        ("tclsh", "819HGW(lab)(tcl)#"),
        ("tclsh", "+>"),
        ("tclsh", "+>(tcl)#"),
    ],

Not saying you should consider including it, but there are cases where it's useful (i.e., when you don't have full control over the environment or you're performing discovery).

Thank you for the great library.

carlmontanari commented 1 year ago

@mickyhale boom, I love it! glad to see that not contains gettin some use! will take a closer peak this weekend. Regardless of if we add this or not, really, really appreciate ya sharing this as it will now be searchable and available for everyone!

carlmontanari commented 1 year ago

sorry for the delay here. I think for now I'm going to close this as @mickyhale solution is perfect and doesn't require any changes to scrapli. @mickyhale if you are keen to it -- we could maybe add a cisco_iosxe+ platform to scrapli community with your priv levels so its even easier for folks to consume -- but no pressure there, just if you're feeling feisty :D