def setUp(self): self.client = SSLClient(host=APPLIANCE, user='******', password=PASSWORD, sslverifyhost=False) self.maxDiff = 5000
def setUp(self): self.client = SSLClient(host=APPLIANCE, user='******', password=PASSWORD, sslverifyhost=False) self.tmpdir = tempfile.mkdtemp() self.upload = os.path.join(self.tmpdir, 'upload') self.download = os.path.join(self.tmpdir, 'download')
def setUp(self): self.client = SSLClient(host=APPLIANCE, user='******', password=PASSWORD, sslverifyhost=False) self.client.send_command( 'CONFIG OBJECT HOST NEW type=host name=hostutf8 ip=1.2.3.4 comment="comment with utf8 characters éè\u2713"' ) self.maxDiff = 5000
def test_sslverifyhost(self): """ Test proxy option """ try: client = SSLClient(host=APPLIANCE, user='******', password=PASSWORD, sslverifypeer=False, proxy=PROXY) self.assertTrue(1 == 1, "SSLClient connects with proxy") except: self.fail("SSLClient did not connect") response = client.send_command('LIST') self.assertEqual(response.ret, 100) client.disconnect()
def test_sslverifypeer(self): """ Test sslverifypeer option """ # by default sslverifypeer is True try: client = SSLClient(host=APPLIANCE, user='******', password=PASSWORD) self.fail("SSLClient should have failed (untrusted CA)") except Exception as exception: self.assertTrue(True, "SSLClient did not connect (untrusted CA)") try: client = SSLClient(host=APPLIANCE, user='******', password=PASSWORD, sslverifypeer=False) self.assertTrue(True, "SSLClient connects with sslverifypeer=False") except Exception as exception: print(exception) self.fail("SSLClient did not connect") response = client.send_command('LIST') self.assertEqual(response.ret, 100) client.disconnect()
class TestUtf8(unittest.TestCase): """ Test INI format """ def setUp(self): self.client = SSLClient(host=APPLIANCE, user='******', password=PASSWORD, sslverifyhost=False) self.client.send_command( 'CONFIG OBJECT HOST NEW type=host name=hostutf8 ip=1.2.3.4 comment="comment with utf8 characters éè\u2713"' ) self.maxDiff = 5000 def tearDown(self): self.client.send_command('CONFIG OBJECT HOST delete name=hostutf8') self.client.disconnect() def test_utf8(self): """ send and receive utf-8 content """ expected = """101 code=00a01000 msg="Begin" format="section_line" [Object] type=host global=0 name=hostutf8 ip=1.2.3.4 modify=1 comment="comment with utf8 characters éè\u2713" type=host 100 code=00a00100 msg="Ok\"""" response = self.client.send_command( 'CONFIG OBJECT LIST type=host search=hostutf8 start=0') self.assertEqual(response.output, expected) self.assertEqual(response.ret, 100)
def test_cert(self): """ Test user certificate authentication """ try: client = SSLClient(host=FQDN, ip=APPLIANCE, usercert=CERT, sslverifyhost=True, cabundle=CABUNDLE) self.assertTrue(1 == 1, "SSLClient connects with cabundle") except Exception as exception: print(exception) self.fail("SSLClient did not connect") response = client.send_command('LIST') self.assertEqual(response.ret, 100) client.disconnect()
def test_cabundle(self): """ Test cabundle option """ try: client = SSLClient(host=FQDN, ip=APPLIANCE, user='******', password=PASSWORD, sslverifyhost=True, cabundle=CABUNDLE) self.assertTrue(1 == 1, "SSLClient connects with cabundle") except Exception as exception: print(exception) self.fail("SSLClient did not connect") response = client.send_command('LIST') self.assertEqual(response.ret, 100) client.disconnect()
def make_completer(): """ load completer for readline """ vocabulary = [] with open(SSLClient.get_completer(), "r") as completelist: for line in completelist: vocabulary.append(line.replace('.', ' ').strip('\n')) def custom_complete(text, state): results = [x for x in vocabulary if x.startswith(text)] + [None] return results[state] return custom_complete
class TestFormatIni(unittest.TestCase): """ Test file upload & download """ def setUp(self): self.client = SSLClient(host=APPLIANCE, user='******', password=PASSWORD, sslverifyhost=False) self.tmpdir = tempfile.mkdtemp() self.upload = os.path.join(self.tmpdir, 'upload') self.download = os.path.join(self.tmpdir, 'download') def tearDown(self): self.client.disconnect() shutil.rmtree(self.tmpdir, ignore_errors=True) def test_upload_download(self): """ Test file upload and download """ letters = string.ascii_letters + 'éèàÎîô' #generate a random file content = ("".join([random.choice(letters) for i in range(2500)])).encode('utf-8') with open(self.upload, "wb") as fh: fh.write(content) response = self.client.send_command( 'CONFIG COMMUNICATION EMAIL TEMPLATE UPLOAD pvm_summary < ' + self.upload) self.assertEqual(response.ret, 100) self.client.send_command('CONFIG COMMUNICATION ACTIVATE') self.assertEqual(response.ret, 100) response = self.client.send_command( 'CONFIG COMMUNICATION EMAIL TEMPLATE DOWNLOAD pvm_summary > ' + self.download) self.assertEqual(response.ret, 100) with open(self.download, "rb") as fh: downloaded = fh.read() self.assertEqual(content, downloaded)
def main(): # parse command line parser = argparse.ArgumentParser(conflict_handler="resolve") group = parser.add_argument_group("Connection parameters") group.add_argument("-h", "--host", help="Remote UTM", default=None) group.add_argument("-i", "--ip", help="Remote UTM ip", default=None) group.add_argument("-P", "--port", help="Remote port", default=443, type=int) group.add_argument("--proxy", help="Proxy URL (scheme://user:password@host:port)", default=None) group.add_argument("-t", "--timeout", help="Connection timeout in seconds", default=-1, type=int) group = parser.add_argument_group("Authentication parameters") group.add_argument("-u", "--user", help="User name", default="admin") group.add_argument("-p", "--password", help="Password", default=None) group.add_argument("-U", "--usercert", help="User certificate file", default=None) group = parser.add_argument_group("SSL parameters") group.add_argument("-C", "--cabundle", help="CA bundle file", default=None) group.add_argument("--sslverifypeer", help="Strict SSL CA check", default=True, action="store_true") group.add_argument("-k", "--no-sslverifypeer", help="Disable strict SSL CA check", default=True, action="store_false", dest="sslverifypeer") group.add_argument("--sslverifyhost", help="Strict SSL host name check", default=True, action="store_true") group.add_argument("-K", "--no-sslverifyhost", help="Disable strict SSL host name check", default=True, action="store_false", dest="sslverifyhost") group = parser.add_argument_group("Protocol parameters") group.add_argument("-c", "--credentials", help="Privilege list", default=None) group.add_argument("-s", "--script", help="Command script", default=None) group.add_argument("-o", "--outputformat", help="Output format (ini|xml)", default="ini") parser.add_argument("--version", help="Library version", default=False, action="store_true") group = parser.add_argument_group("Logging parameters") exclusive = group.add_mutually_exclusive_group() exclusive.add_argument("-v", "--verbose", help="Increase logging output", default=False, action="store_true") exclusive.add_argument("-q", "--quiet", help="Decrease logging output", default=False, action="store_true") group.add_argument("--loglvl", help="Set explicit log level", default=None, choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']) group.add_argument("--logfile", help='Output log messages to file', default=None) args = parser.parse_args() host = args.host ip = args.ip usercert = args.usercert cabundle = args.cabundle password = args.password port = args.port proxy = args.proxy timeout = args.timeout user = args.user sslverifypeer = args.sslverifypeer sslverifyhost = args.sslverifyhost credentials = args.credentials script = args.script outputformat = args.outputformat version = args.version # logging level = logging.INFO if args.loglvl is not None: level = logging.getLevelName(args.loglvl) elif args.verbose: level = logging.DEBUG elif args.quiet: level = logging.WARNING # add custom level logging.addLevelName(OUTPUT_LEVELV_NUM, "OUTPUT") logging.addLevelName(COMMAND_LEVELV_NUM, "COMMAND") def logoutput(self, message, *args, **kwargs): # Yes, logger takes its '*args' as 'args'. self._log(OUTPUT_LEVELV_NUM, message, args, **kwargs) def logcommand(self, message, *args, **kwargs): # Yes, logger takes its '*args' as 'args'. self._log(COMMAND_LEVELV_NUM, message, args, **kwargs) logging.Logger.output = logoutput logging.Logger.command = logcommand # logger logger = logging.getLogger() for handler in logger.handlers: logger.removeHandler(handler) logger.setLevel(level) # attach handlers handler = logging.StreamHandler(sys.stdout) handler.addFilter(CommandFilter()) logger.addHandler(handler) if args.logfile is not None: if platform.system() != 'Windows': handler = logging.handlers.WatchedFileHandler(args.logfile) else: handler = logging.FileHandler(args.logfile) logger.addHandler(handler) for handler in logger.handlers: if handler.__class__ == logging.StreamHandler: handler.setFormatter(FORMATTER) if version: logging.info("snscli - stormshield.sns.sslclient version {}".format(libversion)) sys.exit(0) if script is not None: try: script = open(script, 'r') except Exception as exception: logging.error("Can't open script file - %s", str(exception)) sys.exit(1) if outputformat not in ['ini', 'xml']: logging.error("Unknown output format") sys.exit(1) if host is None: logging.error("No host provided") sys.exit(1) if password is None and usercert is None: password = getpass.getpass() if timeout == -1: timeout = None try: client = SSLClient( host=host, ip=ip, port=port, user=user, password=password, sslverifypeer=sslverifypeer, sslverifyhost=sslverifyhost, credentials=credentials, proxy=proxy, timeout=timeout, usercert=usercert, cabundle=cabundle, autoconnect=False) except Exception as exception: logging.error(str(exception)) sys.exit(1) try: client.connect() except Exception as exception: search = re.search(r'doesn\'t match \'(.*)\'', str(exception)) if search: logging.error(("Appliance name can't be verified, to force connection " "use \"--host %s --ip %s\" or \"--no-sslverifyhost\" " "options"), search.group(1), host) else: logging.error(str(exception)) sys.exit(1) # disconnect gracefuly at exit atexit.register(client.disconnect) if script is not None: for cmd in script.readlines(): cmd = cmd.strip('\r\n') logger.output(cmd) if cmd.startswith('#'): continue if EMPTY_RE.match(cmd): continue try: response = client.send_command(cmd) except Exception as exception: logging.error(str(exception)) sys.exit(1) if outputformat == 'xml': logger.output(highlight(defusedxml.minidom.parseString(response.xml).toprettyxml(), XmlLexer(), TerminalFormatter())) else: logger.output(response.output) sys.exit(0) # Start cli # load history histfile = os.path.join(os.path.expanduser("~"), ".sslclient_history") try: readline.read_history_file(histfile) readline.set_history_length(1000) except FileNotFoundError: pass def save_history(histfile): try: readline.write_history_file(histfile) except: logging.warning("Can't write history") atexit.register(save_history, histfile) # load auto-complete readline.parse_and_bind('tab: complete') readline.set_completer_delims('') readline.set_completer(make_completer()) while True: try: cmd = input("> ") logger.command(cmd) except EOFError: break # skip comments if cmd.startswith('#'): continue try: response = client.send_command(cmd) except ServerError as exception: # do not log error on QUIT if "quit".startswith(cmd.lower()) \ and str(exception) == "Server disconnected": sys.exit(0) logging.error(str(exception)) sys.exit(1) except Exception as exception: logging.error(str(exception)) sys.exit(1) if response.ret == client.SRV_RET_DOWNLOAD: filename = input("File to save: ") try: client.download(filename) logging.info("File downloaded") except Exception as exception: logging.error(str(exception)) elif response.ret == client.SRV_RET_UPLOAD: filename = input("File to upload: ") try: client.upload(filename) logging.info("File uploaded") except Exception as exception: logging.error(str(exception)) else: if outputformat == 'xml': logger.output(highlight(defusedxml.minidom.parseString(response.xml).toprettyxml(), XmlLexer(), TerminalFormatter())) else: logger.output(response.output)
#host = "10.0.0.0.254" #user = "******" #password = "******" #vlanname = "myvlan3" #vlanphy = "Ethernet0" #vlantag = 103 #vlanaddr = "192.168.103.1" #vlanmask = "255.255.255.0" MAXVLAN = 60 # connect to the appliance client = SSLClient(host=host, port=443, user=user, password=password, sslverifyhost=False) def error(msg): global client print("ERROR: {}".format(msg)) client.disconnect() sys.exit(1) def command(cmd): global client
with open(os.path.join(LOG_DIR, filename), "a") as fh: fh.write(msg + "\n") last_dates[logtype]["time"] = date + " " + time last_dates[logtype]["tz"] = tz logger = logging.Logger("logcollector") coloredlogs.install(level='DEBUG', logger=logger, fmt='%(asctime)s %(levelname)s %(message)s', field_styles={'asctime': {'color': 'black'}, 'levelname': { 'bold': True, 'color': 'blue'}}) # connect to the appliance client = SSLClient( host=host, port=443, user=user, password=password, sslverifyhost=False) # request ticket to be able to get the logs response = client.send_command("SYSTEM RIGHT TICKET ACQUIRE") if not response: logger.error("Can't get log ticket") logger.error(response.output) sys.exit(1) for logtype in logtypes: count = 0 while "log available": time = last_dates[logtype]["time"] tz = last_dates[logtype]["tz"] cmd = "LOG DOWNLIMIT name={logtype} first=\"{time}\" tz={tz} number={limit}".format(
parser.add_argument("-p", "--password", help="password", default=None) args = parser.parse_args() host = args.host user = args.user password = args.password if host is None: host = input("Appliance ip address: ") if password is None: password = getpass.getpass("Password: "******"CONFIG NETWORK DEFAULTROUTE SHOW") print("\n".join(defr.output.split("\n")[1:-1]) + "\n") print("-- IPv4 --\n") # get ipv4 static routes sroutev4 = client.send_command("CONFIG NETWORK ROUTE SHOW") print("\n".join(sroutev4.output.split("\n")[1:-1]) + "\n") # get ipv4 reverse routes rev4 = client.send_command("CONFIG NETWORK ROUTE REVERSE SHOW")
def main(): module = AnsibleModule( argument_spec={ "path": { "required": True, "type": "str" }, "force_modify": { "required": False, "type": "bool", "default": False }, "timeout": { "required": False, "type": "int", "default": None }, "appliance": { "required": True, "type": "dict", "options": { "host": { "required": True, "type": "str" }, "ip": { "required": False, "type": "str" }, "port": { "required": False, "type": "int", "default": 443 }, "user": { "required": False, "type": "str", "default": "admin" }, "password": { "required": False, "type": "str" }, "sslverifypeer": { "required": False, "type": "bool", "default": True }, "sslverifyhost": { "required": False, "type": "bool", "default": True }, "cabundle": { "required": False, "type": "str" }, "usercert": { "required": False, "type": "str" }, "proxy": { "required": False, "type": "str" }, } } }) path = module.params['path'] force_modify = module.params['force_modify'] if path is None: module.fail_json(msg="Path of the file is required") options = {} if module.params['timeout'] is not None: options["timeout"] = module.params['timeout'] try: client = SSLClient( host=module.params['appliance']['host'], ip=module.params['appliance']['ip'], port=module.params['appliance']['port'], user=module.params['appliance']['user'], password=module.params['appliance']['password'], sslverifypeer=module.params['appliance']['sslverifypeer'], sslverifyhost=module.params['appliance']['sslverifyhost'], cabundle=module.params['appliance']['cabundle'], usercert=module.params['appliance']['usercert'], proxy=module.params['appliance']['proxy'], autoconnect=False, **options) except Exception as exception: module.fail_json(msg=str(exception)) try: client.connect() except Exception as exception: module.fail_json(msg=str(exception)) if force_modify: try: response = client.send_command("MODIFY FORCE ON") except Exception as exception: client.disconnect() module.fail_json( msg="Can't take Modify privilege: {}".format(str(exception))) if response.ret >= 200: client.disconnect() module.fail_json(msg="Can't take Modify privilege", result=response.output, data=response.parser.serialize_data(), ret=response.ret) if path is not None: try: response = uploadObjectCSV(client, path) except Exception as exception: client.disconnect() module.fail_json(msg=str(exception)) client.disconnect() resultJson = dict() resultJson['output'] = str(response) for (k, v) in dict(response).items(): resultJson[k] = v if response['Status'] == "OK": resultJson['changed'] = True module.exit_json(**resultJson) else: resultJson['changed'] = False resultJson['success'] = False resultJson['msg'] = "Errors occured during the import operation" module.fail_json(**resultJson)
def main(): module = AnsibleModule( argument_spec={ "command": { "required": False, "type": "str" }, "script": { "required": False, "type": "str" }, "expect_disconnect": { "required": False, "type": "bool", "default": False }, "force_modify": { "required": False, "type": "bool", "default": False }, "appliance": { "required": True, "type": "dict", "options": { "host": { "required": True, "type": "str" }, "ip": { "required": False, "type": "str" }, "port": { "required": False, "type": "int", "default": 443 }, "user": { "required": False, "type": "str", "default": "admin" }, "password": { "required": False, "type": "str" }, "sslverifypeer": { "required": False, "type": "bool", "default": True }, "sslverifyhost": { "required": False, "type": "bool", "default": True }, "cabundle": { "required": False, "type": "str" }, "usercert": { "required": False, "type": "str" }, "proxy": { "required": False, "type": "str" }, } } }) EMPTY_RE = re.compile(r'^\s*$') command = module.params['command'] script = module.params['script'] expect_disconnect = module.params['expect_disconnect'] force_modify = module.params['force_modify'] if command is None and script is None: module.fail_json(msg="A command or a script is required") if command is not None and script is not None: module.fail_json(msg="Got both command and script") try: client = SSLClient( host=module.params['appliance']['host'], ip=module.params['appliance']['ip'], port=module.params['appliance']['port'], user=module.params['appliance']['user'], password=module.params['appliance']['password'], sslverifypeer=module.params['appliance']['sslverifypeer'], sslverifyhost=module.params['appliance']['sslverifyhost'], cabundle=module.params['appliance']['cabundle'], usercert=module.params['appliance']['usercert'], proxy=module.params['appliance']['proxy'], autoconnect=False) except Exception as exception: module.fail_json(msg=str(exception)) try: client.connect() except Exception as exception: module.fail_json(msg=str(exception)) if force_modify: try: response = client.send_command("MODIFY FORCE ON") except Exception as exception: client.disconnect() module.fail_json( msg="Can't take Modify privilege: {}".format(str(exception))) if response.ret >= 200: client.disconnect() module.fail_json(msg="Can't take Modify privilege", result=response.output, data=response.parser.serialize_data(), ret=response.ret) if command is not None: # execute single command try: response = client.send_command(command) except Exception as exception: client.disconnect() module.fail_json(msg=str(exception)) client.disconnect() module.exit_json(changed=True, result=response.output, data=response.parser.serialize_data(), ret=response.ret) else: # execute script output = "" success = True need_reboot = False for command in script.splitlines(): command = command.strip('\r\n') output += command + "\n" if command.startswith('#'): continue if EMPTY_RE.match(command): continue try: response = client.send_command(command) output += response.output + "\n" if response.ret >= 200: success = False elif response.ret == client.SRV_RET_MUSTREBOOT: need_reboot = True except Exception as exception: if expect_disconnect and str( exception) == "Server disconnected": break else: client.disconnect() module.fail_json(msg=str(exception), output=output, success=False, need_reboot=need_reboot) client.disconnect() if success: module.exit_json(changed=True, output=output, success=True, need_reboot=need_reboot) else: module.fail_json(msg="Errors during the script execution", output=output, success=False, need_reboot=need_reboot)
class TestFormatIni(unittest.TestCase): """ Test INI format """ def setUp(self): self.client = SSLClient(host=APPLIANCE, user='******', password=PASSWORD, sslverifyhost=False) self.maxDiff = 5000 def tearDown(self): self.client.disconnect() def test_raw(self): """ raw format """ expected_re = """101 code=00a01000 msg="Begin" format="raw" AUTH.* CHPWD.* 100 code=00a00100 msg="Ok\"""" response = self.client.send_command('HELP') self.assertTrue( re.match(expected_re, response.output, re.MULTILINE | re.DOTALL)) self.assertEqual(response.ret, 100) def test_section(self): """ section format """ expected = """101 code=00a01000 msg="Begin" format="section" [Global] State=0 RiskHalfLife=21600 RiskTTL=86400 [Alarm] Minor=2 Major=10 [Sandboxing] Suspicious=2 Malicious=50 Failed=0 [Antivirus] Infected=100 Unknown=2 Failed=0 100 code=00a00100 msg="Ok\"""" response = self.client.send_command('CONFIG HOSTREP SHOW') self.assertEqual(response.output, expected) self.assertEqual(response.ret, 100) def test_section_line(self): """ section_line format """ expected = """101 code=00a01000 msg="Begin" format="section_line" [Result] id=pvm_detailed type=pvm name="Detailed Vulnerability Mail" id=pvm_summary type=pvm name="Summary Vulnerability Mail" id=app_cert_req type=cert_req name="Accept the certificate request" id=rej_cert_req type=cert_req name="Reject the certificate request" id=app_user_req type=user_req name="Accept the user request" id=rej_user_req type=user_req name="Reject the user request" id=sponsor_req type=sponsoring name="Sponsoring request" id=smtp_test_msg type=smtp_conf name="Test SMTP configuration" 100 code=00a00100 msg="Ok\"""" response = self.client.send_command( 'CONFIG COMMUNICATION EMAIL TEMPLATE LIST') self.assertEqual(response.output, expected) self.assertEqual(response.ret, 100) def test_list(self): """ list format """ expected = """101 code=00a01000 msg="Begin" format="list" [Result] labo_network Network_internals 100 code=00a00100 msg="Ok\"""" response = self.client.send_command('CONFIG WEBADMIN ACCESS SHOW') self.assertEqual(response.output, expected) self.assertEqual(response.ret, 100) def test_xml(self): """ xml text output """ expected = """101 code=00a01000 msg="Begin" format="xml" <data format="xml"><filters total_lines="5"> <separator collapse="0" color="c0c0c0" comment="Remote Management: Go to System - Configuration to setup the web administration application access" first_ruleid="1" nb_elements="2" position="1" /> <filter action="pass" comment="Admin from everywhere" index="1" position="2" status="active" type="local_filter_slot"><noconnlog disk="0" ipfix="0" syslog="0" /><from><target type="any" value="any" /></from><to><port type="single" value="firewall_srv" /><port type="single" value="https" /><target type="group" value="firewall_all" /></to></filter> <filter action="pass" comment="Allow Ping from everywhere" icmp_code="0" icmp_type="8" index="2" ipproto="icmp" position="3" proto="none" status="active" type="local_filter_slot"><noconnlog disk="0" ipfix="0" syslog="0" /><from><target type="any" value="any" /></from><to><target type="group" value="firewall_all" /></to></filter> <separator collapse="0" color="c0c0c0" comment="Default policy" first_ruleid="3" nb_elements="1" position="4" /> <filter action="block" comment="Block all" index="3" position="5" status="active" type="local_filter_slot"><noconnlog disk="0" ipfix="0" syslog="0" /><from><target type="any" value="any" /></from><to><target type="any" value="any" /></to></filter> </filters> </data> 100 code=00a00100 msg="Ok\"""" response = self.client.send_command( 'CONFIG FILTER EXPLICIT index=1 type=filter output=xml') self.assertEqual(response.output, expected) self.assertEqual(response.ret, 100)
to get appliance properties and parse the result to extract the appliance model and firmware version. """ import getpass from stormshield.sns.sslclient import SSLClient # user input host = input("Appliance ip address: ") user = input("User:"******"Password: "******"SYSTEM PROPERTY") if response: #get value using parser get method model = response.parser.get(section='Result', token='Model') # get value with direct access to data version = response.data['Result']['Version'] print("") print("Model: {}".format(model)) print("Firmware version: {}".format(version)) else: