[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Thu Mar 24 23:41:01 UTC 2022


The branch, master has been updated
       via  c788ed7b8b4 samba-gpupdate: Implement enhanced logging
      from  c4f9c372405 s3: smbd: smbd_smb2_setinfo_send(). All calls to SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) clobber fsp->fsp_name->st.st_ex_iflags.

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit c788ed7b8b4e1f8331562715d68af48ad9985383
Author: David Mulder <dmulder at suse.com>
Date:   Wed Mar 2 02:23:51 2022 -0700

    samba-gpupdate: Implement enhanced logging
    
    This ports the enhanced logging capabilities from
    AltLinux gpupdate. It generates log messages such
    as:
    2022-03-02 11:28:54.872|[E40104]| Failed to set interfaces for zone | {'val': 'work'}
    2022-03-02 11:28:55.017|[E40104]| Failed to set interfaces for zone | {'val': 'home'}
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Thu Mar 24 23:40:47 UTC 2022 on sn-devel-184

-----------------------------------------------------------------------

Summary of changes:
 python/samba/gp/util/logging.py         | 98 +++++++++++++++++++++++++++++++++
 python/samba/gp_cert_auto_enroll_ext.py | 51 ++++++++---------
 python/samba/gp_chromium_ext.py         | 21 +++----
 python/samba/gp_ext_loader.py           | 11 ++--
 python/samba/gp_firefox_ext.py          | 17 +++---
 python/samba/gp_firewalld_ext.py        | 19 +++----
 python/samba/gp_gnome_settings_ext.py   | 22 ++++----
 python/samba/gp_sec_ext.py              | 21 ++++---
 python/samba/gp_smb_conf_ext.py         |  4 +-
 python/samba/gp_sudoers_ext.py          |  4 +-
 python/samba/gpclass.py                 | 32 +++++------
 python/samba/tests/gpo.py               | 67 ++++++++--------------
 python/samba/tests/gpo_member.py        |  3 +-
 python/samba/vgp_files_ext.py           |  7 +--
 python/samba/vgp_sudoers_ext.py         |  4 +-
 python/samba/vgp_symlink_ext.py         |  4 +-
 source4/scripting/bin/samba-gpupdate    | 24 ++------
 17 files changed, 229 insertions(+), 180 deletions(-)
 create mode 100644 python/samba/gp/util/logging.py


Changeset truncated at 500 lines:

