ArcSight ESM API
Here is an example on how to get a API token
https://esm:8443/www/core-service/rest/LoginService/login?login=admin&password=password
Here is the URL to ESM Swagger
Here is two example
curl -X GET ”https://esm:8443/detect-api/rest/rules/allIds” -H ”accept: /” -H ”Authorization: Bearer EKMQEX_kyH-S34tD0tX3ic6CyVnDZ92NZCrPXkqSa5s=”
curl -X GET ”https://esm:8443/detect-api/rest/activelists/H%2BIrcfm4BABD239ty-mSKog%3D%3D/entries” -H ”accept: /” -H ”Authorization: Bearer QWWj0-MuK8D31ETL2mZPKFrGJgTN-hzoV__oS02rl_U=”
Here is a script that fetches all Connectors and cases in ESM
import json
import os
import sys
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
CRED_FILE = "cred.json"
def load_credentials(filepath):
with open(filepath, "r", encoding="utf-8") as f:
config = json.load(f)
return config.get("url"), config.get("username"), config.get("password")
class ArcSightDetectClient:
def __init__(self, base_url, username, password):
self.base_url = base_url.rstrip("/")
self.username = username
self.password = password
self.token = None
self.headers = {"Accept": "application/json"}
def login(self):
login_url = f"{self.base_url}/www/core-service/rest/LoginService/login"
payload = {"login": self.username, "password": self.password}
headers = {"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}
res = requests.post(login_url, data=payload, headers=headers, verify=False)
res.raise_for_status()
data = res.json()
self.token = (
data.get("log.loginResponse", {}).get("log.return")
or data.get("logonResponse", {}).get("return")
or data.get("loginResponse", {}).get("return")
or data.get("return")
)
self.headers["Authorization"] = f"Bearer {self.token}"
def logout(self):
if not self.token:
return
logout_url = f"{self.base_url}/www/core-service/rest/LoginService/logout"
try:
requests.post(logout_url, data={"authToken": self.token}, headers={"Content-Type": "application/x-www-form-urlencoded"}, verify=False)
except Exception:
pass
def get_all_activelist_ids(self):
url = f"{self.base_url}/detect-api/rest/v1/activelists/allIds"
res = requests.get(url, headers=self.headers, verify=False)
res.raise_for_status()
return res.json()
def get_activelist_details(self, list_id):
url = f"{self.base_url}/detect-api/rest/v1/activelists/{list_id}"
res = requests.get(url, headers=self.headers, verify=False)
if res.status_code == 200:
return res.json()
return None
def get_activelist_entries(self, list_id):
"""Hämtar rader/poster i en Active List."""
url = f"{self.base_url}/detect-api/rest/v1/activelists/{list_id}/entries"
res = requests.get(url, headers=self.headers, verify=False)
if res.status_code == 200:
return res.json()
return None
def main():
client = None
try:
url, username, password = load_credentials(CRED_FILE)
client = ArcSightDetectClient(url, username, password)
client.login()
print("Hämtar Active Lists...")
al_ids = client.get_all_activelist_ids()
# Slår upp de första 5 listorna
print(f"\nVisar de 5 första av totalt {len(al_ids)} Active Lists:")
for list_id in al_ids[:5]:
details = client.get_activelist_details(list_id)
if details:
name = details.get("name", "Namnlös")
uri = details.get("reference", {}).get("uri", "")
# Hämtar rader
entries = client.get_activelist_entries(list_id)
num_entries = len(entries) if isinstance(entries, list) else "N/A"
print(f" - [{name}] (Poster: {num_entries}) | Sökväg: {uri}")
except Exception as e:
print(f"Fel: {e}", file=sys.stderr)
finally:
if client:
client.logout()
if __name__ == "__main__":
main()
The credentials is stored outside of the script like this
lani@fedora:~/arcsight$ cat cred.json
{
"url": "https://esm:8443",
"username": "admin",
"password": "password"
}
lani@fedora:~/arcsight$
Here is the output of the script
lani@fedora:~/arcsight$ python3 gemini6.py
[+] Inloggad! Token: jUIPOgwBmeWt1I6...
=== CONNECTOR STATUS ===
Status: 2 UP | 6 DOWN
[+] Aktiva connectors:
- [UP] testalerts (ID: 3X1yMtpMBABCEMxJEZ+IVjw==)
- [UP] Manager Internal Agent (ID: 3qpZDtpMBABCAZsKho9kV5A==)
[-] Nere connectors:
- [DOWN] threatintel (ID: 3-VMm0JQBABCGPDSb5L9QMw==)
- [DOWN] hana-db (ID: 30R6DQ5YBABCHb2OjWx9gDA==)
- [DOWN] testalertvialani (ID: 322n-uZMBABCEHhj1fzbJpQ==)
- [DOWN] syslog2 (ID: 3fttb4ZkBABC1AJ3ObGTlWQ==)
- [DOWN] lab (ID: 3iIX9epYBABCDN+7LifJltQ==)
- [DOWN] audit (ID: 3kFRW4ZkBABC0BoB8FgB5Pg==)
=== CASES ===
Totalt antal ärenden: 1
- Case: 'Ozzy' | Sökväg: /All Cases/All Cases/Public/Ozzy (ID: 77l3CPqABABCEAsHQl0ZmPA==)
=== ACTIVE LISTS ===
Totalt antal Active Lists i systemet: 113
[+] Sessionen avslutades korrekt.
lani@fedora:~/arcsight$
Here is another script which fetch all entries in
import json
import os
import sys
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
CRED_FILE = "cred.json"
TARGET_LIST_NAME = "Suspicious Addresses List"
def load_credentials(filepath):
"""Läser in inloggningsuppgifter från cred.json."""
if not os.path.exists(filepath):
raise FileNotFoundError(f"Filen '{filepath}' hittades inte.")
with open(filepath, "r", encoding="utf-8") as f:
config = json.load(f)
return config.get("url"), config.get("username"), config.get("password")
class ArcSightDetectClient:
def __init__(self, base_url, username, password):
self.base_url = base_url.rstrip("/")
self.username = username
self.password = password
self.token = None
self.headers = {"Accept": "application/json"}
def login(self):
"""Autentiserar och sparar Bearer-token."""
login_url = f"{self.base_url}/www/core-service/rest/LoginService/login"
payload = {"login": self.username, "password": self.password}
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
}
response = requests.post(
login_url, data=payload, headers=headers, verify=False
)
response.raise_for_status()
data = response.json()
self.token = (
data.get("log.loginResponse", {}).get("log.return")
or data.get("logonResponse", {}).get("return")
or data.get("loginResponse", {}).get("return")
or data.get("return")
)
if not self.token:
raise ValueError("Kunde inte hämta token ur inloggningssvaret.")
self.headers["Authorization"] = f"Bearer {self.token}"
print(f"[+] Inloggad! Token: {self.token[:15]}...")
def logout(self):
"""Avslutar sessionen i ESM."""
if not self.token:
return
logout_url = f"{self.base_url}/www/core-service/rest/LoginService/logout"
payload = {"authToken": self.token}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
try:
requests.post(
logout_url, data=payload, headers=headers, verify=False
)
print("[+] Sessionen avslutades korrekt.")
except Exception as e:
print(f"[-] Fel vid utloggning: {e}")
def find_activelist_id_by_name(self, list_name):
"""Söker upp ID för en Active List baserat på dess namn."""
# 1. Testa direkt namnsökning via API:et
url_by_name = f"{self.base_url}/detect-api/rest/v1/activelists/name/{list_name}"
res = requests.get(url_by_name, headers=self.headers, verify=False)
if res.status_code == 200:
data = res.json()
if isinstance(data, dict) and "resourceId" in data:
return data["resourceId"]
# 2. Fallback: Hämta alla ID:n och leta efter rätt namn
print(f"[!] Direkt namnsökning misslyckades, söker bland alla Active Lists...")
all_ids_url = f"{self.base_url}/detect-api/rest/v1/activelists/allIds"
all_ids_res = requests.get(all_ids_url, headers=self.headers, verify=False)
all_ids_res.raise_for_status()
for list_id in all_ids_res.json():
details_url = f"{self.base_url}/detect-api/rest/v1/activelists/{list_id}"
details_res = requests.get(details_url, headers=self.headers, verify=False)
if details_res.status_code == 200:
info = details_res.json()
if info.get("name") == list_name:
return list_id
return None
def get_activelist_entries(self, list_id):
"""Hämtar alla rader (entries) ur en specifik Active List."""
url = f"{self.base_url}/detect-api/rest/v1/activelists/{list_id}/entries"
res = requests.get(url, headers=self.headers, verify=False)
res.raise_for_status()
return res.json()
def main():
client = None
try:
url, username, password = load_credentials(CRED_FILE)
client = ArcSightDetectClient(url, username, password)
client.login()
print(f"\nSöker efter Active List: '{TARGET_LIST_NAME}'...")
list_id = client.find_activelist_id_by_name(TARGET_LIST_NAME)
if not list_id:
print(f"[-] Hittade ingen Active List med namnet '{TARGET_LIST_NAME}'.")
return
print(f"[+] Hittade listan! ID: {list_id}")
print(f"Hämtar poster från '{TARGET_LIST_NAME}'...\n")
entries = client.get_activelist_entries(list_id)
print(f"=== INNEHÅLL I {TARGET_LIST_NAME.upper()} ({len(entries)} rader) ===")
print(json.dumps(entries, indent=2))
except Exception as e:
print(f"Ett fel uppstod: {e}", file=sys.stderr)
finally:
if client:
client.logout()
if __name__ == "__main__":
main()
Here is the output from the script
lani@fedora:~/arcsight$ python3 gemini7.py
[+] Inloggad! Token: bzDtbsJ7NmZEinD...
Söker efter Active List: 'Suspicious Addresses List'...
[+] Hittade listan! ID: H-pkUTmsBABCA5uAy8FUEvg==
Hämtar poster från 'Suspicious Addresses List'...
=== INNEHÅLL I SUSPICIOUS ADDRESSES LIST (2 rader) ===
{
"fields": [
"address",
"indicatorType",
"firstDetectTime",
"lastDetectTime",
"port",
"sightings",
"threatLevel",
"actors",
"campaign",
"sector",
"mitreAttack",
"description",
"reference",
"mitigation",
"extraInfo",
"creatorOrg",
"cve",
"virusTotalCount",
"malwareName",
"confidence",
"arcsightSearchTerm",
"arcsightBulletinID",
"avSignatureName",
"tiEventID",
"threatActorTypes",
"threatOrigin",
"threatOperations",
"malwareTypes",
"toolName",
"toolTypes",
"targetLocationRegion",
"targetLocationCountry",
"atapPlusCS1",
"atapPlusCS2",
"atapPlusCS3",
"atapPlusCS4",
"atapPlusCS5"
],
"entries": [
{
"fields": [
"8.8.8.8",
"",
"",
"",
"",
"",
"low",
"",
"",
"",
"",
"test",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
""
]
}
]
}
[+] Sessionen avslutades korrekt.
lani@fedora:~/arcsight$