trigger 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- trigger/__init__.py +7 -0
- trigger/acl/__init__.py +32 -0
- trigger/acl/autoacl.py +70 -0
- trigger/acl/db.py +324 -0
- trigger/acl/dicts.py +357 -0
- trigger/acl/grammar.py +112 -0
- trigger/acl/ios.py +222 -0
- trigger/acl/junos.py +422 -0
- trigger/acl/models.py +118 -0
- trigger/acl/parser.py +168 -0
- trigger/acl/queue.py +296 -0
- trigger/acl/support.py +1431 -0
- trigger/acl/tools.py +746 -0
- trigger/bin/__init__.py +0 -0
- trigger/bin/acl.py +233 -0
- trigger/bin/acl_script.py +574 -0
- trigger/bin/aclconv.py +82 -0
- trigger/bin/check_access.py +93 -0
- trigger/bin/check_syntax.py +66 -0
- trigger/bin/fe.py +197 -0
- trigger/bin/find_access.py +191 -0
- trigger/bin/gnng.py +434 -0
- trigger/bin/gong.py +86 -0
- trigger/bin/load_acl.py +841 -0
- trigger/bin/load_config.py +18 -0
- trigger/bin/netdev.py +317 -0
- trigger/bin/optimizer.py +638 -0
- trigger/bin/run_cmds.py +18 -0
- trigger/changemgmt/__init__.py +352 -0
- trigger/changemgmt/bounce.py +57 -0
- trigger/cmds.py +1217 -0
- trigger/conf/__init__.py +94 -0
- trigger/conf/global_settings.py +674 -0
- trigger/contrib/__init__.py +7 -0
- trigger/exceptions.py +307 -0
- trigger/gorc.py +172 -0
- trigger/netdevices/__init__.py +1288 -0
- trigger/netdevices/loader.py +174 -0
- trigger/netscreen.py +1030 -0
- trigger/packages/__init__.py +6 -0
- trigger/packages/peewee.py +8084 -0
- trigger/rancid.py +463 -0
- trigger/tacacsrc.py +584 -0
- trigger/twister.py +2203 -0
- trigger/twister2.py +745 -0
- trigger/utils/__init__.py +88 -0
- trigger/utils/cli.py +349 -0
- trigger/utils/importlib.py +77 -0
- trigger/utils/network.py +157 -0
- trigger/utils/rcs.py +178 -0
- trigger/utils/templates.py +81 -0
- trigger/utils/url.py +78 -0
- trigger/utils/xmltodict.py +298 -0
- trigger-2.0.0.dist-info/METADATA +146 -0
- trigger-2.0.0.dist-info/RECORD +61 -0
- trigger-2.0.0.dist-info/WHEEL +5 -0
- trigger-2.0.0.dist-info/entry_points.txt +15 -0
- trigger-2.0.0.dist-info/licenses/AUTHORS.md +20 -0
- trigger-2.0.0.dist-info/licenses/LICENSE.md +28 -0
- trigger-2.0.0.dist-info/top_level.txt +2 -0
- twisted/plugins/trigger_xmlrpc.py +124 -0
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
# Default Trigger settings. Override these with settings in the module
|
|
2
|
+
# pointed-to by the TRIGGER_SETTINGS environment variable. This is pretty much
|
|
3
|
+
# an exact duplication of how Django does this.
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import socket
|
|
7
|
+
|
|
8
|
+
import IPy
|
|
9
|
+
|
|
10
|
+
# ===============================
|
|
11
|
+
# Global Settings
|
|
12
|
+
# ===============================
|
|
13
|
+
|
|
14
|
+
# This is where Trigger should look for its files.
|
|
15
|
+
PREFIX = "/etc/trigger"
|
|
16
|
+
|
|
17
|
+
# Set to True to enable GPG Authentication
|
|
18
|
+
# Set to False to use the old .tackf encryption method.
|
|
19
|
+
# Should be False unless instructions/integration is ready for GPG
|
|
20
|
+
USE_GPG_AUTH = False
|
|
21
|
+
|
|
22
|
+
# This is used for old auth method. It sucks and needs to die.
|
|
23
|
+
# TODO (jathan): This is deprecated. Remove all references to this and make GPG
|
|
24
|
+
# the default and only method.
|
|
25
|
+
USER_HOME = os.getenv("HOME")
|
|
26
|
+
TACACSRC = os.getenv("TACACSRC", os.path.join(USER_HOME, ".tacacsrc"))
|
|
27
|
+
TACACSRC_KEYFILE = os.getenv("TACACSRC_KEYFILE", os.path.join(PREFIX, ".tackf"))
|
|
28
|
+
|
|
29
|
+
# If set, use the TACACSRC_PASSPHRASE, otherwise default to TACACSRC_KEYFILE
|
|
30
|
+
TACACSRC_USE_PASSPHRASE = False
|
|
31
|
+
|
|
32
|
+
# Use this passphrase to encrypt credentials.CHANGE THIS IN YOUR FILE BEFORE
|
|
33
|
+
# USING THIS IN YOUR ENVIRONMENT.
|
|
34
|
+
TACACSRC_PASSPHRASE = ""
|
|
35
|
+
|
|
36
|
+
# Default login realm to store user credentials (username, password) for
|
|
37
|
+
# general use within the .tacacsrc
|
|
38
|
+
DEFAULT_REALM = "aol"
|
|
39
|
+
|
|
40
|
+
# Default terminal type of xterm if TERM isn't set
|
|
41
|
+
TERM_TYPE = os.getenv("TERM", "xterm")
|
|
42
|
+
|
|
43
|
+
# List of plugins allowed to be importd by Commando. Plugins should be listed as
|
|
44
|
+
# strings depicting the absolute paths.
|
|
45
|
+
#
|
|
46
|
+
# e.g. ['trigger.contrib.config_device', 'trigger.contrib.show_clock', 'bacon.cool_plugin']
|
|
47
|
+
#
|
|
48
|
+
# Currently config_device and execute_commands are automatically imported.
|
|
49
|
+
BUILTIN_PLUGINS = [
|
|
50
|
+
"trigger.contrib.commando.plugins.config_device",
|
|
51
|
+
"trigger.contrib.commando.plugins.show_clock",
|
|
52
|
+
"trigger.contrib.commando.plugins.show_version",
|
|
53
|
+
]
|
|
54
|
+
COMMANDO_PLUGINS = BUILTIN_PLUGINS
|
|
55
|
+
|
|
56
|
+
# Location of firewall policies
|
|
57
|
+
FIREWALL_DIR = "/data/firewalls"
|
|
58
|
+
|
|
59
|
+
# Location of tftproot.
|
|
60
|
+
TFTPROOT_DIR = "/data/tftproot"
|
|
61
|
+
TFTP_HOST = ""
|
|
62
|
+
|
|
63
|
+
# Add internally owned networks here. All network blocks owned/operated and
|
|
64
|
+
# considered part of your network should be included.
|
|
65
|
+
INTERNAL_NETWORKS = [
|
|
66
|
+
IPy.IP("10.0.0.0/8"),
|
|
67
|
+
IPy.IP("172.16.0.0/12"),
|
|
68
|
+
IPy.IP("192.168.0.0/16"),
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
# A dictionary keyed by manufacturer name containing a list of the device types
|
|
72
|
+
# for each that is officially supported by Trigger.
|
|
73
|
+
SUPPORTED_PLATFORMS = {
|
|
74
|
+
"a10": ["SWITCH"],
|
|
75
|
+
"arista": ["SWITCH"], # Your "Cloud" network vendor
|
|
76
|
+
"aruba": ["SWITCH"], # Aruba Wi-Fi controllers
|
|
77
|
+
"avocent": ["CONSOLE"],
|
|
78
|
+
"brocade": ["ROUTER", "SWITCH"],
|
|
79
|
+
"cisco": ["ROUTER", "SWITCH", "FIREWALL"],
|
|
80
|
+
"citrix": ["SWITCH"], # Assumed to be NetScalers
|
|
81
|
+
"cumulus": ["SWITCH"], # Any white-label hardware running Cumulus Linux
|
|
82
|
+
"dell": ["SWITCH"],
|
|
83
|
+
"f5": ["LOAD_BALANCER", "SWITCH"],
|
|
84
|
+
"force10": ["ROUTER", "SWITCH"],
|
|
85
|
+
"foundry": ["ROUTER", "SWITCH"],
|
|
86
|
+
"juniper": ["FIREWALL", "ROUTER", "SWITCH"], # Any devices running Junos
|
|
87
|
+
"mrv": ["CONSOLE", "SWITCH"],
|
|
88
|
+
"netscreen": ["FIREWALL"], # Pre-Juniper NetScreens
|
|
89
|
+
"paloalto": ["FIREWALL"],
|
|
90
|
+
"pica8": ["ROUTER", "SWITCH"],
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# List of supported vendor names derived from SUPPORTED_PLATFORMS
|
|
94
|
+
SUPPORTED_VENDORS = list(SUPPORTED_PLATFORMS)
|
|
95
|
+
VALID_VENDORS = SUPPORTED_VENDORS # For backwards compatibility
|
|
96
|
+
|
|
97
|
+
# A mapping of manufacturer attribute values to canonical vendor name used by
|
|
98
|
+
# Trigger. These single-word, lowercased canonical names are used throughout
|
|
99
|
+
# Trigger.
|
|
100
|
+
#
|
|
101
|
+
# If your internal definition differs from the UPPERCASED ones specified below
|
|
102
|
+
# (which they probably do), customize them here.
|
|
103
|
+
VENDOR_MAP = {
|
|
104
|
+
"A10 NETWORKS": "a10",
|
|
105
|
+
"ARISTA NETWORKS": "arista",
|
|
106
|
+
"ARUBA NETWORKS": "aruba",
|
|
107
|
+
"AVOCENT": "avocent",
|
|
108
|
+
"BROCADE": "brocade",
|
|
109
|
+
"CELESTICA": "cumulus",
|
|
110
|
+
"CISCO SYSTEMS": "cisco",
|
|
111
|
+
"CITRIX": "citrix",
|
|
112
|
+
"CUMULUS": "cumulus",
|
|
113
|
+
"DELL": "dell",
|
|
114
|
+
"F5 NETWORKS": "f5",
|
|
115
|
+
"FORCE10": "force10",
|
|
116
|
+
"FOUNDRY": "foundry",
|
|
117
|
+
"JUNIPER": "juniper",
|
|
118
|
+
"MRV": "mrv",
|
|
119
|
+
"NETSCREEN TECHNOLOGIES": "netscreen",
|
|
120
|
+
"PICA8": "pica8",
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
# The tuple of support device types
|
|
124
|
+
SUPPORTED_TYPES = ("CONSOLE", "DWDM", "FIREWALL", "LOAD_BALANCER", "ROUTER", "SWITCH")
|
|
125
|
+
|
|
126
|
+
# A mapping of of vendor names to the default device type for each in the
|
|
127
|
+
# event that a device object is created and the deviceType attribute isn't set
|
|
128
|
+
# for some reason.
|
|
129
|
+
DEFAULT_TYPES = {
|
|
130
|
+
"a10": "SWITCH",
|
|
131
|
+
"arista": "SWITCH",
|
|
132
|
+
"aruba": "SWITCH",
|
|
133
|
+
"avocent": "CONSOLE",
|
|
134
|
+
"brocade": "SWITCH",
|
|
135
|
+
"citrix": "SWITCH",
|
|
136
|
+
"cisco": "ROUTER",
|
|
137
|
+
"cumulus": "SWITCH",
|
|
138
|
+
"dell": "SWITCH",
|
|
139
|
+
"f5": "LOAD_BALANCER",
|
|
140
|
+
"force10": "ROUTER",
|
|
141
|
+
"foundry": "SWITCH",
|
|
142
|
+
"juniper": "ROUTER",
|
|
143
|
+
"mrv": "CONSOLE",
|
|
144
|
+
"netscreen": "FIREWALL",
|
|
145
|
+
"paloalto": "FIREWALL",
|
|
146
|
+
"pica8": "SWITCH",
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
# When a vendor is not explicitly defined within `DEFAULT_TYPES`, fallback to
|
|
150
|
+
# this type.
|
|
151
|
+
FALLBACK_TYPE = "ROUTER"
|
|
152
|
+
|
|
153
|
+
# When a manufacturer/vendor is not explicitly defined, fallback to to this
|
|
154
|
+
# value.
|
|
155
|
+
FALLBACK_MANUFACTURER = "UNKNOWN"
|
|
156
|
+
|
|
157
|
+
# ===============================
|
|
158
|
+
# Twister
|
|
159
|
+
# ===============================
|
|
160
|
+
|
|
161
|
+
# Default timeout in seconds for commands executed during a session. If a
|
|
162
|
+
# response is not received within this window, the connection is terminated.
|
|
163
|
+
DEFAULT_TIMEOUT = 5 * 60
|
|
164
|
+
|
|
165
|
+
# Default timeout in seconds for initial telnet connections.
|
|
166
|
+
TELNET_TIMEOUT = 60
|
|
167
|
+
|
|
168
|
+
# Whether or not to allow telnet fallback
|
|
169
|
+
TELNET_ENABLED = True
|
|
170
|
+
|
|
171
|
+
# Default ports for SSH
|
|
172
|
+
SSH_PORT = 22
|
|
173
|
+
|
|
174
|
+
# Default port for Telnet
|
|
175
|
+
TELNET_PORT = 23
|
|
176
|
+
|
|
177
|
+
# The preferred order in which SSH authentication methods are tried.
|
|
178
|
+
SSH_AUTHENTICATION_ORDER = ["password", "keyboard-interactive", "publickey"]
|
|
179
|
+
|
|
180
|
+
# A mapping of vendors to the types of devices for that vendor for which you
|
|
181
|
+
# would like to disable interactive (pty) SSH sessions, such as when using
|
|
182
|
+
# bin/gong.
|
|
183
|
+
SSH_PTY_DISABLED = {
|
|
184
|
+
"dell": ["SWITCH"], # Dell SSH is just straight up broken
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
# A mapping of vendors to the types of devices for that vendor for which you
|
|
188
|
+
# would like to disable asynchronous (NON-interactive) SSH sessions, such as
|
|
189
|
+
# when using twister or Commando to remotely control a device.
|
|
190
|
+
SSH_ASYNC_DISABLED = {
|
|
191
|
+
"dell": ["SWITCH"], # Dell SSH is just straight up broken
|
|
192
|
+
"foundry": ["SWITCH"], # Old Foundry switches only do SSHv1
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
# Vendors that basically just emulate Cisco's IOS and can be treated
|
|
196
|
+
# accordingly for the sake of interaction.
|
|
197
|
+
IOSLIKE_VENDORS = (
|
|
198
|
+
"a10",
|
|
199
|
+
"arista",
|
|
200
|
+
"aruba",
|
|
201
|
+
"brocade",
|
|
202
|
+
"cisco",
|
|
203
|
+
"cumulus",
|
|
204
|
+
"dell",
|
|
205
|
+
"force10",
|
|
206
|
+
"foundry",
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Commands executed on devices by default.
|
|
210
|
+
STARTUP_COMMANDS_DEFAULT = ["terminal length 0"]
|
|
211
|
+
|
|
212
|
+
# Startup commands are executed upon login to setup the terminal session for
|
|
213
|
+
# automated execution. Typically these are just to disable pagination or other
|
|
214
|
+
# settings related to capturing output asynchronously. Each vendor is mapped by
|
|
215
|
+
# name. Vendor platforms with differing startup commands based on their device
|
|
216
|
+
# type are now mapped with an underscore separation (e.g. 'Cisco ASA' becomes
|
|
217
|
+
# 'cisco_asa'). The platform-specific lookups are still done in code for now.
|
|
218
|
+
STARTUP_COMMANDS_MAP = {
|
|
219
|
+
"a10": STARTUP_COMMANDS_DEFAULT,
|
|
220
|
+
"arista": STARTUP_COMMANDS_DEFAULT + ["terminal width 999"],
|
|
221
|
+
"aruba": ["no paging"], # v6.2.x this is not necessary
|
|
222
|
+
"brocade": ["skip-page-display"],
|
|
223
|
+
"brocade_vdx": STARTUP_COMMANDS_DEFAULT,
|
|
224
|
+
"cisco": STARTUP_COMMANDS_DEFAULT,
|
|
225
|
+
"cisco_asa": ["terminal pager 0"],
|
|
226
|
+
"citrix": ["set cli mode page off"],
|
|
227
|
+
"cumulus": [], # No startup commands for Cumulus by default!
|
|
228
|
+
"dell": ["terminal datadump"],
|
|
229
|
+
"f5": ["modify cli preference pager disabled"],
|
|
230
|
+
"force10": STARTUP_COMMANDS_DEFAULT,
|
|
231
|
+
"foundry": ["skip-page-display"],
|
|
232
|
+
"juniper": ["set cli screen-length 0"],
|
|
233
|
+
"mrv": ["no pause"],
|
|
234
|
+
"netscreen": ["set console page 0"],
|
|
235
|
+
"paloalto": ["set cli scripting-mode on", "set cli pager off"],
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
# Prompts sent by devices that indicate the device is awaiting user
|
|
239
|
+
# confirmation when interacting with the device. If a continue prompt is
|
|
240
|
+
# detected, Trigger will temporarily set this value to the prompt and send
|
|
241
|
+
# along the next command (for example if you're expecting such a prompt and you
|
|
242
|
+
# want to send along "yes"). These should be as specific as possible because we
|
|
243
|
+
# want to make sure bad things don't happen.
|
|
244
|
+
CONTINUE_PROMPTS = [
|
|
245
|
+
"continue?",
|
|
246
|
+
"proceed?",
|
|
247
|
+
"(y/n):",
|
|
248
|
+
"[y/n]:",
|
|
249
|
+
"[confirm]",
|
|
250
|
+
"[yes/no]: ",
|
|
251
|
+
"overwrite file [startup-config] ?[yes/press any key for no]....",
|
|
252
|
+
"Destination filename [running-config]? ",
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
# The file path where .gorc is expected to be found.
|
|
256
|
+
GORC_FILE = "~/.gorc"
|
|
257
|
+
|
|
258
|
+
# The only root commands that are allowed to be executed when defined within
|
|
259
|
+
# ``~.gorc``. They will be filtered out by `~trigger.gorc.filter_commands()`.
|
|
260
|
+
GORC_ALLOWED_COMMANDS = (
|
|
261
|
+
"cli",
|
|
262
|
+
"enable",
|
|
263
|
+
"exit",
|
|
264
|
+
"get",
|
|
265
|
+
"monitor",
|
|
266
|
+
"ping",
|
|
267
|
+
"quit",
|
|
268
|
+
"set",
|
|
269
|
+
"show",
|
|
270
|
+
"start",
|
|
271
|
+
"term",
|
|
272
|
+
"terminal",
|
|
273
|
+
"traceroute",
|
|
274
|
+
"who",
|
|
275
|
+
"whoami",
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
# ===============================
|
|
279
|
+
# NetDevices
|
|
280
|
+
# ===============================
|
|
281
|
+
|
|
282
|
+
# Globally toggle whether to load ACL associations from the Redis database. If
|
|
283
|
+
# you don't have Redis or aren't using Trigger to manage ACLs set this to
|
|
284
|
+
# False.
|
|
285
|
+
WITH_ACLS = False
|
|
286
|
+
|
|
287
|
+
# The default administrative status (production vs. non-production) of new
|
|
288
|
+
# devices.
|
|
289
|
+
DEFAULT_ADMIN_STATUS = "PRODUCTION"
|
|
290
|
+
|
|
291
|
+
# Path to the explicit module file for autoacl.py so that we can still perform
|
|
292
|
+
# 'from trigger.acl.autoacl import autoacl' without modifying sys.path.
|
|
293
|
+
AUTOACL_FILE = os.environ.get("AUTOACL_FILE", os.path.join(PREFIX, "autoacl.py"))
|
|
294
|
+
|
|
295
|
+
# A tuple of data loader classes, specified as strings. Optionally, a tuple can
|
|
296
|
+
# be used instead of a string. The first item in the tuple should be the
|
|
297
|
+
# Loader's module, subsequent items are passed to the Loader during
|
|
298
|
+
# initialization.
|
|
299
|
+
NETDEVICES_LOADERS = (
|
|
300
|
+
"trigger.netdevices.loaders.filesystem.JSONLoader",
|
|
301
|
+
"trigger.netdevices.loaders.filesystem.XMLLoader",
|
|
302
|
+
"trigger.netdevices.loaders.filesystem.SQLiteLoader",
|
|
303
|
+
"trigger.netdevices.loaders.filesystem.RancidLoader",
|
|
304
|
+
"trigger.netdevices.loaders.filesystem.CSVLoader",
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
# A path or URL to netdevices device metadata source data, which is used to
|
|
308
|
+
# populate trigger.netdevices.NetDevices. For more information on this, see
|
|
309
|
+
# NETDEVICES_LOADERS.
|
|
310
|
+
NETDEVICES_SOURCE = os.environ.get(
|
|
311
|
+
"NETDEVICES_SOURCE", os.path.join(PREFIX, "netdevices.json")
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
# TextFSM Vendor Mappings. Override this if you have defined your own TextFSM
|
|
315
|
+
# templates.
|
|
316
|
+
TEXTFSM_VENDOR_MAPPINGS = {"cisco": ["ios", "nxos"], "arista": ["eos"]}
|
|
317
|
+
|
|
318
|
+
# TextFSM Template Path. Commando will attempt to match a given show command
|
|
319
|
+
# with a template within this folder.
|
|
320
|
+
TEXTFSM_TEMPLATE_DIR = os.getenv(
|
|
321
|
+
"TEXTFSM_TEMPLATE_DIR", os.path.join(PREFIX, "vendor/ntc_templates")
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
# TextFSM Vendor Mappings. Override this if you have defined your own TextFSM templates.
|
|
325
|
+
TEXTFSM_VENDOR_MAPPINGS = {"cisco": ["ios", "nxos"], "arista": ["eos"]}
|
|
326
|
+
|
|
327
|
+
# TextFSM Template Path. Commando will attempt to match a given show command with a template within this folder.
|
|
328
|
+
TEXTFSM_TEMPLATE_DIR = os.getenv(
|
|
329
|
+
"TEXTFSM_TEMPLATE_DIR", os.path.join(PREFIX, "vendor/ntc_templates")
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
# Whether to treat the RANCID root as a normal instance, or as the root to
|
|
333
|
+
# multiple instances. This is only checked when using RANCID as a data source.
|
|
334
|
+
RANCID_RECURSE_SUBDIRS = os.environ.get("RANCID_RECURSE_SUBDIRS", False)
|
|
335
|
+
|
|
336
|
+
# Valid owning teams (e.g. device.owningTeam) go here. These are examples and
|
|
337
|
+
# should be changed to match your environment.
|
|
338
|
+
VALID_OWNERS = (
|
|
339
|
+
#'Data Center',
|
|
340
|
+
#'Backbone Engineering',
|
|
341
|
+
#'Enterprise Networking',
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
# Fields and values defined here will dictate which Juniper devices receive a
|
|
345
|
+
# ``commit-configuration full`` when populating ``NetDevice.commit_commands`.
|
|
346
|
+
# The fields and values must match the objects exactly or it will fallback to
|
|
347
|
+
# ``commit-configuration``.
|
|
348
|
+
JUNIPER_FULL_COMMIT_FIELDS = {
|
|
349
|
+
#'deviceType': 'SWITCH',
|
|
350
|
+
#'make': 'EX4200',
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
# ===============================
|
|
354
|
+
# Prompt Patterns
|
|
355
|
+
# ===============================
|
|
356
|
+
# Specially-defined, per-vendor prompt patterns. If a vendor isn't defined here,
|
|
357
|
+
# try to use IOSLIKE_PROMPT_PAT or fallback to DEFAULT_PROMPT_PAT.
|
|
358
|
+
PROMPT_PATTERNS = {
|
|
359
|
+
"aruba": r"\(\S+\)(?: \(\S+\))?\s?#$", # ArubaOS 6.1
|
|
360
|
+
#'aruba': r'\S+(?: \(\S+\))?\s?#\s$', # ArubaOS 6.2
|
|
361
|
+
"avocent": r"\S+[#\$]|->\s?$",
|
|
362
|
+
"citrix": r"\sDone\n$",
|
|
363
|
+
# This pattern is a regex "or" combination of the Cumulus bash login prompt
|
|
364
|
+
# and IOSLIKE_PROMPT_PAT (for vtysh support)
|
|
365
|
+
"cumulus": r"(?:\S+(\(config(-[a-z:1-9]+)?\))?[\r\s]*#[\s\b]*$)|(?:.*(?:\$|#)\s?$)",
|
|
366
|
+
"f5": r".*\(tmos\).*?#\s{1,2}\r?$",
|
|
367
|
+
"juniper": r"(?:\S+\@)?\S+(?:\>|#)\s$",
|
|
368
|
+
"mrv": r"\r\n?.*(?:\:\d{1})?\s\>\>?$",
|
|
369
|
+
"netscreen": r"(\w+?:|)[\w().-]*\(?([\w.-])?\)?\s*->\s*$",
|
|
370
|
+
"paloalto": r"\r\n\S+(?:\>|#)\s?$",
|
|
371
|
+
"pica8": r"\S+(?:\>|#)\s?$",
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
# When a pattern is not explicitly defined for a vendor, this is what we'll try
|
|
375
|
+
# next (since most vendors are in fact IOS-like).
|
|
376
|
+
IOSLIKE_PROMPT_PAT = r"\S+(\(config(-[a-z:1-9]+)?\))?[\r\s]*#[\s\b]*$"
|
|
377
|
+
IOSLIKE_ENABLE_PAT = r"\S+(\(config(-[a-z:1-9]+)?\))?[\r\s]*>[\s\b]*$"
|
|
378
|
+
|
|
379
|
+
# Generic prompt to match most vendors. It assumes that you'll be greeted with
|
|
380
|
+
# a "#" prompt.
|
|
381
|
+
DEFAULT_PROMPT_PAT = r"\S+#\s?$"
|
|
382
|
+
|
|
383
|
+
# ===============================
|
|
384
|
+
# Bounce Windows/Change Mgmt
|
|
385
|
+
# ===============================
|
|
386
|
+
|
|
387
|
+
# Path of the explicit module file for bounce.py containing custom bounce
|
|
388
|
+
# window mappings.
|
|
389
|
+
BOUNCE_FILE = os.environ.get("BOUNCE_FILE", os.path.join(PREFIX, "bounce.py"))
|
|
390
|
+
|
|
391
|
+
# Default bounce timezone. All BounceWindow objects are configured using
|
|
392
|
+
# US/Eastern for now.
|
|
393
|
+
BOUNCE_DEFAULT_TZ = "US/Eastern"
|
|
394
|
+
|
|
395
|
+
# The default fallback window color for bounce windows. Must be one of
|
|
396
|
+
# ('green', 'yellow', or 'red').
|
|
397
|
+
#
|
|
398
|
+
# green: Low risk
|
|
399
|
+
# yellow: Medium risk
|
|
400
|
+
# red: High risk
|
|
401
|
+
BOUNCE_DEFAULT_COLOR = "red"
|
|
402
|
+
|
|
403
|
+
# ===============================
|
|
404
|
+
# Redis Settings
|
|
405
|
+
# ===============================
|
|
406
|
+
|
|
407
|
+
# Redis master server. This will be used unless it is unreachable.
|
|
408
|
+
REDIS_HOST = "127.0.0.1"
|
|
409
|
+
|
|
410
|
+
# The Redis port. Default is 6379.
|
|
411
|
+
REDIS_PORT = 6379
|
|
412
|
+
|
|
413
|
+
# The Redis DB. Default is 0.
|
|
414
|
+
REDIS_DB = 0
|
|
415
|
+
|
|
416
|
+
# ===============================
|
|
417
|
+
# Database Settings
|
|
418
|
+
# ===============================
|
|
419
|
+
|
|
420
|
+
# These are self-explanatory, I hope. Use the ``init_task_db`` to initialize
|
|
421
|
+
# your database after you've created it! :)
|
|
422
|
+
DATABASE_ENGINE = "mysql" # Choose 'postgresql', 'mysql', 'sqlite3'
|
|
423
|
+
DATABASE_NAME = "" # Or path to database file if using sqlite3
|
|
424
|
+
DATABASE_USER = "" # Not used with sqlite3
|
|
425
|
+
DATABASE_PASSWORD = "" # Not used with sqlite3
|
|
426
|
+
DATABASE_HOST = "" # Set to '' for localhost. Not used with sqlite3
|
|
427
|
+
DATABASE_PORT = "" # Set to '' for default. Not used with sqlite3.
|
|
428
|
+
|
|
429
|
+
# ===============================
|
|
430
|
+
# ACL Management
|
|
431
|
+
# ===============================
|
|
432
|
+
# Whether to allow multi-line comments to be used in Juniper firewall filters.
|
|
433
|
+
# Defaults to False.
|
|
434
|
+
ALLOW_JUNIPER_MULTILINE_COMMENTS = False
|
|
435
|
+
|
|
436
|
+
# FILTER names of ACLs that should be skipped or ignored by tools
|
|
437
|
+
# NOTE: These should be the names of the filters as they appear on devices. We
|
|
438
|
+
# want this to be mutable so it can be modified at runtime.
|
|
439
|
+
# TODO (jathan): Move this into Redis and maintain with 'acl' command?
|
|
440
|
+
IGNORED_ACLS = []
|
|
441
|
+
|
|
442
|
+
# FILE names ACLs that shall not be modified by tools
|
|
443
|
+
# NOTE: These should be the names of the files as they exist in FIREWALL_DIR.
|
|
444
|
+
# Trigger expects ACLs to be prefixed with 'acl.'. These are examples and
|
|
445
|
+
# should be replaced.
|
|
446
|
+
NONMOD_ACLS = []
|
|
447
|
+
|
|
448
|
+
# Mapping of real IP to external NAT. This is used by load_acl in the event
|
|
449
|
+
# that a TFTP or connection from a real IP fails or explicitly when passing the
|
|
450
|
+
# --no-vip flag.
|
|
451
|
+
# format: {local_ip: external_ip}
|
|
452
|
+
VIPS = {}
|
|
453
|
+
|
|
454
|
+
# ===============================
|
|
455
|
+
# ACL Loading/Rate-Limiting
|
|
456
|
+
# ===============================
|
|
457
|
+
# All of the following settings are currently only used in ``load_acl``. If
|
|
458
|
+
# and when the load_acl functionality gets moved into the API, this might
|
|
459
|
+
# change.
|
|
460
|
+
|
|
461
|
+
# Any FILTER name (not filename) in this list will be skipped during automatic loads.
|
|
462
|
+
AUTOLOAD_BLACKLIST = []
|
|
463
|
+
|
|
464
|
+
# Assign blacklist to filter for backwards compatibility
|
|
465
|
+
AUTOLOAD_FILTER = AUTOLOAD_BLACKLIST
|
|
466
|
+
|
|
467
|
+
# Modify this if you want to create a list that if over the specified number of
|
|
468
|
+
# routers will be treated as bulk loads.
|
|
469
|
+
# TODO (jathan): Provide examples so that this has more context/meaning. The
|
|
470
|
+
# current implementation is kind of broken and doesn't scale for data centers
|
|
471
|
+
# with a large of number of devices.
|
|
472
|
+
#
|
|
473
|
+
# Format:
|
|
474
|
+
# { 'filter_name': threshold_count }
|
|
475
|
+
AUTOLOAD_FILTER_THRESH = {}
|
|
476
|
+
|
|
477
|
+
# Any ACL applied on a number of devices >= to this number will be treated as
|
|
478
|
+
# bulk loads.
|
|
479
|
+
AUTOLOAD_BULK_THRESH = 10
|
|
480
|
+
|
|
481
|
+
# Add an acl:max_hits here if you want to override BULK_MAX_HITS_DEFAULT
|
|
482
|
+
# Keep in mind this number is PER EXECUTION of load_acl --auto (typically once
|
|
483
|
+
# per hour or 3 per bounce window).
|
|
484
|
+
#
|
|
485
|
+
# 1 per load_acl execution; ~3 per day, per bounce window
|
|
486
|
+
# 2 per load_acl execution; ~6 per day, per bounce window
|
|
487
|
+
# etc.
|
|
488
|
+
#
|
|
489
|
+
# Format:
|
|
490
|
+
# { 'filter_name': max_hits }
|
|
491
|
+
BULK_MAX_HITS = {}
|
|
492
|
+
|
|
493
|
+
# If an ACL is bulk but not in BULK_MAX_HITS, use this number as max_hits
|
|
494
|
+
BULK_MAX_HITS_DEFAULT = 1
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
# ===============================
|
|
498
|
+
# Stage ACL changes
|
|
499
|
+
# ===============================
|
|
500
|
+
# This variable should be a function that returns the contents of the ACL
|
|
501
|
+
# files that are being pushed and the tftp location for all of them
|
|
502
|
+
#
|
|
503
|
+
# input
|
|
504
|
+
# list of file names, optional log file and boolean for sanitizing
|
|
505
|
+
#
|
|
506
|
+
# return
|
|
507
|
+
# (
|
|
508
|
+
# [<list of string of file contents an each file to push>],
|
|
509
|
+
# [<list of the path to files on the tftp server to push>],
|
|
510
|
+
# [<list of files that failed to stage>]
|
|
511
|
+
# )
|
|
512
|
+
def _stage_acls(acls, log=None, sanitize_acl=False):
|
|
513
|
+
"""stage the new ACL files for load_acl"""
|
|
514
|
+
|
|
515
|
+
import os
|
|
516
|
+
import shutil
|
|
517
|
+
|
|
518
|
+
from trigger.acl import parse as acl_parse
|
|
519
|
+
from trigger.conf import settings
|
|
520
|
+
|
|
521
|
+
acl_contents = []
|
|
522
|
+
tftp_paths = []
|
|
523
|
+
|
|
524
|
+
fails = []
|
|
525
|
+
|
|
526
|
+
for acl in acls:
|
|
527
|
+
nonce = os.urandom(8).encode("hex")
|
|
528
|
+
acl_nonce = f"{acl}.{nonce}"
|
|
529
|
+
src_file = os.path.join(settings.FIREWALL_DIR, acl)
|
|
530
|
+
dst_file = os.path.join(settings.TFTPROOT_DIR, acl_nonce)
|
|
531
|
+
|
|
532
|
+
if not os.path.exists(dst_file):
|
|
533
|
+
try:
|
|
534
|
+
shutil.copyfile(src_file, dst_file)
|
|
535
|
+
except Exception:
|
|
536
|
+
fails.append(f"Unable to stage TFTP File {str(acls)}")
|
|
537
|
+
continue
|
|
538
|
+
else:
|
|
539
|
+
os.chmod(dst_file, 0o644)
|
|
540
|
+
|
|
541
|
+
with open(src_file) as src_acl:
|
|
542
|
+
file_contents = src_acl.read()
|
|
543
|
+
acl_contents.append(file_contents)
|
|
544
|
+
|
|
545
|
+
tftp_paths.append(acl_nonce)
|
|
546
|
+
|
|
547
|
+
# strip comments if brocade
|
|
548
|
+
if sanitize_acl:
|
|
549
|
+
msg = f"Sanitizing ACL {src_file} as {dst_file}"
|
|
550
|
+
log.msg(msg)
|
|
551
|
+
aclobj = acl_parse(file_contents)
|
|
552
|
+
aclobj.strip_comments()
|
|
553
|
+
output = "\n".join(aclobj.output(replace=True)) + "\n"
|
|
554
|
+
with open(dst_file, "w") as dst_acl:
|
|
555
|
+
dst_acl.write(output)
|
|
556
|
+
|
|
557
|
+
return acl_contents, tftp_paths, fails
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
STAGE_ACLS = _stage_acls
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
# ===============================
|
|
564
|
+
# Get the TFTP source
|
|
565
|
+
# ===============================
|
|
566
|
+
def _get_tftp_source(dev=None, no_vip=True): # False): #True):
|
|
567
|
+
"""
|
|
568
|
+
Determine the right TFTP source-address to use (public vs. private)
|
|
569
|
+
based on ``settings.VIPS``, and return that address.
|
|
570
|
+
|
|
571
|
+
:param dev:
|
|
572
|
+
A `~trigger.netdevices.NetDevice` object
|
|
573
|
+
"""
|
|
574
|
+
import socket
|
|
575
|
+
|
|
576
|
+
from trigger.conf import settings
|
|
577
|
+
|
|
578
|
+
host = socket.gethostbyname(socket.getfqdn())
|
|
579
|
+
|
|
580
|
+
if no_vip:
|
|
581
|
+
return host
|
|
582
|
+
elif host not in settings.VIPS:
|
|
583
|
+
return host
|
|
584
|
+
|
|
585
|
+
return settings.VIPS[host]
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
GET_TFTP_SOURCE = _get_tftp_source
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
# ===============================
|
|
592
|
+
# OnCall Engineer Display
|
|
593
|
+
# ===============================
|
|
594
|
+
# This should be a callable that returns data for your on-call engineer, or
|
|
595
|
+
# failing that None. The function should return a dictionary that looks like
|
|
596
|
+
# this:
|
|
597
|
+
#
|
|
598
|
+
# {'username': 'joegineer',
|
|
599
|
+
# 'name': 'Joe Engineer',
|
|
600
|
+
# 'email': 'joe.engineer@example.notreal'}
|
|
601
|
+
#
|
|
602
|
+
# If you want to disable it, just have it return a non-False value.
|
|
603
|
+
# If you want to use it and have it block, have it return a False value (such
|
|
604
|
+
# as None)
|
|
605
|
+
#
|
|
606
|
+
# This example is just providing a string that indicates that on-call lookup is
|
|
607
|
+
# disabled.
|
|
608
|
+
#
|
|
609
|
+
# Default: returns 'disabled'
|
|
610
|
+
def _get_current_oncall_stub(*args, **kwargs):
|
|
611
|
+
return "disabled"
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
GET_CURRENT_ONCALL = _get_current_oncall_stub
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
# ===============================
|
|
618
|
+
# CM Ticket Creation
|
|
619
|
+
# ===============================
|
|
620
|
+
# This should be a callable that creates a CM ticket and returns the ticket
|
|
621
|
+
# number.
|
|
622
|
+
#
|
|
623
|
+
# If you want to disable it, just have it return a non-False value.
|
|
624
|
+
# If you want to use it and have it block, have it return a False value (such
|
|
625
|
+
# as None)
|
|
626
|
+
#
|
|
627
|
+
# This example is just providing a string that indicates that CM ticket
|
|
628
|
+
# creation is disabled.
|
|
629
|
+
#
|
|
630
|
+
# Default: returns ' N/A (CM ticket creation is disabled)'
|
|
631
|
+
def _create_cm_ticket_stub(*args, **kwargs):
|
|
632
|
+
return " N/A (CM ticket creation is disabled)"
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
CREATE_CM_TICKET = _create_cm_ticket_stub
|
|
636
|
+
|
|
637
|
+
# ===============================
|
|
638
|
+
# Notifications
|
|
639
|
+
# ===============================
|
|
640
|
+
# Email sender for integrated toosl. Usually a good idea to make this a
|
|
641
|
+
# no-reply address.
|
|
642
|
+
EMAIL_SENDER = "nobody@not.real"
|
|
643
|
+
|
|
644
|
+
# Who to email when things go well (e.g. load_acl --auto)
|
|
645
|
+
SUCCESS_EMAILS = [
|
|
646
|
+
#'neteng@example.com',
|
|
647
|
+
]
|
|
648
|
+
|
|
649
|
+
# Who to email when things go not well (e.g. load_acl --auto)
|
|
650
|
+
FAILURE_EMAILS = [
|
|
651
|
+
#'primarypager@example.com',
|
|
652
|
+
#'secondarypager@example.com',
|
|
653
|
+
]
|
|
654
|
+
|
|
655
|
+
# The default sender for integrated notifications. This defaults to the fqdn
|
|
656
|
+
# for the localhost.
|
|
657
|
+
NOTIFICATION_SENDER = socket.gethostname()
|
|
658
|
+
|
|
659
|
+
# Destinations (hostnames, addresses) to notify when things go well.
|
|
660
|
+
SUCCESS_RECIPIENTS = [
|
|
661
|
+
# 'foo.example.com',
|
|
662
|
+
]
|
|
663
|
+
|
|
664
|
+
# Destinations (hostnames, addresses) to notify when things go not well.
|
|
665
|
+
FAILURE_RECIPIENTS = [
|
|
666
|
+
# socket.gethostname(), # The fqdn for the localhost
|
|
667
|
+
]
|
|
668
|
+
|
|
669
|
+
# This is a list of fully-qualified paths. Each path should end with a callable
|
|
670
|
+
# that handles a notification event and returns ``True`` in the event of a
|
|
671
|
+
# successful notification, or ``None``.
|
|
672
|
+
NOTIFICATION_HANDLERS = [
|
|
673
|
+
"trigger.utils.notifications.handlers.email_handler",
|
|
674
|
+
]
|