-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Active Directory (Python) Dynamic Folder sample
- Loading branch information
Showing
1 changed file
with
26 additions
and
0 deletions.
There are no files selected for viewing
26 changes: 26 additions & 0 deletions
26
Dynamic Folder/Active Directory/Active Directory (Python).rdfe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"Name": "Dynamic Folder Export", | ||
"Objects": [ | ||
{ | ||
"Type": "DynamicFolder", | ||
"Name": "Active Directory (Python)", | ||
"Notes": "<h2><strong>Active Directory/LDAP Dynamic Folder sample</strong></h2>\n\n<p><strong>Version</strong>: 1.0<br />\n<strong>Author</strong>: Royal Applications</p>\n\n<p>This Dynamic Folder sample allows you to import connections from Active Directory or any other LDAP-based directory. It scans a configurable domain controller/LDAP server for computer objects and stores them in folders mimicking the OU structure of the directory. Based on the operating system of the computer object, either a Remote Desktop (Windows), a VNC (macOS) or an SSH (Linux) connection will be created. The "Custom Properties" section contains configuration parameters which must be populated before reloading the dynamic folder. Please also ensure that valid credentials for accessing the specified domain controller/LDAP server are configured in the "Credentials" section.</p>\n\n<h3><strong>Requirements</strong></h3>\n\n<ul>\n\t<li>Python Module: python-ldap</li>\n</ul>\n\n<h3><strong>Setup</strong></h3>\n\n<ul>\n\t<li>Specify credentials for accessing the domain controller/LDAP server in the "Credentials" section.</li>\n\t<li>Specify the domain controller/LDAP server in the "DC/LDAP Server" field of the "Custom Properties" section. This can either be a fully qualified domain name or an IP address. (Examples: "mydomain.local", "mydomaincontroller.mydomain.local", "192.168.0.1")</li>\n\t<li>Specify the base search path in the "Search Base" field of the "Custom Properties" section. (Example: "DC=mydomain,DC=local")</li>\n</ul>\n", | ||
"CustomProperties": [ | ||
{ | ||
"Name": "DC/LDAP Server", | ||
"Type": "Text", | ||
"Value": "TODO" | ||
}, | ||
{ | ||
"Name": "Search Base", | ||
"Type": "Text", | ||
"Value": "TODO" | ||
} | ||
], | ||
"ScriptInterpreter": "python", | ||
"DynamicCredentialScriptInterpreter": "json", | ||
"DynamicCredentialScript": "{\n\t\"Username\": \"user\",\n\t\"Password\": \"pass\"\n}", | ||
"Script": "import json\nimport ldap\n\nLDAP_SERVER = r\"$CustomProperty.DCLDAPServer$\" # i.e. 'mydomain.local' / '192.168.0.1'\nLDAP_USERNAME = r\"$EffectiveUsername$\"\nLDAP_PASSWORD = r\"$EffectivePassword$\"\nBASE_DN = r\"$CustomProperty.SearchBase$\" # i.e. 'DC=mydomain,DC=local'\n\nLDAP_CONNECTION_STRING = \"ldap://\" + LDAP_SERVER\nSEARCH_FILTER = \"objectCategory=computer\"\n\nATTRIBUTE_CN = \"cn\"\nATTRIBUTE_DNS_HOSTNAME = \"dNSHostName\"\nATTRIBUTE_NETWORK_ADDRESS = \"networkAddress\"\nATTRIBUTE_OPERATING_SYSTEM = \"operatingSystem\"\nATTRIBUTES_TO_QUERY = [ ATTRIBUTE_CN, ATTRIBUTE_DNS_HOSTNAME, ATTRIBUTE_NETWORK_ADDRESS, ATTRIBUTE_OPERATING_SYSTEM ]\n\nOS_WINDOWS = \"windows\"\nOS_MACOS = \"macos\"\nOS_LINUX = \"linux\"\n\nOS_OBJECT_TYPE_MAPPING = {\n\tOS_WINDOWS: \"RemoteDesktopConnection\",\n\tOS_MACOS: \"VNCConnection\",\n\tOS_LINUX: \"TerminalConnection\"\n}\n\ndef create_connection(object_type, terminal_connection_type, name, host, path):\n\tconnection = {\n\t\t\"Type\": object_type,\n\t\t\"Name\": name,\n\t\t\"ComputerName\": host\n\t}\n\n\tif path is not None and path != \"\":\n\t\tconnection[\"Path\"] = path\n\n\treturn connection\n\n\ndef get_object_type(os):\n\tobject_type = OS_OBJECT_TYPE_MAPPING[os]\n\n\treturn object_type\n\n\ndef get_os(operating_system):\n\tos = OS_WINDOWS\n\n\tif operating_system is not None:\n\t\toperating_system_lower = operating_system.lower()\n\n\t\tif operating_system_lower.startswith(\"windows\"):\n\t\t\tos = OS_WINDOWS\n\t\telif operating_system_lower.startswith(\"mac os\"):\n\t\t\tos = OS_MACOS\n\t\telse:\n\t\t\tos = OS_LINUX\n\n\treturn os\n\n\ndef get_entry_value(entry, attribute):\n\tval = None\n\n\tif attribute in entry:\n\t\tval_list = entry[attribute]\n\t\t\n\t\tif isinstance(val_list, list):\n\t\t\tif len(val_list) > 0:\n\t\t\t\tval_potential = val_list[0]\n\t\t\t\t\n\t\t\t\tif isinstance(val_potential, str):\n\t\t\t\t\tval = val_potential\n\t\t\t\telif isinstance(val_potential, bytes):\n\t\t\t\t\tval = val_potential.decode()\n\n\treturn val\n\n\ndef get_ldap_result(ldap_connection_string, ldap_username, ldap_password, base_dn):\n\tad = ldap.initialize(ldap_connection_string)\n\tad.set_option(ldap.OPT_REFERRALS, 0) # to search the object and all its descendants\n\tad.simple_bind_s(ldap_username, ldap_password)\n\n\tresult = ad.search_s(base_dn, ldap.SCOPE_SUBTREE, SEARCH_FILTER, ATTRIBUTES_TO_QUERY)\n\n\treturn result\n\n\ndef get_path(dn, computer_cn):\n\tdn_arr = dn.split(\",\")\n\t\n\tpath_arr = []\n\n\tfor part in dn_arr:\n\t\tpart_lower = part.lower()\n\n\t\tif part_lower.startswith(\"ou=\") or part_lower.startswith(\"cn=\"):\n\t\t\tpart_val_arr = part.split(\"=\")\n\n\t\t\tif len(part_val_arr) > 1:\n\t\t\t\tpart_val = part_val_arr[1]\n\n\t\t\t\tif computer_cn != part_val:\n\t\t\t\t\tpath_arr.append(part_val)\n\n\tpath_arr.reverse()\n\n\tpath = \"/\".join(path_arr)\n\n\treturn path\n\n\ndef ldap_entry_to_connection(dn, entry):\n\tcomputer_cn = get_entry_value(entry, ATTRIBUTE_CN)\n\n\tpath = get_path(dn, computer_cn)\n\n\tdns_hostname = get_entry_value(entry, ATTRIBUTE_DNS_HOSTNAME)\n\tnetwork_address = get_entry_value(entry, ATTRIBUTE_NETWORK_ADDRESS)\n\t\n\tos = get_os(get_entry_value(entry, ATTRIBUTE_OPERATING_SYSTEM))\n\t\n\tobject_type = get_object_type(os)\n\tterminal_connection_type = \"SSHConnection\"\n\n\tcomputer_name = dns_hostname\n\n\tif dns_hostname is None or dns_hostname == \"\":\n\t\tcomputer_name = network_address\n\n\tconnection = None\n\n\tif computer_name is not None and computer_name != \"\":\n\t\tconnection = create_connection(object_type, terminal_connection_type, computer_cn, computer_name, path)\n\n\treturn connection\n\n\ndef get_connections(ldap_connection_string, ldap_username, ldap_password, base_dn):\n\tresult = get_ldap_result(ldap_connection_string, ldap_username, ldap_password, base_dn)\n\n\tconnections = []\n\n\tif isinstance(result, list):\n\t\tfor dn, entry in result:\n\t\t\tif isinstance(entry, dict):\n\t\t\t\tconnection = ldap_entry_to_connection(dn, entry)\n\n\t\t\t\tif connection is None:\n\t\t\t\t\tcontinue\n\n\t\t\t\tconnections.append(connection)\n\n\treturn connections\n\n\nconnections = get_connections(LDAP_CONNECTION_STRING, LDAP_USERNAME, LDAP_PASSWORD, BASE_DN)\n\nstore = {\n\t\"Objects\": connections\n}\n\njsonStr = json.dumps(store)\n\nprint(jsonStr)" | ||
} | ||
] | ||
} |