#!/usr/bin/env python3
'''special agent call file

Set the environment variable ``LDAP_VERIFY_TLS=1`` or pass ``--verify-tls``
to enforce TLS certificate verification.
'''
# -*- mode: Python; encoding: utf-8; indent-offset: 4; autowrap: nil -*-

# (c) Michael Honkoop <mhonkoop@comsolve.nl>

# License: GNU General Public License v2

import os
import sys
import ldap
from cmk_addons.plugins.edirectory_monitor.lib import (
    print_sections,
)

# possible subsections of cn=Monitor
monitor_sections = [
    "Agent",
    "Dclient",
    "DHOST",
    "LDAP",
    "RecordManager",
    "IDM",
]

def main():
    verify_tls = False
    exclude_sections = []
    for args in sys.argv[1:]:  # Skip the script name (sys.argv[0])
        if args.startswith("--exclude="):
            # Extract the part after "--exclude "
            exclude_params = args.split("=", 1)[1]            
            # Split the value by commas, strip whitespace, and ignore empty parts
            exclude_sections = exclude_params.split(",")
            #print(exclude_sections)
        else:
            exclude_sections = None

        if "--verify-tls" in args:
            verify_tls = True

    args = sys.argv[1:]

    env_verify = os.environ.get("LDAP_VERIFY_TLS", "").lower()
    if env_verify in ("1", "true", "yes"):
        verify_tls = True

    if len(args) < 3:
        print("Usage: script.py [--verify-tls] [--exclude=<section(s)>] <LDAP_URI> <BIND_DN> <PASSWORD>")
        return 1
    
    ldap_uri = args[0]
    binddn = args[1] 
    pw = args[2]
    basedn = "cn=Monitor"
    searchFilter = "(objectClass=*)"
    searchAttribute = ["*"]
    searchScope = ldap.SCOPE_SUBTREE

    l = None
    try:
        if verify_tls:
            ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND)
        else:
            ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
        # set timeout to 40 seconds for network
        ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 40)
        # Create LDAPObject instance with given uri
        l = ldap.initialize(ldap_uri)
        # Set LDAP protocol version used
        l.protocol_version = ldap.VERSION3

        try:
            # Attempt to bind with given credentials
            l.simple_bind_s(binddn, pw)
            
            if exclude_sections is None:
                ldap_result_id = l.search(basedn, searchScope, searchFilter, searchAttribute)

                result_set = []

                while True:
                    result_type, result_data = l.result(ldap_result_id, 0, timeout=40)
                    if (result_data == []):
                        break
                    elif result_type == ldap.RES_SEARCH_ENTRY:
                        result_set.append(result_data)
            else:
                result_set = []

                for entry in monitor_sections:
                    if entry.lower() in exclude_sections:
                        continue
                    else:
                        ldap_result_id = l.search("cn=" + entry + "," + basedn, searchScope, searchFilter, searchAttribute)

                        while True:
                            result_type, result_data = l.result(ldap_result_id, 0, timeout=40)
                            if (result_data == []):
                                break
                            elif result_type == ldap.RES_SEARCH_ENTRY:
                                result_set.append(result_data)
                                
            print('<<<edirectory_monitor_agent:sep(124)>>>')
            for i in range(len(result_set)):
                for val in result_set[i]:
                    for element in val:
                        if "cn=Agent" in element:
                            print_sections(result_set[i])
            print('<<<edirectory_monitor_dclient:sep(124)>>>')
            for i in range(len(result_set)):
                for val in result_set[i]:
                    for element in val:
                        if "cn=Dclient" in element:
                            print_sections(result_set[i])
            print('<<<edirectory_monitor_dhost:sep(124)>>>')
            for i in range(len(result_set)):
                for val in result_set[i]:
                    for element in val:
                        if "cn=DHOST" in element:
                            print_sections(result_set[i])
            print('<<<edirectory_monitor_ldap:sep(124)>>>')
            for i in range(len(result_set)):
                for val in result_set[i]:
                    for element in val:
                        if "cn=LDAP" in element:
                            print_sections(result_set[i])
            print('<<<edirectory_monitor_recordmanager:sep(124)>>>')
            for i in range(len(result_set)):
                for val in result_set[i]:
                    for element in val:
                        if "cn=RecordManager" in element:
                            print_sections(result_set[i])
            print('<<<edirectory_monitor_idm:sep(124)>>>')
            for i in range(len(result_set)):
                for val in result_set[i]:
                    for element in val:
                        if "cn=IDM" in element:
                            print_sections(result_set[i])

        except ldap.INVALID_CREDENTIALS as e:
            print(f"Authentication to the LDAP host has failed: {e}")
            return print(f"Authentication to the LDAP host has failed: {e}")
        
        except ldap.LDAPError as e:
            print(f"LDAP error during bind/search: {e}")
            return print(f"LDAP error during bind/search: {e}")
        
    except ldap.LDAPError as e:
        print(f"Failed to initialize LDAP connection: {e}")
        return print(f"Failed to initialize LDAP connection: {e}")
    finally:
        if l is not None:
            try:
                l.unbind_s()
            except ldap.LDAPError:
                pass

if __name__ == "__main__":
    main()

