def flush_aaa_cache(appliances=[], credentials=[], timeout=120, no_check_hostname=False, Domain="", aaa_policy="", web=False): """Flushes the AAA Cache of the specified aaa_policy in the specified Domain. Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-D, --Domain`: The domain where the aaa_policy resides * `-A, --aaa-policy`: the AAAPolicy who's cache you would like to flush * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.accounts") check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) msg = "Attempting to flush AAA cache on {}".format(str(env.appliances)) logger.info(msg) if not web: print msg kwargs = {"PolicyName": aaa_policy, 'domain': Domain} responses = env.perform_action('FlushAAACache', **kwargs) logger.debug("Responses received {}".format(str(responses))) if not web: for host, resp in responses.items(): print "{}\n{}".format(host, "=" * len(host)) pprint_xml(resp.xml) else: return util.render_boolean_results_table( responses, suffix="flush_aaa_cache"), util.render_history(env)
def upload_file(appl, domain, f, overwrite, create_dir, ignore_errors, filestore=None): logger = make_logger("fs-sync") dirname = "/".join(f[1].split("/")[:-1]) location = dirname.split(":")[0] + ":" if filestore is None: filestore = appl.get_filestore(domain=domain, location=location) if create_dir: if (not appl.directory_exists(dirname, domain, filestore)) and (not appl.location_exists(dirname, domain, filestore)): print "\t\t\tCreating Directory {}".format(dirname) resp = appl.CreateDir(domain=domain, Dir=dirname) if "<error-log>" in resp.text: logger.error("An error occurred creating directory {} on {}:{}".format(dirname, appl.hostname, domain)) print "\t\t\t\tERROR Creating directory, stack trace can be found in the logs" if not ignore_errors: raise datapower.AuthenticationFailure filestore = appl.get_filestore(domain=domain, location=location) else: if (not appl.directory_exists(dirname, domain, filestore)) and (not appl.location_exists(dirname, domain, filestore)): logger.error( "Directory {} does not exist in {} domain on {}".format( dirname, domain, appl.hostname)) _exit() resp = appl.set_file(f[0], f[1], domain, overwrite, filestore) if not resp: print "\t\t\tNot overwriting {}".format(f[1]) return filestore
def clone_svn(server, base_uri, vcs_creds, vcs_uri, export_dir): logger = make_logger("mast.datapower.deploy") if not os.path.exists(export_dir): os.makedirs(export_dir) url = "'https://{}{}{}'".format( server, base_uri, vcs_uri).replace("//", "/") username, password = vcs_creds.split(":") command = [ "svn", "export", url, "--force", "--no-auth-cache", "--non-interactive", "--username", "'{}'".format(username), "--password", "'{}'".format(re.escape(password)) ] with cd(export_dir): out, err = system_call(command) if err: logger.err("Error received from svn: {}".format(err)) print "Error received from svn: {}".format(err) sys.exit(-1) return export_dir
def ensure_config_file_exists(): logger = make_logger("mast.datapower.deploy") config_file_default = os.path.join( mast_home, "etc", "default", "deploy.conf" ) config_file_local = os.path.join( mast_home, "etc", "local", "deploy.conf" ) error = False if not os.path.exists(config_file_default): # The default config doesn't exist with open(config_file_default, "w") as fout: fout.write(_get_data_file("deploy.conf")) msg = " ".join(( "default config file not found.", "A blank config file was placed created for you", "Please follow the instructions within this file", "to configure this script.", "The file can be found here: {}".format(config_file_default) )) logger.error(msg) error = True elif not os.path.exists(config_file_local): # The default config exists, the user needs to configure the # local config logger.error( "Configuration not found please follow the instructions " "here {} to configure this script".format(config_file_default)) error = True if error: print "Error: Config file does not exists, see log for details" sys.exit(-1)
def handle(plugin): """main funcion which will be routed to the plugin's endpoint""" logger = make_logger("mast.plugin_functions") import urllib if flask.request.method == 'GET': logger.info("GET Request received") name = flask.request.args.get('callable') logger.debug("name: {}".format(name)) appliances = flask.request.args.getlist('appliances[]') logger.debug("appliances: {}".format(str(appliances))) credentials = [xordecode(urllib.unquote(_), key=xorencode( flask.request.cookies["9x4h/mmek/j.ahba.ckhafn"])) for _ in flask.request.args.getlist('credentials[]')] logger.debug("getting form") try: form = get_form(plugin.replace("mast.", ""), name, appliances, credentials) except: logger.exception("An unhandled exception occurred during execution.") raise logger.debug("Got form") return form elif flask.request.method == 'POST': logger.info("Received POST request for {}".format(plugin)) try: return flask.Markup(str(call_method(plugin, flask.request.form))) except: logger.exception("An unhandled exception occurred during processing of request.") raise
def list_checkpoints(appliances=[], credentials=[], timeout=120, no_check_hostname=False, Domain="", web=False): """Lists the checkpoints which are currently in the specified domain Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-D, --Domain`: The domain to list the checkpoints for * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.backups") check_hostname = not no_check_hostname env = datapower.Environment( appliances, credentials, timeout, check_hostname=check_hostname) logger.info( "Attempting to list checkpoints for {} in {} domain".format( str(env.appliances), Domain)) resp = env.perform_action("get_existing_checkpoints", domain=Domain) logger.debug("Responses received: {}".format(str(resp))) if web: return (util.web_list_checkpoints(resp, Domain), util.render_history(env)) for host, d in resp.items(): print host, '\n', '=' * len(host) for key, value in d.items(): print key, "-".join(value["date"]), ":".join(value["time"]) print
def main(appliances=[], credentials=[], domains=[], no_check_hostname=False, max_sessions=20, timeout=120): logger = make_logger("session_mon") check_hostname = not no_check_hostname env = datapower.Environment( appliances, credentials, timeout, check_hostname=check_hostname) if not domains: domains = ["all-domains"] for appl in env.appliances: print(appl.hostname) response = appl.get_status("ActiveUsers") _domains = domains if "all-domains" in domains: _domains = appl.domains for domain in _domains: print("\t{}".format(domain)) sessions = find_sessions(response_xml=response.xml) logger.debug( "{} total active sessions found on {}".format( len(sessions), appl.hostname ) ) users = get_users_with_sessions(sessions, domain) for user in users: print("\t\t{}".format(user)) users_sessions = get_users_session_ids(sessions, user) logger.debug( "\t\t\tuser {} found with {} active sessions".format( user, len(users_sessions) ) ) print( "\t\t\tuser {} found with {} active sessions".format( user, len(users_sessions) ) ) if len(users_sessions) > max_sessions: logger.info( "user {} found with {} active sessions, this is greater than max, disconnecting.".format( user, len(users_sessions) ) ) print( "\t\t\tuser {} found with {} active sessions, this is greater than max, disconnecting.".format( user, len(users_sessions) ) ) disconnect_all(appl, user, users_sessions)
def initialize_plugins(): """ _function_: `mast.datapower.web.initialize_plugins()` Initializes all of the plugins for the MAST web GUI Logs to: `gui.log` Parameters: This function accepts no arguments. """ logger = make_logger("gui") logger.debug("Running as user {}".format(getpass.getuser())) logger.debug("Running in directory {}".format(os.getcwd())) logger.debug("Attempting to retrieve list of web plugins") plugins_dict = {} for ep in pkg_resources.iter_entry_points(group='mast_web_plugin'): logger.debug("found plugin: {}".format(ep.name)) try: plugins_dict.update({ep.name: ep.load()}) except: logger.exception( "An unhandled exception occurred during execution.") pass logger.info("Collected plugins {}".format(str(plugins_dict.keys()))) plugins = {'css': '', 'html': '', 'js': '', 'tabs': ''} for name, cls in sorted(plugins_dict.items()): _plugin = cls() plugins[name] = _plugin try: plugins["html"] += flask.Markup(_plugin.html()) plugins["tabs"] += flask.Markup( '<li><a href="#mast.datapower.{0}">{0}</a></li>'.format(name)) plugins["css"] += flask.Markup(_plugin.css()) plugins["js"] += flask.Markup(_plugin.js()) except: logger.exception( "An unhandled exception occured while attempting " "to gather the content for web plugin {}".format(name)) raise # Route function try: app.add_url_rule('/%s' % (name), view_func=_plugin.route, methods=["GET", "POST", "DELETE", "PUT"]) except: logger.exception( "An unhandled exception occured while attempting " "to assign a handler for web plugin {}".format(name)) raise return plugins
def flush_rbm_cache(appliances=[], credentials=[], timeout=120, no_check_hostname=False, Domain="", web=False): """Flush the RBM Cache in the specified Domain Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-D, --Domain`: The domain for which to flush the RBM Cache * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.accounts") check_hostname = not no_check_hostname env = datapower.Environment( appliances, credentials, timeout, check_hostname=check_hostname) msg = "Attempting to flush RBM cache on {}".format(str(env.appliances)) logger.info(msg) if not web: print msg responses = env.perform_action('FlushRBMCache', **{'domain': Domain}) logger.debug("Responses received {}".format(str(responses))) if not web: for host, resp in responses.items(): print "{}\n{}".format(host, "="*len(host)) pprint_xml(resp.xml) else: return util.render_boolean_results_table( responses, suffix="flush_rbm_cache"), util.render_history(env)
def list_checkpoints(appliances=[], credentials=[], timeout=120, no_check_hostname=False, Domain="", web=False): """Lists the checkpoints which are currently in the specified domain Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-D, --Domain`: The domain to list the checkpoints for * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.backups") check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) logger.info("Attempting to list checkpoints for {} in {} domain".format( str(env.appliances), Domain)) resp = env.perform_action("get_existing_checkpoints", domain=Domain) logger.debug("Responses received: {}".format(str(resp))) if web: return (util.web_list_checkpoints(resp, Domain), util.render_history(env)) for host, d in resp.items(): print host, '\n', '=' * len(host) for key, value in d.items(): print key, "-".join(value["date"]), ":".join(value["time"]) print
def create_inprogress_file(environment): logger = make_logger("mast.datapower.deploy") fname = os.path.join(mast_home, "tmp", "{}.inprogress".format(environment)) if os.path.exists(fname): logger.error("Deployment already in progress, aborting!") print "Deployment already in progress, aborting!" sys.exit(-1) else: with open(fname, "w") as fout: fout.write(Timestamp().timestamp)
def run(self): """ _method_: `mast.datapower.web.Plugin.run(self)` This method is responsible for starting the web gui. It will log to `mast.datapower.web.log` When starting and/or stopping. """ logger = make_logger("mast.datapower.web") logger.info("Attempting to start web gui.") main() logger.info("web gui stopped")
def __init__(self): logger = make_logger("mast.status") global mast_home logger.debug("found MAST_HOME: {}".format(mast_home)) self.route = self.status config_file = os.path.join(mast_home, "etc", "default", "status.conf") if not os.path.exists(config_file): logger.debug("Config file doesn't exist creating default config") with open(config_file, "w") as fout: fout.write(get_data_file("plugin.conf"))
def main(): """ _function_: `mast.datapower.web.main()` This is the main function which will spin up a server listening to the configured port and block until a SIGTERM or equivalent (Ctrl + C) is received at which point it will quit. Logs to: `gui.main.log` Parameters: This function does not accept any arguments. """ logger = make_logger("gui.main") logger.debug("Running as user {}".format(getpass.getuser())) logger.debug("Running in directory {}".format(os.getcwd())) cherrypy.tree.graft(app, '/') # Set the configuration of the web server cherrypy.config.update({ 'engine.autoreload.on': False, 'log.screen': False, 'server.socket_port': port, 'server.socket_host': host, 'server.max_request_body_size': max_file_upload_size }) if secure: logger.debug("Configuring TLS") cherrypy.server.ssl_module = 'builtin' CherryPyWSGIServer.ssl_adapter = BuiltinSSLAdapter( cert, key, cacert) # Start the CherryPy WSGI web server try: engine = cherrypy.engine engine.signal_handler.subscribe() if hasattr(engine, "console_control_handler"): engine.console_control_handler.subscribe() print "MAST Web listening on https://{}:{}".format(host, port) cherrypy.engine.start() cherrypy.engine.block() except KeyboardInterrupt: cherrypy.engine.exit() except: logger.exception( "Sorry, an unhandled exception occurred while starting CherryPy")
def run(self): """ _method_: `mast.daemon.MASTd.run(self)` This method will be called when mastd has successfully been spawned and forked. This is where most of the logic happens. If the plugin's thread is found to be dead, it will be restarted. """ logger = make_logger("mast.daemon") os.chdir(mast_home) try: if not hasattr(self, "named_objects"): self.get_plugins() threads = {} while True: for key, value in self.named_objects.items(): if key in threads.keys(): if threads[key].isAlive(): continue else: logger.debug("Plugin {} found, but dead, attempting to restart".format(key)) try: threads[key] = value() threads[key].start() continue except: logger.exception( "An unhandled exception occurred " "during execution.") continue else: logger.info( "Plugin " "{} not found. Attempting to start.".format( key)) try: threads[key] = value() threads[key].start() continue except: logger.exception( "An unhandled exception occurred " "during execution.") continue continue sleep(60) except: logger.exception( "An uhhandled exception occurred during execution") raise
def main( appliances=[], credentials=[], domains=[], no_check_hostname=False, timeout=120, object_class="", commands=[], dry_run=False, save_config=False, ): logger = make_logger("session_mon") check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) for appliance in env.appliances: print("{}\n================\n\n".format(appliance.hostname)) _domains = domains if "all-domains" in domains: _domains = appliance.domains _commands = [] for domain in _domains: config = appliance.get_config( _class=object_class, domain=domain, persisted=False, ) objs = config.xml.findall(datapower.CONFIG_XPATH) if not objs: continue _commands.append("switch domain {}".format(domain)) _commands.append("co") for obj in objs: _commands.append("{} {}".format(object_class, obj.get("name"))) for command in commands: _commands.append(command) _commands.append("exit") if save_config: _commands.append("write mem") _commands.append("exit") if dry_run: for _command in _commands: print(_command) else: appliance.ssh_connect() for _command in _commands: print(appliance.ssh_issue_command(_command)) appliance.ssh_disconnect()
def status(self): logger = make_logger("mast.datapower.status") t = Timestamp() check_hostname = "true" in flask.request.form.get( 'check_hostname').lower() appliances = flask.request.form.getlist('appliances[]') credentials = [xordecode( _, key=xorencode( flask.request.cookies["9x4h/mmek/j.ahba.ckhafn"])) for _ in flask.request.form.getlist('credentials[]')] if not appliances: return flask.abort(404) env = datapower.Environment( appliances, credentials, check_hostname=check_hostname) providers = flask.request.form.getlist("providers[]") resp = { "appliances": appliances, "time": t.short} for provider in providers: _provider = provider.split(".")[0] resp[provider] = [] for appliance in env.appliances: try: _status = appliance.get_status(_provider) except datapower.AuthenticationFailure: # This is to handle an intermittent authentication failure # sometimes issued by the DataPower. We will sleep 2 # seconds and try again sleep(2) try: return self.status() except: logger.exception( "An unhandled exception occurred during execution") raise except: logger.exception( "An unhandled exception occurred during execution") raise metric = _status.xml.find(PROVIDER_MAP[provider]).text resp[provider].append(metric) return flask.jsonify(resp)
def main(): """ _function_: `mast.datapower.web.main()` This is the main function which will spin up a server listening to the configured port and block until a SIGTERM or equivalent (Ctrl + C) is received at which point it will quit. Logs to: `gui.main.log` Parameters: This function does not accept any arguments. """ logger = make_logger("gui.main") logger.debug("Running as user {}".format(getpass.getuser())) logger.debug("Running in directory {}".format(os.getcwd())) cherrypy.tree.graft(app, '/') # Set the configuration of the web server cherrypy.config.update({ 'engine.autoreload.on': False, 'log.screen': False, 'server.socket_port': port, 'server.socket_host': host, 'server.max_request_body_size': max_file_upload_size }) if secure: logger.debug("Configuring TLS") cherrypy.server.ssl_module = 'builtin' WSGIServer.ssl_adapter = BuiltinSSLAdapter(cert, key, cacert) # Start the CherryPy WSGI web server try: engine = cherrypy.engine engine.signal_handler.subscribe() if hasattr(engine, "console_control_handler"): engine.console_control_handler.subscribe() print "MAST Web listening on https://{}:{}".format(host, port) cherrypy.engine.start() cherrypy.engine.block() except KeyboardInterrupt: cherrypy.engine.exit() except: logger.exception( "Sorry, an unhandled exception occurred while starting CherryPy")
def clone_repo_from_vcs(vcs_details): logger = make_logger("mast.datapower.deploy") vcs_type = vcs_details[0] if vcs_type.lower() == "git": repo_path = clone_git(*vcs_details[1:]) elif vcs_type.lower() == "svn": repo_path = clone_svn(*vcs_details[1:]) elif vcs_type.lower() == "tfs": repo_path = clone_tfs(*vcs_details[1:]) else: logger.error("Unsupported VCS type defined") print "Unsupported VCS type defined" sys.exit(-1) return repo_path
def run(self): """ _method_: `mast.daemon.MASTd.run(self)` This function does the brunt of the work by looping through the plugins and starting them. After that it enters an infinite loop checking the status of each plugin. If the plugin is found dead it will attempt to restart the plugin. """ logger = make_logger("mast.daemon") servicemanager.LogInfoMsg("Inside run") global PLUGINS servicemanager.LogInfoMsg("Plugins: {}".format(PLUGINS)) try: threads = {} servicemanager.LogInfoMsg("Entering main loop") while not self.stop_requested: for key, value in PLUGINS.items(): if key in threads.keys(): if threads[key].isAlive(): continue else: logger.debug("Plugin {} found, but dead, attempting to restart".format(key)) try: threads[key] = value() threads[key].start() logger.debug("Plugin {} started".format(key)) continue except: logger.exception("An unhandled exception " "occurred during execution.") continue else: logger.info("Plugin " "{} not found. Attempting to start.".format(key)) try: threads[key] = value() threads[key].start() continue except: logger.exception("An unhandled exception occurred " "during execution.") continue continue rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout) # Check to see if self.hWaitStop happened if rc == win32event.WAIT_OBJECT_0: # Stop signal encountered servicemanager.LogInfoMsg("SomeShortNameVersion - STOPPED!") break except: logger.exception("An uhhandled exception occurred during execution") raise
def __init__(self): logger = make_logger("mast.status") global mast_home logger.debug("found MAST_HOME: {}".format(mast_home)) self.route = self.status config_file = os.path.join( mast_home, "etc", "default", "status.conf") if not os.path.exists(config_file): logger.debug("Config file doesn't exist creating default config") with open(config_file, "w") as fout: fout.write(get_data_file("plugin.conf"))
def status(self): logger = make_logger("mast.datapower.status") t = Timestamp() check_hostname = "true" in flask.request.form.get( 'check_hostname').lower() appliances = flask.request.form.getlist('appliances[]') credentials = [ xordecode(_, key=xorencode( flask.request.cookies["9x4h/mmek/j.ahba.ckhafn"])) for _ in flask.request.form.getlist('credentials[]') ] if not appliances: return flask.abort(404) env = datapower.Environment(appliances, credentials, check_hostname=check_hostname) providers = flask.request.form.getlist("providers[]") resp = {"appliances": appliances, "time": t.short} for provider in providers: _provider = provider.split(".")[0] resp[provider] = [] for appliance in env.appliances: try: _status = appliance.get_status(_provider) except datapower.AuthenticationFailure: # This is to handle an intermittent authentication failure # sometimes issued by the DataPower. We will sleep 2 # seconds and try again sleep(2) try: return self.status() except: logger.exception( "An unhandled exception occurred during execution") raise except: logger.exception( "An unhandled exception occurred during execution") raise metric = _status.xml.find(PROVIDER_MAP[provider]).text resp[provider].append(metric) return flask.jsonify(resp)
def get_plugins(self): """ _method_: `mast.daemon.MASTd.get_plugins(self)` This method uses `pkg_resources.iter_entry_points` to locate all `mastd_plugin`s and return them. """ logger = make_logger("mast.daemon") self.named_objects = {} for ep in pkg_resources.iter_entry_points(group="mastd_plugin"): try: self.named_objects.update({ep.name: ep.load()}) except: logger.exception("An unhandled exception occurred during execution.") pass logger.info("Collected plugins {}".format(str(self.named_objects.keys())))
def from_dp(appliances=[], credentials=[], timeout=120, no_check_hostname=False, location="", out_dir="tmp", Domain="", recursive=False, ignore_errors=False): """This will get all of the files from a directory on the appliances in the specified domain.""" logger = make_logger("fs-sync") check_hostname = not no_check_hostname env = datapower.Environment( appliances, credentials, timeout, check_hostname=check_hostname) for appliance in env.appliances: logger.info("Syncing with {}".format(appliance.hostname)) print appliance.hostname print "\t", Domain _out_dir = os.path.join(out_dir, appliance.hostname) print "\t\t", location, "->", _out_dir if not os.path.exists(_out_dir) or not os.path.isdir(_out_dir): logger.info("Making directory {}".format(_out_dir)) os.makedirs(_out_dir) try: download_directory(appliance, location, _out_dir, Domain, recursive=recursive, ignore_errors=ignore_errors) except: logger.exception("An error occurred during download of " "{} to {} from {}:{}".format(location, _out_dir, appliance.hostname, Domain)) print "\t\t\tERROR downloading above directory stacktrace can be found in the logs" if ignore_errors: pass else: raise
def main(appliances=[], credentials=[], timeout=120, no_check_hostname=False, domains=[], out_file="tmp/cert-audit.json", object_classes=[], object_names=[]): logger = make_logger("find_refs") if out_file is None: logger.error("Must specify out file") sys.exit(2) if not os.path.exists(os.path.dirname(out_file)): os.makedirs(os.path.dirname(out_file)) check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) out = tree() for appliance in env.appliances: hostname = appliance.hostname print(hostname) logger.info("Checking appliance {}".format(appliance.hostname)) _domains = domains if "all-domains" in domains: _domains = appliance.domains for domain in _domains: print("\t{}".format(domain)) logger.info("In domain {}".format(domain)) config = etree.fromstring(str(appliance.get_config(domain=domain))) for object_class, object_name in splice(object_classes, object_names): obj = config.xpath(".//{}[@name='{}']".format( object_class, object_name)) if not obj: print("\t\t{}: {} Not Found".format( object_class, object_name)) continue print("\t\t{}: {}".format(object_class, object_name)) node = out[hostname][domain]["{}: {}".format( object_class, object_name)] recurse_config(config, object_class, object_name, node) with open(out_file, "wb") as fp: json.dump(out, fp, indent=4)
def get_plugins(self): """ _method_: `mast.daemon.MASTd.get_plugins(self)` This method uses `pkg_resources.iter_entry_points` to locate all `mastd_plugin`s and return them. """ logger = make_logger("mast.daemon") self.named_objects = {} for ep in pkg_resources.iter_entry_points(group='mastd_plugin'): try: self.named_objects.update({ep.name: ep.load()}) except: logger.exception( "An unhandled exception occurred during execution.") pass logger.info( "Collected plugins {}".format( str(self.named_objects.keys())))
def log_access(): """ _function_: `mast.datapower.web.log_access()` This function logs information about each request received. Logs To: `mast.web.access.log` Parameters: This function accepts no arguments. """ r = flask.request logger = make_logger("mast.web.access") logger.info("method: {}, url: {}, client: {}".format( r.method, r.url, r.remote_addr)) logger.debug("data: {}, headers: {}".format( r.data, str(r.headers).replace("\n", "; ")))
def disconnect_all(appliance, user, ids): logger = make_logger("session_mon") for session_id in ids: resp = appliance.Disconnect(id=session_id) if resp: logger.debug( "Successfully disconnected {} - {} from {}".format( user, session_id, appliance.hostname ) ) else: logger.error( "Failed to disconnect {} - {} from {}. Response: {}".format( user, session_id, appliance.hostname, repr(resp) ) )
def __init__(self, args): """ _method_: `mast.daemon.MASTd.__init__(self, args)` Initialize the service. Parameters: * `args`: These are the args being passed to `win32serviceutil.ServiceFramework`. These args usually come from the user via the command line, and should not need to be called directly. """ logger = make_logger("mast.daemon") logger.debug("mastd running in {}".format(os.getcwd())) servicemanager.LogInfoMsg("In __init__ args: {}".format(str(args))) win32serviceutil.ServiceFramework.__init__(self, args) self.stop_event = win32event.CreateEvent(None, 0, 0, None) socket.setdefaulttimeout(60) self.timeout = 60000 self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) self.stop_requested = False
def main(appliances=[], credentials=[], no_check_hostname=False, max_sessions=20, timeout=120): logger = make_logger("session_mon") check_hostname = not no_check_hostname env = datapower.Environment( appliances, credentials, timeout, check_hostname=check_hostname) for appl in env.appliances: response = appl.get_status("ActiveUsers") sessions = find_sessions(response_xml=response.xml) logger.debug( "{} total active sessions found on {}".format( len(sessions), appl.hostname ) ) users = get_users_with_sessions(sessions) for user in users: users_sessions = get_users_session_ids(sessions, user) logger.debug( "user {} found with {} active sessions".format( user, len(users_sessions) ) ) if len(users_sessions) > max_sessions: logger.info( "user {} found with {} active sessions, this is greater than max, disconnecting.".format( user, len(users_sessions) ) ) disconnect_all(appl, user, users_sessions)
def main( appliances=[], credentials=[], domains=[], no_check_hostname=False, timeout=120, ): logger = make_logger("session_mon") check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) for appliance in env.appliances: print(appliance.hostname) _domains = domains if "all-domains" in domains: _domains = appliance.domains for domain in _domains: print("\t{}".format(domain)) config = appliance.get_config( _class="WSRRSubscription", domain=domain, persisted=False, ) objs = config.xml.findall(datapower.CONFIG_XPATH) if not objs: continue for obj in objs: print("\t\t{}".format(obj.get("name"))) resp = appliance.WsrrSynchronize( domain=domain, WSRRSubscription=obj.get("name")) print("\t\t\t" + "\n\t\t\t{}".join( resp.xml.find( ".//{http://www.datapower.com/schemas/management}result" ).itertext()))
def disconnect_all(appliance, user, ids): logger = make_logger("session_mon") for session_id in ids: resp = appliance.Disconnect(id=session_id, domain="default") if resp: logger.debug( "Successfully disconnected {} - {} from {}".format( user, session_id, appliance.hostname ) ) print( "\t\t\t\tSuccessfully disconnected {} - {} from {}".format( user, session_id, appliance.hostname ) ) else: logger.error( "Failed to disconnect {} - {} from {}. Response: {}".format( user, session_id, appliance.hostname, repr(resp) ) ) print( "\t\t\t\tFailed to disconnect {} - {} from {}. Response: {}".format( user, session_id, appliance.hostname, repr(resp) ) )
def handle(plugin): """main funcion which will be routed to the plugin's endpoint""" logger = make_logger("mast.plugin_functions") import urllib if flask.request.method == 'GET': logger.info("GET Request received") name = flask.request.args.get('callable') logger.debug("name: {}".format(name)) appliances = flask.request.args.getlist('appliances[]') logger.debug("appliances: {}".format(str(appliances))) credentials = [ xordecode(urllib.unquote(_), key=xorencode( flask.request.cookies["9x4h/mmek/j.ahba.ckhafn"])) for _ in flask.request.args.getlist('credentials[]') ] logger.debug("getting form") try: form = get_form(plugin.replace("mast.", ""), name, appliances, credentials) except: logger.exception( "An unhandled exception occurred during execution.") raise logger.debug("Got form") return form elif flask.request.method == 'POST': logger.info("Received POST request for {}".format(plugin)) try: return flask.Markup(str(call_method(plugin, flask.request.form))) except: logger.exception( "An unhandled exception occurred during processing of request." ) raise
def set_checkpoint(appliances=[], credentials=[], timeout=120, no_check_hostname=False, Domain=['default'], comment='', remove_oldest=True, web=False): """Sets a checkpoint in the given domains on the specified appliances Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-D, --Domain`: Domains to set checkpoints in. To spcify multiple domains, use multiple entries of the form `[-D domain1 [-D domain2...]]` * `-C, --comment`: The comment to use for the checkpoint (will also be used to build the checkpoint name) * `-N, --no-remove-oldest`: If specified this script will attempt to remove the oldest checkpoint __IF__ the maximum number of checkpoints exist * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.backups") check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) logger.info("Attempting to set checkpoint on {} in {} domain(s)".format( str(env.appliances), str(Domain))) t = Timestamp() if web: header_row = ("Appliance", "Result") rows = [] for appliance in env.appliances: if not web: print appliance.hostname _domains = Domain print Domain print _domains if "all-domains" in _domains: _domains = appliance.domains print _domains for domain in _domains: print domain if not web: print "\t", domain name = '{0}-{1}-{2}'.format(comment, domain, t.timestamp) logger.debug( "Attempting to set checkpoint {} on {} in {} domain".format( name, appliance, domain)) if remove_oldest: _max = appliance.max_checkpoints(domain) if len(appliance.get_existing_checkpoints(domain)) >= _max: logger.info( "Maximum number of checkpoints for domain " "{} on {} reached. Removing oldest checkpoint.".format( domain, appliance.hostname)) _resp = appliance.remove_oldest_checkpoint(domain) logger.debug("Response received: {}".format(_resp)) kwargs = {'domain': domain, 'ChkName': name} resp = appliance.SaveCheckpoint(**kwargs) logger.debug("Response received: {}".format(resp)) if not web: if resp: print "\t\tSuccessful" else: print "\t\tFailed" if web: if resp: rows.append( ("{}-{}-set_checkpoint".format(appliance.hostname, domain), "Succeeded")) else: rows.append( ("{}-{}-set_checkpoint".format(appliance.hostname, domain), "Failed")) if web: return flask.render_template("results_table.html", header_row=header_row, rows=rows), util.render_history(env)
def restore_normal_backup(appliances=[], credentials=[], timeout=120, no_check_hostname=False, file_in=None, Domain="", source_type="ZIP", overwrite_files=True, overwrite_objects=True, rewrite_local_ip=True, deployment_policy=None, import_domain=True, reset_domain=True, dry_run=False, out_dir="tmp", web=False): """Restores a normal backup to the specified appliances and Domains. Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-f, --file-in`: The backup file which will be restored. This must be in the format specified in source_type * `-D, --Domain`: The domain to which to restore the backup * `-s, --source-type`: The type of backup, must be either "ZIP" or "XML" * `-N, --no-overwrite-files`: Whether to overwrite files when restoring the backup * `--no-overwrite-objects`: Whether to overwrite objects when restoring the backup * `--no-rewrite-local-ip`: Whether to rewrite the local IP Addresses * `-d, --deployment-policy`: The deployment policy to apply when restoring the backup * `--no-import-domain`: Whether we are importing a domain * `--no-reset-domain`: Whether to reset the domain * `--dry-run`: Whether this should be a dry-run * `-o, --out_dir`: (NOT NEEDED IN WEB GUI) The directory (local) where you would want all of the files generated by the restore to be placed * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.backups") t = Timestamp() check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) logger.info( "Attempting to restore normal backup on {} in {} domain".format( str(env.appliances), Domain)) kwargs = { "file_in": file_in, "source_type": source_type, "domain": Domain, "overwrite_files": overwrite_files, "overwrite_objects": overwrite_objects, "rewrite_local_ip": rewrite_local_ip, "deployment_policy": deployment_policy, "import_domain": import_domain, "reset_domain": reset_domain, "dry_run": dry_run } resp = env.perform_action("restore_normal_backup", **kwargs) logger.debug("Responses received {}".format(str(resp))) out_dir = os.path.join(out_dir, "restore_normal_backup", t.timestamp) os.makedirs(out_dir) for host, r in resp.items(): filename = os.path.join( out_dir, "{}-{}-{}-results.xml".format(t.timestamp, host, Domain)) with open(filename, 'wb') as fout: fout.write(r.pretty) if web: return util.render_see_download_table(resp), util.render_history(env)
filename, size, modified)) for directory in _location.findall(".//directory"): dir_name = directory.get("name") print "\t\t\t{}".format(dir_name) for _file in directory.findall(".//file"): filename = _file.get("name") print "\t\t\t\t{}".format(filename) size = _file.find("size").text modified = _file.find("modified").text rows.append((appliance.hostname, domain, dir_name, filename, size, modified)) wb = openpyxl.Workbook() ws = wb.active for row in rows: ws.append(row) wb.save(out_file) if __name__ == "__main__": try: cli = Cli(main=main) cli.run() except: make_logger("error").exception("An unhandled exception occured.") raise
atexit.register(env.perform_action, "ssh_disconnect") for appliance in env.appliances: issue_command = appliance.ssh_issue_command print appliance.hostname, "\n" print issue_command("config") print issue_command("interface {}".format(EthernetInterface)) print issue_command("show route") for static_route in del_static_routes: print issue_command("no ip route {}".format(static_route)) for static_route in add_static_routes: print issue_command("ip route {}".format(static_route)) print issue_command("exit") if save_config: print issue_command("write mem") print issue_command("y") print issue_command("show route") print issue_command("exit") if __name__ == "__main__": cli = Cli(main=main, description=main.__doc__) try: cli.run() except SystemExit: # Don't need logs when user asks for help pass except: make_logger("error").exception( "An exception ocurred during execution.") raise
def cert_file_audit(appliances=[], credentials=[], timeout=120, no_check_hostname=False, out_file=os.path.join("tmp", "cert-file-audit.xlsx"), web=False): """Perform an audit of all files which reside in `cert:`, `pubcert:` and `sharedcert:` on the specified appliances. Output: A table and an excel spreadsheet. Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-o, --out-file`: The excel spreadsheet to output, use either relative or absolute path. The file should end in `.xlsx` * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("cert-file-audit") if out_file is None: logger.error("Must specify out file") if not web: print "Must specify out_file" sys.exit(2) if not os.path.exists(os.path.dirname(out_file)): os.makedirs(os.path.dirname(out_file)) locations = ["cert:", "pubcert:", "sharedcert:"] check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) header_row = ["appliance", "domain", "directory", "filename", "size", "modified"] rows = [header_row] for appliance in env.appliances: if not web: print appliance.hostname domain = "default" for location in locations: if not web: print "\t{}".format(location) filestore = appliance.get_filestore(domain=domain, location=location) _location = filestore.xml.find(datapower.FILESTORE_XPATH) if _location is None: continue if _location.findall("./file") is not None: for _file in _location.findall("./file"): dir_name = _location.get("name") filename = _file.get("name") if not web: print "\t\t{}".format(filename) size = _file.find("size").text modified = _file.find("modified").text rows.append([appliance.hostname, domain, dir_name, filename, size, modified]) for directory in _location.findall(".//directory"): dir_name = directory.get("name") if not web: print "\t\t{}".format(dir_name) for _file in directory.findall(".//file"): filename = _file.get("name") if not web: print "\t\t\t{}".format(filename) size = _file.find("size").text modified = _file.find("modified").text rows.append([appliance.hostname, domain, dir_name, filename, size, modified]) wb = openpyxl.Workbook() ws = wb.active ws.title = "CertFileAudit" for row in rows: ws.append(row) wb.save(out_file) if not web: print_table(rows) else: return (html_table(rows, table_class="width-100", header_row_class="results_table_header_row", header_cell_class="results_table_header_column", body_row_class="result_table_row", body_cell_class="result_table_cell"), util.render_history(env))
print "Output of installation:\n" for line in out.splitlines(): print "\t", line if err: print "Errors were encountered during installation:\n" for line in err.splitlines(): print "\t", line else: print "No Errors were encountered during installation" print "See more details in log file: {}".format(os.path.join( dist_dir, "install.log")) if remove_build_dir: # Get out of build_dir so we can zip it up os.chdir(cwd) shutil.rmtree(build_dir) print "\n\nhotfix zip can be found here: {}".format(output_file) if __name__ == "__main__": try: cli = Cli(main=main, description=dedent(main.__doc__)) cli.run() except SystemExit: pass except: make_logger("error").exception( "An unhandled exception occurred during execution") raise
def _import(appliances=[], credentials=[], timeout=120, no_check_hostname=False, Domain=[], file_in=None, deployment_policy=None, deployment_policy_variables=None, dry_run=False, overwrite_files=True, overwrite_objects=True, rewrite_local_ip=True, source_type='ZIP', out_dir="tmp/", web=False): """Import a service/object into the specified appliances Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-D. --Domain`: The domain into which the configuration will be imported * `-f, --file-in`: The file to import into the specified domain. This __MUST__ match the format specified in source_type * `-d, --deployment-policy`: The deployment policy to use for the import (must already exist on the appliances) * `--dry-run`: Whether to do a dry-run (nothing will be imported) * `-N, --no-overwrite-files`: If specified, no files will be overwritten as part of the import * `--no-overwrite-objects`: If specified, no objects will be overwritten as part of the import * `--no-rewrite-local-ip`: If specified, no local ip addresses will be rewritten as part of the import * `-s, --source-type`: The type of file to import. Can be "XML" or "ZIP" * `-o, --out-dir`: The directory to output artifacts generated by this script * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.developer") t = Timestamp() check_hostname = not no_check_hostname env = datapower.Environment( appliances, credentials, timeout, check_hostname=check_hostname) msg = "Attempting to import {} to {}".format(file_in, str(env.appliances)) logger.info(msg) if not web: print msg results = {} out_dir = os.path.join(out_dir, "import_results", t.timestamp) os.makedirs(out_dir) for appliance in env.appliances: if not web: print appliance.hostname results[appliance.hostname] = {} domains = Domain if "all-domains" in domains: domains = appliance.domains for domain in domains: if not web: print "\t", domain kwargs = { 'domain': domain, 'zip_file': file_in, 'deployment_policy': deployment_policy, 'deployment_policy_variables': deployment_policy_variables, 'dry_run': dry_run, 'overwrite_files': overwrite_files, 'overwrite_objects': overwrite_objects, 'rewrite_local_ip': rewrite_local_ip, 'source_type': source_type} resp = appliance.do_import(**kwargs) results[appliance.hostname][domain] = resp if not web: pprint_xml(resp.xml) logger.debug("Response received: {}".format(str(resp))) filename = os.path.join( out_dir, "{}-{}-import_results.xml".format( appliance.hostname, domain ) ) with open(filename, 'wb') as fout: fout.write(resp.pretty) if web: return util.render_see_download_table( results, suffix="import"), util.render_history(env)
if version: print "mast.testsuite - version {}".format(__version__) sys.exit(0) suites = [] if unit: suites.append(unittest_suite) if integration: suites.append(integration_suite) if regression: suites.append(regression_suite) if All: suites = [unittest_suite, integration_suite, regression_suite] suite = unittest.TestSuite(suites) if out_file is "stdout": unittest.TextTestRunner(stream=sys.stdout, verbosity=0).run(suite) else: with open(out_file, "w") as fp_out: unittest.TextTestRunner(stream=fp_out, verbosity=0).run(suite) if __name__ == "__main__": cli = Cli(main=main, description=main.__doc__) try: cli.run() except SystemExit: pass except: make_logger("error").exception("An unhandled exception occurred during execution") raise
""" import os import sys from mast.cli import Cli from mast.logging import make_logger import pandas as pd def main(config_xlsx="", status_xlsx="", out_file=""): config = pd.read_excel(config_xlsx) status = pd.read_excel(status_xlsx) status.rename( columns={"hostname": "appliance", "LogTarget": "Object Name"}, inplace=True ) new = pd.merge(status, config, on=["appliance", "domain", "Object Name"]) new.to_excel(out_file) if __name__ == "__main__": try: cli = Cli(main=main) cli.run() except SystemExit: pass except: make_logger("error").exception( "Sorry, an unhandled exception occurred while executing command") raise
def export_certs(appliances=[], credentials=[], timeout=120, no_check_hostname=False, domains=[], out_dir="tmp", delay=0.5, web=False): """Export all CryptoCertificate objects which are up and enabled from the specified domains on the specified appliances in PEM format and download them to `out-dir` Output: Downloaded files Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-d, --domains`: The domains to audit, to audit all domains, provide `all-domains`, to specify multiple domains use multiple entries of the form `[-d domain1 [-d domain2...]]`. * `-o, --out-dir`: The directory to which to download the certificates. * `-D, --delay`: The amount of time in seconds to wait between exporting each certificate. If you are experiencing intermitten `AuthenticationFailure`s, it is a good idea to increase this parameter. * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("export-certs") check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) for appliance in env.appliances: logger.info("Checking appliance {}".format(appliance.hostname)) if not web: print appliance.hostname _domains = domains if "all-domains" in domains: _domains = appliance.domains for domain in _domains: logger.info("In domain {}".format(domain)) if not web: print "\t", domain # Get a list of all certificates in this domain config = appliance.get_config("CryptoCertificate", domain=domain) certs = [x for x in config.xml.findall(datapower.CONFIG_XPATH)] # Filter out disabled objects because the results won't change, # but we will perform less network traffic certs = filter( lambda x: x.find("mAdminState").text == "enabled", certs) if not certs: continue # Create a directory structure $out_dir/hostname/domain dir_name = os.path.join(out_dir, appliance.hostname, domain) if not os.path.exists(dir_name): os.makedirs(dir_name) for cert in certs: logger.info("Exporting cert {}".format(cert)) # Get filename as it will appear locally filename = cert.find("Filename").text out_file = re.sub(r":[/]*", "/", filename) out_file = out_file.split("/") out_file = os.path.join(dir_name, *out_file) # extract directory name as it will appear locally _out_dir = out_file.split(os.path.sep)[:-1] _out_dir = os.path.join(*_out_dir) # Create the directory if it doesn't exist if not os.path.exists(_out_dir): os.makedirs(_out_dir) name = cert.get("name") if not web: print "\t\t", name export = appliance.CryptoExport(domain=domain, ObjectType="cert", ObjectName=name, OutputFilename=name) # TODO: Test export and handle failure logger.info("Finished exporting cert {}".format(cert)) try: logger.info( "Retrieving file temporary:///{}".format(name)) cert = appliance.getfile(domain, "temporary:///{}".format(name)) logger.info( "Finished retrieving file temporary:///{}".format( name)) logger.info( "Attempting to delete file temporary:///{}".format( name)) appliance.DeleteFile(domain=domain, File="temporary:///{}".format(name)) logger.info( "Finished deleting file temporary:///{}".format(name)) except: logger.exception("An unhandled exception has occurred") if not web: print "SKIPPING CERT" continue cert = etree.fromstring(cert) with open(out_file, "w") as fout: _contents = insert_newlines(cert.find("certificate").text) contents = "{}\n{}\n{}\n".format( "-----BEGIN CERTIFICATE-----", _contents, "-----END CERTIFICATE-----") fout.write(contents) if web: return (util.render_see_download_table({k.hostname: "" for k in env.appliances}, "export-certs"), util.render_history(env))
for domain in _domains: changed = False print "\t", domain config = appliance.get_config(domain=domain, persisted=False) config = etree.fromstring(str(config)) objs = config.xpath('.//*[./DebugMode/text()="on"]') if len(objs): change = True for obj in objs: if not ignore_unsaved and obj.find("DebugMode").attrib.get("persisted") == "false": appliance.request.clear() request = appliance.request.request(domain=domain).modify_config()[obj.tag](name=obj.attrib.get("name")) request.append(debug_mode_off) if not dry_run: print(appliance.send_request()) else: print(appliance.request) if save_config and not dry_run and changed: appliance.SaveConfig(domain=domain) if __name__ == "__main__": cli = Cli(main=main, description=__doc__) try: cli.run() except SystemExit: pass except: make_logger("error").exception("An unhandled exception occurred") raise
def export(appliances=[], credentials=[], timeout=120, no_check_hostname=False, Domain="", object_name=None, object_class=None, comment='', format='ZIP', persisted=True, all_files=True, referenced_files=True, referenced_objects=True, out_dir='tmp', web=False): """Exports a service or object to be used to import into another domain or appliance Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-D, --Domain`: The domain from which to export service/object * `-o, --object-name`: The name of the object to export * `-O, --object-class`: The class of the object to export * `-C, --comment`: The comment to embed into the export * `-f, --format`: the format in which to export the configuration. This can be either "XML" or "ZIP" * `-N, --no-persisted`: If specified, the running configuration will be exported as opposed to the persisted configuration * `--no-all-files`: If specified, the export will not include all files * `--no-referenced-files`: If specified, the referenced files will not be included in the export * `--no-referenced-objects`: If specified, referenced objects will not be included in the export. * `--out-dir`: (**NOT NEEDED IN THE WEB GUI**)The directory (local) in which to save the export * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.developer") t = Timestamp() if object_name is None or object_class is None: try: raise TypeError("Must Provide both object name and object class") except: logger.exception("Must Provide both object name and object class") raise check_hostname = not no_check_hostname env = datapower.Environment( appliances, credentials, timeout, check_hostname=check_hostname) msg = "Attempting to export {} from {}".format(object_name, str(env.appliances)) logger.info(msg) kwargs = { 'domain': Domain, 'obj': object_name, 'object_class': object_class, 'comment': comment, 'format': format, 'persisted': persisted, 'all_files': all_files, 'referenced_objects': referenced_objects, 'referenced_files': referenced_files} results = env.perform_action( 'export', **kwargs) for hostname, _export in results.items(): d = os.path.join(out_dir, hostname, t.timestamp) os.makedirs(d) extention = format.lower() filename = os.path.join(d, '%s-%s-%s.%s' % ( t.timestamp, hostname, object_name, extention)) msg = "Writing export of {} from {} to {}".format(object_name, hostname, filename) logger.debug(msg) if not web: print msg with open(filename, 'wb') as fout: fout.write(_export) if web: return util.render_see_download_table( results, suffix="export"), util.render_history(env)
def cert_audit(appliances=[], credentials=[], timeout=120, no_check_hostname=False, domains=[], out_file="tmp/cert-audit.xlsx", delay=0.5, date_time_format="%A, %B %d, %Y, %X", localtime=False, days_only=False, web=False): """Perform an audit of all CryptoCertificate objects which are up and enabled for the specified appliances and domains. Output: A table and an excel spreadsheet. Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-d, --domains`: The domains to audit, to audit all domains, provide `all-domains`, to specify multiple domains use multiple entries of the form `[-d domain1 [-d domain2...]]`. * `-o, --out-file`: The excel spreadsheet to output, use either relative or absolute path. The file should end in `.xlsx` * `-D, --delay`: The amount of time in seconds to wait between auditing each certificate. If you are experiencing intermitten `AuthenticationFailure`s, it is a good idea to increase this parameter. * `--date-time-format`: The format for date-timestamps. Refer to [this document](https://docs.python.org/2/library/time.html#time.strftime) for information on using this parameter * `-l, --localtime`: If specified, the date-timestamps will be output in local time instead of UTC. * `--days-only`: If specified, only the number of days (floored) will be reported in the `time-since-expiration` and `time-until-expiration` columns. * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("cert-audit") if out_file is None: logger.error("Must specify out file") if not web: print "Must specify out_file" sys.exit(2) if not os.path.exists(os.path.dirname(out_file)): os.makedirs(os.path.dirname(out_file)) check_hostname = not no_check_hostname env = datapower.Environment( appliances, credentials, timeout, check_hostname=check_hostname) header_row = [ "appliance", "domain", "certificate-object", "filename", "serial-number", "subject", "signature_algorithm", "not_before", "not_after", "issuer", "is-expired", "time-since-expiration", "time-until-expiration"] rows = [header_row] for appliance in env.appliances: logger.info("Checking appliance {}".format(appliance.hostname)) if not web: print appliance.hostname _domains = domains if "all-domains" in domains: _domains = appliance.domains for domain in _domains: logger.info("In domain {}".format(domain)) if not web: print "\t", domain config = appliance.get_config("CryptoCertificate", domain=domain) certs = [x for x in config.xml.findall(datapower.CONFIG_XPATH)] # Filter out disabled objects because the results won't change, # but we will perform less network traffic certs = filter( lambda x: x.find("mAdminState").text == "enabled", certs) for cert in certs: logger.info("Exporting cert {}".format(cert)) filename = cert.find("Filename").text name = cert.get("name") _filename = name if not web: print "\t\t", name row = [appliance.hostname, domain, name, filename] appliance.CryptoExport( domain=domain, ObjectType="cert", ObjectName=name, OutputFilename=_filename) logger.info("Finished exporting cert {}".format(cert)) try: logger.info( "Retrieving file {}".format( "temporary:///{}".format(_filename))) cert = appliance.getfile( domain, "temporary:///{}".format(_filename)) logger.info( "Finished retrieving file {}".format( "temporary:///{}".format(_filename))) logger.info( "Attempting to delete file {}".format( "temporary:///{}".format(_filename))) appliance.DeleteFile( domain=domain, File="temporary:///{}".format(_filename)) logger.info( "Finished deleting file {}".format( "temporary:///{}".format(_filename))) except: logger.exception("An unhandled exception has occurred") rows.append(row) if not web: print "SKIPPING CERT" continue cert = etree.fromstring(cert) _contents = insert_newlines(cert.find("certificate").text) certificate = \ "-----BEGIN CERTIFICATE-----\n" +\ _contents +\ "\n-----END CERTIFICATE-----\n" _cert = OpenSSL.crypto.load_certificate( OpenSSL.crypto.FILETYPE_PEM, certificate) subject = "'{}'".format( ";".join( ["=".join(x) for x in _cert.get_subject().get_components()])) issuer = "'{}'".format( ";".join( ["=".join(x) for x in _cert.get_issuer().get_components()])) serial_number = _cert.get_serial_number() try: signature_algorithm = _cert.get_signature_algorithm() except AttributeError: signature_algorithm = "" local_tz = tz.tzlocal() utc_tz = tz.tzutc() notBefore_utc = parser.parse(_cert.get_notBefore()) notBefore_local = notBefore_utc.astimezone(local_tz) notAfter_utc = parser.parse(_cert.get_notAfter()) notAfter_local = notAfter_utc.astimezone(local_tz) if localtime: notAfter = notAfter_local.strftime(date_time_format) notBefore = notBefore_local.strftime(date_time_format) else: notAfter = notAfter_utc.strftime(date_time_format) notBefore = notBefore_utc.strftime(date_time_format) if _cert.has_expired(): time_since_expiration = datetime.utcnow().replace(tzinfo=utc_tz) - notAfter_utc if days_only: time_since_expiration = time_since_expiration.days else: time_since_expiration = str(time_since_expiration) time_until_expiration = 0 else: time_until_expiration = notAfter_utc - datetime.utcnow().replace(tzinfo=utc_tz) if days_only: time_until_expiration = time_until_expiration.days else: time_until_expiration = str(time_until_expiration) time_since_expiration = 0 row.extend( [serial_number, subject, signature_algorithm, notBefore, notAfter, issuer, str(_cert.has_expired()), time_since_expiration, time_until_expiration]) rows.append(row) sleep(delay) wb = openpyxl.Workbook() ws = wb.active for row in rows: ws.append(row) wb.save(out_file) if not web: print "\n\nCertificate Report (available at {}):".format(os.path.abspath(out_file)) print_table(rows) print else: return (html_table(rows, table_class="width-100", header_row_class="results_table_header_row", header_cell_class="results_table_header_column", body_row_class="result_table_row", body_cell_class="result_table_cell"), util.render_history(env))
""" """ import re import os import OpenSSL import openpyxl import pandas as pd from time import sleep from mast.cli import Cli from mast.logging import make_logger import xml.etree.cElementTree as etree import mast.datapower.datapower as datapower from getconfig import main as getconfig logger = make_logger("mast.crypto-audit") def cert_file_audit(appliances=[], credentials=[], timeout=120, no_check_hostname=False, out_file=os.path.join("tmp", "cert-file-audit.xlsx")): locations = ["cert:", "pubcert:", "sharedcert:"] check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) header_row = ["appliance", "domain",
def _import(appliances=[], credentials=[], timeout=120, no_check_hostname=False, Domain=[], file_in=None, deployment_policy=None, dry_run=False, overwrite_files=True, overwrite_objects=True, rewrite_local_ip=True, source_type='ZIP', out_dir="tmp/", web=False): """Import a service/object into the specified appliances Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-D. --Domain`: The domain into which the configuration will be imported * `-f, --file-in`: The file to import into the specified domain. This __MUST__ match the format specified in source_type * `-d, --deployment-policy`: The deployment policy to use for the import (must already exist on the appliances) * `--dry-run`: Whether to do a dry-run (nothing will be imported) * `-N, --no-overwrite-files`: If specified, no files will be overwritten as part of the import * `--no-overwrite-objects`: If specified, no objects will be overwritten as part of the import * `--no-rewrite-local-ip`: If specified, no local ip addresses will be rewritten as part of the import * `-s, --source-type`: The type of file to import. Can be "XML" or "ZIP" * `-o, --out-dir`: The directory to output artifacts generated by this script * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.developer") t = Timestamp() check_hostname = not no_check_hostname env = datapower.Environment( appliances, credentials, timeout, check_hostname=check_hostname) msg = "Attempting to import {} to {}".format(file_in, str(env.appliances)) logger.info(msg) if not web: print msg results = {} out_dir = os.path.join(out_dir, "import_results", t.timestamp) os.makedirs(out_dir) for appliance in env.appliances: if not web: print appliance.hostname results[appliance.hostname] = {} domains = Domain if "all-domains" in domains: domains = appliance.domains for domain in domains: if not web: print "\t", domain kwargs = { 'domain': domain, 'zip_file': file_in, 'deployment_policy': deployment_policy, 'dry_run': dry_run, 'overwrite_files': overwrite_files, 'overwrite_objects': overwrite_objects, 'rewrite_local_ip': rewrite_local_ip, 'source_type': source_type} resp = appliance.do_import(**kwargs) results[appliance.hostname][domain] = resp if not web: pprint_xml(resp.xml) logger.debug("Response received: {}".format(str(resp))) filename = os.path.join( out_dir, "{}-{}-import_results.xml".format( appliance.hostname, domain ) ) with open(filename, 'wb') as fout: fout.write(resp.pretty) if web: return util.render_see_download_table( results, suffix="import"), util.render_history(env)
def get_normal_backup(appliances=[], credentials=[], timeout=120, no_check_hostname=False, Domain=[], comment="", out_dir='tmp', individual=False, web=False): """Performs a normal backup of the specified domain. Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-D, --Domain`: The domains to backup (all-domains will backup all domains) To spcify multiple domains, use multiple entries of the form `[-D domain1 [-D domain2...]]` * `-C, --comment`: The comment to add to the backup * `-o, --out-dir`: (NOT NEEDED IN WEB GUI) The directory (local) where you would like to store the backup * `-I, --individual`: If specified and all-domains is specified as --Domain then backup each domain individually instead of "all-domains" * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.backups") t = Timestamp() check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) if not Domain: raise ValueError( "Must provide one or more domains including 'all-domains'") if isinstance(Domain, basestring): Domain = [Domain] # Fixes duplicate domains issue Domain = list(set(Domain)) results = {} if not individual: logger.info("Attempting to retrieve normal backup from " "{} in {} domain".format(str(env.appliances), Domain)) kwargs = {'domains': Domain, 'comment': comment} _results = env.perform_async_action('get_normal_backup', **kwargs) logger.debug("backups retrieved, check file for contents") for hostname, backup in _results.items(): directory = os.path.join(out_dir, hostname, "NormalBackup", t.timestamp) os.makedirs(directory) filename = os.path.join( directory, '%s-%s-%s.zip' % (t.timestamp, hostname, "_".join(Domain))) logger.debug("Writing backup for {} to {}".format( hostname, filename)) with open(filename, 'wb') as fout: fout.write(backup) if _verify_zip(filename): logger.info("backup for {} in {} domain verified".format( hostname, str(Domain))) results[hostname + "-" + "_".join(Domain) + "-normalBackup"] = "Verified" else: logger.info("backup for {} in {} domain corrupt".format( hostname, str(Domain))) results[hostname + "-" + "_".join(Domain) + "-normalBackup"] = "Corrupt" else: for domain in Domain: logger.info("Attempting to retrieve normal backup from " "{} in {} domain".format(str(env.appliances), domain)) kwargs = {'domains': domain, 'comment': comment} _results = env.perform_async_action('get_normal_backup', **kwargs) logger.debug("backups retrieved, check file for contents") for hostname, backup in _results.items(): directory = os.path.join(out_dir, hostname, "NormalBackup", t.timestamp) if not os.path.exists(directory): os.makedirs(directory) filename = os.path.join( directory, '%s-%s-%s.zip' % (t.timestamp, hostname, domain)) logger.debug("Writing backup for {} to {}".format( hostname, filename)) with open(filename, 'wb') as fout: fout.write(backup) if _verify_zip(filename): logger.info("backup for {} in {} domain verified".format( hostname, domain)) results[hostname + "-" + domain + "-normalBackup"] = "Verified" else: logger.info("backup for {} in {} domain corrupt".format( hostname, domain)) results[hostname + "-" + domain + "-normalBackup"] = "Corrupt" if web: return util.render_results_table(results), util.render_history(env) for k, v in results.items(): print print k print '=' * len(k) print v print
def get_secure_backup(appliances=[], credentials=[], timeout=1200, no_check_hostname=False, out_dir='tmp', CryptoCertificate="", destination='local:/raid0', include_iscsi=False, include_raid=False, remove=True, quiesce_before=True, unquiesce_after=True, quiesce_timeout=60, web=False): """Performs a secure backup of the specified domain. Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-o, --out-dir`: (NOT NEEDED IN WEB GUI) The directory (local) to store the backup * `-C, --CryptoCertificate`: The CryptoCertificate object to use to encrypt the backup * `-d, --destination`: The base location (on the appliance) to store the backup * `-i, --include-iscsi`: Whether to include the iscsi filesystem * `-I, --include-raid`: Whether to include the RAID filesystem * `-N, --no-remove`: If specified the backup will NOT be removed from the DataPower * `--no-quiesce-before`: If specified, the appliance will not be quiesced before performing the secure backup * `--no-unquiesce-after`: If specified, the appliance will not be unquiesced after performing the secure backup * `-q, --quiesce-timeout`: The timeout to wait before the appliance attempts to quiesce * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.backups") check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) output = "" if quiesce_before: resp = {} for appliance in env.appliances: logger.info("Quiescing {} in preparation of Secure Backup".format( appliance.hostname)) resp[appliance.hostname] = appliance.QuiesceDP( timeout=quiesce_timeout) logger.debug("Response received {}".format( resp[appliance.hostname])) if web: output += util.render_boolean_results_table( resp, suffix="Quiesce_appliance") sleep(quiesce_timeout) t = Timestamp() if destination.endswith("/"): destination = destination.rstrip("/") destination = '%s/%s' % (destination, t.timestamp) kwargs = {'Dir': destination, 'domain': 'default'} logger.info("Creating directory {} on {} to store Secure Backup".format( destination, str(env.appliances))) resp = env.perform_async_action('CreateDir', **kwargs) logger.debug("Responses received {}".format(str(resp))) if web: output += util.render_boolean_results_table(resp, suffix="CreateDir") include_raid = 'on' if include_raid else 'off' include_iscsi = 'on' if include_iscsi else 'off' kwargs = { 'cert': CryptoCertificate, 'destination': destination, 'include_iscsi': include_iscsi, 'include_raid': include_raid } logger.info("Attempting to perform a Secure Backup on {}".format( str(env.appliances))) resp = env.perform_async_action('SecureBackup', **kwargs) logger.debug("Responses received: {}".format(str(resp))) if web: output += util.render_boolean_results_table(resp, suffix="SecureBackup") if web: results = {} remove_results = {} for appliance in env.appliances: directory = os.path.join(out_dir, appliance.hostname, "SecureBackup", t.timestamp) start = time() while not appliance.file_exists( '{}/backupmanifest.xml'.format(destination), 'default'): sleep(5) if time() - start > timeout: raise TimeoutError logger.info("Attempting to retrieve Secure Backup from {}".format( appliance.hostname)) appliance.copy_directory(destination, directory) _directory = os.path.join( directory, destination.replace(":", "").replace("///", "/")) try: logger.info("Attempting to verify Secure Backup for {}".format( appliance.hostname)) if appliance.verify_local_backup(_directory): logger.info("Secure Backup integrity verified for {}".format( appliance.hostname)) if web: results[appliance.hostname] = "Succeeded" else: print '\t', appliance.hostname, " - ", "Succeeded" if remove: logger.info( "Attempting to remove Secure Backup from appliance " "{}".format(appliance.hostname)) _resp = appliance.RemoveDir(Dir=destination, domain='default') logger.debug("Response received: {}".format(_resp)) if web: remove_results[appliance.hostname] = _resp else: logger.warn("Secure Backup for {} Corrupt!".format( appliance.hostname)) if web: results[appliance.hostname] = "Failed" else: print '\t', appliance.hostname, " - ", "Failed" appliance.log_error('Verification of backup in %s failed' % (_directory)) except: if web: results[appliance.hostname] = "Failed" logger.exception( "An unhandled exception occurred during execution.") if web: output += util.render_results_table(results, suffix="verify-SecureBackup") output += util.render_boolean_results_table(remove_results, suffix="RemoveDir") if unquiesce_after: resp = {} for appliance in env.appliances: logger.info("Attempting to unquiesce {}".format( str(appliance.hostname))) resp[appliance.hostname] = appliance.UnquiesceDP() logger.debug("Response received: {}".format( resp[appliance.hostname])) if web: output += util.render_boolean_results_table( resp, suffix="Unquiesce_appliance") if web: return output, util.render_history(env)
def restore_secure_backup(appliances=[], credentials=[], timeout=1200, no_check_hostname=False, CryptoCertificate="", location="", validate_only=False, web=False): """Restores a secure backup to the specified appliances. Parameters: * `-a, --appliances`: The hostname(s), ip address(es), environment name(s) or alias(es) of the appliances you would like to affect. For details on configuring environments please see the comments in `environments.conf` located in `$MAST_HOME/etc/default`. For details on configuring aliases, please see the comments in `hosts.conf` located in `$MAST_HOME/etc/default`. To pass multiple arguments to this parameter, use multiple entries of the form `[-a appliance1 [-a appliance2...]]` * `-c, --credentials`: The credentials to use for authenticating to the appliances. Should be either one set to use for all appliances or one set for each appliance. Credentials should be in the form `username:password`. To pass multiple credentials to this parameter, use multiple entries of the form `[-c credential1 [-c credential2...]]`. When referencing multiple appliances with multiple credentials, there must be a one-to-one correspondence of credentials to appliances: `[-a appliance1 [-a appliance2...]] [-c credential1 [-c credential2...]]` If you would prefer to not use plain-text passwords, you can use the output of `$ mast-system xor <username:password>`. * `-t, --timeout`: The timeout in seconds to wait for a response from an appliance for any single request. __NOTE__ Program execution may halt if a timeout is reached. * `-n, --no-check-hostname`: If specified SSL verification will be turned off when sending commands to the appliances. * `-C, --CryptoCertificate`: The CryptoCertificate object with which the secure backup was encrypted * `-l, --location`: The location on the appliances where the SecureBackup resides (This means that you will have to upload the secure backup if you got it from MAST, external to the appliance) * `-v, --validate-only`: If specified then the appliances will only attemp to validate the backup instead of actually restoring it * `-w, --web`: __For Internel Use Only, will be removed in future versions. DO NOT USE.__""" logger = make_logger("mast.backups") check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) logger.info("Attempting to restore Secure Backup on {}".format( str(env.appliances))) validate = "on" if validate_only else "off" kwargs = { "cred": CryptoCertificate, "source": location, "validate": validate } resp = env.perform_action("SecureRestore", **kwargs) logger.debug("Responses received: {}".format(str(resp))) if web: return (util.render_boolean_results_table(resp), util.render_history(env)) for host, msg in resp.items(): print host, '\n', "=" * len(host) print msg print
def initialize_plugins(): """ _function_: `mast.datapower.web.initialize_plugins()` Initializes all of the plugins for the MAST web GUI Logs to: `gui.log` Parameters: This function accepts no arguments. """ logger = make_logger("gui") logger.debug("Running as user {}".format(getpass.getuser())) logger.debug("Running in directory {}".format(os.getcwd())) logger.debug("Attempting to retrieve list of web plugins") plugins_dict = {} for ep in pkg_resources.iter_entry_points(group='mast_web_plugin'): logger.debug("found plugin: {}".format(ep.name)) try: plugins_dict.update({ep.name: ep.load()}) except: logger.exception( "An unhandled exception occurred during execution.") pass logger.info("Collected plugins {}".format(str(plugins_dict.keys()))) plugins = { 'css': '', 'html': '', 'js': '', 'tabs': ''} for name, cls in sorted(plugins_dict.items()): _plugin = cls() plugins[name] = _plugin try: plugins["html"] += flask.Markup(_plugin.html()) plugins["tabs"] += flask.Markup( '<li><a href="#mast.datapower.{0}">{0}</a></li>'.format(name)) plugins["css"] += flask.Markup(_plugin.css()) plugins["js"] += flask.Markup(_plugin.js()) except: logger.exception( "An unhandled exception occured while attempting " "to gather the content for web plugin {}".format(name)) raise # Route function try: app.add_url_rule( '/%s' % (name), view_func=_plugin.route, methods=["GET", "POST", "DELETE", "PUT"]) except: logger.exception( "An unhandled exception occured while attempting " "to assign a handler for web plugin {}".format(name)) raise return plugins
# Find cert:/// file references cert_matches = defaultdict(list) for dirname in glob(os.path.join(out_dir, "*", "*", "*", "*")): for root, dirs, filenames in os.walk(dirname): for filename in [os.path.join(root, f) for f in filenames]: with open(filename, "r") as fp: for line in fp: if "cert:///" in line: for match in re.findall( '.*?(cert:///.*?)[<"]', line): cert_matches[match].append(filename) cert_file = os.path.join(out_dir, "referenced_cert_files.txt") with open(cert_file, "wb") as fp: for cert, filenames in cert_matches.items(): fp.write("{}{}".format(cert, os.linesep)) for filename in filenames: fp.write("\t{}{}".format(filename, os.linesep)) if __name__ == "__main__": cli = Cli(main=main) try: cli.run() except SystemExit: pass except: make_logger("error").exception( "Sorry, an unhandled exception occurred.") raise
def main(appliances=[], credentials=[], timeout=120, no_check_hostname=False, out_file=default_out_file, delay=0.5): logger = make_logger("mast.file-sizes") locations = ["cert:", "chkpoints:", "config:", "export:", "image:", "local:", "logstore:", "logtemp:", "pubcert:", "sharedcert:", "store:", "tasktemplates:", "temporary:"] check_hostname = not no_check_hostname env = datapower.Environment(appliances, credentials, timeout, check_hostname=check_hostname) root_node = etree.fromstring("<filestores />") header = ("appliance", "domain", "directory", "filename", "size", "modified") rows = [header] for appliance in env.appliances: print appliance.hostname appliance_node = etree.fromstring( '<filestores appliance="{}" />'.format(appliance.hostname)) for domain in appliance.domains: print "\t{}".format(domain) for location in locations: sleep(delay) print "\t\t{}".format(location) filestore = appliance.get_filestore(domain=domain, location=location) _location = filestore.xml.find(datapower.FILESTORE_XPATH) if _location is None: continue if _location.findall("./file") is not None: for _file in _location.findall("./file"): dir_name = _location.get("name") filename = _file.get("name") print "\t\t\t{}".format(filename) size = _file.find("size").text modified = _file.find("modified").text rows.append((appliance.hostname, domain, dir_name, filename, size, modified)) for directory in _location.findall(".//directory"): dir_name = directory.get("name") print "\t\t\t{}".format(dir_name) for _file in directory.findall(".//file"): filename = _file.get("name") print "\t\t\t\t{}".format(filename) size = _file.find("size").text modified = _file.find("modified").text rows.append((appliance.hostname, domain, dir_name, filename, size, modified)) wb = openpyxl.Workbook() ws = wb.active for row in rows: ws.append(row) wb.save(out_file)