[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