Skip to content

Commit

Permalink
Updated the DataConnector code by implementing Durable Function App.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jayesh Prajapati authored and Jayesh Prajapati committed Oct 24, 2023
1 parent 0c533c8 commit 6ded2d6
Show file tree
Hide file tree
Showing 34 changed files with 530 additions and 443 deletions.
87 changes: 0 additions & 87 deletions Solutions/RubrikSecurityCloud/Data Connectors/README.md

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""This __init__ file will be called by Orchastrator function to ingest data in Sentinel."""
import inspect
import time
from shared_code.logger import applogger
from shared_code.consts import LOGS_STARTS_WITH
from shared_code.rubrik_exception import RubrikException
from .rubrik import Rubrik


def main(name) -> str:
"""Start Execution of Activity Function.
Args:
name (dict): data received via Rubrik Webhook.
Returns:
str: status message of activity function.
"""
__method_name = inspect.currentframe().f_code.co_name
try:
applogger.info(
"{}(method={}) Activity function called!".format(
LOGS_STARTS_WITH, __method_name
)
)
start = time.time()
rubrik_obj = Rubrik()
rubrik_obj.post_data_to_sentinel(name)
end = time.time()
applogger.info(
"{}(method={}) time taken for data ingestion is {} sec".format(
LOGS_STARTS_WITH, __method_name, int(end - start)
)
)
applogger.info(
"{}(method={}) Activity function Completed!".format(
LOGS_STARTS_WITH, __method_name
)
)
except RubrikException as err:
return err
except Exception as err:
applogger.error("{}(method={}) {}".format(LOGS_STARTS_WITH, __method_name, err))
return err
return "Data Posted successfully to {}".format(name.get("log_type"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "name",
"type": "activityTrigger",
"direction": "in"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"""This file contains implementation to ingest Dataminr RTAP alert data into sentinel."""
import inspect
from .sentinel import MicrosoftSentinel
from shared_code.consts import (
LOGS_STARTS_WITH,
ANOMALY_LOG_TYPE,
RANSOMWARE_LOG_TYPE,
THREATHUNT_LOG_TYPE,
)
from shared_code.rubrik_exception import RubrikException
from shared_code.logger import applogger


class Rubrik:
"""This class contains methods to get data from request body pushed via Rubrik Webhook and ingest into Sentinel."""

def __init__(self) -> None:
"""Initialize instance variables for class."""
self.logs_starts_with = LOGS_STARTS_WITH
self.microsoftsentinel = MicrosoftSentinel()
self.error_logs = "{}(method={}) {}"
self.check_environment_var_existance()

def check_environment_var_existance(self):
"""To verify that all required environment variables exist.
Raises:
RubrikException: raise exception if any of the required environment variable is not set.
"""
__method_name = inspect.currentframe().f_code.co_name
env_var = [
{"Anomalies_table_name": ANOMALY_LOG_TYPE},
{"RansomwareAnalysis_table_name": RANSOMWARE_LOG_TYPE},
{"ThreatHunts_table_name": THREATHUNT_LOG_TYPE},
]
try:
applogger.debug(
"{}(method={}) Checking environment variables are exist or not.".format(
self.logs_starts_with, __method_name
)
)
for i in env_var:
key, val = next(iter(i.items()))
if val is None:
raise RubrikException(
"{} is not set in the environment please set the environment variable.".format(
key
)
)
applogger.debug(
"{}(method={}) All custom environment variables exist.".format(
self.logs_starts_with, __method_name
)
)
except RubrikException as err:
applogger.error(
"{}".format(
self.error_logs.format(self.logs_starts_with, __method_name, err)
)
)
raise RubrikException(err)
except Exception as err:
applogger.error(
"{}".format(
self.error_logs.format(self.logs_starts_with, __method_name, err)
)
)
raise RubrikException(err)

def post_data_to_sentinel(self, data):
"""To post data received via Rubrik Webhook into Sentinel.
Args:
data (dict): data received via Rubrik Webhook.
"""
__method_name = inspect.currentframe().f_code.co_name
try:
sentinel_obj = MicrosoftSentinel()
body = data.get("data")
log_type = data.get("log_type")
sentinel_obj.post_data(body, log_type)
except Exception as err:
applogger.error(
"{}".format(
self.error_logs.format(self.logs_starts_with, __method_name, err)
)
)
raise RubrikException(err)
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@
import datetime
import hashlib
import hmac
import logging
import os
import requests
from .RubrikException import RubrikException
from ..shared_code.consts import LOGS_STARTS_WITH, WORKSPACE_ID, WORKSPACE_KEY
from ..shared_code.logger import applogger
from ..shared_code.rubrik_exception import RubrikException

customer_id = os.environ.get("WorkspaceID")
shared_key = os.environ.get("WorkspaceKey")


class AzureSentinel:
class MicrosoftSentinel:
"""AzureSentinel class is used to post data into log Analytics workspace."""

def __init__(self) -> None:
"""Intialize instance variables for MicrosoftSentinel class."""
self.logs_start_with = "{}(MicrosoftSentinel)".format(LOGS_STARTS_WITH)
self.customer_id = WORKSPACE_ID
self.shared_key = WORKSPACE_KEY

def build_signature(
self,
date,
Expand All @@ -37,11 +40,11 @@ def build_signature(
+ resource
)
bytes_to_hash = bytes(string_to_hash, encoding="utf-8")
decoded_key = base64.b64decode(shared_key)
decoded_key = base64.b64decode(self.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)
authorization = "SharedKey {}:{}".format(self.customer_id, encoded_hash)
return authorization

# Build and send a request to the POST API
Expand Down Expand Up @@ -69,13 +72,13 @@ def post_data(self, body, log_type):
resource,
)
except Exception as err:
logging.error("Error occurred: {}".format(err))
applogger.error("{} Error occurred: {}".format(self.logs_start_with, err))
raise RubrikException(
"Error while generating signature for posting data into log analytics."
)
uri = (
"https://"
+ customer_id
+ self.customer_id
+ ".ods.opinsights.azure.com"
+ resource
+ "?api-version=2016-04-01"
Expand All @@ -90,20 +93,27 @@ def post_data(self, body, log_type):
try:
response = requests.post(uri, data=body, headers=headers)
if response.status_code >= 200 and response.status_code <= 299:
logging.info(response.status_code)
logging.info("Accepted: Data Posted Successfully to microsoft sentinel.")
applogger.info(
"{} Data posted successfully to {} table in Log Analytics Workspace.".format(
self.logs_start_with, log_type
)
)
else:
applogger.info(
"Response code: {} from posting data to log analytics.\nError: {}".format(
response.status_code, response.content
)
)
raise RubrikException(
"Response code: {} from posting data to log analytics.\nError: {}".format(
response.status_code, response.content
)
)
except RubrikException as err:
logging.error(err)
except RubrikException as error:
applogger.error("{} Error:{}".format(self.logs_start_with, error))
raise RubrikException(
"RubrikException: Error while posting data to sentinel."
)
except Exception as error:
logging.error(error)
raise RubrikException("Exception: Error while posting data to sentinel.")
return response.status_code
applogger.error("{} Error:{}".format(self.logs_start_with, error))
raise RubrikException()

This file was deleted.

Loading

0 comments on commit 6ded2d6

Please sign in to comment.