all user facing errors now customizable

This commit is contained in:
checktheroads 2019-05-28 11:50:31 -07:00
parent 4c72ad0814
commit 0174e58692
6 changed files with 73 additions and 102 deletions

View file

@ -11,6 +11,7 @@ from hyperglass import configuration
code = configuration.codes()
g = configuration.general()
def frr(cmd, ipprefix, device):
@ -39,7 +40,7 @@ def frr(cmd, ipprefix, device):
msg = f"{ipprefix} matched large community."
return (msg, code.success, d_address, query)
else:
msg = f"<b>{ipprefix}</b> is an invalid BGP Community Format."
msg = g.msg_error_invaliddual.format(i=ipprefix, qt="BGP Community")
logger.error(f"{msg}, {code.danger}, {d_name}, {query}")
return (msg, code.danger, d_address, query)
# BGP AS_PATH Query
@ -49,7 +50,7 @@ def frr(cmd, ipprefix, device):
msg = f"{ipprefix} matched AS_PATH regex."
return (msg, code.success, d_address, query)
else:
msg = f"<b>{ipprefix}</b> is an invalid AS_PATH regex."
msg = g.msg_error_invaliddual.format(i=ipprefix, qt="AS Path")
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
return (msg, code.danger, d_address, query)
# BGP Route Query
@ -67,7 +68,7 @@ def frr(cmd, ipprefix, device):
return (msg, code.success, d_address, query)
# Exception from netaddr library will return a user-facing error
except:
msg = f"<b>{ipprefix}</b> is an invalid IP Address."
msg = g.msg_error_invalidip.format(i=ipprefix)
logger.error(f"{msg}, {code.danger}, {d_name}, {query}")
return (msg, code.danger, d_address, query)
# Ping/Traceroute
@ -93,10 +94,10 @@ def frr(cmd, ipprefix, device):
"target": ipprefix,
}
)
msg = f"<b>{ipprefix}</b> is a valid IPv6 Adddress."
msg = f"{ipprefix} is a valid IPv6 Adddress."
return (msg, code.success, d_address, query)
except:
msg = f"<b>{ipprefix}</b> is an invalid IP Address."
msg = g.msg_error_invalidip.format(i=ipprefix)
logger.error(f"{msg}, {code.danger}, {d_name}, {query}")
return (msg, code.danger, d_name, query)
else:
@ -137,7 +138,7 @@ def ssh(cmd, ipprefix, device):
msg = f"{ipprefix} matched large community."
return (msg, code.success, d_address, d_type, command)
else:
msg = f"<b>{ipprefix}</b> is an invalid BGP Community Format."
msg = g.msg_error_invaliddual.format(i=ipprefix, qt="BGP Community")
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
return (msg, code.danger, d_name, cmd, ipprefix)
# BGP AS_PATH Query
@ -148,7 +149,7 @@ def ssh(cmd, ipprefix, device):
msg = f"{ipprefix} matched AS_PATH regex."
return (msg, code.success, d_address, d_type, command)
else:
msg = f"<b>{ipprefix}</b> is an invalid AS_PATH regex."
msg = g.msg_error_invaliddual.format(i=ipprefix, qt="AS Path")
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
return (msg, code.danger, d_name, cmd, ipprefix)
# BGP Route Query
@ -168,7 +169,7 @@ def ssh(cmd, ipprefix, device):
return (msg, code.success, d_address, d_type, command)
# Exception from netaddr library will return a user-facing error
except:
msg = f"<b>{ipprefix}</b> is an invalid IP Address."
msg = g.msg_error_invalidip.format(i=ipprefix)
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
return (msg, code.danger, d_name, cmd, ipprefix)
# Ping/Traceroute
@ -185,7 +186,7 @@ def ssh(cmd, ipprefix, device):
msg = f"{ipprefix} is a valid IPv6 Adddress."
return (msg, code.success, d_address, d_type, command)
except:
msg = f"<b>{ipprefix}</b> is an invalid IP Address."
msg = g.msg_error_invalidip.format(i=ipprefix)
logger.error(f"{msg}, {code.danger}, {d_name}, {cmd}, {ipprefix}")
return (msg, code.danger, d_name, cmd, ipprefix)
else:

View file

