From eb947a7c178af008b0fa46e5d4f02d1d70ece11e Mon Sep 17 00:00:00 2001 From: checktheroads Date: Fri, 10 May 2019 14:10:32 -0700 Subject: [PATCH] fixed issue with IPv6 BGP Route lookups --- docs/configuration/router-privileges.md | 58 +++++++++++++++++++++ hyperglass/app.py | 5 +- hyperglass/cmd_construct.py | 67 +++++++++++++------------ hyperglass/cmd_execute.py | 2 + hyperglass/manage.py | 13 ++--- hyperglass/templates/index.html | 1 + 6 files changed, 107 insertions(+), 39 deletions(-) create mode 100644 docs/configuration/router-privileges.md diff --git a/docs/configuration/router-privileges.md b/docs/configuration/router-privileges.md new file mode 100644 index 0000000..40ad41c --- /dev/null +++ b/docs/configuration/router-privileges.md @@ -0,0 +1,58 @@ +More than likely, you'll want to "lock down" what commands can be executed with the credentials you've provided in `hyperglass/hyperglass/config/devices.toml`. It is **strongly** recommended to use a low privilege read only account and not your full administrator account. Even though Hyperglass is coded to only run certain commands to begin with, you're more than likely still exposing the server Hyperglass runs on to the internet, and on that server is a plain text file with your router's credentials in it. Take precautions. + +# Creating Restricted Accounts + +## Cisco IOS + +On Cisco IOS, **parser views** are the recommended tool to restrict access. Basic instructions for configuring Cisco IOS parser views for the default enabled query types are below: + +``` +parser view hyperglass + secret + commands exec include all terminal width + commands exec include all terminal length + commands exec include all traceroute + commands exec include all ping + commands exec include all show bgp +! +username hyperglass privilege 15 view hyperglass secret +``` + +!!! info "Terminal" + The `terminal length` and `terminal width` commands are required by Netmiko for session handling. If you remove these, Hyperglass will not work. + +## Cisco IOS-XR + +On Cisco IOS-XR, **taskgroups** are the recommended tool to restrict access. Basic instructoins for configuring Cisco IOS-XR taskgroups for the default enabled query types are below: + +``` +taskgroup hyperglass + task read bgp +! +usergroup hyperglass + taskgroup hyperglass +! +username hyperglass + group hyperglass + group operator + secret +``` + + +!!! warning "IOS-XR" + I have not yet figured out a way to enable all the extended options for `ping` and `traceroute` (source IP, count, etc.) without adding the `group operator` statement to the taskgroup. If anyone knows of a way to do this, I welcome a docs PR. + +## Juniper + +On JunOS, **system login classes** are the recommended tool to restrict access. Basic instructoins for configuring Juniper JunOS login classes for the default enabled query types are below: + +``` +edit system login class hyperglass + +set permissions floppy + +set allow-commands-regexp [ "show route protocol bgp" ping traceroute "show route protocol bgp table inet.0" "show route protocol bgp table inet6.0" "ping inet" "ping inet6" "traceroute inet" "traceroute inet6" ] + +top +set system login user hyperglass class hyperglass authentication plain-text-password +``` diff --git a/hyperglass/app.py b/hyperglass/app.py index 1f10a6d..b60ec05 100644 --- a/hyperglass/app.py +++ b/hyperglass/app.py @@ -68,7 +68,10 @@ cache = Cache( def clearCache(): """Function to clear the Flask-Caching cache""" with app.app_context(): - cache.clear() + try: + cache.clear() + except: + raise # Main / Flask route where html is rendered via Jinja2 diff --git a/hyperglass/cmd_construct.py b/hyperglass/cmd_construct.py index 081f8ff..40fb557 100644 --- a/hyperglass/cmd_construct.py +++ b/hyperglass/cmd_construct.py @@ -21,6 +21,7 @@ routers_list = devices["router"] # Also handles input validation & error handling def cmd_construct(router, cmd, ipprefix): inputParams = router, cmd, ipprefix + log.warning(*inputParams) try: # Loop through routers config file, match input router with configured routers, set variables for r in routers_list: @@ -56,7 +57,9 @@ def cmd_construct(router, cmd, ipprefix): i=ipprefix ) code = 200 - log.info(msg, code, router, type, command) + log.warning( + msg, code, router, type, command + ) return (msg, code, router, type, command) # Extended Communities, 32 bit format elif re.match("^[0-9]{1,10}$", ipprefix): @@ -67,7 +70,9 @@ def cmd_construct(router, cmd, ipprefix): i=ipprefix ) code = 200 - log.info(msg, code, router, type, command) + log.warning( + msg, code, router, type, command + ) return (msg, code, router, type, command) # RFC 8092 Large Community Support elif re.match( @@ -81,7 +86,9 @@ def cmd_construct(router, cmd, ipprefix): i=ipprefix ) code = 200 - log.info(msg, code, router, type, command) + log.warning( + msg, code, router, type, command + ) return (msg, code, router, type, command) else: msg = "{i} is an invalid BGP Community Format.".format( @@ -100,7 +107,9 @@ def cmd_construct(router, cmd, ipprefix): i=ipprefix ) code = 200 - log.info(msg, code, router, type, command) + log.warning( + msg, code, router, type, command + ) return (msg, code, router, type, command) else: msg = "{i} is an invalid AS_PATH regex.".format( @@ -121,7 +130,7 @@ def cmd_construct(router, cmd, ipprefix): i=ipprefix ) code = 200 - log.info( + log.warning( msg, code, router, type, command ) return ( @@ -132,31 +141,25 @@ def cmd_construct(router, cmd, ipprefix): command, ) # Use netaddr library to verify if input is a valid IPv6 address or prefix - elif IPNetwork(ipprefix).ip.version == 6: - for a, c in ipv6_commands.items(): - if a == cmd: - command = c.format( - target=ipprefix - ) - msg = "{i} is a valid IPv6 Adddress.".format( - i=ipprefix - ) - code = 200 - log.info( - msg, - code, - router, - type, - command, - ) - return ( - msg, - code, - router, - type, - command, - ) - # Exception from netaddr library will return a user-facing error + elif IPNetwork(ipprefix).ip.version == 6: + for a, c in ipv6_commands.items(): + if a == cmd: + command = c.format(target=ipprefix) + msg = "{i} is a valid IPv6 Adddress.".format( + i=ipprefix + ) + code = 200 + log.warning( + msg, code, router, type, command + ) + return ( + msg, + code, + router, + type, + command, + ) + # Exception from netaddr library will return a user-facing error except: msg = "{i} is an invalid IP Address.".format( i=ipprefix @@ -178,7 +181,7 @@ def cmd_construct(router, cmd, ipprefix): i=ipprefix ) code = 200 - log.info( + log.warning( msg, code, router, type, command ) return ( @@ -199,7 +202,7 @@ def cmd_construct(router, cmd, ipprefix): i=ipprefix ) code = 200 - log.info( + log.warning( msg, code, router, type, command ) return ( diff --git a/hyperglass/cmd_execute.py b/hyperglass/cmd_execute.py index 374d06c..1df3ebb 100644 --- a/hyperglass/cmd_execute.py +++ b/hyperglass/cmd_execute.py @@ -26,6 +26,7 @@ general_error = "Error connecting to device." def cmd_execute(lg_data): + log.warning(lg_data) # Check POST data from JS, if location matches a configured router's # location, use the router's configured IP address to connect for r in routers_list: @@ -47,6 +48,7 @@ def cmd_execute(lg_data): log.error(msg, code, lg_data) return (msg, code, lg_data) # Send "clean" request to cmd_construct to build the command that will be sent to the router + print(lg_router_address) msg, status, router, type, command = cmd_construct( lg_router_address, lg_data["cmd"], lg_data["ipprefix"] ) diff --git a/hyperglass/manage.py b/hyperglass/manage.py index b3e9307..8487ded 100644 --- a/hyperglass/manage.py +++ b/hyperglass/manage.py @@ -1,6 +1,9 @@ import os import sys import app +import logging + +log = logging.getLogger(__name__) def clearcache(): @@ -11,10 +14,8 @@ def clearcache(): for arg in sys.argv: - try: - if arg == "clearcache": + if arg == "clearcache": + try: clearcache() - print("Successfully cleared cache.") - except: - print("Failed to clear cache.") - raise + except: + raise diff --git a/hyperglass/templates/index.html b/hyperglass/templates/index.html index daeac30..7bc77c5 100644 --- a/hyperglass/templates/index.html +++ b/hyperglass/templates/index.html @@ -85,6 +85,7 @@