From 546b9de247dc4a7964bb0da063127f6b75e474d2 Mon Sep 17 00:00:00 2001 From: juju4 Date: Sun, 13 Nov 2022 01:11:04 +0000 Subject: [PATCH 01/14] add sumologic as source --- cartography/cli.py | 33 ++++++++ cartography/config.py | 6 ++ .../cleanup/sumologic_import_cleanup.json | 10 +++ cartography/intel/sumologic/__init__.py | 63 +++++++++++++++ cartography/intel/sumologic/endpoints.py | 54 +++++++++++++ cartography/intel/sumologic/util.py | 80 +++++++++++++++++++ cartography/sync.py | 2 + 7 files changed, 248 insertions(+) create mode 100644 cartography/data/jobs/cleanup/sumologic_import_cleanup.json create mode 100644 cartography/intel/sumologic/__init__.py create mode 100644 cartography/intel/sumologic/endpoints.py create mode 100644 cartography/intel/sumologic/util.py diff --git a/cartography/cli.py b/cartography/cli.py index 78ebc6886..36245795c 100644 --- a/cartography/cli.py +++ b/cartography/cli.py @@ -393,6 +393,30 @@ def _build_parser(self): 'The crowdstrike URL, if using self-hosted. Defaults to the public crowdstrike API URL otherwise.' ), ) + parser.add_argument( + '--sumologic-access-id', + type=str, + default=None, + help=( + 'The sumologic access id for authentication.' + ), + ) + parser.add_argument( + '--sumologic-access-key-env-var', + type=str, + default=None, + help=( + 'The name of environment variable containing the sumologic access key for authentication.' + ), + ) + parser.add_argument( + '--sumologic-api-url', + type=str, + default=None, + help=( + 'The url of the target Sumologic API instance - https://help.sumologic.com/docs/api/getting-started/#sumo-logic-endpoints-by-deployment-and-firewall-security.' + ), + ) return parser def main(self, argv: str) -> int: @@ -522,6 +546,15 @@ def main(self, argv: str) -> int: else: config.crowdstrike_client_secret = None + # Sumologic config + if config.sumologic_access_key_env_var: + logger.debug( + f"Reading password for sumologic from environment variable {config.sumologic_access_key_env_var}", + ) + config.sumologic_access_key = os.environ.get(config.sumologic_access_key_env_var) + else: + config.sumologic_access_key = None + # Run cartography try: return cartography.sync.run_with_config(self.sync, config) diff --git a/cartography/config.py b/cartography/config.py index a323c8a4d..0063ecf2b 100644 --- a/cartography/config.py +++ b/cartography/config.py @@ -124,6 +124,9 @@ def __init__( crowdstrike_client_id=None, crowdstrike_client_secret=None, crowdstrike_api_url=None, + sumologic_access_id=None, + sumologic_access_key=None, + sumologic_api_url=None, ): self.neo4j_uri = neo4j_uri self.neo4j_user = neo4j_user @@ -164,3 +167,6 @@ def __init__( self.crowdstrike_client_id = crowdstrike_client_id self.crowdstrike_client_secret = crowdstrike_client_secret self.crowdstrike_api_url = crowdstrike_api_url + self.sumologic_access_id = sumologic_access_id + self.sumologic_access_key = sumologic_access_key + self.sumologic_api_url = sumologic_api_url diff --git a/cartography/data/jobs/cleanup/sumologic_import_cleanup.json b/cartography/data/jobs/cleanup/sumologic_import_cleanup.json new file mode 100644 index 000000000..26cc68eb0 --- /dev/null +++ b/cartography/data/jobs/cleanup/sumologic_import_cleanup.json @@ -0,0 +1,10 @@ +{ + "statements": [ + { + "query": "WITH datetime()-duration('P7D') AS threshold MATCH (h:SumologicHost) WHERE h.lastupdated < threshold WITH h LIMIT $LIMIT_SIZE DETACH DELETE (h)", + "iterative": true, + "iterationsize": 100 + } + ], + "name": "cleanup sumologic" +} diff --git a/cartography/intel/sumologic/__init__.py b/cartography/intel/sumologic/__init__.py new file mode 100644 index 000000000..0790382f2 --- /dev/null +++ b/cartography/intel/sumologic/__init__.py @@ -0,0 +1,63 @@ +""" +cartography/intel/sumologic +""" +import logging + +import neo4j + +from cartography.config import Config +from cartography.intel.sumologic.endpoints import sync_hosts +from cartography.stats import get_stats_client +from cartography.util import merge_module_sync_metadata +from cartography.util import run_cleanup_job +from cartography.util import timeit + +logger = logging.getLogger(__name__) +stat_handler = get_stats_client(__name__) + + +@timeit +def start_sumologic_ingestion( + neo4j_session: neo4j.Session, + config: Config, +) -> None: + """ + Perform ingestion of Sumologic data. + :param neo4j_session: Neo4J session for database interface + :param config: A cartography.config object + :return: None + """ + common_job_parameters = { + "UPDATE_TAG": config.update_tag, + } + if not config.sumologic_access_id or not config.sumologic_access_key: + logger.error("sumologic config not found") + return + + authorization = ( + config.sumologic_access_id, + config.sumologic_access_key, + config.sumologic_api_url, + ) + sync_hosts( + neo4j_session, + config.update_tag, + authorization, + ) + run_cleanup_job( + "sumologic_import_cleanup.json", + neo4j_session, + common_job_parameters, + ) + + group_id = "public" + if config.sumologic_api_url: + group_id = config.sumologic_api_url + merge_module_sync_metadata( + neo4j_session, + group_type="sumologic", + group_id=group_id, + synced_type="sumologic", + update_tag=config.update_tag, + stat_handler=stat_handler, + ) diff --git a/cartography/intel/sumologic/endpoints.py b/cartography/intel/sumologic/endpoints.py new file mode 100644 index 000000000..92dbfc5e6 --- /dev/null +++ b/cartography/intel/sumologic/endpoints.py @@ -0,0 +1,54 @@ +""" +cartography/intel/sumologic/endpoints +""" +# pylint: disable=missing-function-docstring,too-many-arguments +import logging +from typing import Dict +from typing import List + +import neo4j + +from .util import sumologic_hosts +from cartography.util import timeit + +logger = logging.getLogger(__name__) + + +@timeit +def sync_hosts( + neo4j_session: neo4j.Session, + update_tag: int, + authorization: tuple[str, str, str], +) -> None: + sumologic_hosts_list = sumologic_hosts(authorization) + for host_data in sumologic_hosts_list: + load_host_data(neo4j_session, host_data, update_tag) + + +def load_host_data( + neo4j_session: neo4j.Session, + data: List[Dict], + update_tag: int, +) -> None: + """ + Transform and load scan information + """ + ingestion_cypher_query = """ + UNWIND $Hosts AS host + MERGE (h:SumologicHost{hostname: host.hostname}) + ON CREATE SET h.hostname = host.hostname, + h.sumologic_instance = host.instance, + h.tool_first_seen = host.firstseen + SET h.short_hostname = host.short_hostname, + h.tool_last_seen = host.lastseen, + h.sumologic_bu = host.bu, + h.sumologic_dc = host.dc, + h.modified_timestamp = host.modified_timestamp, + h.lastupdated = $update_tag + """ + logger.info("Loading %s sumologic hosts.", len(data)) + neo4j_session.run( + ingestion_cypher_query, + Hosts=data, + update_tag=update_tag, + ) diff --git a/cartography/intel/sumologic/util.py b/cartography/intel/sumologic/util.py new file mode 100644 index 000000000..e7cca936c --- /dev/null +++ b/cartography/intel/sumologic/util.py @@ -0,0 +1,80 @@ +""" +cartography/intel/sumologic/util +""" +# pylint: disable=invalid-name,broad-except +import datetime +import json +import logging +from array import array + +from msticpy.data.data_providers import QueryProvider + +logger = logging.getLogger(__name__) + + +def sumologic_hosts( + authorization: tuple[str, str, str], + timeout_max: int = 600, +) -> array: + """ + Get Sumologic (Logging) coverage inventory + + Timeout should be adapted to context, mostly size of indexes and searched timeperiod. + + https://help.sumologic.com/docs/api/search-job/ + https://msticpy.readthedocs.io/en/latest/data_acquisition/DataProv-Sumologic.html + """ + + ( + sumologic_access_id, + sumologic_access_key, + sumologic_server_url, + ) = authorization + end_time = datetime.datetime.now() + start_time = end_time - datetime.timedelta(hours=1) + + qry_prov = QueryProvider("Sumologic") + qry_prov.connect( + connection_str=sumologic_server_url, + accessid=sumologic_access_id, + accesskey=sumologic_access_key, + ) + + # _sourceCategory, _sourceHost and _collector will get multiple entries for same host... + # Exact query depends on your context and how structured in your platform and + # the existence of a hostname (through Field Extraction Rule for example) + # or use Sumologic Cloud SIEMT Enterprise normalized schema if apply + # | formatDate(_messageTime,"yyyy/dd/MM HH:mm:ss") as date + # | formatDate(_messageTime,"yyyy/MM/dd'T'HH:mm:ss'Z'") as date - NOK + # | formatDate(_messageTime,"yyyy-MM-dd HH:mm:ss") as date - NOK + vm_assets_query = r"""(_sourceCategory=*/*/SERVER or _sourceCategory=*/*/NXLOG_*) +| formatDate(_messageTime,"yyyy-MM-dd'T'HH:mm:ss'Z'") as date +| tolowercase(replace(hostname, /\..*$/, "")) as short_hostname +| tolowercase(hostname) as hostname +| first(date) as lastseen, last(date) as firstseen by bu,dc,hostname,short_hostname +| count bu,dc,hostname,short_hostname,firstseen,lastseen +| fields bu,dc,hostname,short_hostname,firstseen,lastseen""" + df_vm_assets = qry_prov.exec_query( + vm_assets_query, + start_time=start_time, + end_time=end_time, + timeout=timeout_max, + verbosity=2, + ) + + df_vm_assets.columns = df_vm_assets.columns.str.lstrip("map.") + df_vm_assets["instance"] = sumologic_server_url.replace( + ".sumologic.com/api", "", + ).replace("https://api.", "") + + logger.info("SumologicHosts count final: %s", df_vm_assets.shape[0]) + logger.warning("SumologicHosts count final: %s", df_vm_assets.shape[0]) + + if df_vm_assets.shape[0]: + flatten_data = json.loads(df_vm_assets.to_json(orient="records")) + logger.debug("Example: %s", flatten_data[0]) + logger.warning("Example: %s", flatten_data[0]) + return flatten_data + + logger.warning("No data returned") + return {} diff --git a/cartography/sync.py b/cartography/sync.py index 4ac02593c..7cbbb89f2 100644 --- a/cartography/sync.py +++ b/cartography/sync.py @@ -25,6 +25,7 @@ import cartography.intel.kubernetes import cartography.intel.oci import cartography.intel.okta +import cartography.intel.sumologic from cartography.config import Config from cartography.stats import set_stats_client from cartography.util import STATUS_FAILURE @@ -176,6 +177,7 @@ def build_default_sync() -> Sync: ('aws', cartography.intel.aws.start_aws_ingestion), ('azure', cartography.intel.azure.start_azure_ingestion), ('crowdstrike', cartography.intel.crowdstrike.start_crowdstrike_ingestion), + ('sumologic', cartography.intel.sumologic.start_sumologic_ingestion), ('gcp', cartography.intel.gcp.start_gcp_ingestion), ('gsuite', cartography.intel.gsuite.start_gsuite_ingestion), ('crxcavator', cartography.intel.crxcavator.start_extension_ingestion), From 0b9f4621beae11795fa51a9fb33f2198dd44430a Mon Sep 17 00:00:00 2001 From: juju4 Date: Sun, 13 Nov 2022 03:10:54 +0000 Subject: [PATCH 02/14] fix flake8 --- cartography/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cartography/cli.py b/cartography/cli.py index 36245795c..bf75d0b05 100644 --- a/cartography/cli.py +++ b/cartography/cli.py @@ -414,7 +414,8 @@ def _build_parser(self): type=str, default=None, help=( - 'The url of the target Sumologic API instance - https://help.sumologic.com/docs/api/getting-started/#sumo-logic-endpoints-by-deployment-and-firewall-security.' + 'The url of the target Sumologic API instance - https://help.sumologic.com/' + 'docs/api/getting-started/#sumo-logic-endpoints-by-deployment-and-firewall-security.' ), ) return parser From 5772ef2d1a6ae074fa198e028d8cd850cf9e0144 Mon Sep 17 00:00:00 2001 From: juju4 Date: Sun, 13 Nov 2022 03:47:00 +0000 Subject: [PATCH 03/14] fix few mypy findings --- cartography/intel/sumologic/util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cartography/intel/sumologic/util.py b/cartography/intel/sumologic/util.py index e7cca936c..877fb7fe6 100644 --- a/cartography/intel/sumologic/util.py +++ b/cartography/intel/sumologic/util.py @@ -6,6 +6,7 @@ import json import logging from array import array +from typing import Tuple from msticpy.data.data_providers import QueryProvider @@ -13,7 +14,7 @@ def sumologic_hosts( - authorization: tuple[str, str, str], + authorization: Tuple[str, str, str], timeout_max: int = 600, ) -> array: """ From 7ec98d00979528d81837fdf8a0259c8e719b4c1f Mon Sep 17 00:00:00 2001 From: juju4 Date: Sun, 13 Nov 2022 03:51:20 +0000 Subject: [PATCH 04/14] fix mypy: another tuple --- cartography/intel/sumologic/endpoints.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cartography/intel/sumologic/endpoints.py b/cartography/intel/sumologic/endpoints.py index 92dbfc5e6..5e22d0ddb 100644 --- a/cartography/intel/sumologic/endpoints.py +++ b/cartography/intel/sumologic/endpoints.py @@ -5,6 +5,7 @@ import logging from typing import Dict from typing import List +from typing import Tuple import neo4j @@ -18,7 +19,7 @@ def sync_hosts( neo4j_session: neo4j.Session, update_tag: int, - authorization: tuple[str, str, str], + authorization: Tuple[str, str, str], ) -> None: sumologic_hosts_list = sumologic_hosts(authorization) for host_data in sumologic_hosts_list: From e056d6b919d46ad99f0623a2ba2580a036300475 Mon Sep 17 00:00:00 2001 From: juju4 Date: Sat, 19 Nov 2022 14:33:08 +0000 Subject: [PATCH 05/14] fix mypy --- cartography/intel/sumologic/util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cartography/intel/sumologic/util.py b/cartography/intel/sumologic/util.py index 877fb7fe6..aabb8ba4c 100644 --- a/cartography/intel/sumologic/util.py +++ b/cartography/intel/sumologic/util.py @@ -5,7 +5,7 @@ import datetime import json import logging -from array import array +from typing import List from typing import Tuple from msticpy.data.data_providers import QueryProvider @@ -16,7 +16,7 @@ def sumologic_hosts( authorization: Tuple[str, str, str], timeout_max: int = 600, -) -> array: +) -> List: """ Get Sumologic (Logging) coverage inventory @@ -78,4 +78,4 @@ def sumologic_hosts( return flatten_data logger.warning("No data returned") - return {} + return [] From 78be15df9c1b2b46d3de0615ecfd1a963d248af6 Mon Sep 17 00:00:00 2001 From: juju4 Date: Sat, 19 Nov 2022 19:59:23 +0000 Subject: [PATCH 06/14] update data/indexes.cypher --- cartography/data/indexes.cypher | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cartography/data/indexes.cypher b/cartography/data/indexes.cypher index dedaa4c37..baaf0c5a8 100644 --- a/cartography/data/indexes.cypher +++ b/cartography/data/indexes.cypher @@ -451,3 +451,5 @@ CREATE INDEX IF NOT EXISTS FOR (n:KubernetesSecret) ON (n.lastupdated); CREATE INDEX IF NOT EXISTS FOR (n:KubernetesService) ON (n.id); CREATE INDEX IF NOT EXISTS FOR (n:KubernetesService) ON (n.name); CREATE INDEX IF NOT EXISTS FOR (n:KubernetesService) ON (n.lastupdated); +CREATE INDEX IF NOT EXISTS FOR (n:SumologicHost) ON (n.hostname); +CREATE INDEX IF NOT EXISTS FOR (n:SumologicHost) ON (n.lastupdated); From b4d73e81a102a4ecdaa57382a51d179638451935 Mon Sep 17 00:00:00 2001 From: juju4 Date: Sat, 7 Jan 2023 15:52:24 +0000 Subject: [PATCH 07/14] add msticpy to setup.py --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index f6ce7bb7b..42c72ef01 100644 --- a/setup.py +++ b/setup.py @@ -59,6 +59,7 @@ "pdpyras>=4.3.0", "crowdstrike-falconpy>=0.5.1", "python-dateutil", + "msticpy>=2.2.0", ], extras_require={ ':python_version<"3.7"': [ From b197682240c5dac75ecb65c7d731219d30d1c695 Mon Sep 17 00:00:00 2001 From: juju4 Date: Sat, 7 Jan 2023 19:36:56 +0000 Subject: [PATCH 08/14] add verb to functions --- cartography/intel/sumologic/endpoints.py | 4 ++-- cartography/intel/sumologic/util.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cartography/intel/sumologic/endpoints.py b/cartography/intel/sumologic/endpoints.py index 5e22d0ddb..a8f933d8a 100644 --- a/cartography/intel/sumologic/endpoints.py +++ b/cartography/intel/sumologic/endpoints.py @@ -9,7 +9,7 @@ import neo4j -from .util import sumologic_hosts +from .util import get_sumologic_hosts from cartography.util import timeit logger = logging.getLogger(__name__) @@ -21,7 +21,7 @@ def sync_hosts( update_tag: int, authorization: Tuple[str, str, str], ) -> None: - sumologic_hosts_list = sumologic_hosts(authorization) + sumologic_hosts_list = get_sumologic_hosts(authorization) for host_data in sumologic_hosts_list: load_host_data(neo4j_session, host_data, update_tag) diff --git a/cartography/intel/sumologic/util.py b/cartography/intel/sumologic/util.py index aabb8ba4c..b7ae4d28a 100644 --- a/cartography/intel/sumologic/util.py +++ b/cartography/intel/sumologic/util.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) -def sumologic_hosts( +def get_sumologic_hosts( authorization: Tuple[str, str, str], timeout_max: int = 600, ) -> List: From b4fd6a8ff87bc403dcd2de955679e88f913fc71c Mon Sep 17 00:00:00 2001 From: juju4 Date: Sat, 7 Jan 2023 19:38:42 +0000 Subject: [PATCH 09/14] pylint+black review, cleaning --- cartography/intel/sumologic/util.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cartography/intel/sumologic/util.py b/cartography/intel/sumologic/util.py index b7ae4d28a..61a5427be 100644 --- a/cartography/intel/sumologic/util.py +++ b/cartography/intel/sumologic/util.py @@ -65,16 +65,15 @@ def get_sumologic_hosts( df_vm_assets.columns = df_vm_assets.columns.str.lstrip("map.") df_vm_assets["instance"] = sumologic_server_url.replace( - ".sumologic.com/api", "", + ".sumologic.com/api", + "", ).replace("https://api.", "") logger.info("SumologicHosts count final: %s", df_vm_assets.shape[0]) - logger.warning("SumologicHosts count final: %s", df_vm_assets.shape[0]) if df_vm_assets.shape[0]: flatten_data = json.loads(df_vm_assets.to_json(orient="records")) logger.debug("Example: %s", flatten_data[0]) - logger.warning("Example: %s", flatten_data[0]) return flatten_data logger.warning("No data returned") From a0b0fc9d1296c1a065251f2f1b687a80b1e50112 Mon Sep 17 00:00:00 2001 From: juju4 Date: Sat, 7 Jan 2023 19:43:49 +0000 Subject: [PATCH 10/14] add tests/data/sumologic --- tests/data/sumologic/sumologic_endpoints.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/data/sumologic/sumologic_endpoints.py diff --git a/tests/data/sumologic/sumologic_endpoints.py b/tests/data/sumologic/sumologic_endpoints.py new file mode 100644 index 000000000..f067665d4 --- /dev/null +++ b/tests/data/sumologic/sumologic_endpoints.py @@ -0,0 +1,11 @@ +GET_HOSTS = [ + { + "firstseen": "2020-12-01T10:20:30Z", + "lastseen": "2022-12-15T15:15:15Z", + "hostname": "sumohostname.example.com", + "bu": "myBU", + "short_hostname": "sumohostname", + "dc": "REGION1", + "instance": "us2", + }, +] From 4afe1569a6dc91586faca52597b2280730dfbbae Mon Sep 17 00:00:00 2001 From: juju4 Date: Sat, 7 Jan 2023 19:59:03 +0000 Subject: [PATCH 11/14] add sumologic docs --- docs/root/modules/sumologic/config.md | 15 +++++++++++++++ docs/root/modules/sumologic/schema.md | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 docs/root/modules/sumologic/config.md create mode 100644 docs/root/modules/sumologic/schema.md diff --git a/docs/root/modules/sumologic/config.md b/docs/root/modules/sumologic/config.md new file mode 100644 index 000000000..c84af47c4 --- /dev/null +++ b/docs/root/modules/sumologic/config.md @@ -0,0 +1,15 @@ +## Sumologic Configuration + +.. _sumologic_config: + +Follow these steps to collect Sumologic hosts data with Cartography: + +1. Set up an Access key as per https://help.sumologic.com/docs/manage/security/access-keys/ +1. Populate environment variable with the value generated in the previous step (for example, `SUMO_ACCESSKEY`) +1. Call the `cartography` CLI with: + ```bash + --sumologic-access-id xxx \ + --sumologic-access-key-env-var SUMO_ACCESSKEY \ + --sumologic-api-url https://api.us2.sumologic.com/api + ``` + API url per https://help.sumologic.com/docs/api/getting-started/ diff --git a/docs/root/modules/sumologic/schema.md b/docs/root/modules/sumologic/schema.md new file mode 100644 index 000000000..ce7c5360c --- /dev/null +++ b/docs/root/modules/sumologic/schema.md @@ -0,0 +1,18 @@ +## Sumologic Schema + +.. _sumologic_schema: + +### Sumologic core platform + +Representation of a system sending logs to Sumologic core platform. Be aware that this may vary depending on your environment. +Default code expects _sourceCategory to be formatted as BU/DC/SOURCE_TYPE aka business unit, datacenter or location, and source type. Source type as SERVER or NXLOG_* to match targeted systems (linux, windows...). Some fields may need to be set through [Field Extraction Rules](https://help.sumologic.com/docs/manage/field-extractions/) + +| Field | Description | +|-------|-------------| +|tool_first_seen| Timestamp of when first available logs for host is available since first sync| +|tool_last_seen| Timestamp of when last available logs for host is available per last sync| +|lastupdated| Timestamp of the last time the node was updated| +|**hostname**| The Hostname Computer name| +|short_hostname| The short hostname, lowercase| +|bu| The business unit| +|dc| The datacenter| From 949dea3cad23bcbe929b88a4ff18c90fd19aa015 Mon Sep 17 00:00:00 2001 From: juju4 Date: Sat, 21 Jan 2023 16:35:03 +0000 Subject: [PATCH 12/14] fix: use msticpy[azure] in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 42c72ef01..7bd3f0566 100644 --- a/setup.py +++ b/setup.py @@ -59,7 +59,7 @@ "pdpyras>=4.3.0", "crowdstrike-falconpy>=0.5.1", "python-dateutil", - "msticpy>=2.2.0", + "msticpy[azure]>=2.2.0", ], extras_require={ ':python_version<"3.7"': [ From d0ce424d7be7159209d704037e98abab48885f5a Mon Sep 17 00:00:00 2001 From: juju4 Date: Sat, 21 Jan 2023 16:36:25 +0000 Subject: [PATCH 13/14] fix: add sumologic-sdk to setup.py --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 7bd3f0566..702b83709 100644 --- a/setup.py +++ b/setup.py @@ -60,6 +60,7 @@ "crowdstrike-falconpy>=0.5.1", "python-dateutil", "msticpy[azure]>=2.2.0", + "sumologic-sdk>=1.1.13", ], extras_require={ ':python_version<"3.7"': [ From 4bb89807f07d85c3f091280c7d68bd94e1b858a1 Mon Sep 17 00:00:00 2001 From: juju4 Date: Sat, 21 Jan 2023 16:45:02 +0000 Subject: [PATCH 14/14] fix: add sumologic-sdk to setup.py +fix typo --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 702b83709..965654fb3 100644 --- a/setup.py +++ b/setup.py @@ -60,7 +60,7 @@ "crowdstrike-falconpy>=0.5.1", "python-dateutil", "msticpy[azure]>=2.2.0", - "sumologic-sdk>=1.1.13", + "sumologic-sdk>=0.1.13", ], extras_require={ ':python_version<"3.7"': [