]> Frank Brehm's Git Trees - pixelpark/admin-tools.git/commitdiff
Adding pp_lib/ldap_app.py
authorFrank Brehm <frank.brehm@pixelpark.com>
Fri, 17 Mar 2017 14:33:23 +0000 (15:33 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Fri, 17 Mar 2017 14:33:23 +0000 (15:33 +0100)
mk-home
pp_lib/cfg_app.py
pp_lib/ldap_app.py [new file with mode: 0644]

diff --git a/mk-home b/mk-home
index 4983818c2920bdda7bf5e2c360e75aac3d4888a4..12f5ccab7ddb10b76e1739a37baf9a0b4dbd2815 100755 (executable)
--- a/mk-home
+++ b/mk-home
@@ -17,7 +17,7 @@ if os.path.exists(os.path.join(cur_dir, 'pp_lib')):
 
 from pp_lib.common import pp
 
-from pp_lib.cfg_app import PpConfigApplication
+from pp_lib.ldap_app import PpLdapApplication
 
 log = logging.getLogger(__name__)
 
@@ -28,7 +28,7 @@ appname = os.path.basename(sys.argv[0])
 
 locale.setlocale(locale.LC_ALL, '')
 
-app = PpConfigApplication(appname=appname, cfg_stems=['ldap', 'mk-home'])
+app = PpLdapApplication(appname=appname, cfg_stems='mk-home')
 app.initialized = True
 
 if app.verbose > 2:
index 23dfac14b1667f782d3f540b775be5bb01a545de..08cfea47e835a3a32ea68101c4ce000cad6c4ee2 100644 (file)
@@ -4,7 +4,8 @@
 @author: Frank Brehm
 @contact: frank.brehm@pixelpark.com
 @copyright: © 2017 by Frank Brehm, Berlin
-@summary: The module for the application object.
+@summary: The module for the application object with support
+          for configuration files.
 """
 from __future__ import absolute_import
 
diff --git a/pp_lib/ldap_app.py b/pp_lib/ldap_app.py
new file mode 100644 (file)
index 0000000..5e828f4
--- /dev/null
@@ -0,0 +1,213 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+@author: Frank Brehm
+@contact: frank.brehm@pixelpark.com
+@copyright: © 2017 by Frank Brehm, Berlin
+@summary: The module for a LDAP based application object.
+"""
+from __future__ import absolute_import
+
+# Standard modules
+import sys
+import os
+import logging
+import logging.config
+import re
+import traceback
+import textwrap
+import copy
+
+# Third party modules
+import six
+
+import ldap3
+
+# Own modules
+from .global_version import __version__ as __global_version__
+
+from .errors import FunctionNotImplementedError, PpAppError
+
+from .common import pp, terminal_can_colors, to_bytes, to_bool
+
+from .merge import merge_structure
+
+from .cfg_app import PpCfgAppError, PpConfigApplication
+
+__version__ = '0.2.1'
+LOG = logging.getLogger(__name__)
+
+
+# =============================================================================
+class PpLdapAppError(PpCfgAppError):
+    """Base error class for all exceptions happened during
+    execution this configured application"""
+
+    pass
+
+
+# =============================================================================
+class PpLdapApplication(PpConfigApplication):
+    """
+    Class for configured application objects.
+    """
+
+    default_ldap_hosts = [
+        'ldap.pixelpark.com'
+    ]
+
+    default_ldap_port = 389
+    default_ldap_port_ssl = 636
+    default_ldap_use_ssl = False
+
+    default_ldap_base_dn = 'o=isp'
+    default_ldap_bind_dn = 'uid=Solaris_NSS,ou=Unix NSS,ou=Applications,o=pixelpark,o=isp'
+    default_ldap_timeout = 10
+
+    fs_re = re.compile(r'(?:\s+|\s*[,;]\s*)')
+
+    # -------------------------------------------------------------------------
+    def __init__(
+        self, appname=None, verbose=0, version=__version__, base_dir=None,
+            initialized=None, usage=None, description=None,
+            argparse_epilog=None, argparse_prefix_chars='-', env_prefix=None,
+            cfg_dir=None, cfg_stems=None, cfg_encoding='utf-8', need_config_file=False):
+
+        self.ldap_hosts = copy.copy(self.default_ldap_hosts)
+        self.ldap_use_ssl = self.default_ldap_use_ssl
+        self.ldap_port = self.default_ldap_port
+        if self.ldap_use_ssl:
+            self.ldap_port = self.default_ldap_port_ssl
+
+        self.ldap_base_dn = self.default_ldap_base_dn
+        self.ldap_bind_dn = self.default_ldap_bind_dn
+        self.ldap_bind_pw = None
+        self.ldap_timeout = self.default_ldap_timeout
+
+        # Either a single Server object or a ServerPool object
+        self.ldap_server = None
+        self.ldap_connection = None
+
+        stems = []
+        if cfg_stems:
+            if isinstance(cfg_stems, list):
+                for stem in cfg_stems:
+                    s = str(stem).strip()
+                    if not s:
+                        msg = "Invalid configuration stem {!r} given.".format(stem)
+                        raise PpLdapAppError(msg)
+                    stems.append(s)
+            else:
+                s = str(cfg_stems).strip()
+                if not s:
+                    msg = "Invalid configuration stem {!r} given.".format(cfg_stems)
+                    raise PpLdapAppError(msg)
+                stems.append(s)
+        else:
+            stems = self.appname
+        if not 'ldap' in stems:
+            stems.insert(0, 'ldap')
+
+        super(PpLdapApplication, self).__init__(
+            appname=appname, verbose=verbose, version=version, base_dir=base_dir,
+            initialized=False, usage=usage, description=description,
+            argparse_epilog=argparse_epilog, argparse_prefix_chars=argparse_prefix_chars,
+            env_prefix=env_prefix, cfg_dir=cfg_dir, cfg_stems=stems,
+            cfg_encoding=cfg_encoding, need_config_file=need_config_file,
+        )
+
+        pass
+
+    # -------------------------------------------------------------------------
+    def perform_config(self):
+
+        """
+        Execute some actions after reading the configuration.
+
+        This method should be explicitely called by all perform_config()
+        methods in descendant classes.
+        """
+
+        got_host = False
+        for section in self.cfg.keys():
+
+            if not section.lower() == 'ldap':
+                continue
+            ldap_section = self.cfg[section]
+
+            if 'host' in ldap_section:
+                hosts = self.fs_re.split(ldap_section['host'])
+                for host in hosts:
+                    if not host:
+                        continue
+                    if not got_host:
+                        self.ldap_hosts = []
+                        got_host = True
+                    host = host.lower()
+                    if host in self.ldap_hosts:
+                        continue
+                    self.ldap_hosts.append(host)
+
+            if 'port' in ldap_section:
+                try:
+                    port = int(ldap_section['port'])
+                except (ValueError, TypeError) as e:
+                    msg = "Invalid LDAP port ({s}/port => {v!r}) found in configuration.".format(
+                        s=section, v=ldap_section['port'])
+                    raise PpLdapAppError(msg)
+                if port <= 0 or port >= 2 ** 16:
+                    msg = "Invalid LDAP port ({s}/port => {v!r}) found in configuration.".format(
+                        s=section, v=port)
+                    raise PpLdapAppError(msg)
+                self.ldap_port = port
+
+            if 'ssl' in ldap_section:
+                self.ldap_use_ssl = to_bool(ldap_section['ssl'])
+
+            if 'tls' in ldap_section:
+                self.ldap_use_ssl = to_bool(ldap_section['tls'])
+
+            if 'base_dn' in ldap_section:
+                self.ldap_base_dn = ldap_section['base_dn'].strip()
+            if 'bind_dn' in ldap_section:
+                self.ldap_bind_dn = ldap_section['bind_dn'].strip()
+            if 'bind_pw' in ldap_section:
+                self.ldap_bind_pw = ldap_section['bind_pw']
+            if 'timeout' in ldap_section:
+                try:
+                    timeout = int(ldap_section['timeout'])
+                except (ValueError, TypeError) as e:
+                    msg = "Invalid LDAP timeout ({s}/port => {v!r}) found in configuration.".format(
+                        s=section, v=ldap_section['timeout'])
+                    LOG.error(msg)
+                if timeout > 0:
+                    self.ldap_timeout = timeout
+
+        # ----------------------
+        def _get_ldap_server(host):
+            return ldap3.Server(
+                host, port=self.ldap_port, use_ssl=self.ldap_use_ssl,
+                mode=ldap3.IP_V4_PREFERRED, connect_timeout=self.ldap_timeout)
+
+        # Init LDAP Server objects
+        if len(self.ldap_hosts) > 1:
+            self.ldap_server = ldap3.ServerPool(None, ldap3.ROUND_ROBIN)
+            for h in self.ldap_hosts:
+                server = _get_ldap_server(h)
+                self.ldap_server.add(server)
+        elif len(self.ldap_hosts) == 1:
+            self.ldap_server = _get_ldap_server(self.ldap_hosts[0])
+        else:
+            msg = "No LDAP servers found in configuration."
+            raise PpLdapAppError(msg)
+
+
+# =============================================================================
+
+if __name__ == "__main__":
+
+    pass
+
+# =============================================================================
+
+# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list