-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/master'
- Loading branch information
Showing
28 changed files
with
1,897 additions
and
861 deletions.
There are no files selected for viewing
375 changes: 375 additions & 0 deletions
375
...mis/Data Connectors/ArmisAlertsActivities/ArmisAlertActivitySentinelConnector/__init__.py
Large diffs are not rendered by default.
Oops, something went wrong.
35 changes: 35 additions & 0 deletions
35
...Armis/Data Connectors/ArmisAlertsActivities/ArmisAlertActivitySentinelConnector/consts.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
"""Module for constants.""" | ||
|
||
import os | ||
|
||
# Armis constants | ||
API_KEY = os.environ.get("ArmisSecretKey", "") | ||
URL = os.environ.get("ArmisURL", "") | ||
ACCESS_TOKEN_SUFFIX = "/access_token/" | ||
SEARCH_SUFFIX = "/search/" | ||
ACTIVITY_FIELDS = ["title", "type", "time", "site", "sensor", "protocol", "content", "activityUUID"] | ||
ALERT_FIELDS = [ | ||
"alertId", | ||
"type", | ||
"title", | ||
"description", | ||
"severity", | ||
"time", | ||
"status", | ||
"deviceIds", | ||
"activityUUIDs", | ||
] | ||
RETRY_COUNT_401 = 3 | ||
|
||
# Sentinel constants | ||
CONNECTION_STRING = os.environ.get("AzureWebJobsStorage", "") | ||
ARMIS_ALERTS_TABLE = os.environ.get("ArmisAlertsTableName", "") | ||
ARMIS_ACTIVITIES_TABLE = os.environ.get("ArmisActivitiesTableName", "") | ||
IS_AVOID_DUPLICATES = os.environ.get("AvoidDuplicates", "") | ||
WORKSPACE_ID = os.environ.get("WorkspaceID", "") | ||
WORKSPACE_KEY = os.environ.get("WorkspaceKey", "") | ||
CHUNK_SIZE = 35 | ||
FILE_SHARE = "funcstatemarkershare" | ||
CHECKPOINT_FILE = "funcarmisalertsfile" | ||
LOG_FORMAT = "Armis Alerts Activities Connector: (method = {}) : {}" | ||
REQUEST_TIMEOUT = 300 |
11 changes: 11 additions & 0 deletions
11
...s/Data Connectors/ArmisAlertsActivities/ArmisAlertActivitySentinelConnector/function.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"scriptFile": "__init__.py", | ||
"bindings": [ | ||
{ | ||
"name": "mytimer", | ||
"type": "timerTrigger", | ||
"direction": "in", | ||
"schedule": "%Schedule%" | ||
} | ||
] | ||
} |
163 changes: 163 additions & 0 deletions
163
...mis/Data Connectors/ArmisAlertsActivities/ArmisAlertActivitySentinelConnector/sentinel.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
"""Module for Sentinel utility.""" | ||
|
||
import inspect | ||
import base64 | ||
import hashlib | ||
import hmac | ||
import logging | ||
import datetime | ||
import requests | ||
from Exceptions.ArmisExceptions import ArmisException | ||
from . import consts | ||
|
||
customer_id = consts.WORKSPACE_ID | ||
shared_key = consts.WORKSPACE_KEY | ||
|
||
|
||
class AzureSentinel: | ||
"""AzureSentinel is Used to post data to log analytics.""" | ||
|
||
def build_signature( | ||
self, | ||
date, | ||
content_length, | ||
method, | ||
content_type, | ||
resource, | ||
): | ||
"""To build the signature.""" | ||
x_headers = "x-ms-date:" + date | ||
string_to_hash = method + "\n" + str(content_length) + "\n" + content_type + "\n" + x_headers + "\n" + resource | ||
bytes_to_hash = bytes(string_to_hash, encoding="utf-8") | ||
decoded_key = base64.b64decode(shared_key) | ||
encoded_hash = base64.b64encode( | ||
hmac.new(decoded_key, bytes_to_hash, digestmod=hashlib.sha256).digest() | ||
).decode() | ||
authorization = "SharedKey {}:{}".format(customer_id, encoded_hash) | ||
return authorization | ||
|
||
# Build and send a request to the POST API | ||
def post_data(self, body, log_type, timestamp): | ||
"""Build and send a request to the POST API.""" | ||
method = "POST" | ||
content_type = "application/json" | ||
resource = "/api/logs" | ||
rfc1123date = datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") | ||
content_length = len(body) | ||
timestamp_date = timestamp | ||
__method_name = inspect.currentframe().f_code.co_name | ||
try: | ||
signature = self.build_signature( | ||
rfc1123date, | ||
content_length, | ||
method, | ||
content_type, | ||
resource, | ||
) | ||
uri = "https://" + customer_id + ".ods.opinsights.azure.com" + resource + "?api-version=2016-04-01" | ||
|
||
headers = { | ||
"content-type": content_type, | ||
"Authorization": signature, | ||
"Log-Type": log_type, | ||
"x-ms-date": rfc1123date, | ||
"time-generated-field": timestamp_date, | ||
} | ||
|
||
response = requests.post(uri, data=body, headers=headers, timeout=consts.REQUEST_TIMEOUT) | ||
if response.status_code >= 200 and response.status_code <= 299: | ||
logging.info(consts.LOG_FORMAT.format(__method_name, "Data posted successfully to microsoft sentinel.")) | ||
elif response.status_code == 400: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, "Bad Request = {}, Status code : {}.".format(response.text, response.status_code) | ||
) | ||
) | ||
raise ArmisException() | ||
elif response.status_code == 403: | ||
logging.error( | ||
consts.LOG_FORMAT.format(__method_name, "Forbidden, Status code : {}.".format(response.status_code)) | ||
) | ||
raise ArmisException() | ||
elif response.status_code == 404: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, "Request Not Found , Status code : {}.".format(response.status_code) | ||
) | ||
) | ||
raise ArmisException() | ||
elif response.status_code == 429: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, | ||
"Too Many Requests, Status code : {}.".format(response.status_code), | ||
) | ||
) | ||
raise ArmisException() | ||
elif response.status_code == 500: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, | ||
"Internal Server Error, Status code : {}.".format(response.status_code), | ||
) | ||
) | ||
raise ArmisException() | ||
elif response.status_code == 503: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, | ||
"Service Unavailable, Status code : {}.".format(response.status_code), | ||
) | ||
) | ||
raise ArmisException() | ||
else: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, | ||
"Error while posting data to microsoft sentinel Response code: {}.".format( | ||
response.status_code | ||
), | ||
) | ||
) | ||
raise ArmisException() | ||
except requests.ConnectionError as err: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, | ||
"Connection Error while posting data to microsoft sentinel : {}.".format(err), | ||
) | ||
) | ||
raise ArmisException() | ||
except requests.HTTPError as err: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, | ||
"HTTP Error while posting data to microsoft sentinel : {}.".format(err), | ||
) | ||
) | ||
raise ArmisException() | ||
except requests.Timeout as err: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, | ||
"Timeout Error while posting data to microsoft sentinel : {}.".format(err), | ||
) | ||
) | ||
raise ArmisException() | ||
except requests.exceptions.InvalidURL as err: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, | ||
"Invalid URL Error while posting data to microsoft sentinel : {}.".format(err), | ||
) | ||
) | ||
raise ArmisException() | ||
except ArmisException: | ||
raise ArmisException() | ||
except Exception as err: | ||
logging.error( | ||
consts.LOG_FORMAT.format( | ||
__method_name, "Error while posting data to microsoft sentinel : {}.".format(err) | ||
) | ||
) | ||
raise ArmisException() |
38 changes: 38 additions & 0 deletions
38
...ata Connectors/ArmisAlertsActivities/ArmisAlertActivitySentinelConnector/state_manager.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
"""This module will help to save file to statemanager.""" | ||
from azure.storage.fileshare import ShareClient | ||
from azure.storage.fileshare import ShareFileClient | ||
from azure.core.exceptions import ResourceNotFoundError | ||
from . import consts | ||
|
||
|
||
class StateManager: | ||
"""State manager class for specific operation.""" | ||
|
||
def __init__( | ||
self, | ||
connection_string, | ||
file_path, | ||
share_name=consts.FILE_SHARE, | ||
): | ||
"""Initialize the share_cli and file_client.""" | ||
self.share_cli = ShareClient.from_connection_string( | ||
conn_str=connection_string, share_name=share_name | ||
) | ||
self.file_cli = ShareFileClient.from_connection_string( | ||
conn_str=connection_string, share_name=share_name, file_path=file_path | ||
) | ||
|
||
def post(self, marker_text: str): | ||
"""Post method for posting the data to azure storage.""" | ||
try: | ||
self.file_cli.upload_file(marker_text) | ||
except ResourceNotFoundError: | ||
self.share_cli.create_share() | ||
self.file_cli.upload_file(marker_text) | ||
|
||
def get(self): | ||
"""Get method for getting the data from azure storage.""" | ||
try: | ||
return self.file_cli.download_file().readall().decode() | ||
except ResourceNotFoundError: | ||
return None |
Oops, something went wrong.