mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
complete restructure 2
This commit is contained in:
175
hyperglass/command/execute.py
Normal file
175
hyperglass/command/execute.py
Normal file
@@ -0,0 +1,175 @@
|
||||
import sys
|
||||
import time
|
||||
from netaddr import *
|
||||
from loguru import logger
|
||||
from netmiko import redispatch
|
||||
from netmiko import ConnectHandler
|
||||
from hyperglass import configuration
|
||||
from hyperglass.command import construct
|
||||
from hyperglass.command import parse
|
||||
|
||||
# Load TOML devices file
|
||||
devices = configuration.devices()
|
||||
# Filter config to router list
|
||||
routers_list = devices["router"]
|
||||
# Filter config to credential list
|
||||
credentials_list = devices["credential"]
|
||||
# Filter config to proxy servers
|
||||
proxies_list = devices["proxy"]
|
||||
|
||||
blacklist_config = configuration.blacklist()
|
||||
blacklist = IPSet(blacklist_config["blacklist"])
|
||||
|
||||
general_error = "Error connecting to device."
|
||||
|
||||
logger.add(sys.stderr)
|
||||
|
||||
|
||||
def execute(lg_data):
|
||||
logger.info(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:
|
||||
if r["location"] == lg_data["router"]:
|
||||
lg_router_address = r["address"]
|
||||
|
||||
# Check blacklist.toml array for prefixes/IPs and return an error upon a match
|
||||
if lg_data["cmd"] in ["bgp_route", "ping", "traceroute"]:
|
||||
try:
|
||||
if IPNetwork(lg_data["ipprefix"]).ip in blacklist:
|
||||
msg = "{i} is not allowed.".format(i=lg_data["ipprefix"])
|
||||
code = 405
|
||||
logger.error(msg, code, lg_data)
|
||||
return (msg, code, lg_data)
|
||||
# If netaddr library throws an exception, return a user-facing error.
|
||||
except:
|
||||
msg = "{i} is not a valid IP Address.".format(i=lg_data["ipprefix"])
|
||||
code = 415
|
||||
logger.error(msg, code, lg_data)
|
||||
return (msg, code, lg_data)
|
||||
# Send "clean" request to constructor to build the command that will be sent to the router
|
||||
print(lg_router_address)
|
||||
msg, status, router, type, command = construct.construct(
|
||||
lg_router_address, lg_data["cmd"], lg_data["ipprefix"]
|
||||
)
|
||||
# Loop through proxy config, match configured proxy name for each router with a configured proxy
|
||||
# Return configured proxy parameters for netmiko
|
||||
def matchProxy(search_proxy):
|
||||
if configured_proxy in proxies_list:
|
||||
proxy_address = proxies_list[search_proxy]["address"]
|
||||
proxy_username = proxies_list[search_proxy]["username"]
|
||||
proxy_password = proxies_list[search_proxy]["password"]
|
||||
proxy_type = proxies_list[search_proxy]["type"]
|
||||
proxy_ssh_command = proxies_list[search_proxy]["ssh_command"]
|
||||
return (
|
||||
proxy_address,
|
||||
proxy_username,
|
||||
proxy_password,
|
||||
proxy_type,
|
||||
proxy_ssh_command,
|
||||
)
|
||||
else:
|
||||
msg = "Router does not have a proxy configured."
|
||||
code = 415
|
||||
logger.error(msg, code, lg_data)
|
||||
return (msg, code, lg_data)
|
||||
|
||||
# Matches router with configured credential
|
||||
def findCred(router):
|
||||
for r in routers_list:
|
||||
if r["address"] == router:
|
||||
configured_credential = r["credential"]
|
||||
return configured_credential
|
||||
|
||||
# Matches configured credential with real username/password
|
||||
def returnCred(configured_credential):
|
||||
if configured_credential in credentials_list:
|
||||
matched_username = credentials_list[configured_credential]["username"]
|
||||
matched_password = credentials_list[configured_credential]["password"]
|
||||
return matched_username, matched_password
|
||||
else:
|
||||
msg = "Credential {i} does not exist".format(i=configured_credential)
|
||||
code = 415
|
||||
logger.error(msg, code, lg_data)
|
||||
return (general_error, code, lg_data)
|
||||
|
||||
# Connect to the router via netmiko library, return the command output
|
||||
def getOutputDirect():
|
||||
try:
|
||||
nm_connect_direct = ConnectHandler(**nm_host)
|
||||
nm_output_direct = nm_connect_direct.send_command(command)
|
||||
return nm_output_direct
|
||||
except:
|
||||
msg = "Unable to reach target {l}".format(l=lg_data["router"])
|
||||
code = 415
|
||||
logger.error(msg, code, lg_data)
|
||||
return (general_error, code, lg_data)
|
||||
|
||||
# Connect to the proxy server via netmiko library, then log into the router
|
||||
# via standard SSH
|
||||
def getOutputProxy(router_proxy):
|
||||
nm_proxy = {
|
||||
"host": matchProxy(router_proxy)[0],
|
||||
"username": matchProxy(router_proxy)[1],
|
||||
"password": matchProxy(router_proxy)[2],
|
||||
"device_type": matchProxy(router_proxy)[3],
|
||||
}
|
||||
nm_connect_proxied = ConnectHandler(**nm_proxy)
|
||||
nm_ssh_command = matchProxy(router_proxy)[4].format(**nm_host) + "\n"
|
||||
nm_connect_proxied.write_channel(nm_ssh_command)
|
||||
time.sleep(1)
|
||||
proxy_output = nm_connect_proxied.read_channel()
|
||||
try:
|
||||
# Accept SSH key warnings
|
||||
if "Are you sure you want to continue connecting" in proxy_output:
|
||||
nm_connect_proxied.write_channel("yes" + "\n")
|
||||
time.sleep(1)
|
||||
nm_connect_proxied.write_channel(nm_host["password"] + "\n")
|
||||
# Send password on prompt
|
||||
elif "assword" in proxy_output:
|
||||
nm_connect_proxied.write_channel(nm_host["password"] + "\n")
|
||||
time.sleep(1)
|
||||
proxy_output += nm_connect_proxied.read_channel()
|
||||
# Reclassify netmiko connection as configured device type
|
||||
redispatch(nm_connect_proxied, nm_host["device_type"])
|
||||
|
||||
host_output = nm_connect_proxied.send_command(command)
|
||||
if host_output:
|
||||
return host_output
|
||||
except:
|
||||
msg = "Proxy server {p} unable to reach target {d}".format(
|
||||
p=nm_proxy["host"], d=nm_host["host"]
|
||||
)
|
||||
code = 415
|
||||
logger.error(msg, code, lg_data)
|
||||
return (general_error, code, lg_data)
|
||||
|
||||
nm_host = {
|
||||
"host": router,
|
||||
"device_type": type,
|
||||
"username": returnCred(findCred(router))[0],
|
||||
"password": returnCred(findCred(router))[1],
|
||||
}
|
||||
|
||||
# Loop through router list, determine if proxy exists
|
||||
for r in routers_list:
|
||||
if r["address"] == router:
|
||||
configured_proxy = r["proxy"]
|
||||
if len(configured_proxy) == 0:
|
||||
connection_proxied = False
|
||||
else:
|
||||
connection_proxied = True
|
||||
if status == 200:
|
||||
try:
|
||||
if connection_proxied is True:
|
||||
output_proxied = getOutputProxy(configured_proxy)
|
||||
parsed_output = parse.parse(output_proxied, type, lg_data["cmd"])
|
||||
return parsed_output, status, router, type, command
|
||||
elif connection_proxied is False:
|
||||
output_direct = getOutputDirect()
|
||||
parsed_output = parse.parse(output_direct, type, lg_data["cmd"])
|
||||
return parsed_output, status, router, type, command
|
||||
except:
|
||||
raise
|
||||
else:
|
||||
return msg, status, router, type, command
|
Reference in New Issue
Block a user