mirror of
https://github.com/splunk/security_content
synced 2026-06-08 17:32:49 +00:00
Azure_AD_Locking_Playbook
This commit is contained in:
@@ -0,0 +1,277 @@
|
||||
{
|
||||
"blockly": false,
|
||||
"blockly_xml": "<xml></xml>",
|
||||
"category": "Account Locking",
|
||||
"coa": {
|
||||
"data": {
|
||||
"description": "Accepts user name that needs to be disabled in Azure Active Directory. Generates an observable output based on the status of account locking or disabling.",
|
||||
"edges": [
|
||||
{
|
||||
"id": "port_0_to_port_2",
|
||||
"sourceNode": "0",
|
||||
"sourcePort": "0_out",
|
||||
"targetNode": "2",
|
||||
"targetPort": "2_in"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
"id": "port_2_to_port_3",
|
||||
"sourceNode": "2",
|
||||
"sourcePort": "2_out",
|
||||
"targetNode": "3",
|
||||
"targetPort": "3_in"
|
||||
},
|
||||
{
|
||||
"id": "port_4_to_port_1",
|
||||
"sourceNode": "4",
|
||||
"sourcePort": "4_out",
|
||||
"targetNode": "1",
|
||||
"targetPort": "1_in"
|
||||
},
|
||||
{
|
||||
"id": "port_3_to_port_5",
|
||||
"sourceNode": "3",
|
||||
"sourcePort": "3_out",
|
||||
"targetNode": "5",
|
||||
"targetPort": "5_in"
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
"id": "port_5_to_port_4",
|
||||
"sourceNode": "5",
|
||||
"sourcePort": "5_out",
|
||||
"targetNode": "4",
|
||||
"targetPort": "4_in"
|
||||
}
|
||||
],
|
||||
"hash": "b96df0d674917e6a8082cd6c447eeeaaf80330a6",
|
||||
"nodes": {
|
||||
"0": {
|
||||
"data": {
|
||||
"advanced": {
|
||||
"join": []
|
||||
},
|
||||
"functionName": "on_start",
|
||||
"id": "0",
|
||||
"type": "start"
|
||||
},
|
||||
"errors": {},
|
||||
"id": "0",
|
||||
"type": "start",
|
||||
"warnings": {},
|
||||
"x": 20,
|
||||
"y": 0
|
||||
},
|
||||
"1": {
|
||||
"data": {
|
||||
"advanced": {
|
||||
"join": []
|
||||
},
|
||||
"functionName": "on_finish",
|
||||
"id": "1",
|
||||
"type": "end"
|
||||
},
|
||||
"errors": {},
|
||||
"id": "1",
|
||||
"type": "end",
|
||||
"warnings": {},
|
||||
"x": 20,
|
||||
"y": 860
|
||||
},
|
||||
"2": {
|
||||
"data": {
|
||||
"advanced": {
|
||||
"customName": "user name filter",
|
||||
"customNameId": 0,
|
||||
"description": "Filter user name inputs to route inputs to appropriate actions.",
|
||||
"join": [],
|
||||
"note": "Filter user name inputs to route inputs to appropriate actions."
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"comparisons": [
|
||||
{
|
||||
"conditionIndex": 0,
|
||||
"op": "!=",
|
||||
"param": "playbook_input:user_name",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"conditionIndex": 0,
|
||||
"customName": "user_name_check",
|
||||
"logic": "and"
|
||||
}
|
||||
],
|
||||
"functionId": 1,
|
||||
"functionName": "user_name_filter",
|
||||
"id": "2",
|
||||
"type": "filter"
|
||||
},
|
||||
"errors": {},
|
||||
"id": "2",
|
||||
"type": "filter",
|
||||
"warnings": {
|
||||
"config": [
|
||||
"Reconfigure invalid datapath."
|
||||
]
|
||||
},
|
||||
"x": 60,
|
||||
"y": 140
|
||||
},
|
||||
"3": {
|
||||
"data": {
|
||||
"action": "disable user",
|
||||
"actionType": "generic",
|
||||
"advanced": {
|
||||
"customName": "disable user account",
|
||||
"customNameId": 0,
|
||||
"description": "Disable the user attributes for filtered playbook inputs.",
|
||||
"join": [],
|
||||
"note": "Disable the user attributes for filtered playbook inputs."
|
||||
},
|
||||
"connector": "Azure AD Graph",
|
||||
"connectorConfigs": [
|
||||
"azure active directory"
|
||||
],
|
||||
"connectorId": "c6d3b801-5c26-4abd-9e89-6d8007e2778f",
|
||||
"connectorVersion": "v1",
|
||||
"functionId": 1,
|
||||
"functionName": "disable_user_account",
|
||||
"id": "3",
|
||||
"parameters": {
|
||||
"user_id": "playbook_input:user_name"
|
||||
},
|
||||
"requiredParameters": [
|
||||
{
|
||||
"data_type": "string",
|
||||
"field": "user_id"
|
||||
}
|
||||
],
|
||||
"type": "action"
|
||||
},
|
||||
"errors": {},
|
||||
"id": "3",
|
||||
"type": "action",
|
||||
"warnings": {
|
||||
"config": [
|
||||
"Reconfigure invalid datapath."
|
||||
]
|
||||
},
|
||||
"x": 0,
|
||||
"y": 328
|
||||
},
|
||||
"4": {
|
||||
"data": {
|
||||
"advanced": {
|
||||
"customName": "username observables",
|
||||
"customNameId": 0,
|
||||
"description": "Format a normalized output for each user.",
|
||||
"join": [],
|
||||
"note": "Format a normalized output for each user."
|
||||
},
|
||||
"functionId": 1,
|
||||
"functionName": "username_observables",
|
||||
"id": "4",
|
||||
"inputParameters": [
|
||||
"disable_user_account:action_result.parameter.user_id",
|
||||
"disable_user_account:action_result.status",
|
||||
"disable_user_account:action_result.message"
|
||||
],
|
||||
"outputVariables": [
|
||||
"observable_array"
|
||||
],
|
||||
"type": "code"
|
||||
},
|
||||
"errors": {},
|
||||
"id": "4",
|
||||
"type": "code",
|
||||
"userCode": "\n # Write your custom code here...\n username_observables__observable_array = []\n \n for user_id, status, msg in zip(disable_user_account_parameter_user_id, disable_user_account_result_item_1, disable_user_account_result_message):\n user_acc_status = {\n \"account_type\": \"Azure AD Account\",\n \"user\": user_id,\n \"disable_message\": msg,\n \"disable_status\": status\n }\n username_observables__observable_array.append(user_acc_status)\n #phantom.debug(username_observables__observable_array)\n",
|
||||
"warnings": {},
|
||||
"x": 0,
|
||||
"y": 680
|
||||
},
|
||||
"5": {
|
||||
"data": {
|
||||
"advanced": {
|
||||
"customName": "filter disable result",
|
||||
"customNameId": 0,
|
||||
"description": "filter check if the user is disabled successfully.",
|
||||
"join": [],
|
||||
"note": "filter check if the user is disabled successfully."
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"comparisons": [
|
||||
{
|
||||
"conditionIndex": 0,
|
||||
"op": "==",
|
||||
"param": "disable_user_account:action_result.status",
|
||||
"value": "success"
|
||||
}
|
||||
],
|
||||
"conditionIndex": 0,
|
||||
"customName": "disabled_success",
|
||||
"logic": "and"
|
||||
}
|
||||
],
|
||||
"functionId": 2,
|
||||
"functionName": "filter_disable_result",
|
||||
"id": "5",
|
||||
"type": "filter"
|
||||
},
|
||||
"errors": {},
|
||||
"id": "5",
|
||||
"type": "filter",
|
||||
"warnings": {},
|
||||
"x": 60,
|
||||
"y": 500
|
||||
}
|
||||
},
|
||||
"notes": "Inputs: users\nInteractions: Azure AD Graph\nActions: Account Locking/Disabling\nOutputs: observables"
|
||||
},
|
||||
"input_spec": [
|
||||
{
|
||||
"contains": [
|
||||
"user name"
|
||||
],
|
||||
"description": "A user name provided to be disable - Azure AD",
|
||||
"name": "user_name"
|
||||
}
|
||||
],
|
||||
"output_spec": [
|
||||
{
|
||||
"contains": [],
|
||||
"datapaths": [
|
||||
"username_observables:custom_function:observable_array"
|
||||
],
|
||||
"deduplicate": false,
|
||||
"description": "An array of observable dictionaries ",
|
||||
"metadata": {},
|
||||
"name": "observable"
|
||||
}
|
||||
],
|
||||
"playbook_type": "data",
|
||||
"python_version": "3",
|
||||
"schema": "5.0.9",
|
||||
"version": "6.0.0.114895"
|
||||
},
|
||||
"create_time": "2023-05-08T15:56:10.320874+00:00",
|
||||
"draft_mode": false,
|
||||
"labels": [
|
||||
"*"
|
||||
],
|
||||
"tags": [
|
||||
"user",
|
||||
"azure_ad_graph",
|
||||
"disable_account",
|
||||
"D3-AL"
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
@@ -0,0 +1,165 @@
|
||||
"""
|
||||
Accepts user name that needs to be disabled in Azure Active Directory. Generates an observable output based on the status of account locking or disabling.
|
||||
"""
|
||||
|
||||
|
||||
import phantom.rules as phantom
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
@phantom.playbook_block()
|
||||
def on_start(container):
|
||||
phantom.debug('on_start() called')
|
||||
|
||||
# call 'user_name_filter' block
|
||||
user_name_filter(container=container)
|
||||
|
||||
return
|
||||
|
||||
@phantom.playbook_block()
|
||||
def user_name_filter(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug("user_name_filter() called")
|
||||
|
||||
################################################################################
|
||||
# Filter user name inputs to route inputs to appropriate actions.
|
||||
################################################################################
|
||||
|
||||
# collect filtered artifact ids and results for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
conditions=[
|
||||
["playbook_input:user_name", "!=", ""]
|
||||
],
|
||||
name="user_name_filter:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
disable_user_account(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@phantom.playbook_block()
|
||||
def disable_user_account(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug("disable_user_account() called")
|
||||
|
||||
# phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
################################################################################
|
||||
# Disable the user attributes for filtered playbook inputs.
|
||||
################################################################################
|
||||
|
||||
playbook_input_user_name = phantom.collect2(container=container, datapath=["playbook_input:user_name"])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'disable_user_account' call
|
||||
for playbook_input_user_name_item in playbook_input_user_name:
|
||||
if playbook_input_user_name_item[0] is not None:
|
||||
parameters.append({
|
||||
"user_id": playbook_input_user_name_item[0],
|
||||
})
|
||||
|
||||
################################################################################
|
||||
## Custom Code Start
|
||||
################################################################################
|
||||
|
||||
# Write your custom code here...
|
||||
|
||||
################################################################################
|
||||
## Custom Code End
|
||||
################################################################################
|
||||
|
||||
phantom.act("disable user", parameters=parameters, name="disable_user_account", assets=["azure active directory"], callback=filter_disable_result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@phantom.playbook_block()
|
||||
def username_observables(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug("username_observables() called")
|
||||
|
||||
################################################################################
|
||||
# Format a normalized output for each user.
|
||||
################################################################################
|
||||
|
||||
disable_user_account_result_data = phantom.collect2(container=container, datapath=["disable_user_account:action_result.parameter.user_id","disable_user_account:action_result.status","disable_user_account:action_result.message"], action_results=results)
|
||||
|
||||
disable_user_account_parameter_user_id = [item[0] for item in disable_user_account_result_data]
|
||||
disable_user_account_result_item_1 = [item[1] for item in disable_user_account_result_data]
|
||||
disable_user_account_result_message = [item[2] for item in disable_user_account_result_data]
|
||||
|
||||
username_observables__observable_array = None
|
||||
|
||||
################################################################################
|
||||
## Custom Code Start
|
||||
################################################################################
|
||||
|
||||
# Write your custom code here...
|
||||
username_observables__observable_array = []
|
||||
|
||||
for user_id, status, msg in zip(disable_user_account_parameter_user_id, disable_user_account_result_item_1, disable_user_account_result_message):
|
||||
user_acc_status = {
|
||||
"account_type": "Azure AD Account",
|
||||
"user": user_id,
|
||||
"disable_message": msg,
|
||||
"disable_status": status
|
||||
}
|
||||
username_observables__observable_array.append(user_acc_status)
|
||||
#phantom.debug(username_observables__observable_array)
|
||||
################################################################################
|
||||
## Custom Code End
|
||||
################################################################################
|
||||
|
||||
phantom.save_run_data(key="username_observables:observable_array", value=json.dumps(username_observables__observable_array))
|
||||
|
||||
return
|
||||
|
||||
|
||||
@phantom.playbook_block()
|
||||
def filter_disable_result(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug("filter_disable_result() called")
|
||||
|
||||
################################################################################
|
||||
# filter check if the user is disabled successfully.
|
||||
################################################################################
|
||||
|
||||
# collect filtered artifact ids and results for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
conditions=[
|
||||
["disable_user_account:action_result.status", "==", "success"]
|
||||
],
|
||||
name="filter_disable_result:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
username_observables(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@phantom.playbook_block()
|
||||
def on_finish(container, summary):
|
||||
phantom.debug("on_finish() called")
|
||||
|
||||
username_observables__observable_array = json.loads(_ if (_ := phantom.get_run_data(key="username_observables:observable_array")) != "" else "null") # pylint: disable=used-before-assignment
|
||||
|
||||
output = {
|
||||
"observable": username_observables__observable_array,
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## Custom Code Start
|
||||
################################################################################
|
||||
|
||||
# Write your custom code here...
|
||||
|
||||
################################################################################
|
||||
## Custom Code End
|
||||
################################################################################
|
||||
|
||||
phantom.save_playbook_output_data(output=output)
|
||||
|
||||
return
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Azure AD Locking Account
|
||||
id: f15e4ab7-b057-4225-86ae-c36ab78b50f2
|
||||
version: 1
|
||||
date: '2023-05-08'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: Investigation
|
||||
description: "Accepts user, to be disabled using Azure AD Graph connector. This playbook produces a normalized observables output for each user and device."
|
||||
playbook: Azure_AD_Locking_Account
|
||||
how_to_implement: This input playbook requires the Azure AD Graph connector to be configured.
|
||||
It is designed to work in conjunction with the Dynamic Attribute Lookup playbook or other playbooks in the same style.
|
||||
references: []
|
||||
app_list:
|
||||
- Azure AD Graph API
|
||||
tags:
|
||||
platform_tags:
|
||||
- user
|
||||
- D3-AL
|
||||
- azure_ad_graph
|
||||
- disable_account
|
||||
playbook_type: Input
|
||||
vpe_type: Modern
|
||||
playbook_fields: []
|
||||
product:
|
||||
- Splunk SOAR
|
||||
Reference in New Issue
Block a user