| 1 | # from typing import Any |
| 2 | # from typing import Dict |
| 3 | # from typing import Optional |
| 4 | |
| 5 | # import httpx |
| 6 | # from fastapi import HTTPException |
| 7 | # from loguru import logger |
| 8 | # from sqlalchemy.ext.asyncio import AsyncSession |
| 9 | |
| 10 | # from app.connectors.utils import get_connector_info_from_db |
| 11 | # from app.connectors.wazuh_indexer.utils.universal import create_wazuh_indexer_client |
| 12 | # from app.db.db_session import get_db_session |
| 13 | # from app.integrations.alert_escalation.schema.general_alert import CreateAlertRequest |
| 14 | # from app.integrations.alert_escalation.schema.general_alert import GenericAlertModel |
| 15 | # from app.integrations.alert_escalation.schema.general_alert import GenericSourceModel |
| 16 | # from app.integrations.ask_socfortress.schema.ask_socfortress import ( |
| 17 | # AskSocfortressRequest, |
| 18 | # ) |
| 19 | # from app.integrations.ask_socfortress.schema.ask_socfortress import ( |
| 20 | # AskSocfortressSigmaRequest, |
| 21 | # ) |
| 22 | # from app.integrations.ask_socfortress.schema.ask_socfortress import ( |
| 23 | # AskSocfortressSigmaResponse, |
| 24 | # ) |
| 25 | # from app.utils import get_connector_attribute |
| 26 | |
| 27 | |
| 28 | # async def get_single_alert_details( |
| 29 | # alert_details: CreateAlertRequest, |
| 30 | # ) -> GenericAlertModel: |
| 31 | # """ |
| 32 | # Fetches the details of a single alert. |
| 33 | |
| 34 | # Args: |
| 35 | # alert_details (CreateAlertRequest): The details of the alert to fetch. |
| 36 | |
| 37 | # Returns: |
| 38 | # GenericAlertModel: The model representing the fetched alert. |
| 39 | |
| 40 | # Raises: |
| 41 | # HTTPException: If there is an error while fetching the alert details. |
| 42 | # """ |
| 43 | # logger.info( |
| 44 | # f"Fetching alert details for alert {alert_details.alert_id} in index {alert_details.index_name}", |
| 45 | # ) |
| 46 | # es_client = await create_wazuh_indexer_client("Wazuh-Indexer") |
| 47 | # try: |
| 48 | # alert = es_client.get(index=alert_details.index_name, id=alert_details.alert_id) |
| 49 | # source_model = GenericSourceModel(**alert["_source"]) |
| 50 | # return GenericAlertModel( |
| 51 | # _source=source_model, |
| 52 | # _id=alert["_id"], |
| 53 | # _index=alert["_index"], |
| 54 | # _version=alert["_version"], |
| 55 | # ) |
| 56 | # except Exception as e: |
| 57 | # logger.debug(f"Failed to collect alert details: {e}") |
| 58 | # raise HTTPException( |
| 59 | # status_code=400, |
| 60 | # detail=f"Failed to collect alert details: {e}", |
| 61 | # ) |
| 62 | |
| 63 | |
| 64 | # async def get_ask_socfortress_attributes( |
| 65 | # column_name: str, |
| 66 | # session: AsyncSession, |
| 67 | # ) -> str: |
| 68 | # """ |
| 69 | # Gets the Ask SocFortress attribute from the database. |
| 70 | |
| 71 | # Args: |
| 72 | # column_name (str): The column name of the Ask SocFortress attribute. |
| 73 | # session (AsyncSession): The database session. |
| 74 | |
| 75 | # Raises: |
| 76 | # HTTPException: Raised if the Ask SocFortress Attribute is not found. |
| 77 | |
| 78 | # Returns: |
| 79 | # str: The Ask SocFortress Attribute. |
| 80 | |
| 81 | # """ |
| 82 | # attribute_value = await get_connector_attribute( |
| 83 | # connector_id=9, |
| 84 | # column_name=column_name, |
| 85 | # session=session, |
| 86 | # ) |
| 87 | # # Close the session |
| 88 | # await session.close() |
| 89 | # if not attribute_value: |
| 90 | # raise HTTPException( |
| 91 | # status_code=500, |
| 92 | # detail="Ask Socfortress attributes not found in the database.", |
| 93 | # ) |
| 94 | # return attribute_value |
| 95 | |
| 96 | |
| 97 | # async def verify_ask_socfortress_credentials( |
| 98 | # attributes: Dict[str, Any], |
| 99 | # ) -> Dict[str, Any]: |
| 100 | # """ |
| 101 | # Verifies the Ask SocFortress credentials. |
| 102 | |
| 103 | # Args: |
| 104 | # attributes (Dict[str, Any]): The connector attributes. |
| 105 | |
| 106 | # Returns: |
| 107 | # Dict[str, Any]: The connector attributes. |
| 108 | |
| 109 | # Raises: |
| 110 | # HTTPException: Raised if the Ask SocFortress credentials are invalid. |
| 111 | # """ |
| 112 | # api_key = attributes.get("connector_api_key", None) |
| 113 | # url = attributes.get("connector_url", None) |
| 114 | # if api_key is None or url is None: |
| 115 | # logger.error("No Ask Socfortress credentials found in the database") |
| 116 | # raise HTTPException( |
| 117 | # status_code=500, |
| 118 | # detail="Ask Socfortress credentials not found in the database", |
| 119 | # ) |
| 120 | # return attributes |
| 121 | |
| 122 | |
| 123 | # async def verify_ask_socfortress_connector(connector_name: str) -> str: |
| 124 | # """ |
| 125 | # Verifies the Ask SocFortress connector. |
| 126 | |
| 127 | # Args: |
| 128 | # connector_name (str): The name of the connector. |
| 129 | |
| 130 | # Returns: |
| 131 | # str: The connector name. |
| 132 | |
| 133 | # Raises: |
| 134 | # HTTPException: Raised if the connector name is not Ask SocFortress. |
| 135 | # """ |
| 136 | # logger.info("Verifying Ask Socfortress connector") |
| 137 | # async with get_db_session() as session: # This will correctly enter the context manager |
| 138 | # attributes = await get_connector_info_from_db(connector_name, session) |
| 139 | # if attributes is None: |
| 140 | # logger.error("No Ask Socfortress connector found in the database") |
| 141 | # return None |
| 142 | # request = AskSocfortressSigmaRequest( |
| 143 | # sigma_rule_name="Process Explorer Driver Creation By Non-Sysinternals Binary", |
| 144 | # ) |
| 145 | # response = await invoke_ask_socfortress_api( |
| 146 | # attributes["connector_api_key"], |
| 147 | # attributes["connector_url"], |
| 148 | # request, |
| 149 | # ) |
| 150 | # if response["message"] != "Forbidden": |
| 151 | # logger.info("Ask Socfortress connector verified successfully") |
| 152 | # return { |
| 153 | # "connectionSuccessful": True, |
| 154 | # "message": "Successfully verified ASK SOCFortress connector", |
| 155 | # } |
| 156 | # else: |
| 157 | # logger.error("Failed to verify Ask Socfortress connector") |
| 158 | # return { |
| 159 | # "connectionSuccessful": False, |
| 160 | # "message": "Failed to verify ASK SOCFortress connector", |
| 161 | # } |
| 162 | |
| 163 | |
| 164 | # async def invoke_ask_socfortress_api( |
| 165 | # api_key: str, |
| 166 | # url: str, |
| 167 | # request: AskSocfortressSigmaRequest, |
| 168 | # ) -> dict: |
| 169 | # """ |
| 170 | # Invokes the Socfortress Threat Intel API with the provided API key, URL, and request parameters. |
| 171 | |
| 172 | # Args: |
| 173 | # api_key (str): The API key for authentication. |
| 174 | # url (str): The URL of the Socfortress Threat Intel API. |
| 175 | # request (SocfortressThreatIntelRequest): The request object containing the IOC value and customer code. |
| 176 | |
| 177 | # Returns: |
| 178 | # dict: The JSON response from the Socfortress Threat Intel API. |
| 179 | |
| 180 | # Raises: |
| 181 | # httpx.HTTPStatusError: If the API request fails with a non-successful status code. |
| 182 | # """ |
| 183 | # headers = { |
| 184 | # "module-version": "your_module_version", |
| 185 | # "x-api-key": api_key, |
| 186 | # "Content-Type": "application/json", |
| 187 | # } |
| 188 | # data = {"sigma_rule_name": request.sigma_rule_name} |
| 189 | # async with httpx.AsyncClient(timeout=60) as client: |
| 190 | # response = await client.post(url=f"{url}/v1/sigma", headers=headers, json=data) |
| 191 | # return response.json() |
| 192 | |
| 193 | |
| 194 | # async def get_ask_socfortress_response( |
| 195 | # request: AskSocfortressSigmaRequest, |
| 196 | # session: AsyncSession, |
| 197 | # ) -> AskSocfortressSigmaResponse: |
| 198 | # """ |
| 199 | # Retrieves IoC response from Socfortress Threat Intel API. |
| 200 | |
| 201 | # Args: |
| 202 | # request (SocfortressThreatIntelRequest): The request object containing the IoC data. |
| 203 | # session (AsyncSession): The async session object for making HTTP requests. |
| 204 | |
| 205 | # Returns: |
| 206 | # IoCResponse: The response object containing the IoC data and success status. |
| 207 | # """ |
| 208 | # api_key = await get_ask_socfortress_attributes("connector_api_key", session) |
| 209 | # url = await get_ask_socfortress_attributes("connector_url", session) |
| 210 | # response_data = await invoke_ask_socfortress_api(api_key, url, request) |
| 211 | |
| 212 | # # Using .get() with default values |
| 213 | # success = response_data.get("success", False) |
| 214 | # message = response_data.get("message", "No message provided") |
| 215 | |
| 216 | # return AskSocfortressSigmaResponse(success=success, message=message) |
| 217 | |
| 218 | |
| 219 | # async def add_alert_to_document( |
| 220 | # es_client, |
| 221 | # alert: CreateAlertRequest, |
| 222 | # result: str, |
| 223 | # session: AsyncSession, |
| 224 | # ) -> Optional[str]: |
| 225 | # """ |
| 226 | # Update the alert document in Elasticsearch with the provided SOC alert ID URL. |
| 227 | |
| 228 | # Parameters: |
| 229 | # - es_client: The Elasticsearch client instance to use for the update. |
| 230 | # - alert: The alert request object containing alert_id and index_name. |
| 231 | # - soc_alert_id: The alert ID as it exists within IRIS. |
| 232 | # - session: The database session for retrieving connector information. |
| 233 | |
| 234 | # Returns: |
| 235 | # - True if the update is successful, False otherwise. |
| 236 | # """ |
| 237 | # try: |
| 238 | # es_client.update( |
| 239 | # index=alert.index_name, |
| 240 | # id=alert.alert_id, |
| 241 | # body={"doc": {"ask_socfortress_message": result}}, |
| 242 | # ) |
| 243 | # logger.info( |
| 244 | # f"Added Ask SOCFortress Message to alert {alert.alert_id} in index {alert.index_name}", |
| 245 | # ) |
| 246 | # return None |
| 247 | # except Exception as e: |
| 248 | # logger.error( |
| 249 | # f"Failed to add Ask SOCFortress Message to alert {alert.alert_id} in index {alert.index_name}: {e}", |
| 250 | # ) |
| 251 | |
| 252 | # # Attempt to remove read-only block |
| 253 | # try: |
| 254 | # es_client.indices.put_settings( |
| 255 | # index=alert.index_name, |
| 256 | # body={"index.blocks.write": None}, |
| 257 | # ) |
| 258 | # logger.info( |
| 259 | # f"Removed read-only block from index {alert.index_name}. Retrying update.", |
| 260 | # ) |
| 261 | |
| 262 | # # Retry the update operation |
| 263 | # es_client.update( |
| 264 | # index=alert.index_name, |
| 265 | # id=alert.alert_id, |
| 266 | # body={"doc": {"ask_socfortress": result}}, |
| 267 | # ) |
| 268 | # logger.info( |
| 269 | # f"Added Ask SOCFortress Message to alert {alert.alert_id} in index {alert.index_name} after removing read-only block", |
| 270 | # ) |
| 271 | |
| 272 | # # Reenable the write block |
| 273 | # es_client.indices.put_settings( |
| 274 | # index=alert.index_name, |
| 275 | # body={"index.blocks.write": True}, |
| 276 | # ) |
| 277 | # return True |
| 278 | # except Exception as e2: |
| 279 | # logger.error( |
| 280 | # f"Failed to remove read-only block from index {alert.index_name}: {e2}", |
| 281 | # ) |
| 282 | # return False |
| 283 | |
| 284 | |
| 285 | # async def ask_socfortress_lookup( |
| 286 | # alert: AskSocfortressRequest, |
| 287 | # session: AsyncSession, |
| 288 | # ) -> AskSocfortressSigmaResponse: |
| 289 | # """ |
| 290 | # Performs a Ask SOCFortress lookup using the Socfortress service. |
| 291 | |
| 292 | # Args: |
| 293 | # request (SocfortressThreatIntelRequest): The request object containing the IoC to lookup. |
| 294 | # session (AsyncSession): The async session object for making HTTP requests. |
| 295 | |
| 296 | # Returns: |
| 297 | # IoCResponse: The response object containing the Ask SOCFortress information. |
| 298 | # """ |
| 299 | # alert_details = await get_single_alert_details(alert_details=alert) |
| 300 | # logger.info(f"Alert details: {alert_details}") |
| 301 | # if alert_details._source.rule_group3 != "sigma": |
| 302 | # raise HTTPException(status_code=400, detail="Alert is not a Sigma alert.") |
| 303 | # sigma_rule_name = AskSocfortressSigmaRequest( |
| 304 | # sigma_rule_name=alert_details._source.data_name, |
| 305 | # ) |
| 306 | # ask_socfortress_response = await get_ask_socfortress_response( |
| 307 | # sigma_rule_name, |
| 308 | # session, |
| 309 | # ) |
| 310 | # result = ask_socfortress_response.message |
| 311 | # es_client = await create_wazuh_indexer_client("Wazuh-Indexer") |
| 312 | # await add_alert_to_document(es_client, alert, result, session=session) |
| 313 | # return ask_socfortress_response |