@ -166,39 +166,33 @@ def execute(lg_data):
global code
code = configuration.codes()
# Initialize general configuration parameters class, create global variable for reuse.
global general
general = configuration.general()
# Validate prefix input with netaddr library
if lg_cmd in ["bgp_route", "ping", "traceroute"]:
# Initialize prefix regex check class
ipc = ipcheck().test(lg_ipprefix)
msg = general.msg_error_invalidip.format(i=lg_ipprefix)
try:
# Initialize prefix regex check class
ipc = ipcheck().test(lg_ipprefix)
if IPNetwork(lg_ipprefix).ip.is_reserved():
msg = f"<b>{lg_ipprefix}</b> is not a valid IP address."
return (msg, code.danger, lg_data)
elif IPNetwork(lg_ipprefix).ip.is_netmask():
msg = f"<b>{lg_ipprefix}</b> is not a valid IP address."
return (msg, code.danger, lg_data)
elif IPNetwork(lg_ipprefix).ip.is_hostmask():
msg = f"<b>{lg_ipprefix}</b> is not a valid IP address."
return (msg, code.danger, lg_data)
elif IPNetwork(lg_ipprefix).ip.is_loopback():
msg = f"<b>{lg_ipprefix}</b> is not a valid IP address."
return (msg, code.danger, lg_data)
elif IPNetwork(lg_ipprefix).ip.is_unicast():
pass
else:
msg = f"<b>{lg_ipprefix}</b> is not a valid unicast IP address."
return (msg, code.danger, lg_data)
except:
msg = f"<b>{lg_ipprefix}</b> is not a valid IP Address."
return (msg, code.danger, lg_data)
if lg_cmd == "Query Type":
msg = "You must select a query type."
return (msg, code.warning, lg_data)
# Initialize general configuration parameters class, create global variable for reuse.
global general
general = configuration.general()
return (general.msg_error_querytype, code.warning, lg_data)
global d
d = configuration.device(lg_router)
@ -209,15 +203,14 @@ def execute(lg_data):
# Check blacklist list for prefixes/IPs and return an error upon a match
if lg_cmd in ["bgp_route", "ping", "traceroute"]:
blacklist = IPSet(configuration.blacklist())
msg = general.msg_error_notallowed.format(i=lg_ipprefix)
if IPNetwork(lg_ipprefix).ip in blacklist:
msg = f"<b>{lg_ipprefix}</b> is not allowed."
return (msg, code.warning, lg_data)
if lg_cmd == "bgp_route" and IPNetwork(lg_ipprefix).version == 6:
if requires_ipv6_cidr == True and ipc["type"] == "host":
msg = f"<b>{d.display_name}</b> requires IPv6 BGP lookups to be in CIDR notation."
msg = general.msg_error_ipv6cidr.format(d=d.display_name)
return (msg, code.warning, lg_data)
if lg_cmd in ["ping", "traceroute"] and ipc["type"] == "cidr":
msg = f"<code>{lg_cmd}</code> does not allow networks masks."
return (msg, code.warning, lg_data)
# If enable_max_prefix feature enabled, require BGP Route queries be smaller than prefix size limit
@ -226,13 +219,17 @@ def execute(lg_data):
IPNetwork(lg_ipprefix).version == 4
and IPNetwork(lg_ipprefix).prefixlen > general.max_prefix_length_ipv4
):
msg = f"Prefix length must be smaller than /{general.max_prefix_length_ipv4}. <b>{IPNetwork(lg_ipprefix)}</b> is too specific."
msg = general.msg_max_prefix.format(
m=general.max_prefix_length_ipv4, i=IPNetwork(lg_ipprefix)
)
return (msg, code.warning, lg_data)
if (
IPNetwork(lg_ipprefix).version == 6
and IPNetwork(lg_ipprefix).prefixlen > general.max_prefix_length_ipv6
):
msg = f"Prefix length must be smaller than /{general.max_prefix_length_ipv4}. <b>{IPNetwork(lg_ipprefix)}</b> is too specific."
msg = general.msg_max_prefix.format(
m=general.max_prefix_length_ipv6, i=IPNetwork(lg_ipprefix)
)
return (msg, code.warning, lg_data)
if d.type == "frr":

View file