diff --git a/python/samba/gp/util/logging.py b/python/samba/gp/util/logging.py
new file mode 100644
index 00000000000..7373af0961e
--- /dev/null
+++ b/python/samba/gp/util/logging.py
@@ -0,0 +1,98 @@
+#
+# samba-gpupdate enhanced logging
+#
+# Copyright (C) 2019-2020 BaseALT Ltd.
+# Copyright (C) David Mulder <dmulder at samba.org> 2022
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import json
+import datetime
+import logging
+import gettext
+import random
+import sys
+
+logger = logging.getLogger()
+def logger_init(name, log_level):
+    logger = logging.getLogger(name)
+    logger.addHandler(logging.StreamHandler(sys.stdout))
+    logger.setLevel(logging.CRITICAL)
+    if log_level == 1:
+        logger.setLevel(logging.ERROR)
+    elif log_level == 2:
+        logger.setLevel(logging.WARNING)
+    elif log_level == 3:
+        logger.setLevel(logging.INFO)
+    elif log_level >= 4:
+        logger.setLevel(logging.DEBUG)
+
+class slogm(object):
+    '''
+    Structured log message class
+    '''
+    def __init__(self, message, kwargs=dict()):
+        self.message = message
+        self.kwargs = kwargs
+        if not isinstance(self.kwargs, dict):
+            self.kwargs = { 'val': self.kwargs }
+
+    def __str__(self):
+        now = str(datetime.datetime.now().isoformat(sep=' ', timespec='milliseconds'))
+        args = dict()
+        args.update(self.kwargs)
+        result = '{}|{} | {}'.format(now, self.message, args)
+
+        return result
+
+def message_with_code(mtype, message):
+    random.seed(message)
+    code = random.randint(0, 99999)
+    return '[' + mtype + str(code).rjust(5, '0') + ']| ' + \
+           gettext.gettext(message)
+
+class log(object):
+    @staticmethod
+    def info(message, data={}):
+        msg = message_with_code('I', message)
+        logger.info(slogm(msg, data))
+        return msg
+
+    @staticmethod
+    def warning(message, data={}):
+        msg = message_with_code('W', message)
+        logger.warning(slogm(msg, data))
+        return msg
+
+    @staticmethod
+    def warn(message, data={}):
+        return log.warning(message, data)
+
+    @staticmethod
+    def error(message, data={}):
+        msg = message_with_code('E', message)
+        logger.error(slogm(msg, data))
+        return msg
+
+    @staticmethod
+    def fatal(message, data={}):
+        msg = message_with_code('F', message)
+        logger.fatal(slogm(msg, data))
+        return msg
+
+    @staticmethod
+    def debug(message, data={}):
+        msg = message_with_code('D', message)
+        logger.debug(slogm(msg, data))
+        return msg
diff --git a/python/samba/gp_cert_auto_enroll_ext.py b/python/samba/gp_cert_auto_enroll_ext.py
index 60927709eaa..b61aaf7b985 100644
--- a/python/samba/gp_cert_auto_enroll_ext.py
+++ b/python/samba/gp_cert_auto_enroll_ext.py
@@ -27,6 +27,7 @@ from subprocess import Popen, PIPE
 import re
 from glob import glob
 import json
