IBM QRadar SOAR

 View Only

Step-by-Step Guide to Syncing Incidents Between ManageEngine ITSM and IBM SOAR

By Anuj Shrivastava posted 5 days ago

  

Introduction
Integrating IT Service Management (ITSM) tools like ManageEngine with security orchestration platforms like IBM Security Orchestration, Automation, and Response (SOAR) ensures seamless incident management. This guide walks through a Python script that syncs incidents from ManageEngine ITSM to IBM SOAR. We'll explain the code logic, API interactions, and security considerations.

Prerequisites

  1. API Access: Ensure you have:

    • ManageEngine ITSM API credentials (client_id, client_secret, refresh_token).

    • IBM SOAR API credentials (Base64-encoded Authorization header).

  2. Python Environment: Install Python 3.x and required libraries:

    pip install requests
  3. SSL Certificates: Disable SSL verification only in development (verify=False). Use valid certificates in production.

Step-by-Step Procedure

1. Authentication with ManageEngine ITSM

  • Purpose: Obtain an OAuth access token to authenticate ManageEngine API requests.
ME_TOKEN_URL = "https://accounts.zoho.in/oauth/v2/token?refresh_token=1000.005fce...&grant_type=refresh_token&client_id=1000.EHM6T4ZUL...&client_secret=46c99c7e0fa..."
response = requests.post(url=ME_TOKEN_URL, verify=False)
access_token = json.loads(response.text)["access_token"]

Refresh Token: Used to generate short-lived access tokens without user interaction.

  • Headers: Include Zoho-oauthtoken in subsequent requests.

2. Fetch Existing Incidents from IBM SOAR

  • Purpose: Retrieve current incidents to determine the latest synced incident ID.
INCIDENT_URL = "https://9.30.57.77/rest/orgs/201/incidents"
headers = {'Authorization': 'Basic NGVkMTBiZjAtZjU1MS00MTE5LWI0YzQtN2ViZDBjNThiOTBi...'}
incident_list = requests.request("GET", url=INCIDENT_URL, headers=headers, verify=False)
  • Basic Authentication: Uses Base64-encoded credentials for IBM SOAR.

  • SSL Verification: verify=False bypasses certificate checks (use cautiously).


3. Query ManageEngine for New Requests

Purpose: Fetch unresolved incidents from ManageEngine filtered by the latest IBM SOAR incident ID.

list_info = {
    "list_info": {
        "row_count": 10,
        "filter_by": {"id": "17028000000026038"},
        "search_criteria": {
            "field": "display_id",
            "condition": "greater than",
            "value": json.loads(incident_list.text)[0]['external_id']
        }
    }
}
params = {"input_data": json.dumps(list_info)}
request_list = requests.get(ME_REQUEST_URL, headers=ME_headers, params=params, verify=False)
  • Filtering: Only requests with display_id greater than the latest SOAR incident are fetched.

  • Pagination: row_count limits results; adjust based on needs.

4. Create Incidents in IBM SOAR

Purpose: Loop through ManageEngine requests and create corresponding incidents in SOAR.

for request_to_add in json.loads(request_list.text)['requests']:
    payload = json.dumps({
        "external_id": request_to_add["display_id"],
        "name": request_to_add["subject"],
        "discovered_date": int(request_to_add["created_time"]["value"]),
        "properties": {"manage_engine_id": int(request_to_add["display_id"])}
    })
    incident_added = requests.post(INCIDENT_URL, headers=headers, data=payload, verify=False)
  • Payload Mapping: Critical fields like external_id and discovered_date ensure traceability.

  • Custom Properties: properties.manage_engine_id links SOAR incidents back to ManageEngine.


5. Error Handling

Purpose: Gracefully handle exceptions to avoid script failure.

try:
    # ... code ...
except Exception as e:
    print("CLIENT ERROR: {0}\n".format(e))
  • Logging: Implement logging (e.g., logging module) for production use.


Best Practices

  1. Security:

    • Avoid hardcoding credentials; use environment variables or vaults.

    • Enable SSL verification in production.

  2. Scheduling:

    • Run the script periodically via cron jobs or CI/CD pipelines.

  3. Enhancements:

    • Add two-way sync to update ManageEngine when SOAR incidents change.

    • Include pagination for large datasets.


Full Code with Comments

import requests
import json

def main():
    try:
        # Step 1: Authenticate with ManageEngine
        ME_TOKEN_URL = "https://accounts.zoho.in/oauth/v2/token?refresh_token=1000.005fce...&grant_type=refresh_token"
        response = requests.post(ME_TOKEN_URL, verify=False)
        access_token = json.loads(response.text)["access_token"]
        
        # Step 2: Configure ManageEngine API headers
        ME_headers = {
            "Accept": "application/vnd.manageengine.v3+json",
            "Authorization": "Zoho-oauthtoken " + access_token
        }
        
        # Step 3: Fetch latest incidents from IBM SOAR
        INCIDENT_URL = "https://9.30.57.XX/rest/orgs/201/incidents"
        soar_headers = {'Authorization': 'Basic NGVkMTBiZjAtZjU1MS00MTE5LWI0YzQtN2ViZDBjNThiOTBi...'}
        incident_list = requests.get(INCIDENT_URL, headers=soar_headers, verify=False)
        
        # Step 4: Fetch new requests from ManageEngine
        list_info = {
            "list_info": {
                "search_criteria": {
                    "field": "display_id",
                    "condition": "greater than",
                    "value": json.loads(incident_list.text)[0]['external_id']
                }
            }
        }
        params = {"input_data": json.dumps(list_info)}
        request_list = requests.get("https://sdpondemand.manageengine.in/api/v3/requests", 
                                   headers=ME_headers, params=params, verify=False)
        
        # Step 5: Sync to IBM SOAR
        if request_list.json().get('requests'):
            for req in request_list.json()['requests']:
                payload = json.dumps({
                    "external_id": req["display_id"],
                    "name": req["subject"],
                    "discovered_date": int(req["created_time"]["value"]),
                    "properties": {"manage_engine_id": req["display_id"]}
                })
                requests.post(INCIDENT_URL, headers=soar_headers, data=payload, verify=False)
                
    except Exception as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    main()

below images are from ManageEngine ITSM and IBM SOAR where ID 37 is synced with IBM SOAR.

Conclusion

This script automates one-way incident syncing from ManageEngine ITSM to IBM SOAR. By understanding API interactions and security practices, you can extend this to handle bidirectional syncs, attachments, or custom fields. Always test in a non-production environment before deployment.

Reach out to us if you need further guidance. Let’s elevate your security operations together!

Honey Gidwani honey.gidwani@ibm.com
Anuj Shrivastava  - ashrivastava@in.ibm.com

0 comments
6 views

Permalink