@ -1,5 +1,3 @@
#!/usr/bin/env python3
# Module Imports
import os
import math
@ -143,10 +141,26 @@ class general:
self.org_name = g.get("org_name", "The Company")
self.debug = g.get("debug", False)
self.google_analytics = g.get("google_analytics", "")
self.message_error = g.get("message_error", "{input} is invalid.")
self.message_blacklist = g.get("message_blacklist", "{input} is not allowed.")
self.message_general_error = g.get(
"message_general_error", "Error connecting to device."
self.msg_error_querytype = g.get(
"msg_error_querytype", "You must select a query type."
)
self.msg_error_notallowed = g.get(
"msg_error_notallowed", "<b>{i}</b> is not allowed."
)
self.msg_error_ipv6cidr = g.get(
"msg_error_ipv6cidr",
"<b>{d}</b> requires IPv6 BGP lookups to be in CIDR notation.",
)
self.msg_error_invalidip = g.get(
"msg_error_invalidip", "<b>{i}</b> is not a valid IP address."
)
self.msg_error_invaliddual = g.get(
"msg_error_invaliddual", "<b>{i}</b> is an invalid {qt}."
)
self.msg_error_general = g.get("msg_error_general", "A general error occurred.")
self.msg_max_prefix = g.get(
"msg_max_prefix",
"Prefix length must be smaller than /{m}. <b>{i}</b> is too specific.",
)
self.rate_limit_query = g.get("rate_limit_query", "5")
self.message_rate_limit_query = g.get(
@ -192,13 +206,8 @@ class branding:
"logo_path",
os.path.join(hyperglass_root, "static/images/hyperglass-dark.png"),
)
self.favicon16_path = b.get(
"favicon16_path", "static/images/favicon/favicon-16x16.png"
)
self.favicon32_path = b.get(
"favicon32_path", "static/images/favicon/favicon-32x32.png"
)
self.logo_width = b.get("logo_width", "384")
self.favicon_dir = b.get("favicon_path", "static/images/favicon/")
self.placeholder_prefix = b.get(
"placeholder_prefix", "IP, Prefix, Community, or AS_PATH"
)

View file

@ -1,58 +1,23 @@
# General site-wide parameters
[[general]]
primary_asn = ""
org_name = ""
debug = false
google_analytics = ""
message_error = ""
message_blacklist = ""
message_rate_limit_query = ""
enable_bgp_route = true
enable_bgp_community = true
enable_bgp_aspath = true
enable_ping = true
enable_traceroute = true
rate_limit_query = ""
rate_limit_site = ""
cache_timeout = 120
cache_directory = ""
# primary_asn = ""
# org_name = ""
# google_analytics = ""
# enable_bgp_route = ""
# enable_bgp_community = ""
# enable_bgp_aspath = ""
# enable_ping = ""
# enable_traceroute = ""
# enable_max_prefix = ""
# max_prefix_length_ipv4 = ""
# max_prefix_length_ipv6 = ""
# Branding/Site Customization Parameters
[[branding]]
site_title = ""
title_mode = ""
title = ""
subtitle = ""
enable_footer = true
enable_credit = true
color_bg = ""
color_danger = ""
color_btn_submit = ""
color_tag_loctitle = ""
color_tag_cmdtitle = ""
color_tag_cmd = ""
color_tag_loc = ""
color_progressbar = ""
logo_path = ""
logo_width = ""
favicon16_path = ""
favicon32_path = ""
placeholder_prefix = ""
show_peeringdb = true
text_results = ""
text_location = ""
text_cache = ""
text_limiter_title = ""
text_limiter_subtitle = ""
text_500_title = ""
text_500_subtitle = ""
text_500_button = ""
text_help_bgp_route = ""
text_help_bgp_community = ""
text_help_bgp_aspath = ""
text_help_ping = ""
text_help_traceroute = ""
primary_font_url = ""
primary_font_name = ""
mono_font_url = ""
mono_font_name = ""
# site_title = ""
# title = ""
# subtitle = ""
# title_mode = ""
# logo_path = ""
# logo_width = ""
# favicon_dir = ""

View file

@ -68,8 +68,7 @@ class html:
footer_content=md.convert(footer_jinja),
logo_path=branding.logo_path,
logo_width=branding.logo_width,
favicon16_path=branding.favicon16_path,
favicon32_path=branding.favicon32_path,
favicon_dir=branding.favicon_dir,
placeholder_prefix=branding.placeholder_prefix,
show_peeringdb=branding.show_peeringdb,
text_results=branding.text_results,

View file

@ -6,14 +6,14 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<link rel="apple-touch-icon" sizes="180x180" href="static/images/favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{ favicon32_path }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ favicon16_path }}">
<link rel="manifest" href="static/images/favicon/site.webmanifest">
<link rel="mask-icon" href="static/images/favicon/safari-pinned-tab.svg" color="{{ color_tag_cmd }}">
<link rel="shortcut icon" href="static/images/favicon/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="{{ favicon_dir }}apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{ favicon_dir }}favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{ favicon_dir }}favicon-32x32.png">
<link rel="manifest" href="{{ favicon_dir }}site.webmanifest">
<link rel="mask-icon" href="{{ favicon_dir }}safari-pinned-tab.svg" color="{{ color_tag_cmd }}">
<link rel="shortcut icon" href="{{ favicon_dir }}favicon.ico">
<meta name="msapplication-TileColor" content="{{ color_tag_loctitle }}">
<meta name="msapplication-config" content="static/images/favicon/browserconfig.xml">
<meta name="msapplication-config" content="{{ favicon_dir }}browserconfig.xml">
<meta name="theme-color" content="{{ color_btn_submit }}">
<link href="static/css/icofont/icofont.min.css" rel="stylesheet" />
<link href="static/css/hyperglass.css" rel="stylesheet" />