XSOAR Engineer Training
The XSOAR Engineer Training (XET) integration provides sample data to fetch events into Cortex XSOAR, and commands to build playbooks around. Use for training purposes only.
Utilities · XSOAR Engineer Training
Details
| ID | XSOAR Engineer Training |
|---|---|
| Provider | Palo Alto Networks |
| Category | Utilities |
| From Version | 6.9.0 |
| Docker Image | demisto/python3:3.12.8.3296088 |
README
The XSOAR Engineer Training (XET) integration provides sample data to fetch events into Cortex XSOAR, and commands to build playbooks around.
Use for training purposes only.
This integration was integrated and tested with versions 6.9+ and 8.3 of XSOAR.
Configure XSOAR Engineer Training in Cortex
| Parameter | Required |
|---|---|
| Fetch incidents | False |
| Incident type | False |
| Incidents Fetch Interval | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
xet-get-events
Fetches events from the XSOAR Engineer Training (XET) integration.
Base Command
xet-get-events
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
There is no context output for this command.
Command example
#### Human Readable Output
>### Training Events
>
>|eventID|occurred|sourceIP|sourceUser|type|url|urlCategory|userAgent|
>|---|---|---|---|---|---|---|---|
>| 4218 | 2023-10-04T21:30:06Z | 10.8.8.8 | m@xsoar.local | url blocked | https:<span>//</span>xsoar.pan.dev/52/download.zip | MALWARE | Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0 |
### xet-ad-get-user
***
Retrieves detailed information about a user account. The user can be specified by username, email address, or as an Active Directory Distinguished Name (DN).
#### Base Command
`xet-ad-get-user`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| dn | The Distinguished Name of the user in which to return information. | Optional |
| username | Queries users by the samAccountName attribute. | Optional |
| email | Queries by the user's email address. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| ActiveDirectory.Users.dn | unknown | The Distinguished Name of the user. |
| ActiveDirectory.Users.displayName | unknown | The display name of the user. |
| ActiveDirectory.Users.name | unknown | The common name of the user. |
| ActiveDirectory.Users.sAMAccountName | unknown | The sAMAccountName of the user. |
| ActiveDirectory.Users.userAccountControl | unknown | The account control flag of the user. |
| ActiveDirectory.Users.mail | unknown | The email address of the user. |
| ActiveDirectory.Users.manager | unknown | The manager of the user. |
| ActiveDirectory.Users.memberOf | unknown | Groups for which the user is a member. |
| Account.DisplayName | unknown | The display name of the user. |
| Account.Groups | unknown | Groups for which the user is a member. |
| Account.Manager | unknown | The manager of the user. |
| Account.ID | unknown | The Distinguished Name of the user. |
| Account.Username | unknown | The samAccountName of the user. |
| Account.Email | unknown | The email address of the user. |
#### Command example
```!xet-ad-get-user email="james.bond@xsoar.local"```
#### Context Example
```json
{
"Account": {
"DisplayName": [
"James Bond"
],
"Email": [
"james.bond@xsoar.local"
],
"Groups": [
"CN=Agents,CN=Users,DC=xsoar,DC=local"
],
"ID": "CN=James Bond,CN=Users,DC=xsoar,DC=local",
"Manager": [
"CN=M,CN=Users,DC=xsoar,DC=local"
],
"Type": "AD",
"Username": [
"XSOAR007"
]
},
"ActiveDirectory": {
"Users": {
"displayName": [
"James Bond"
],
"dn": "CN=James Bond,CN=Users,DC=xsoar,DC=local",
"mail": [
"james.bond@xsoar.local"
],
"manager": [
"CN=M,CN=Users,DC=xsoar,DC=local"
],
"memberOf": [
"CN=Agents,CN=Users,DC=xsoar,DC=local"
],
"name": [
"James Bond"
],
"sAMAccountName": [
"XSOAR007"
],
"userAccountControl": [
512
]
}
}
}
Human Readable Output
Active Directory - Get Users
displayName dn manager memberOf name sAMAccountName userAccountControl James Bond CN=James Bond,CN=Users,DC=xsoar,DC=local james.bond@xsoar.local CN=M,CN=Users,DC=xsoar,DC=local CN=Agents,CN=Users,DC=xsoar,DC=local James Bond XSOAR007 512
xet-ad-expire-password
Expires the password of an Active Directory user.
Base Command
xet-ad-expire-password
Input
| Argument Name | Description | Required |
|---|---|---|
| username | The username (samAccountName) of the user to modify. | Required |
Context Output
There is no context output for this command.
Command example
!xet-ad-expire-password username="XSOAR007"
Human Readable Output
Expired password successfully
xet-ad-set-new-password
Sets a new password for an Active Directory user.
Base Command
xet-ad-set-new-password
Input
| Argument Name | Description | Required |
|---|---|---|
| username | The username of the account to disable (sAMAccountName). | Required |
| password | The password to set for the user. | Required |
Context Output
There is no context output for this command.
Command example
!xet-ad-set-new-password username="XSOAR007" password="bondjamesbond"
Human Readable Output
User password successfully set
xet-siem-search
Searches the simulated SIEM for events.
Base Command
xet-siem-search
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The query to execute against the SIEM. | Required |
| result_type | Type of result to return for this SIEM integration. Possible values are: email, hosts. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| SIEM.Result | unknown | The results of the SIEM search. The results are a JSON array, in which each item is a SIEM event. |
Command example
!xet-siem-search query="host:crossiscoming81"
Human Readable Output
SIEM Search results for query: host:crossiscoming81
No entries.
xet-send-mail
Send an email. (Doesn’t actually send an email.)
Base Command
xet-send-mail
Input
| Argument Name | Description | Required |
|---|---|---|
| to | Who to send the fake email to. | Required |
| body | The body of the fake email that we are not actually sending. | Required |
Context Output
There is no context output for this command.
Command example
!xet-send-mail to="james.bond@xsoar.local" body="shaken or stirred?"
Human Readable Output
XSOAR Engineer Training: fake email notification not sent
Configuration parameters
isFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Interval
Commands (6)
-
xet-ad-expire-passwordExpires the password of an Active Directory user.
-
xet-ad-get-userRetrieves detailed information about a user account. The user can be specified by username, email address, or as an Active Directory Distinguished Name (DN).
-
xet-ad-set-new-passwordSets a new password for an Active Directory user.
-
xet-get-eventsFetches events from the XSOAR Engineer Training (XET) integration.
-
xet-send-mailSend an email. (Doesn't actually send an email.)
-
xet-siem-searchSearches the simulated SIEM for events.
import json from copy import deepcopy from datetime import datetime, timedelta from random import choice, randint, randrange import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 """ SAMPLE EVENTS """ SAMPLE_EVENT = { "type": "url allowed", "eventID": "007", "urlCategory": "MALWARE", "sourceIP": "10.8.8.8", "occurred": "2023-01-01T00:00:01.000Z", "sourceUser": "james.bond@xsoar.local", "url": "https://xsoar.pan.dev/login.zip", "userAgent": "Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0", } TYPES = ["url allowed", "url blocked"] CATEGORIES = ["PHISH", "MALWARE", "SPAM"] DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" """ ACTIVE DIRECTORY QUERY V2 INTEGRATION """ USERS = [ { "email": "james.bond@xsoar.local", "displayname": "James Bond", "samaccountname": "XSOAR007", "dn": "CN=James Bond,CN=Users,DC=xsoar,DC=local", "group": "CN=Agents,CN=Users,DC=xsoar,DC=local", "manager": "CN=M,CN=Users,DC=xsoar,DC=local", }, { "email": "eve.moneypenny@xsoar.local", "displayname": "Eve Moneypenny", "samaccountname": "XSOAR002", "dn": "CN=Eve Moneypenny,CN=Users,DC=xsoar,DC=local", "group": "CN=Administration,CN=Users,DC=xsoar,DC=local", "manager": "CN=M,CN=Users,DC=xsoar,DC=local", }, { "email": "m@xsoar.local", "displayname": "M", "samaccountname": "XSOAR001", "dn": "CN=M,CN=Users,DC=xsoar,DC=local", "group": "CN=Managers,CN=Users,DC=xsoar,DC=local", "manager": "CN=James Bond,CN=Users,DC=xsoar,DC=local", }, { "email": "q@xsoar.local", "displayname": "Q", "samaccountname": "XSOAR003", "dn": "CN=Q,CN=Users,DC=xsoar,DC=local", "group": "CN=Gadgets,CN=Users,DC=xsoar,DC=local", "manager": "CN=James Bond,CN=Users,DC=xsoar,DC=local", }, ] """ Helper functions """ def get_now(): """ A wrapper function of datetime.now helps handle tests Returns: datetime: time right now """ return datetime.now() def mock_data(total): """ Changes mocks the data to randomize the alerts a bit. """ now = get_now() data = [] count = 0 users = [x["email"] for x in USERS] while count < total: item = deepcopy(SAMPLE_EVENT) item["occurred"] = (now - timedelta(minutes=randrange(6, 60))).strftime("%Y-%m-%dT%H:%M:%SZ") item["eventID"] = str(randrange(100, 10000)) item["type"] = choice(TYPES) if item["type"] == "url blocked": item["urlCategory"] = choice(CATEGORIES) else: item["urlCategory"] = choice(CATEGORIES) item["sourceUser"] = choice(users) item["sourceIP"] = f"10.8.8.{randrange(2,250)}" if item["urlCategory"] == "MALWARE": item["url"] = f"https://xsoar.pan.dev/{randrange(1,88)}/download.zip" if item["urlCategory"] == "PHISH": item["url"] = f"https://xsoar.pan.dev/{randrange(1,88)}/login.php" if item["urlCategory"] == "SPAM": item["url"] = f"https://xsoar.pan.dev/{randrange(1,88)}/getnewbike" data.append(item) count += 1 return data def lookup_ad_user(lookup, attribute): """ Returns the user details from the USERS global var """ found_user = False for u in USERS: if u[attribute] == lookup: found_user = True user: Dict | None = u break if not found_user: user = None return user def create_ad_user_output(user): """ returns the user object for using the USER_TEMPLATE """ user_template = { "attributes": { "displayName": [f"{user['displayname']}"], "mail": [f"{user['email']}"], "manager": [f"{user['manager']}"], "memberOf": [f"{user['group']}"], "name": [f"{user['displayname']}"], "sAMAccountName": [f"{user['samaccountname']}"], "userAccountControl": [512], "dn": f"{user['dn']}", }, "account": { "DisplayName": [f"{user['displayname']}"], "Email": [f"{user['email']}"], "Manager": [f"{user['manager']}"], "Groups": [f"{user['group']}"], "Type": "AD", "Username": [f"{user['samaccountname']}"], "ID": f"{user['dn']}", }, } return user_template """ Command functions """ def get_events_command(args): """ returns the events, in this case the mock data """ args.get("eventTypes") total = randrange(10, 20) events = mock_data(total) readable = tableToMarkdown("Training Events", events) results = CommandResults(readable_output=readable, ignore_auto_extract=True) return results def simple_response_command(command): """ returns a text response for the Active Directory and send mail Commands """ command_map = { "xet-ad-expire-password": "Expired password successfully", # guardrails-disable-line "xet-ad-set-new-password": "User password successfully set", # guardrails-disable-line "xet-send-mail": "XSOAR Engineer Training: fake email notification not sent", } return CommandResults(readable_output=command_map[command], ignore_auto_extract=True) def ad_get_user_command(args): """ Returns the user details from our simulated AD if the user is found """ user: dict | None = {} demisto.debug(f"Initializing {user=}") # error handing if one of username, email or dn is not passed to the command if not args.get("username") and not args.get("email") and not args.get("dn"): return_error("Need either a username, email, or dn") # lookup the user if args.get("email"): username = args.get("email") user = lookup_ad_user(username, "email") if args.get("username"): username = args.get("username") user = lookup_ad_user(username, "samaccountname") if args.get("dn"): username = args.get("dn") user = lookup_ad_user(username, "dn") # create the user response if user: user_output = create_ad_user_output(user) # return results like AD query would. demisto_entry = { "ContentsFormat": formats["json"], "Type": entryTypes["note"], "Contents": user_output, "ReadableContentsFormat": formats["markdown"], "HumanReadable": tableToMarkdown("Active Directory - Get Users", user_output.get("attributes")), "EntryContext": { "ActiveDirectory.Users(obj.dn == val.dn)": user_output.get("attributes"), "Account(obj.ID == val.ID)": user_output.get("account"), }, } return demisto_entry else: return "No user found" def siem_search_command(args): """ Returns the results from the siem-search command """ query = args.get("query") result_type = args.get("result_type") number = randint(1, 10) # return results for demo of siem search in example playbook. if result_type == "email" or query.startswith("email"): result = [{"Username": "XSOAR007", "Email": "james.bond@xsoar.local"}, {"Username": "XSOAR001", "Email": "m@xsoar.local"}] # return some data if the number is right. elif number >= 7 or result_type == "hosts" or query.startswith("username"): result = [{"Host": "crossiscoming01", "Online": "Yes"}, {"Host": "crossiscoming02", "Online": "No"}] # return some data if the number is right. elif query.startswith("ip"): result = [{"Host": "crossiscoming01", "Online": "Yes"}] else: result = [] results = CommandResults( readable_output=tableToMarkdown(f"SIEM Search results for query: {query}", result), outputs_prefix="SIEM.Result", outputs=result, ) return results def fetch_incidents(limit): """ fetch Incidents """ incidents = [] count = randrange(10, limit) events = mock_data(count) for event in events: if event.get("type") == "url allowed": event_type = "URL Allowed" else: event_type = "URL Blocked" event_user = event.get("sourceUser", "") incident = {"name": f"Alert - {event_type}- {event_user}", "rawJSON": json.dumps(event), "occurred": event["occurred"]} incidents.append(incident) # return our list of Incidents return incidents[:limit] """ COMMANDS MANAGER / SWITCH PANEL """ def main(): """ main function to run things """ fetch_limit = 20 command = demisto.command() LOG(f"Command being called is {command}") try: commands = { "xet-get-events": get_events_command, "xet-ad-expire-password": simple_response_command, "xet-ad-set-new-password": simple_response_command, "xet-send-mail": simple_response_command, } if command == "test-module": demisto.results("ok") elif demisto.command() == "fetch-incidents": demisto.incidents(fetch_incidents(limit=fetch_limit)) elif demisto.command() == "xet-get-events": return_results(get_events_command(demisto.args())) elif demisto.command() == "xet-ad-get-user": demisto.results(ad_get_user_command(demisto.args())) elif demisto.command() == "xet-siem-search": return_results(siem_search_command(demisto.args())) elif command in commands: return_results(commands[command](command)) except Exception as e: return_error(str(e)) if __name__ in ["__main__", "builtin", "builtins"]: main()