Skip to content

Commit

Permalink
Merge branch 'Azure:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
roberteliass authored Sep 23, 2024
2 parents 89385a3 + 8bc66b5 commit 65a555a
Show file tree
Hide file tree
Showing 28 changed files with 1,897 additions and 861 deletions.

Large diffs are not rendered by default.

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
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%"
}
]
}
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()
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
Loading

0 comments on commit 65a555a

Please sign in to comment.