feat(active-directory): LDAP directory administration integration
Active Directory over LDAP/LDAPS via the ldap3 library, designed to run on a remote engine inside the AD network. 24 commands: raw search, get user/computer/group-members (with userAccountControl decoding), enable/disable/ unlock accounts, set/expire password, password-never-expire, add/remove group membership, move user/computer OU, create/update/delete user/contact/group, and credential testing. Scripts share an ldap3 connection helper that handles SSL/LDAPS/Start TLS, NTLM bind, certificate trust and paged search. ldap3 is imported defensively: if it is missing on the engine host the command returns a clear "pip install ldap3" message instead of crashing. No ingestion source, so no OCSF mapper. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,348 @@
|
||||
id: active_directory
|
||||
name: Active Directory
|
||||
version: 1.0.0
|
||||
description: "Active Directory over LDAP/LDAPS — query and manage users, computers, groups and contacts (search, enable/disable/unlock, set/expire password, group membership, OU moves, create/update/delete). Runs on a remote engine inside the AD network. Requires the Python 'ldap3' library on the engine host (pip install ldap3)."
|
||||
changelog: "1.0.0 — Initial release: full directory administration over LDAP (search, get user/computer/group-members, create/update/delete user/contact/group, enable/disable/unlock, set/expire password, password-never-expire, add/remove group membership, move user/computer OU, test credentials)."
|
||||
category: identity
|
||||
|
||||
# Per-instance configuration. The integration binds to a Domain Controller over
|
||||
# LDAP (389) or LDAPS (636). Secure connection (SSL/Start TLS) is required for
|
||||
# password operations. Run this integration on a remote engine that can reach the
|
||||
# Domain Controller. The bundled scripts require the Python 'ldap3' library to be
|
||||
# installed on the engine host: pip install ldap3
|
||||
config_schema:
|
||||
properties:
|
||||
server_ip:
|
||||
type: string
|
||||
description: "Domain Controller host or IP (e.g. dc01.company.com or 192.168.0.1)"
|
||||
port:
|
||||
type: string
|
||||
description: "LDAP port. Default 389 for LDAP / Start TLS, 636 for LDAPS."
|
||||
username:
|
||||
type: string
|
||||
description: "Bind username (e.g. DOMAIN\\\\user or user@company.com)"
|
||||
password:
|
||||
type: string
|
||||
description: "Bind password"
|
||||
x-soar-sensitive: true
|
||||
base_dn:
|
||||
type: string
|
||||
description: "Base DN (e.g. dc=company,dc=com)"
|
||||
secure_connection:
|
||||
type: string
|
||||
description: "Connection security: None, SSL (LDAPS), TLS, or Start TLS. Password operations require SSL or TLS."
|
||||
default: SSL
|
||||
ssl_version:
|
||||
type: string
|
||||
description: "SSL/TLS protocol: None, TLS, TLSv1, TLSv1_1, TLSv1_2, or TLS_CLIENT. Default None (let the library negotiate)."
|
||||
default: None
|
||||
ntlm:
|
||||
type: boolean
|
||||
description: "Use NTLM authentication for the bind"
|
||||
default: false
|
||||
unsecure:
|
||||
type: boolean
|
||||
description: "Trust any TLS certificate (not secure)"
|
||||
default: false
|
||||
page_size:
|
||||
type: string
|
||||
description: "LDAP paging size for searches"
|
||||
default: "500"
|
||||
default_base_query:
|
||||
type: string
|
||||
description: "Default LDAP filter used by ad-get-user when no query argument is given"
|
||||
default: "(&(objectClass=User)(objectCategory=person))"
|
||||
required:
|
||||
- server_ip
|
||||
- username
|
||||
- password
|
||||
- base_dn
|
||||
|
||||
commands:
|
||||
# ── Connectivity ──────────────────────────────────────────────────────────
|
||||
- id: test_connection
|
||||
name: ad-test-connection
|
||||
description: "Bind to the Domain Controller and verify the configured base DN (used by the Test button)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties: {}
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Search / read ─────────────────────────────────────────────────────────
|
||||
- id: ad_search
|
||||
name: ad-search
|
||||
description: "Run a raw LDAP query and return the matching entries. Paging is handled internally up to size-limit."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
filter: { type: string, description: "LDAP search filter, e.g. (&(objectCategory=person)(objectClass=user))" }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
attributes: { type: string, description: "CSV list of attributes to return, or ALL for every attribute" }
|
||||
size-limit: { type: number, description: "Maximum entries to return (default 50)" }
|
||||
time-limit: { type: number, description: "Maximum search time in seconds" }
|
||||
page-size: { type: number, description: "Paging size (overrides size-limit when set)" }
|
||||
required: [filter]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_get_user
|
||||
name: ad-get-user
|
||||
description: "Retrieve user accounts by DN, name, email, sAMAccountName or a custom attribute. Decodes userAccountControl flags."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
dn: { type: string, description: "Distinguished Name of the user" }
|
||||
name: { type: string, description: "Common name (cn) of the user" }
|
||||
email: { type: string, description: "User email (mail)" }
|
||||
username: { type: string, description: "sAMAccountName" }
|
||||
sAMAccountName: { type: string, description: "sAMAccountName (alias of username)" }
|
||||
custom-field-type: { type: string, description: "Attribute name to query by" }
|
||||
custom-field-data: { type: string, description: "Attribute value (required with custom-field-type)" }
|
||||
attributes: { type: string, description: "CSV list of extra attributes to add to the defaults" }
|
||||
attributes-to-exclude: { type: string, description: "CSV list of attributes to remove from the result" }
|
||||
limit: { type: number, description: "Maximum users to return (default 20)" }
|
||||
page-size: { type: number, description: "Paging size (overrides limit when set)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_get_computer
|
||||
name: ad-get-computer
|
||||
description: "Retrieve computer accounts by DN, name or a custom attribute."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
dn: { type: string, description: "Distinguished Name of the computer" }
|
||||
name: { type: string, description: "Computer name" }
|
||||
custom-field-type: { type: string, description: "Attribute name to query by" }
|
||||
custom-field-data: { type: string, description: "Attribute value (required with custom-field-type)" }
|
||||
attributes: { type: string, description: "CSV list of extra attributes to add to the defaults" }
|
||||
limit: { type: number, description: "Maximum computers to return" }
|
||||
page-size: { type: number, description: "Paging size (overrides limit when set)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_get_group_members
|
||||
name: ad-get-group-members
|
||||
description: "List the users, computers or nested groups that are members of a group (recursive by default)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
group-dn: { type: string, description: "Distinguished Name of the group" }
|
||||
member-type: { type: string, description: "Member type to return: person, computer or group (default person)" }
|
||||
attributes: { type: string, description: "CSV list of extra attributes to add to the defaults" }
|
||||
time_limit: { type: number, description: "Search time limit in seconds (default 180)" }
|
||||
disable-nested-search: { type: string, description: "Set true to disable recursive membership resolution (default false)" }
|
||||
sAMAccountName: { type: string, description: "Filter members by sAMAccountName (default *)" }
|
||||
limit: { type: number, description: "Maximum members to return" }
|
||||
page-size: { type: number, description: "Paging size (overrides limit when set)" }
|
||||
required: [group-dn]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Account state ─────────────────────────────────────────────────────────
|
||||
- id: ad_enable_account
|
||||
name: ad-enable-account
|
||||
description: "Enable a previously disabled user account."
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "sAMAccountName of the account to enable" }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
restore_user: { type: string, description: "Set true to restore the account's previous userAccountControl flags" }
|
||||
required: [username]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_disable_account
|
||||
name: ad-disable-account
|
||||
description: "Disable a user account."
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "sAMAccountName of the account to disable" }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
required: [username]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_unlock_account
|
||||
name: ad-unlock-account
|
||||
description: "Unlock a locked-out user account."
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "sAMAccountName of the account to unlock" }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
required: [username]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_set_new_password
|
||||
name: ad-set-new-password
|
||||
description: "Set a new password for a user. Requires a secure connection (SSL or TLS)."
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "sAMAccountName whose password will be set" }
|
||||
password: { type: string, description: "New password", x-soar-sensitive: true }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
required: [username, password]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_expire_password
|
||||
name: ad-expire-password
|
||||
description: "Force a user to change their password at next login."
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "sAMAccountName of the user" }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
required: [username]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_modify_password_never_expire
|
||||
name: ad-modify-password-never-expire
|
||||
description: "Set or clear the 'Password Never Expire' flag on a user account."
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "sAMAccountName of the user" }
|
||||
value: { type: string, description: "true to set 'Password Never Expire', false to clear it" }
|
||||
required: [username, value]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Group membership ──────────────────────────────────────────────────────
|
||||
- id: ad_add_to_group
|
||||
name: ad-add-to-group
|
||||
description: "Add a user, computer or nested group to a group."
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "Username(s) to add (single or CSV). Mutually exclusive with computer-name." }
|
||||
computer-name: { type: string, description: "Computer name(s) to add (single or CSV)" }
|
||||
nested_group_cn: { type: string, description: "A group CN to add as a nested member" }
|
||||
group-cn: { type: string, description: "Target group CN" }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
required: [group-cn]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_remove_from_group
|
||||
name: ad-remove-from-group
|
||||
description: "Remove a user or computer from a group."
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "Username to remove. Mutually exclusive with computer-name." }
|
||||
computer-name: { type: string, description: "Computer name to remove" }
|
||||
group-cn: { type: string, description: "Target group CN" }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
required: [group-cn]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Organizational unit ───────────────────────────────────────────────────
|
||||
- id: ad_modify_user_ou
|
||||
name: ad-modify-user-ou
|
||||
description: "Move a user to a different organizational unit within the domain."
|
||||
inputs_schema:
|
||||
properties:
|
||||
user-name: { type: string, description: "Name of the user to move" }
|
||||
full-superior-dn: { type: string, description: "Target OU DN, e.g. OU=users,DC=domain,DC=com" }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
required: [user-name, full-superior-dn]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_modify_computer_ou
|
||||
name: ad-modify-computer-ou
|
||||
description: "Move a computer to a different organizational unit within the domain."
|
||||
inputs_schema:
|
||||
properties:
|
||||
computer-name: { type: string, description: "Name of the computer to move" }
|
||||
full-superior-dn: { type: string, description: "Target OU DN, e.g. OU=computers,DC=domain,DC=com" }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
required: [computer-name, full-superior-dn]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Object lifecycle: users ───────────────────────────────────────────────
|
||||
- id: ad_create_user
|
||||
name: ad-create-user
|
||||
description: "Create a user account, set its initial password and enable it. Requires a secure connection (SSL or TLS)."
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "sAMAccountName for the new user" }
|
||||
password: { type: string, description: "Initial password (user must change at next login)", x-soar-sensitive: true }
|
||||
user-dn: { type: string, description: "Full DN of the new user" }
|
||||
display-name: { type: string, description: "Display name" }
|
||||
description: { type: string, description: "Description" }
|
||||
email: { type: string, description: "Email (mail)" }
|
||||
telephone-number: { type: string, description: "Telephone number" }
|
||||
title: { type: string, description: "Job title" }
|
||||
custom-attributes: { type: string, description: "JSON object of extra attributes, e.g. {\"company\":\"ACME\"}" }
|
||||
required: [username, password, user-dn]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_update_user
|
||||
name: ad-update-user
|
||||
description: "Replace a single attribute on an existing user."
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "sAMAccountName of the user" }
|
||||
attribute-name: { type: string, description: "Attribute to modify (e.g. sn, displayName, mail)" }
|
||||
attribute-value: { type: string, description: "New value" }
|
||||
base-dn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
required: [username, attribute-name, attribute-value]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_delete_user
|
||||
name: ad-delete-user
|
||||
description: "Delete a user (or any object) by its DN."
|
||||
inputs_schema:
|
||||
properties:
|
||||
user-dn: { type: string, description: "DN of the object to delete" }
|
||||
required: [user-dn]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Object lifecycle: contacts ────────────────────────────────────────────
|
||||
- id: ad_create_contact
|
||||
name: ad-create-contact
|
||||
description: "Create a contact object."
|
||||
inputs_schema:
|
||||
properties:
|
||||
contact-dn: { type: string, description: "Full DN of the new contact" }
|
||||
display-name: { type: string, description: "Display name" }
|
||||
description: { type: string, description: "Description" }
|
||||
email: { type: string, description: "Email (mail)" }
|
||||
telephone-number: { type: string, description: "Telephone number" }
|
||||
title: { type: string, description: "Job title" }
|
||||
custom-attributes: { type: string, description: "JSON object of extra attributes" }
|
||||
required: [contact-dn]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_update_contact
|
||||
name: ad-update-contact
|
||||
description: "Replace a single attribute on an existing contact."
|
||||
inputs_schema:
|
||||
properties:
|
||||
contact-dn: { type: string, description: "DN of the contact" }
|
||||
attribute-name: { type: string, description: "Attribute to modify" }
|
||||
attribute-value: { type: string, description: "New value" }
|
||||
required: [contact-dn, attribute-name, attribute-value]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Object lifecycle: groups ──────────────────────────────────────────────
|
||||
- id: ad_create_group
|
||||
name: ad-create-group
|
||||
description: "Create a security or distribution group."
|
||||
inputs_schema:
|
||||
properties:
|
||||
name: { type: string, description: "Group name (sAMAccountName)" }
|
||||
group-type: { type: string, description: "security or distribution" }
|
||||
dn: { type: string, description: "Full DN of the new group" }
|
||||
members: { type: array, description: "DNs of initial members" }
|
||||
required: [name, group-type, dn]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_update_group
|
||||
name: ad-update-group
|
||||
description: "Replace a single attribute on an existing group."
|
||||
inputs_schema:
|
||||
properties:
|
||||
groupname: { type: string, description: "Group name (cn) to update" }
|
||||
attributename: { type: string, description: "Attribute to modify (e.g. description, displayName)" }
|
||||
attributevalue: { type: string, description: "New value" }
|
||||
basedn: { type: string, description: "Search base (defaults to the instance base_dn)" }
|
||||
required: [attributename, attributevalue]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: ad_delete_group
|
||||
name: ad-delete-group
|
||||
description: "Delete a security or distribution group by its DN."
|
||||
inputs_schema:
|
||||
properties:
|
||||
dn: { type: string, description: "DN of the group" }
|
||||
required: [dn]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Credentials ───────────────────────────────────────────────────────────
|
||||
- id: ad_test_credentials
|
||||
name: ad-test-credentials
|
||||
description: "Test whether a username/password can bind to the Domain Controller."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
username: { type: string, description: "Username to test (user or SERVER\\\\user)" }
|
||||
password: { type: string, description: "Password to test", x-soar-sensitive: true }
|
||||
required: [username, password]
|
||||
outputs_schema: { properties: {} }
|
||||
Reference in New Issue
Block a user