+from samba.gp.util.logging import log
 
 cert_wrap = b"""
 -----BEGIN CERTIFICATE-----
@@ -76,7 +77,7 @@ def find_cepces_submit():
                        '/usr/libexec/certmonger']
     return which('cepces-submit', path=':'.join(certmonger_dirs))
 
-def get_supported_templates(server, logger):
+def get_supported_templates(server):
     cepces_submit = find_cepces_submit()
     if os.path.exists(cepces_submit):
         env = os.environ
@@ -85,12 +86,12 @@ def get_supported_templates(server, logger):
                        stdout=PIPE, stderr=PIPE)
         out, err = p.communicate()
         if p.returncode != 0:
-            logger.warn('Failed to fetch the list of supported templates.')
-            logger.debug(err.decode())
+            log.warn('Failed to fetch the list of supported templates.')
+            log.debug(err.decode())
         return out.strip().split()
     return []
 
-def cert_enroll(ca, trust_dir, private_dir, logger):
+def cert_enroll(ca, trust_dir, private_dir):
     # Install the root certificate chain
     data = {'files': [], 'templates': []}
     sscep = which('sscep')
@@ -101,9 +102,9 @@ def cert_enroll(ca, trust_dir, private_dir, logger):
         ret = Popen([sscep, 'getca', '-F', 'sha1', '-c',
                      root_cert, '-u', url]).wait()
         if ret != 0:
-            logger.warn('sscep failed to fetch the root certificate chain.')
-            logger.warn('Ensure you have installed and configured the' +
-                        ' Network Device Enrollment Service.')
+            log.warn('sscep failed to fetch the root certificate chain.')
+            log.warn('Ensure you have installed and configured the' +
+                     ' Network Device Enrollment Service.')
         root_certs = glob('%s*' % root_cert)
         data['files'].extend(root_certs)
         for src in root_certs:
@@ -113,21 +114,20 @@ def cert_enroll(ca, trust_dir, private_dir, logger):
                 os.symlink(src, dst)
                 data['files'].append(dst)
             except PermissionError:
-                logger.warn('Failed to symlink root certificate to the' +
-                            ' admin trust anchors')
+                log.warn('Failed to symlink root certificate to the' +
+                         ' admin trust anchors')
             except FileNotFoundError:
-                logger.warn('Failed to symlink root certificate to the' +
-                            ' admin trust anchors.' +
-                            ' The directory %s was not found' % \
-                                                        global_trust_dir)
+                log.warn('Failed to symlink root certificate to the' +
+                         ' admin trust anchors.' +
+                         ' The directory was not found', global_trust_dir)
             except FileExistsError:
                 # If we're simply downloading a renewed cert, the symlink
                 # already exists. Ignore the FileExistsError. Preserve the
                 # existing symlink in the unapply data.
                 data['files'].append(dst)
     else:
-        logger.warn('sscep is not installed, which prevents the installation' +
-                    ' of the root certificate chain.')
+        log.warn('sscep is not installed, which prevents the installation' +
+                 ' of the root certificate chain.')
     update = which('update-ca-certificates')
     if update is not None:
         Popen([update]).wait()
@@ -139,11 +139,10 @@ def cert_enroll(ca, trust_dir, private_dir, logger):
                   '%s --server=%s' % (cepces_submit, ca['dNSHostName'][0])],
                   stdout=PIPE, stderr=PIPE)
         out, err = p.communicate()
-        logger.debug(out.decode())
+        log.debug(out.decode())
         if p.returncode != 0:
-            logger.debug(err.decode())
-        supported_templates = get_supported_templates(ca['dNSHostName'][0],
-                                                      logger)
+            log.debug(err.decode())
+        supported_templates = get_supported_templates(ca['dNSHostName'][0])
         for template, attrs in ca['certificateTemplates'].items():
             if template not in supported_templates:
                 continue
@@ -156,16 +155,16 @@ def cert_enroll(ca, trust_dir, private_dir, logger):
                        '-g', attrs['msPKI-Minimal-Key-Size'][0]],
                        stdout=PIPE, stderr=PIPE)
             out, err = p.communicate()
-            logger.debug(out.decode())
+            log.debug(out.decode())
             if p.returncode != 0:
-                logger.debug(err.decode())
+                log.debug(err.decode())
             data['files'].extend([keyfile, certfile])
             data['templates'].append(nickname)
         if update is not None:
             Popen([update]).wait()
     else:
-        logger.warn('certmonger and cepces must be installed for ' +
-                    'certificate auto enrollment to work')
+        log.warn('certmonger and cepces must be installed for ' +
+                 'certificate auto enrollment to work')
     return json.dumps(data)
 
 class gp_cert_auto_enroll_ext(gp_pol_ext):
@@ -225,8 +224,7 @@ class gp_cert_auto_enroll_ext(gp_pol_ext):
                                       lp=self.lp, credentials=self.creds)
                             cas = fetch_certification_authorities(ldb)
                             for ca in cas:
-                                data = cert_enroll(ca, trust_dir,
-                                                   private_dir, self.logger)
+                                data = cert_enroll(ca, trust_dir, private_dir)
                                 self.gp_db.store(str(self),
                                      base64.b64encode(ca['cn'][0]).decode(),
                                      data)
@@ -260,8 +258,7 @@ class gp_cert_auto_enroll_ext(gp_pol_ext):
                         output[policy][cn]['Auto Enrollment Server'] = \
                             ca['dNSHostName'][0]
                         supported_templates = \
-                            get_supported_templates(ca['dNSHostName'][0],
-                                                    self.logger)
+                            get_supported_templates(ca['dNSHostName'][0])
                         output[policy][cn]['Templates'] = \
                             [t.decode() for t in supported_templates]
         return output
diff --git a/python/samba/gp_chromium_ext.py b/python/samba/gp_chromium_ext.py
index c3193d04433..befce47085d 100644
--- a/python/samba/gp_chromium_ext.py
+++ b/python/samba/gp_chromium_ext.py
@@ -19,6 +19,7 @@ import json
 from samba.gpclass import gp_pol_ext
 from samba.dcerpc import misc
 from samba.common import get_string
+from samba.gp.util.logging import log
 
 def parse_entry_data(name, e):
     dict_entries = ['VirtualKeyboardFeatures',
@@ -389,11 +390,10 @@ class gp_chromium_ext(gp_pol_ext):
             os.makedirs(self.__managed_policies_path, exist_ok=True)
             with open(managed_policies, 'w') as f:
                 json.dump(managed, f)
-                self.logger.debug('Wrote Chromium preferences to %s' % \
-                                  managed_policies)
+                log.debug('Wrote Chromium preferences', managed_policies)
         except PermissionError:
-            self.logger.debug('Failed to write Chromium preferences to %s' % \
-                              managed_policies)
+            log.debug('Failed to write Chromium preferences',
+                      managed_policies)
 
 
     def set_recommended_machine_policy(self, recommended):
@@ -403,11 +403,10 @@ class gp_chromium_ext(gp_pol_ext):
             os.makedirs(self.__recommended_policies_path, exist_ok=True)
             with open(recommended_policies, 'w') as f:
                 json.dump(recommended, f)
-                self.logger.debug('Wrote Chromium preferences to %s' % \
-                                  recommended_policies)
+                log.debug('Wrote Chromium preferences', recommended_policies)
         except PermissionError:
-            self.logger.debug('Failed to write Chromium preferences to %s' % \
-                              recommended_policies)
+            log.debug('Failed to write Chromium preferences',
+                      recommended_policies)
 
     def get_managed_machine_policy(self):
         managed_policies = os.path.join(self.__managed_policies_path,
@@ -415,8 +414,7 @@ class gp_chromium_ext(gp_pol_ext):
         if os.path.exists(managed_policies):
             with open(managed_policies, 'r') as r:
                 managed = json.load(r)
-                self.logger.debug('Read Chromium preferences from %s' % \
-                                  managed_policies)
+                log.debug('Read Chromium preferences', managed_policies)
         else:
             managed = {}
         return managed
@@ -427,8 +425,7 @@ class gp_chromium_ext(gp_pol_ext):
         if os.path.exists(recommended_policies):
             with open(recommended_policies, 'r') as r:
                 recommended = json.load(r)
-                self.logger.debug('Read Chromium preferences from %s' % \
-                                  recommended_policies)
+                log.debug('Read Chromium preferences', recommended_policies)
         else:
             recommended = {}
         return recommended
diff --git a/python/samba/gp_ext_loader.py b/python/samba/gp_ext_loader.py
index 29a265e3d01..3db8442ea3f 100644
--- a/python/samba/gp_ext_loader.py
+++ b/python/samba/gp_ext_loader.py
@@ -16,6 +16,7 @@
 
 from samba.gpclass import list_gp_extensions
 from samba.gpclass import gp_ext
+from samba.gp.util.logging import log
 
 try:
     import importlib.util
@@ -40,7 +41,7 @@ def get_gp_ext_from_module(name, mod):
     return None
 
 
-def get_gp_client_side_extensions(logger, smb_conf):
+def get_gp_client_side_extensions(smb_conf):
     user_exts = []
     machine_exts = []
     gp_exts = list_gp_extensions(smb_conf)
@@ -49,10 +50,10 @@ def get_gp_client_side_extensions(logger, smb_conf):
         ext = get_gp_ext_from_module(gp_ext['ProcessGroupPolicy'], module)
         if ext and gp_ext['MachinePolicy']:
             machine_exts.append(ext)
-            logger.info('Loaded machine extension from %s: %s'
-                        % (gp_ext['DllName'], ext.__name__))
+            log.info('Loaded machine extension from %s: %s'
+                     % (gp_ext['DllName'], ext.__name__))
         if ext and gp_ext['UserPolicy']:
             user_exts.append(ext)
-            logger.info('Loaded user extension from %s: %s'
-                        % (gp_ext['DllName'], ext.__name__))
+            log.info('Loaded user extension from %s: %s'
+                     % (gp_ext['DllName'], ext.__name__))
     return (machine_exts, user_exts)
diff --git a/python/samba/gp_firefox_ext.py b/python/samba/gp_firefox_ext.py
index afe582502b1..6dbded0cae7 100644
--- a/python/samba/gp_firefox_ext.py
+++ b/python/samba/gp_firefox_ext.py
@@ -19,6 +19,7 @@ import json
 from samba.gpclass import gp_pol_ext
 from samba.dcerpc import misc
 from samba.common import get_string
+from samba.gp.util.logging import log
 
 def parse_entry_data(e):
     if e.type == misc.REG_MULTI_SZ:
@@ -96,33 +97,29 @@ class gp_firefox_ext(gp_pol_ext):
             os.makedirs(self.__firefox_installdir1, exist_ok=True)
             with open(self.__destfile1, 'w') as f:
                 json.dump(policies, f)
-                self.logger.debug('Wrote Firefox preferences to %s' % \
-                                  self.__destfile1)
+                log.debug('Wrote Firefox preferences', self.__destfile1)
         except PermissionError:
-            self.logger.debug('Failed to write Firefox preferences to %s' % \
+            log.debug('Failed to write Firefox preferences',
                               self.__destfile1)
 
         try:
             os.makedirs(self.__firefox_installdir2, exist_ok=True)
             with open(self.__destfile2, 'w') as f:
                 json.dump(policies, f)
-                self.logger.debug('Wrote Firefox preferences to %s' % \
-                                  self.__destfile2)
+                log.debug('Wrote Firefox preferences', self.__destfile2)
         except PermissionError:
-            self.logger.debug('Failed to write Firefox preferences to %s' % \
+            log.debug('Failed to write Firefox preferences',
                               self.__destfile2)
 
     def get_machine_policy(self):
         if os.path.exists(self.__destfile2):
             with open(self.__destfile2, 'r') as r:
                 policies = json.load(r)
-                self.logger.debug('Read Firefox preferences from %s' % \
-                                  self.__destfile2)
+                log.debug('Read Firefox preferences', self.__destfile2)
         elif os.path.exists(self.__destfile1):
             with open(self.__destfile1, 'r') as r:
                 policies = json.load(r)
-                self.logger.debug('Read Firefox preferences from %s' % \
-                                  self.__destfile1)
+                log.debug('Read Firefox preferences', self.__destfile1)
         else:
             policies = {'policies': {}}
         return policies
diff --git a/python/samba/gp_firewalld_ext.py b/python/samba/gp_firewalld_ext.py
index 0fbd87371e0..3b60cf44ad3 100644
--- a/python/samba/gp_firewalld_ext.py
+++ b/python/samba/gp_firewalld_ext.py
@@ -20,6 +20,7 @@ from hashlib import blake2b
 from shutil import which
 import json
 from samba.gpclass import gp_pol_ext
+from samba.gp.util.logging import log
 
 def firewall_cmd(*args):
     fw_cmd = which('firewall-cmd')
@@ -47,19 +48,18 @@ class gp_firewalld_ext(gp_pol_ext):
     def apply_zone(self, zone):
         ret = firewall_cmd('--permanent', '--new-zone=%s' % zone)[0]
         if ret != 0:
-            self.logger.error('Failed to add new zone %s' % zone)
+            log.error('Failed to add new zone', zone)
         else:
             self.gp_db.store(str(self), 'zone:%s' % zone, zone)
         # Default to matching the interface(s) for the default zone
         ret, out = firewall_cmd('--list-interfaces')
         if ret != 0:
-            self.logger.error('Failed to set interfaces for zone: %s' % zone)
+            log.error('Failed to set interfaces for zone', zone)
         for interface in out.strip().split():
             ret = firewall_cmd('--permanent', '--zone=%s' % zone,
                                '--add-interface=%s' % interface.decode())
             if ret != 0:
-                self.logger.error('Failed to set interfaces for zone: %s' % \
-                                  zone)
+                log.error('Failed to set interfaces for zone', zone)
 
     def apply_rules(self, rule_dict):
         for zone, rules in rule_dict.items():
@@ -82,12 +82,11 @@ class gp_firewalld_ext(gp_pol_ext):
                     rule_parsed += rule_segment_parse(list(action)[0],
                                                       rule[list(action)[0]])
                 else:
-                    self.logger.error('Invalid firewall rule syntax')
+                    log.error('Invalid firewall rule syntax')
                 ret = firewall_cmd('--permanent', '--zone=%s' % zone,
                                    '--add-rich-rule', rule_parsed.strip())[0]
                 if ret != 0:
-                    self.logger.error('Failed to add firewall rule: %s' % \
-                                      rule_parsed)
+                    log.error('Failed to add firewall rule', rule_parsed)
                 else:
                     rhash = blake2b(rule_parsed.encode()).hexdigest()
                     self.gp_db.store(str(self), 'rule:%s:%s' % (zone, rhash),
@@ -102,8 +101,7 @@ class gp_firewalld_ext(gp_pol_ext):
                         ret = firewall_cmd('--permanent',
                                            '--delete-zone=%s' % value)[0]
                         if ret != 0:
-                            self.logger.error('Failed to remove zone: %s' % \
-                                              value)
+                            log.error('Failed to remove zone', value)
                         else:
                             self.gp_db.delete(str(self), attribute)
                     elif attribute.startswith('rule'):
@@ -111,8 +109,7 @@ class gp_firewalld_ext(gp_pol_ext):
                         ret = firewall_cmd('--permanent', '--zone=%s' % zone,
                                            '--remove-rich-rule', value)[0]
                         if ret != 0:
-                            self.logger.error('Failed to remove firewall'
-                                              ' rule: %s' % value)
+                            log.error('Failed to remove firewall rule', value)
                         else:
                             self.gp_db.delete(str(self), attribute)
             self.gp_db.commit()
diff --git a/python/samba/gp_gnome_settings_ext.py b/python/samba/gp_gnome_settings_ext.py
index 27425029d05..1a5e73bea0a 100644
--- a/python/samba/gp_gnome_settings_ext.py
+++ b/python/samba/gp_gnome_settings_ext.py
@@ -23,8 +23,9 @@ from subprocess import Popen, PIPE
 from samba.common import get_bytes, get_string
 from glob import glob
 import xml.etree.ElementTree as etree
+from samba.gp.util.logging import log
 
-def dconf_update(log, test_dir):
+def dconf_update(test_dir):
     if test_dir is not None:
         return
     dconf = shutil.which('dconf')
@@ -34,7 +35,7 @@ def dconf_update(log, test_dir):
     p = Popen([dconf, 'update'], stdout=PIPE, stderr=PIPE)
     out, err = p.communicate()
     if p.returncode != 0:
-        log.error('Failed to update dconf: %s' % get_string(err))
+        log.error('Failed to update dconf', get_string(err))
 
 def create_locks_dir(test_dir):
     locks_dir = '/etc/dconf/db/local.d/locks'
@@ -124,8 +125,7 @@ class gp_gnome_settings_ext(gp_pol_ext):
                      'Scroll Lock': 'compose:sclk'
                    }
         if data['Key Name'] not in data_map.keys():
-            self.logger.error('Compose Key \'%s\' not recognized' % \
-                              data['Key Name'])
+            log.error('Compose Key not recognized', data)
             return
         parser = ConfigParser()
         section = 'org/gnome/desktop/input-sources'
@@ -143,7 +143,7 @@ class gp_gnome_settings_ext(gp_pol_ext):
         with open(lock, 'w') as w:
             w.write('/org/gnome/desktop/input-sources/xkb-options')
 
-        dconf_update(self.logger, self.test_dir)
+        dconf_update(self.test_dir)
         self.gp_db.store(str(self), attribute, ';'.join([local_db, lock]))


-- 
Samba Shared Repository



More information about the samba-cvs mailing list