Skip to content

Commit

Permalink
Active Directory (Python) Dynamic Folder sample
Browse files Browse the repository at this point in the history
  • Loading branch information
lemonmojo committed Jan 8, 2019
1 parent c115cdb commit a9c556c
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions Dynamic Folder/Active Directory/Active Directory (Python).rdfe
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 &quot;Custom Properties&quot; 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 &quot;Credentials&quot; 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&nbsp;domain controller/LDAP server in the &quot;Credentials&quot; section.</li>\n\t<li>Specify the domain controller/LDAP server in the &quot;DC/LDAP Server&quot; field of the&nbsp;&quot;Custom Properties&quot; section. This can either be a fully qualified domain name or an IP address. (Examples: &quot;mydomain.local&quot;, &quot;mydomaincontroller.mydomain.local&quot;, &quot;192.168.0.1&quot;)</li>\n\t<li>Specify the base search path in the &quot;Search Base&quot; field of the&nbsp;&quot;Custom Properties&quot; section. (Example: &quot;DC=mydomain,DC=local&quot;)</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)"
}
]
}

0 comments on commit a9c556c

Please sign in to comment.