def test_config_cert_chain_incompatible_case(self): """ Test that verifies that an incompatible certificate with a chain raises an exception. """ engine_config = SenderConfigSSL( address=(self.server, self.port), key=self.key, cert=self.cert, chain="{!s}/local_certs/keys/server/server_cert.pem".format( os.path.dirname(os.path.abspath(__file__))), check_hostname=False, verify_mode=CERT_NONE, verify_config=False) with self.assertRaises(DevoSenderException) as result: engine_config.check_config_certificate_chain() expected_exception = "Error in config, " \ "the chain: " + engine_config.chain +\ " is not compatible with " \ "the certificate: " + engine_config.cert self.assertIn(expected_exception, str(result.exception))
def test_config_cert_chain_standard_case(self): """ Test that verifies that a compatible certificate and chain are detected. """ engine_config = SenderConfigSSL(address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE, verify_config=False) result = engine_config.check_config_certificate_chain() self.assertTrue(result)
def test_Sender_with_default_logger(self): """ Test that tries to check that Sender class can still use an internal logger and shows both local and remote traces """ try: engine_config = SenderConfigSSL(address=self.server, port=self.port, key=self.key, cert=self.cert, chain=self.chain) con = Sender(engine_config, tag=self.my_app) for i in range(0, self.default_numbers_sendings): # NOTE: this logger logging traces will be visible in console con.logger.info( "Testing Sender default handler functionality in local console... INFO - log" ) # NOTE: this logger logging traces will be visible in the remote table con.info( "Testing Sender default handler functionality in remote table... INFO - log" ) con.close() except Exception as error: self.fail("Problems with test: %s" % error)
def test_ssl_lookup_simplify(self): engine_config = SenderConfigSSL( address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE, ) con = Sender(engine_config) lookup = Lookup(name=self.lookup_name, historic_tag=None, con=con) lookup.send_headers(headers=["KEY", "HEX", "COLOR"], key="KEY", action="START") if len(con.socket.recv(1000)) == 0: raise Exception("Not msg sent!") lookup.send_data_line(key="11", fields=["11", "HEX12", "COLOR12"]) if len(con.socket.recv(1000)) == 0: raise Exception("Not msg sent!") lookup.send_headers(headers=["KEY", "HEX", "COLOR"], key="KEY", action="END") if len(con.socket.recv(1000)) == 0: raise Exception("Not msg sent!") con.socket.shutdown(0)
def test_sender_with_default_logger(self): """ Test that tries to check that Sender class can still use an internal logger and shows both local and remote traces """ try: engine_config = SenderConfigSSL(address=self.server, port=self.port, key=self.key, cert=self.cert, chain=self.chain) con = Sender(engine_config, tag=self.my_app) # NOTE: this logger logging traces will be visible in console con.logger.info("Testing Sender default handler functionality in " "local console... INFO - log") # NOTE: this logger logging traces will be visible in the remote # table con.info("Testing Sender default handler functionality in remote " "table... INFO - log") if len(con.socket.recv(5000)) == 0: raise Exception('Not msg sent!') con.close() except Exception as error: self.fail("Problems with test: %s" % error)
def test_config_files_path_incorrect_chain(self): wrong_chain = SenderConfigSSL(address=(self.server, self.port), key=self.chain, cert=self.cert, chain="Incorrect chain", check_hostname=False, verify_mode=CERT_NONE, verify_config=False) wrong_chain_message = "Error in the configuration, " + \ wrong_chain.chain + \ " is not a file or the path does not exist" with self.assertRaises(DevoSenderException) as result: wrong_chain.check_config_files_path() self.assertEqual(wrong_chain_message, str(result.exception))
def test_config_files_path_standard_case(self): """ Test that verifies that a correct path for the configuration file is detected. """ engine_config = SenderConfigSSL(address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE, verify_config=False) result = engine_config.check_config_files_path() self.assertTrue(result)
def test_get_common_names(self): engine_config = SenderConfigSSL(address=("eu.elb.relay.logtrust.net", 442), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE, verify_config=False) cert_1 = engine_config.fake_get_peer_cert_chain(self.chain) cert_2 = engine_config.fake_get_peer_cert_chain(self.chain) subject = engine_config.get_common_names(cert_1, "get_subject") issuer = engine_config.get_common_names(cert_2, "get_issuer") self.assertTrue(issuer.issubset(subject))
def test_create_lookup_key_index_preserves_structure(self): engine_config = SenderConfigSSL( address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE, ) con = Sender(engine_config) lookup = Lookup(name=self.lookup_name, con=con) headers = ["col1", "col2", "col3"] fields = ["a", "b", "c"] expected_headers = '[{"col1":{"type":"str","key":true}},{"col2":{"type":"str"}},{"col3":{"type":"str"}}]' with mock.patch.object(lookup, "send_control", wraps=lookup.send_control) as lookup_spy: lookup.send_headers(headers=headers, key_index=0, event="START", action="FULL") lookup_spy.assert_called_with(action="FULL", event="START", headers=expected_headers) lookup.send_data_line(key_index=0, fields=fields) lookup.send_headers(headers=headers, key_index=0, event="END", action="FULL") lookup_spy.assert_called_with(action="FULL", event="END", headers=expected_headers) con.socket.shutdown(0)
def test_sender_with_default_logger(self): """ Test that tries to check that Sender class can still use an internal logger and shows both local and remote traces """ try: engine_config = SenderConfigSSL(address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE) con = Sender.for_logging(config=engine_config, tag=self.my_app, level=TEST_FACILITY) # NOTE: this logger logging traces will be visible in console con.logger.info("Testing Sender default handler functionality in " "local console... INFO - log") # NOTE: this logger logging traces will be visible in the remote # table con.info("Testing Sender default handler functionality in remote " "table... INFO - log") data_received = con.socket.recv(5000) print(b"\n" + data_received) if len(data_received) == 0: raise Exception('Not msg sent!') con.close() except Exception as error: self.fail("Problems with test: %s" % str(error))
def test_config_cert_address_standard_case(self): """ Test that verifies that a compatible certificate and address are detected. """ engine_config = SenderConfigSSL(address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE, verify_config=False) chain = engine_config.fake_get_peer_cert_chain(self.chain) with mock.patch.object(SSL.Connection, 'get_peer_cert_chain', mock.MagicMock(return_value=chain)): result = engine_config.check_config_certificate_address() self.assertTrue(result)
def test_sender_as_handler(self): """ Test that tries to check that Sender class can be used as a Handler and related logs are send to remote server """ try: engine_config = SenderConfigSSL(address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE) con = Sender.for_logging(config=engine_config, tag=self.my_app, level=TEST_FACILITY) logger = get_log(name="DevoLogger", handler=con, level=TEST_FACILITY) print("Testing logger info") logger.info("Testing Sender inherit logging handler functio" "nality... INFO - log") data_received = con.socket.recv(5000) print(b"\n" + data_received) if len(data_received) == 0: raise Exception('Not msg sent!') print("Testing logger error") logger.error("Testing Sender inherit logging handler function" "ality... ERROR - log") data_received = con.socket.recv(5000) print(b"\n" + data_received) if len(data_received) == 0: raise Exception('Not msg sent!') print("Testing logger warning") logger.warning("Testing Sender inherit logging handler functio" "nality... WARNING - log") data_received = con.socket.recv(5000) print(b"\n" + data_received) if len(data_received) == 0: raise Exception('Not msg sent!') print("Testing logger debug") logger.debug("Testing Sender inherit logging handler functiona" "lity... DEBUG - log") data_received = con.socket.recv(5000) print(b"\n" + data_received) if len(data_received) == 0: raise Exception('Not msg sent!') print("Testing logger critical") logger.critical("Testing Sender inherit logging handler functio" "nality... CRITICAL - log") data_received = con.socket.recv(5000) print(b"\n" + data_received) if len(data_received) == 0: raise Exception('Not msg sent!') con.close() except Exception as error: self.fail("Problems with test: %s" % str(error))
def write_to_table_command(): table_name = demisto.args()['tableName'] records = check_type(demisto.args()['records'], list) linq_base = demisto.args().get('linqLinkBase', None) creds = get_writer_creds() linq = f"from {table_name}" sender = Sender( SenderConfigSSL(address=(WRITER_RELAY, PORT), key=creds['key'].name, cert=creds['crt'].name, chain=creds['chain'].name)) for r in records: try: sender.send(tag=table_name, msg=json.dumps(r)) except TypeError: sender.send(tag=table_name, msg=f"{r}") querylink = { 'DevoTableLink': build_link(linq, int(1000 * time.time()) - 3600000, int(1000 * time.time()), linq_base=linq_base) } entry = { 'Type': entryTypes['note'], 'Contents': { 'recordsWritten': records }, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'EntryContext': { 'Devo.RecordsWritten': records, 'Devo.LinqQuery': linq } } entry_linq = { 'Type': entryTypes['note'], 'Contents': querylink, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'EntryContext': { 'Devo.QueryLink': createContext(querylink) } } md = tableToMarkdown('Entries to load into Devo', records) entry['HumanReadable'] = md md_linq = tableToMarkdown( 'Link to Devo Query', {'DevoTableLink': f'[Devo Direct Link]({querylink["DevoTableLink"]})'}) entry_linq['HumanReadable'] = md_linq return [entry, entry_linq]
def fake_get_peer_cert_chain(self): engine_config = SenderConfigSSL(address=("eu.elb.relay.logtrust.net", 442), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE, verify_config=False) fake_chain_cert = \ engine_config.fake_get_peer_cert_chain(self.chain) with open(self.chain, "rb") as chain_file: chain_certs = [] for _ca in pem.parse(chain_file.read()): chain_certs.append( crypto.load_certificate(crypto.FILETYPE_PEM, str(_ca))) self.assertEqual(chain_certs, fake_chain_cert)
def test_config_files_path_incorrect_key(self): """ Test that verifies that an incorrect path for the configuration raises an exception. """ wrong_key = SenderConfigSSL(address=(self.server, self.port), key="Incorrect key", cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE, verify_config=False) wrong_key_message = "Error in the configuration, " + \ wrong_key.key + \ " is not a file or the path does not exist" with self.assertRaises(DevoSenderException) as result: wrong_key.check_config_files_path() self.assertEqual(wrong_key_message, str(result.exception))
def test_config_cert_address_incompatible_port(self): """ Test that verifies that a wrong port raises an exception. """ engine_config = SenderConfigSSL(address=("eu.elb.relay.logtrust.net", 442), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE, verify_config=False) with self.assertRaises(DevoSenderException) as result: engine_config.check_config_certificate_address() expected_exception = "Possible error in config, " \ "a timeout could be related " + \ "to an incorrect address/port: " + \ str(engine_config.address) self.assertIn(expected_exception, str(result.exception))
def test_ssl_lookup_override(self): engine_config = SenderConfigSSL(address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain) con = Sender(engine_config) lookup = Lookup(name=self.lookup_name, historic_tag=None, con=con) p_headers = Lookup.list_to_headers(['KEY', 'HEX', 'COLOR'], 'KEY') lookup.send_control('START', p_headers, 'FULL') lookup.send_data_line(key="11", fields=["11", "HEX12", "COLOR12"]) lookup.send_control('END', p_headers, 'FULL') con.socket.shutdown(0)
def test_config_cert_address_incompatible_address(self): """ Test that verifies that an incompatible certificate and address raises an exception. """ engine_config = SenderConfigSSL(address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain, check_hostname=False, verify_mode=CERT_NONE, verify_config=False) with self.assertRaises(DevoSenderException) as result: engine_config.check_config_certificate_address() expected_exception = "Error in config, " + \ "the certificate in the address: " + \ engine_config.address[0] +\ " is not compatible with: " +\ engine_config.chain self.assertIn(expected_exception, str(result.exception))
def test_sender_as_handler(self): """ Test that tries to check that Sender class can be used as a Handler and related logs are send to remote server """ try: engine_config = SenderConfigSSL(address=self.server, port=self.port, key=self.key, cert=self.cert, chain=self.chain) con = Sender(engine_config, tag=self.my_app) logger = logging.getLogger('DEVO_logger') logger.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s|%(levelname)s' '|%(message)s') con.setFormatter(formatter) con.setLevel(logging.DEBUG) logger.addHandler(con) logger.info("Testing Sender inherit logging handler functio" "nality... INFO - log") if len(con.socket.recv(5000)) == 0: raise Exception('Not msg sent!') logger.error("Testing Sender inherit logging handler function" "ality... ERROR - log") if len(con.socket.recv(5000)) == 0: raise Exception('Not msg sent!') logger.warning("Testing Sender inherit logging handler functio" "nality... WARNING - log") if len(con.socket.recv(5000)) == 0: raise Exception('Not msg sent!') logger.debug("Testing Sender inherit logging handler functiona" "lity... DEBUG - log") if len(con.socket.recv(5000)) == 0: raise Exception('Not msg sent!') logger.critical("Testing Sender inherit logging handler functio" "nality... CRITICAL - log") if len(con.socket.recv(5000)) == 0: raise Exception('Not msg sent!') con.close() except Exception as error: self.fail("Problems with test: %s" % error)
def test_ssl_lookup_csv_send(self): engine_config = SenderConfigSSL(address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain) con = Sender(engine_config) lookup = Lookup(name=self.lookup_name, historic_tag=None, con=con) with open(self.lookup_file) as f: line = f.readline() lookup.send_csv(self.lookup_file, headers=line.rstrip().split(","), key=self.lookup_key) con.socket.shutdown(0)
def test_ssl_rt_send(self): """ Test that tries to send a message through a ssl connection """ try: engine_config = SenderConfigSSL(address=self.server, port=self.port, key=self.key, cert=self.cert, chain=self.chain) con = Sender(engine_config) for i in range(0, self.default_numbers_sendings): con.send(tag=self.my_app, msg='Test SSL msg_ python_sdk_ fork') con.close() except Exception as error: self.fail("Problems with test: %s" % error)
def test_rt_send_no_certs(self): """ Test that tries to send a message without using certificates """ if self.test_tcp == "True": try: engine_config = SenderConfigSSL(address=(self.server, self.port)) con = Sender(engine_config) for i in range(self.default_numbers_sendings): con.send(tag=self.my_app, msg=self.test_msg) con.close() except Exception as error: return False else: return True
def test_rt_send_no_certs(self): """ Test that tries to send a message without using certificates """ if self.test_tcp == "True": try: engine_config = SenderConfigSSL(address=self.tcp_server, port=self.tcp_port, cert_reqs=False) con = Sender(engine_config) for i in range(0, self.default_numbers_sendings): con.send(tag=self.my_app, msg='Test RT msg') con.close() except Exception as error: self.fail("Problems with test: %s" % error) else: return True
def test_escape_quotes_in_send_data_line(self): engine_config = SenderConfigSSL( address=(self.server, self.port), key=self.key, cert=self.cert, ) con = Sender(engine_config) lookup = Lookup(name=self.lookup_name, historic_tag=None, con=con, escape_quotes=True) with mock.patch.object(Lookup, 'clean_field', wraps=Lookup.clean_field) as clean_field: lookup.send_data_line(fields=["11", 'Double quotes"']) clean_field.assert_called_with('Double quotes"', True)
def test_multiline_send(self): """ Test that tries to send a multiple line message through a ssl connection """ try: engine_config = SenderConfigSSL(address=self.server, port=self.port, key=self.key, cert=self.cert, chain=self.chain) con = Sender(engine_config) with open(self.test_file, 'r') as file: content = file.read() con.send(tag=self.my_app, msg=content, multiline=True) con.close() except Exception as error: self.fail("Problems with test: %s" % error)
def test_ssl_lookup_simplify(self): engine_config = SenderConfigSSL(address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain) con = Sender(engine_config) lookup = Lookup(name=self.lookup_name, historic_tag=None, con=con) lookup.send_headers(headers=['KEY', 'HEX', 'COLOR'], key='KEY', action='START') lookup.send_data_line(key="11", fields=["11", "HEX12", "COLOR12"]) lookup.send_headers(headers=['KEY', 'HEX', 'COLOR'], key='KEY', action='END') con.socket.shutdown(0)
def test_ssl_rt_send(self): """ Test that tries to send a message through a ssl connection """ try: engine_config = SenderConfigSSL(address=(self.server, self.port), key=self.key, cert=self.cert, chain=self.chain) con = Sender(engine_config) for i in range(self.default_numbers_sendings): con.send(tag=self.my_app, msg=self.test_msg) if len(con.socket.recv(5000)) == 0: raise Exception('Not msg sent!') con.close() except Exception as error: self.fail("Problems with test: %s" % str(error))
def write_to_lookup_table_command(): lookup_table_name = demisto.args()['lookupTableName'] headers = check_type(demisto.args()['headers'], list) records = check_type(demisto.args()['records'], list) creds = get_writer_creds() engine_config = SenderConfigSSL(address=(WRITER_RELAY, 443), key=creds['key'].name, cert=creds['crt'].name, chain=creds['chain'].name) try: con = Sender(config=engine_config, timeout=60) lookup = Lookup(name=lookup_table_name, historic_tag=None, con=con) # Order sensitive list pHeaders = json.dumps(headers) lookup.send_control('START', pHeaders, 'INC') for r in records: lookup.send_data_line(key=r['key'], fields=r['values']) lookup.send_control('END', pHeaders, 'INC') finally: con.flush_buffer() con.socket.shutdown(0) entry = { 'Type': entryTypes['note'], 'Contents': { 'recordsWritten': records }, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'EntryContext': { 'Devo.RecordsWritten': records } } md = tableToMarkdown('Entries to load into Devo', records) entry['HumanReadable'] = md return [entry]
def check_configuration(): # Check all settings related if set # Basic functionality of integration list( ds.Reader(oauth_token=READER_OAUTH_TOKEN, end_point=READER_ENDPOINT, verify=not ALLOW_INSECURE).query(HEALTHCHECK_QUERY, start=int(time.time() - 1), stop=int(time.time()), output='dict')) if WRITER_RELAY and WRITER_CREDENTIALS: creds = get_writer_creds() Sender(SenderConfigSSL(address=(WRITER_RELAY, PORT), key=creds['key'].name, cert=creds['crt'].name, chain=creds['chain'].name))\ .send(tag=HEALTHCHECK_WRITER_TABLE, msg=f'{HEALTHCHECK_WRITER_RECORD}') if FETCH_INCIDENTS_FILTER: alert_filters = check_type(FETCH_INCIDENTS_FILTER, dict) assert alert_filters['type'] in [ 'AND', 'OR' ], 'Missing key:"type" or unsupported value in fetch_incidents_filters' filters = check_type(alert_filters['filters'], list) for filt in filters: assert filt[ 'key'], 'Missing key: "key" in fetch_incidents_filters.filters configuration' assert filt['operator'] in ['=', '/=', '>', '<', '>=', '<=', 'and', 'or', '->'], 'Missing key: "operator"'\ ' or unsupported operator in fetch_incidents_filters.filters configuration' assert filt[ 'value'], 'Missing key:"value" in fetch_incidents_filters.filters configuration' if FETCH_INCIDENTS_DEDUPE: dedupe_conf = check_type(FETCH_INCIDENTS_DEDUPE, dict) assert isinstance( dedupe_conf['cooldown'], (int, float)), 'Invalid fetch_incidents_deduplication configuration' return True
def test_escape_quotes_in_send_csv(self): engine_config = SenderConfigSSL( address=(self.server, self.port), key=self.key, cert=self.cert, ) con = Sender(engine_config) lookup = Lookup(name=self.lookup_name, historic_tag=None, con=con, escape_quotes=True) with mock.patch.object(Lookup, 'clean_field', wraps=Lookup.clean_field) as clean_field: lookup.send_csv(path=self.lookup_file, has_header=True, key=self.lookup_key) clean_field.assert_called_with('ffffff', True)