Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Refactor] Transform all rdfe scripts to rdfx #121

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open

This file was deleted.

2,426 changes: 2,426 additions & 0 deletions Dynamic Folder/Active Directory/AD Servers (Windows PowerShell).rdfx

Large diffs are not rendered by default.

27 changes: 0 additions & 27 deletions Dynamic Folder/Active Directory/Active Directory (Python).rdfe

This file was deleted.

220 changes: 220 additions & 0 deletions Dynamic Folder/Active Directory/Active Directory (Python).rdfx
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
<DynamicFolderExport>
<Name>Dynamic Folder Export</Name>
<Objects>
<DynamicFolderExportObject>
<Type>DynamicFolder</Type>
<Name>Active Directory (Python)</Name>
<Description>This Dynamic Folder sample allows you to import connections from Active Directory or any other LDAP-based directory.</Description>
<Notes><![CDATA[<h2><strong>Active Directory/LDAP Dynamic Folder sample</strong></h2>

<p><strong>Version</strong>: 1.0<br />
<strong>Author</strong>: Royal Applications</p>

<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>

<h3><strong>Requirements</strong></h3>

<ul>
<li>Python Module: python-ldap</li>
</ul>

<h3><strong>Setup</strong></h3>

<ul>
<li>Specify credentials for accessing the&nbsp;domain controller/LDAP server in the &quot;Credentials&quot; section.</li>
<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>
<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>
</ul>
]]></Notes>
<CustomProperties>
<CustomProperty>
<Name>DC/LDAP Server</Name>
<Type>Text</Type>
<Value>TODO</Value>
</CustomProperty>
<CustomProperty>
<Name>Search Base</Name>
<Type>Text</Type>
<Value>TODO</Value>
</CustomProperty>
</CustomProperties>
<ScriptInterpreter>python</ScriptInterpreter>
<Script><![CDATA[import json
import ldap

LDAP_SERVER = r"$CustomProperty.DCLDAPServer$" # i.e. 'mydomain.local' / '192.168.0.1'
LDAP_USERNAME = r"$EffectiveUsername$"
LDAP_PASSWORD = r"$EffectivePassword$"
BASE_DN = r"$CustomProperty.SearchBase$" # i.e. 'DC=mydomain,DC=local'

LDAP_CONNECTION_STRING = "ldap://" + LDAP_SERVER
SEARCH_FILTER = "objectCategory=computer"

ATTRIBUTE_CN = "cn"
ATTRIBUTE_DNS_HOSTNAME = "dNSHostName"
ATTRIBUTE_NETWORK_ADDRESS = "networkAddress"
ATTRIBUTE_OPERATING_SYSTEM = "operatingSystem"
ATTRIBUTES_TO_QUERY = [ ATTRIBUTE_CN, ATTRIBUTE_DNS_HOSTNAME, ATTRIBUTE_NETWORK_ADDRESS, ATTRIBUTE_OPERATING_SYSTEM ]

OS_WINDOWS = "windows"
OS_MACOS = "macos"
OS_LINUX = "linux"

OS_OBJECT_TYPE_MAPPING = {
OS_WINDOWS: "RemoteDesktopConnection",
OS_MACOS: "VNCConnection",
OS_LINUX: "TerminalConnection"
}

def create_connection(object_type, terminal_connection_type, name, host, path):
connection = {
"Type": object_type,
"Name": name,
"ComputerName": host
}

if path is not None and path != "":
connection["Path"] = path

return connection


def get_object_type(os):
object_type = OS_OBJECT_TYPE_MAPPING[os]

return object_type


def get_os(operating_system):
os = OS_WINDOWS

if operating_system is not None:
operating_system_lower = operating_system.lower()

if operating_system_lower.startswith("windows"):
os = OS_WINDOWS
elif operating_system_lower.startswith("mac os"):
os = OS_MACOS
else:
os = OS_LINUX

return os


def get_entry_value(entry, attribute):
val = None

if attribute in entry:
val_list = entry[attribute]

if isinstance(val_list, list):
if len(val_list) > 0:
val_potential = val_list[0]

if isinstance(val_potential, str):
val = val_potential
elif isinstance(val_potential, bytes):
val = val_potential.decode()

return val


def get_ldap_result(ldap_connection_string, ldap_username, ldap_password, base_dn):
ad = ldap.initialize(ldap_connection_string)
ad.set_option(ldap.OPT_REFERRALS, 0) # to search the object and all its descendants
ad.simple_bind_s(ldap_username, ldap_password)

result = ad.search_s(base_dn, ldap.SCOPE_SUBTREE, SEARCH_FILTER, ATTRIBUTES_TO_QUERY)

return result


def get_path(dn, computer_cn):
dn_arr = dn.split(",")

path_arr = []

for part in dn_arr:
part_lower = part.lower()

if part_lower.startswith("ou=") or part_lower.startswith("cn="):
part_val_arr = part.split("=")

if len(part_val_arr) > 1:
part_val = part_val_arr[1]

if computer_cn != part_val:
path_arr.append(part_val)

path_arr.reverse()

path = "/".join(path_arr)

return path


def ldap_entry_to_connection(dn, entry):
computer_cn = get_entry_value(entry, ATTRIBUTE_CN)

path = get_path(dn, computer_cn)

dns_hostname = get_entry_value(entry, ATTRIBUTE_DNS_HOSTNAME)
network_address = get_entry_value(entry, ATTRIBUTE_NETWORK_ADDRESS)

os = get_os(get_entry_value(entry, ATTRIBUTE_OPERATING_SYSTEM))

object_type = get_object_type(os)
terminal_connection_type = "SSHConnection"

computer_name = dns_hostname

if dns_hostname is None or dns_hostname == "":
computer_name = network_address

connection = None

if computer_name is not None and computer_name != "":
connection = create_connection(object_type, terminal_connection_type, computer_cn, computer_name, path)

return connection


def get_connections(ldap_connection_string, ldap_username, ldap_password, base_dn):
result = get_ldap_result(ldap_connection_string, ldap_username, ldap_password, base_dn)

connections = []

if isinstance(result, list):
for dn, entry in result:
if isinstance(entry, dict):
connection = ldap_entry_to_connection(dn, entry)

if connection is None:
continue

connections.append(connection)

return connections


connections = get_connections(LDAP_CONNECTION_STRING, LDAP_USERNAME, LDAP_PASSWORD, BASE_DN)

store = {
"Objects": connections
}

jsonStr = json.dumps(store)

print(jsonStr)]]></Script>
<DynamicCredentialScriptInterpreter>json</DynamicCredentialScriptInterpreter>
<DynamicCredentialScript><![CDATA[{
"Username": "user",
"Password": "pass"
}]]></DynamicCredentialScript>
<DynamicFolderScriptTokenMode>ReplaceInline</DynamicFolderScriptTokenMode>
<DynamicFolderScriptEnvironmentPrefix>DynFolder_</DynamicFolderScriptEnvironmentPrefix>
<DynamicCredentialScriptTokenMode>ReplaceInline</DynamicCredentialScriptTokenMode>
<DynamicCredentialScriptEnvironmentPrefix>DynCredential_</DynamicCredentialScriptEnvironmentPrefix>
</DynamicFolderExportObject>
</Objects>
</DynamicFolderExport>
Loading