howler-sentinel-plugin 0.2.0.dev100__tar.gz → 0.2.0.dev103__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/PKG-INFO +1 -1
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/pyproject.toml +1 -1
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/actions/azure_emit_hash.py +2 -3
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/actions/send_to_sentinel.py +6 -1
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/actions/update_defender_xdr_alert.py +11 -2
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/utils/tenant_utils.py +4 -2
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/LICENSE +0 -0
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/README.md +0 -0
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/__init__.py +0 -0
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/mapping/sentinel_incident.py +0 -0
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/mapping/xdr_alert.py +0 -0
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/mapping/xdr_alert_evidence.py +0 -0
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/odm/hit.py +0 -0
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/odm/models/sentinel.py +0 -0
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/routes/__init__.py +0 -0
- {howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/routes/ingest.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "howler-sentinel-plugin"
|
|
3
|
-
version = "0.2.0.
|
|
3
|
+
version = "0.2.0.dev103"
|
|
4
4
|
description = "A howler plugin for integration with Microsoft's Sentinel API"
|
|
5
5
|
authors = [{ name = "CCCS", email = "analysis-development@cyber.gc.ca" }]
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -83,10 +83,9 @@ def specification():
|
|
|
83
83
|
return {
|
|
84
84
|
"id": OPERATION_ID,
|
|
85
85
|
"title": "Emit sha256 hash to Sentinel",
|
|
86
|
-
"priority":
|
|
87
|
-
"i18nKey": "operations.add_label",
|
|
86
|
+
"priority": 28,
|
|
88
87
|
"description": {
|
|
89
|
-
"short": "
|
|
88
|
+
"short": "Emit sha256 hash to Sentinel",
|
|
90
89
|
"long": execute.__doc__,
|
|
91
90
|
},
|
|
92
91
|
"roles": ["automation_basic"],
|
|
@@ -50,7 +50,7 @@ def execute(query: str, **kwargs):
|
|
|
50
50
|
continue
|
|
51
51
|
|
|
52
52
|
try:
|
|
53
|
-
token, credentials = get_token(tenant_id)
|
|
53
|
+
token, credentials = get_token(tenant_id, "https://monitor.azure.com/.default")
|
|
54
54
|
except HowlerRuntimeError as err:
|
|
55
55
|
logger.exception("Error on token fetching")
|
|
56
56
|
report.append(
|
|
@@ -79,6 +79,11 @@ def execute(query: str, **kwargs):
|
|
|
79
79
|
|
|
80
80
|
response = requests.post(uri, headers=headers, json=payload, timeout=5.0)
|
|
81
81
|
if not response.ok:
|
|
82
|
+
logger.warning(
|
|
83
|
+
"POST request to Azure Monitor failed with status code %s. Content:\n%s",
|
|
84
|
+
response.status_code,
|
|
85
|
+
response.text,
|
|
86
|
+
)
|
|
82
87
|
report.append(
|
|
83
88
|
{
|
|
84
89
|
"query": f"howler.id:{hit.howler.id}",
|
|
@@ -89,7 +89,7 @@ def execute(query: str, **kwargs):
|
|
|
89
89
|
continue
|
|
90
90
|
|
|
91
91
|
try:
|
|
92
|
-
token = get_token(tenant_id)[0]
|
|
92
|
+
token = get_token(tenant_id, "https://graph.microsoft.com/.default")[0]
|
|
93
93
|
except HowlerRuntimeError as err:
|
|
94
94
|
logger.exception("Error on token fetching")
|
|
95
95
|
report.append(
|
|
@@ -106,7 +106,11 @@ def execute(query: str, **kwargs):
|
|
|
106
106
|
alert_url = f"https://graph.microsoft.com/v1.0/security/alerts_v2/{hit.rule.id}"
|
|
107
107
|
response = requests.get(alert_url, headers={"Authorization": f"Bearer {token}"}, timeout=5.0)
|
|
108
108
|
if not response.ok:
|
|
109
|
-
logger.warning(
|
|
109
|
+
logger.warning(
|
|
110
|
+
"GET request to Microsoft Graph failed with status code %s. Content:\n%s",
|
|
111
|
+
response.status_code,
|
|
112
|
+
response.text,
|
|
113
|
+
)
|
|
110
114
|
report.append(
|
|
111
115
|
{
|
|
112
116
|
"query": query,
|
|
@@ -148,6 +152,11 @@ def execute(query: str, **kwargs):
|
|
|
148
152
|
timeout=5.0,
|
|
149
153
|
)
|
|
150
154
|
if not response.ok:
|
|
155
|
+
logger.warning(
|
|
156
|
+
"PATCH request to Microsoft Graph failed with status code %s. Content:\n%s",
|
|
157
|
+
response.status_code,
|
|
158
|
+
response.text,
|
|
159
|
+
)
|
|
151
160
|
report.append(
|
|
152
161
|
{
|
|
153
162
|
"query": query,
|
|
@@ -10,7 +10,7 @@ logger = get_logger(__file__)
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
@cache.memoize(15 * 60)
|
|
13
|
-
def get_token(tenant_id: str) -> tuple[str, dict[str, str]]:
|
|
13
|
+
def get_token(tenant_id: str, scope: str) -> tuple[str, dict[str, str]]:
|
|
14
14
|
"""Get a borealis token based on the current howler token"""
|
|
15
15
|
# Get bearer token
|
|
16
16
|
try:
|
|
@@ -18,6 +18,8 @@ def get_token(tenant_id: str) -> tuple[str, dict[str, str]]:
|
|
|
18
18
|
except (KeyError, json.JSONDecodeError):
|
|
19
19
|
raise HowlerRuntimeError("Credential data not configured.")
|
|
20
20
|
|
|
21
|
+
logger.info("Generating client credential token for client id %s with scope %s", credentials["client_id"], scope)
|
|
22
|
+
|
|
21
23
|
token_request_url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
|
|
22
24
|
response = requests.post(
|
|
23
25
|
token_request_url,
|
|
@@ -25,7 +27,7 @@ def get_token(tenant_id: str) -> tuple[str, dict[str, str]]:
|
|
|
25
27
|
"grant_type": "client_credentials",
|
|
26
28
|
"client_id": credentials["client_id"],
|
|
27
29
|
"client_secret": credentials["client_secret"],
|
|
28
|
-
"scope":
|
|
30
|
+
"scope": scope,
|
|
29
31
|
},
|
|
30
32
|
timeout=5.0,
|
|
31
33
|
)
|
|
File without changes
|
|
File without changes
|
{howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_sentinel_plugin-0.2.0.dev100 → howler_sentinel_plugin-0.2.0.dev103}/sentinel/odm/hit.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|