mirror of
https://github.com/altlinux/gpupdate.git
synced 2025-10-10 03:33:16 +03:00
Compare commits
1 Commits
fix_kde_ve
...
fix_check_
Author | SHA1 | Date | |
---|---|---|---|
527c4f8172 |
@@ -13,7 +13,7 @@ _gpoa()
|
||||
return
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=($(compgen -W '--dc --nodomain --noupdate --noplugins --list-backends --loglevel --help --force' -- "$cur"))
|
||||
COMPREPLY=($(compgen -W '--dc --nodomain --noupdate --noplugins --list-backends --loglevel --help' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
@@ -17,7 +17,7 @@ _gpupdate()
|
||||
return
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=($(compgen -W '--user --target --loglevel --system --help --force' -- "$cur"))
|
||||
COMPREPLY=($(compgen -W '--user --target --loglevel --system --help' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
@@ -45,9 +45,6 @@ Don't run plugins.
|
||||
.TP
|
||||
\fB--loglevel \fILOGLEVEL\fP
|
||||
Set logging verbosity from 0 to 5.
|
||||
.TP
|
||||
\fB--force\fP
|
||||
Force GPT download.
|
||||
.
|
||||
.SH FILES
|
||||
\fB/usr/sbin/gpoa\fR utility uses \fB/usr/share/local-policy/default\fR
|
||||
@@ -58,10 +55,8 @@ All data is located in \fB/var/cache/gpupdate\fR. Also domain GPTs are
|
||||
taken from Samba's \fB/var/cache/samba\fR.
|
||||
.
|
||||
The settings read from Samba are stored in
|
||||
Dconf. Machine policies are stored in the \fB/etc/dconf/db/policy.d/policy.ini\fR file,
|
||||
user policies are stored in the \fB/etc/dconf/db/policy<UID>.d/policy<UID>.ini\fR file
|
||||
(where UID is the user ID in the system)."Local Policy" settings
|
||||
read from \fB/usr/share/local-policy/\fR are converted
|
||||
\fB/var/cache/gpupdate/registry.sqlite\fR and "Local Policy" settings
|
||||
read from \fB/usr/local/share/local-policy/default\fR are converted
|
||||
into GPT and stored as \fB/var/cache/gpupdate/local-policy\fR.
|
||||
.SH "SEE ALSO"
|
||||
gpupdate(1)
|
||||
|
@@ -43,9 +43,6 @@ Show help.
|
||||
.TP
|
||||
\fB--user \fIusername\fR
|
||||
Run \fBgpupdate\fP for \fIusername\fP.
|
||||
.TP
|
||||
\fB--force\fP
|
||||
Force GPT download.
|
||||
.
|
||||
.SS "EXIT CODES"
|
||||
.TP
|
||||
|
@@ -23,8 +23,8 @@ from .nodomain_backend import nodomain_backend
|
||||
from util.logging import log
|
||||
from util.config import GPConfig
|
||||
from util.util import get_uid_by_username, touch_file
|
||||
from util.paths import get_dconf_config_file
|
||||
from storage.dconf_registry import Dconf_registry, create_dconf_ini_file, add_preferences_to_global_registry_dict
|
||||
from util.paths import get_dconf_config_path
|
||||
from storage.dconf_registry import Dconf_registry, create_dconf_ini_file
|
||||
|
||||
def backend_factory(dc, username, is_machine, no_domain = False):
|
||||
'''
|
||||
@@ -62,14 +62,12 @@ def backend_factory(dc, username, is_machine, no_domain = False):
|
||||
|
||||
return back
|
||||
|
||||
def save_dconf(username, is_machine, nodomain=None):
|
||||
def save_dconf(username, is_machine):
|
||||
if is_machine:
|
||||
uid = None
|
||||
else:
|
||||
uid = get_uid_by_username(username) if not is_machine else None
|
||||
target_file = get_dconf_config_file(uid)
|
||||
target_file = get_dconf_config_path(uid)
|
||||
touch_file(target_file)
|
||||
Dconf_registry.apply_template(uid)
|
||||
add_preferences_to_global_registry_dict(username, is_machine)
|
||||
Dconf_registry.update_dict_to_previous()
|
||||
create_dconf_ini_file(target_file,Dconf_registry.global_registry_dict, uid, nodomain)
|
||||
create_dconf_ini_file(target_file,Dconf_registry.global_registry_dict)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -16,14 +16,18 @@
|
||||
# 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 logging
|
||||
import os
|
||||
|
||||
from .applier_backend import applier_backend
|
||||
from storage import registry_factory
|
||||
from gpt.gpt import get_local_gpt
|
||||
from gpt.gpt import gpt, get_local_gpt
|
||||
from util.util import (
|
||||
get_machine_name
|
||||
)
|
||||
from util.sid import get_sid
|
||||
import util.preg
|
||||
from util.logging import slogm
|
||||
|
||||
class nodomain_backend(applier_backend):
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -26,15 +26,16 @@ except ImportError:
|
||||
from .applier_backend import applier_backend
|
||||
from storage import registry_factory
|
||||
from gpt.gpt import gpt, get_local_gpt
|
||||
from gpt.gpo_dconf_mapping import GpoInfoDconf
|
||||
from util.util import (
|
||||
get_machine_name
|
||||
get_machine_name,
|
||||
is_machine_name
|
||||
)
|
||||
from util.kerberos import (
|
||||
machine_kinit
|
||||
, machine_kdestroy
|
||||
)
|
||||
from util.sid import get_sid
|
||||
import util.preg
|
||||
from util.logging import log
|
||||
|
||||
class samba_backend(applier_backend):
|
||||
@@ -65,9 +66,6 @@ class samba_backend(applier_backend):
|
||||
self.sambacreds = sambacreds
|
||||
|
||||
self.cache_dir = self.sambacreds.get_cache_dir()
|
||||
self.gpo_cache_part ='gpo_cache'
|
||||
self._cached = False
|
||||
self.storage.set_info('cache_dir', os.path.join(self.cache_dir, self.gpo_cache_part))
|
||||
logdata = dict({'cachedir': self.cache_dir})
|
||||
log('D7', logdata)
|
||||
|
||||
@@ -106,6 +104,8 @@ class samba_backend(applier_backend):
|
||||
raise exc
|
||||
|
||||
if self._is_machine_username:
|
||||
self.storage.wipe_hklm()
|
||||
self.storage.wipe_user(self.storage.get_info('machine_sid'))
|
||||
for gptobj in machine_gpts:
|
||||
try:
|
||||
gptobj.merge_machine()
|
||||
@@ -123,6 +123,7 @@ class samba_backend(applier_backend):
|
||||
except Exception as exc:
|
||||
log('F3')
|
||||
raise exc
|
||||
self.storage.wipe_user(self.sid)
|
||||
|
||||
# Merge user settings if UserPolicyMode set accordingly
|
||||
# and user settings (for HKCU) are exist.
|
||||
@@ -153,15 +154,10 @@ class samba_backend(applier_backend):
|
||||
'''
|
||||
Check if there is SYSVOL path for GPO assigned
|
||||
'''
|
||||
self._cached = False
|
||||
if not gpo.file_sys_path:
|
||||
# GPO named "Local Policy" has no entry by its nature so
|
||||
# no reason to print warning.
|
||||
if gpo.display_name in self.storage._dict_gpo_name_version_cache.keys():
|
||||
gpo.file_sys_path = self.storage._dict_gpo_name_version_cache.get(gpo.display_name, {}).get('correct_path')
|
||||
self._cached = True
|
||||
return True
|
||||
elif 'Local Policy' != gpo.name:
|
||||
if 'Local Policy' != gpo.name:
|
||||
logdata = dict({'gponame': gpo.name})
|
||||
log('W4', logdata)
|
||||
return False
|
||||
@@ -176,18 +172,20 @@ class samba_backend(applier_backend):
|
||||
log('D46')
|
||||
for gpo in gpos:
|
||||
if self._check_sysvol_present(gpo):
|
||||
if not self._cached:
|
||||
path = check_safe_path(gpo.file_sys_path).upper()
|
||||
slogdata = dict({'sysvol_path': gpo.file_sys_path, 'gpo_name': gpo.display_name, 'gpo_path': path})
|
||||
log('D30', slogdata)
|
||||
gpt_abspath = os.path.join(self.cache_dir, self.gpo_cache_part, path)
|
||||
else:
|
||||
gpt_abspath = gpo.file_sys_path
|
||||
log('D211', {'sysvol_path': gpo.file_sys_path, 'gpo_name': gpo.display_name})
|
||||
path = check_safe_path(gpo.file_sys_path).upper()
|
||||
slogdata = dict({'sysvol_path': gpo.file_sys_path, 'gpo_name': gpo.display_name, 'gpo_path': path})
|
||||
log('D30', slogdata)
|
||||
gpt_abspath = os.path.join(self.cache_dir, 'gpo_cache', path)
|
||||
gpo_version=None
|
||||
try:
|
||||
gpo_version=gpo.version
|
||||
except:
|
||||
log('D210')
|
||||
|
||||
if self._is_machine_username:
|
||||
obj = gpt(gpt_abspath, sid, None, GpoInfoDconf(gpo))
|
||||
obj = gpt(gpt_abspath, sid, None, version=gpo_version)
|
||||
else:
|
||||
obj = gpt(gpt_abspath, sid, self.username, GpoInfoDconf(gpo))
|
||||
obj = gpt(gpt_abspath, sid, self.username, version=gpo_version)
|
||||
obj.set_name(gpo.display_name)
|
||||
gpts.append(obj)
|
||||
else:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
from abc import ABC
|
||||
|
||||
from util.logging import log
|
||||
|
||||
def check_experimental_enabled(storage):
|
||||
experimental_enable_flag = '/Software/BaseALT/Policies/GPUpdate/GlobalExperimental'
|
||||
@@ -48,7 +49,7 @@ def check_module_enabled(storage, module_name):
|
||||
|
||||
result = None
|
||||
flag = str(flag)
|
||||
if flag and flag!='None':
|
||||
if flag:
|
||||
if '1' == flag:
|
||||
result = True
|
||||
else:
|
||||
|
@@ -17,7 +17,9 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import subprocess
|
||||
from util.logging import log
|
||||
import threading
|
||||
import logging
|
||||
from util.logging import slogm, log
|
||||
|
||||
def control_subst(preg_name):
|
||||
'''
|
||||
@@ -99,14 +101,14 @@ class control:
|
||||
if status == None:
|
||||
logdata = dict()
|
||||
logdata['control'] = self.control_name
|
||||
logdata['inpossible values'] = self.control_value
|
||||
logdata['inpossible values'] = self.self.control_value
|
||||
log('E42', logdata)
|
||||
return
|
||||
elif type(self.control_value) == str:
|
||||
if self.control_value not in self.possible_values:
|
||||
logdata = dict()
|
||||
logdata['control'] = self.control_name
|
||||
logdata['inpossible values'] = self.control_value
|
||||
logdata['inpossible values'] = self.self.control_value
|
||||
log('E59', logdata)
|
||||
return
|
||||
status = self.control_value
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -17,40 +17,27 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from os.path import isfile
|
||||
from util.logging import slogm
|
||||
import logging
|
||||
|
||||
from util.arguments import (
|
||||
from gpt.envvars import (
|
||||
FileAction
|
||||
, action_letter2enum
|
||||
)
|
||||
from util.windows import expand_windows_var
|
||||
from util.util import get_homedir
|
||||
from util.logging import log
|
||||
from util.util import (
|
||||
get_homedir,
|
||||
homedir_exists
|
||||
)
|
||||
|
||||
class Envvar:
|
||||
__envvar_file_path = '/etc/gpupdate/environment'
|
||||
__envvar_file_path_user = '/.gpupdate_environment'
|
||||
|
||||
def __init__(self, envvars, username=''):
|
||||
self.username = username
|
||||
self.envvars = envvars
|
||||
if self.username == 'root':
|
||||
self.envvar_file_path = Envvar.__envvar_file_path
|
||||
self.envvar_file_path = '/etc/gpupdate/environment'
|
||||
else:
|
||||
self.envvar_file_path = get_homedir(self.username) + Envvar.__envvar_file_path_user
|
||||
|
||||
@staticmethod
|
||||
def clear_envvar_file(username = False):
|
||||
if username:
|
||||
file_path = get_homedir(username) + Envvar.__envvar_file_path_user
|
||||
else:
|
||||
file_path = Envvar.__envvar_file_path
|
||||
|
||||
try:
|
||||
with open(file_path, 'w') as file:
|
||||
file.write('')
|
||||
log('D215', {'path':file_path})
|
||||
except Exception as exc:
|
||||
log('D216', {'path': file_path, 'exc': exc})
|
||||
self.envvar_file_path = get_homedir(self.username) + '/.gpupdate_environment'
|
||||
|
||||
def _open_envvar_file(self):
|
||||
fd = None
|
||||
|
@@ -17,7 +17,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from util.arguments import (
|
||||
from gpt.folders import (
|
||||
FileAction
|
||||
, action_letter2enum
|
||||
)
|
||||
|
@@ -20,7 +20,7 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
from util.arguments import (
|
||||
from gpt.folders import (
|
||||
FileAction
|
||||
, action_letter2enum
|
||||
)
|
||||
|
@@ -18,9 +18,10 @@
|
||||
|
||||
import configparser
|
||||
import os
|
||||
import logging
|
||||
from gi.repository import Gio, GLib
|
||||
|
||||
from util.logging import log
|
||||
from util.logging import slogm, log
|
||||
|
||||
class system_gsetting:
|
||||
def __init__(self, schema, path, value, lock, helper_function=None):
|
||||
|
@@ -18,7 +18,7 @@
|
||||
|
||||
|
||||
|
||||
from util.arguments import (
|
||||
from gpt.folders import (
|
||||
FileAction
|
||||
, action_letter2enum
|
||||
)
|
||||
|
@@ -18,7 +18,7 @@
|
||||
|
||||
import subprocess
|
||||
|
||||
from util.arguments import (
|
||||
from gpt.folders import (
|
||||
FileAction
|
||||
, action_letter2enum
|
||||
)
|
||||
|
@@ -17,8 +17,9 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import dbus
|
||||
import logging
|
||||
|
||||
from util.logging import log
|
||||
from util.logging import slogm, log
|
||||
|
||||
class systemd_unit:
|
||||
def __init__(self, unit_name, state):
|
||||
@@ -37,9 +38,6 @@ class systemd_unit:
|
||||
if self.desired_state == 1:
|
||||
self.manager.UnmaskUnitFiles([self.unit_name], dbus.Boolean(False))
|
||||
self.manager.EnableUnitFiles([self.unit_name], dbus.Boolean(False), dbus.Boolean(True))
|
||||
if self.unit_name == 'gpupdate.service':
|
||||
if self.manager.GetUnitFileState(dbus.String(self.unit_name)) == 'enabled':
|
||||
return
|
||||
self.manager.StartUnit(self.unit_name, 'replace')
|
||||
logdata = dict()
|
||||
logdata['unit'] = self.unit_name
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -39,7 +39,8 @@ class chromium_applier(applier_frontend):
|
||||
self.sid = sid
|
||||
self.username = username
|
||||
self._is_machine_name = is_machine_name(self.username)
|
||||
self.chromium_keys = self.storage.filter_hklm_entries(self.__registry_branch)
|
||||
chromium_filter = '{}%'.format(self.__registry_branch)
|
||||
self.chromium_keys = self.storage.filter_hklm_entries(chromium_filter)
|
||||
|
||||
self.policies_json = dict()
|
||||
|
||||
@@ -121,11 +122,6 @@ class chromium_applier(applier_frontend):
|
||||
'ProxyServerMode',
|
||||
'ExtensionManifestV2Availability',
|
||||
'ExtensionUnpublishedAvailability',
|
||||
'CreateThemesSettings',
|
||||
'DevToolsGenAiSettings',
|
||||
'GenAILocalFoundationalModelSettings',
|
||||
'HelpMeWriteSettings',
|
||||
'TabOrganizerSettings',
|
||||
'BrowserSwitcherParsingMode',
|
||||
'CloudAPAuthEnabled',
|
||||
'AdsSettingForIntrusiveAdsSites',
|
||||
@@ -139,14 +135,10 @@ class chromium_applier(applier_frontend):
|
||||
'HeadlessMode',
|
||||
'IncognitoModeAvailability',
|
||||
'IntranetRedirectBehavior',
|
||||
'LensOverlaySettings',
|
||||
'MemorySaverModeSavings',
|
||||
'NetworkPredictionOptions',
|
||||
'ProfilePickerOnStartupAvailability',
|
||||
'ProfileReauthPrompt',
|
||||
'RelaunchNotification',
|
||||
'SafeSitesFilterBehavior',
|
||||
'ToolbarAvatarLabelSettings',
|
||||
'UserAgentReduction',
|
||||
'BatterySaverModeAvailability_recommended',
|
||||
'DownloadRestrictions_recommended',
|
||||
|
@@ -26,7 +26,7 @@ from .applier_frontend import (
|
||||
applier_frontend
|
||||
, check_enabled
|
||||
)
|
||||
from util.util import get_homedir, get_uid_by_username
|
||||
from util.util import get_homedir
|
||||
from util.logging import log
|
||||
|
||||
def storage_get_drives(storage, sid):
|
||||
@@ -152,24 +152,12 @@ class cifs_applier_user(applier_frontend):
|
||||
__template_auto = 'autofs_auto.j2'
|
||||
__template_mountpoints_hide = 'autofs_mountpoints_hide.j2'
|
||||
__template_auto_hide = 'autofs_auto_hide.j2'
|
||||
__enable_home_link = '/Software/BaseALT/Policies/GPUpdate/DriveMapsHome'
|
||||
__enable_home_link_user = '/Software/BaseALT/Policies/GPUpdate/DriveMapsHomeUser'
|
||||
__name_dir = '/Software/BaseALT/Policies/GPUpdate'
|
||||
__name_link_prefix = '/Software/BaseALT/Policies/GPUpdate/DriveMapsHomeDisableNet'
|
||||
__name_link_prefix_user = '/Software/BaseALT/Policies/GPUpdate/DriveMapsHomeDisableNetUser'
|
||||
__key_link_prefix = 'DriveMapsHomeDisableNet'
|
||||
__key_link_prefix_user = 'DriveMapsHomeDisableNetUser'
|
||||
__timeout_user_key = '/Software/BaseALT/Policies/GPUpdate/TimeoutAutofsUser'
|
||||
__timeout_key = '/Software/BaseALT/Policies/GPUpdate/TimeoutAutofs'
|
||||
__enable_home_link = 'Software\\BaseALT\\Policies\\GPUpdate\\DriveMapsHome'
|
||||
__enable_home_link_user = 'Software\\BaseALT\\Policies\\GPUpdate\\DriveMapsHomeUser'
|
||||
__target_mountpoint = '/media/gpupdate'
|
||||
__target_mountpoint_user = '/run/media'
|
||||
__mountpoint_dirname = 'drives.system'
|
||||
__mountpoint_dirname_user = 'drives'
|
||||
__key_cifs_previous_value = 'Previous/Software/BaseALT/Policies/GPUpdate'
|
||||
__key_preferences = 'Software/BaseALT/Policies/Preferences/'
|
||||
__key_preferences_previous = 'Previous/Software/BaseALT/Policies/Preferences/'
|
||||
__name_value = 'DriveMapsName'
|
||||
__name_value_user = 'DriveMapsNameUser'
|
||||
|
||||
def __init__(self, storage, sid, username):
|
||||
self.storage = storage
|
||||
@@ -177,43 +165,14 @@ class cifs_applier_user(applier_frontend):
|
||||
self.username = username
|
||||
self.state_home_link = False
|
||||
self.state_home_link_user = False
|
||||
self.dict_registry_machine = self.storage.get_dictionary_from_dconf_file_db()
|
||||
self.homedir = ''
|
||||
name_dir = self.__name_dir[1:]
|
||||
|
||||
if username:
|
||||
self.dict_registry_user = self.storage.get_dictionary_from_dconf_file_db(get_uid_by_username(username))
|
||||
self.home = self.__target_mountpoint_user + '/' + username
|
||||
self.state_home_link = self.storage.check_enable_key(self.__enable_home_link)
|
||||
self.state_home_link_disable_net = self.storage.check_enable_key(self.__name_link_prefix)
|
||||
self.state_home_link_disable_net_user = self.storage.check_enable_key(self.__name_link_prefix_user)
|
||||
|
||||
self.state_home_link_user = self.storage.check_enable_key(self.__enable_home_link_user)
|
||||
self.timeout = self.storage.get_entry(self.__timeout_user_key)
|
||||
dirname = self.storage.get_entry(self.__name_dir + '/' + self.__name_value_user)
|
||||
dirname_system_from_machine = self.dict_registry_machine.get(name_dir, dict()).get(self.__name_value, None)
|
||||
self.__mountpoint_dirname_user = dirname.data if dirname and dirname.data else self.__mountpoint_dirname_user
|
||||
self.__mountpoint_dirname = dirname_system_from_machine if dirname_system_from_machine else self.__mountpoint_dirname
|
||||
mntTarget = self.__mountpoint_dirname_user
|
||||
|
||||
self.keys_cifs_previous_values_user = self.dict_registry_user.get(self.__key_cifs_previous_value,dict())
|
||||
self.keys_cifs_values_user = self.dict_registry_user.get(name_dir,dict())
|
||||
self.keys_the_preferences_previous_values_user = self.dict_registry_user.get((self.__key_preferences_previous+self.username),dict()).get('Drives', dict())
|
||||
self.keys_the_preferences_values_user = self.dict_registry_user.get((self.__key_preferences+self.username),dict()).get('Drives', dict())
|
||||
|
||||
self.state_home_link = self.check_enable_home_link(self.__enable_home_link)
|
||||
self.state_home_link_user = self.check_enable_home_link(self.__enable_home_link_user)
|
||||
else:
|
||||
self.home = self.__target_mountpoint
|
||||
self.timeout = self.storage.get_entry(self.__timeout_key)
|
||||
dirname_system = self.storage.get_entry(self.__name_dir + '/' + self.__name_value)
|
||||
self.__mountpoint_dirname = dirname_system.data if dirname_system and dirname_system.data else self.__mountpoint_dirname
|
||||
mntTarget = self.__mountpoint_dirname
|
||||
|
||||
self.keys_cifs_previous_values_machine = self.dict_registry_machine.get(self.__key_cifs_previous_value,dict())
|
||||
self.keys_cifs_values_machine = self.dict_registry_machine.get(name_dir,dict())
|
||||
self.keys_the_preferences_previous_values = self.dict_registry_machine.get((self.__key_preferences_previous+'Machine'),dict()).get('Drives', dict())
|
||||
self.keys_the_preferences_values = self.dict_registry_machine.get((self.__key_preferences+'Machine'),dict()).get('Drives', dict())
|
||||
|
||||
self.mntTarget = mntTarget.translate(str.maketrans({" ": r"\ "}))
|
||||
conf_file = '{}.conf'.format(sid)
|
||||
conf_hide_file = '{}_hide.conf'.format(sid)
|
||||
autofs_file = '{}.autofs'.format(sid)
|
||||
@@ -236,6 +195,10 @@ class cifs_applier_user(applier_frontend):
|
||||
self.user_autofs_hide.unlink()
|
||||
self.user_creds = self.auto_master_d / cred_file
|
||||
|
||||
if username:
|
||||
self.mntTarget = self.__mountpoint_dirname_user
|
||||
else:
|
||||
self.mntTarget = self.__mountpoint_dirname
|
||||
|
||||
self.mount_dir = Path(os.path.join(self.home))
|
||||
self.drives = storage_get_drives(self.storage, self.sid)
|
||||
@@ -256,20 +219,12 @@ class cifs_applier_user(applier_frontend):
|
||||
, self.__module_experimental
|
||||
)
|
||||
|
||||
|
||||
def is_mount_point_dirname(self):
|
||||
if self.username:
|
||||
return self.mount_dir.joinpath(self.__mountpoint_dirname_user).is_mount()
|
||||
def check_enable_home_link(self, enable_home_link):
|
||||
if self.storage.get_hkcu_entry(self.sid, enable_home_link):
|
||||
data = self.storage.get_hkcu_entry(self.sid, enable_home_link).data
|
||||
return bool(int(data)) if data else None
|
||||
else:
|
||||
return self.mount_dir.joinpath(self.__mountpoint_dirname).is_mount()
|
||||
|
||||
def is_changed_keys(self):
|
||||
if self.username:
|
||||
return (self.keys_cifs_previous_values_user.get(self.__name_value_user) != self.keys_cifs_values_user.get(self.__name_value_user) or
|
||||
self.keys_the_preferences_previous_values_user != self.keys_the_preferences_values_user)
|
||||
else:
|
||||
return (self.keys_cifs_previous_values_machine.get(self.__name_value) != self.keys_cifs_values_machine.get(self.__name_value) or
|
||||
self.keys_the_preferences_previous_values != self.keys_the_preferences_values)
|
||||
return False
|
||||
|
||||
def user_context_apply(self):
|
||||
'''
|
||||
@@ -325,8 +280,6 @@ class cifs_applier_user(applier_frontend):
|
||||
autofs_settings['home_dir'] = self.home
|
||||
autofs_settings['mntTarget'] = self.mntTarget
|
||||
autofs_settings['mount_file'] = self.user_config.resolve()
|
||||
autofs_settings['timeout'] = self.timeout.data if self.timeout and self.timeout.data else 120
|
||||
|
||||
autofs_text = self.template_auto.render(**autofs_settings)
|
||||
|
||||
with open(self.user_autofs.resolve(), 'w') as f:
|
||||
@@ -341,111 +294,59 @@ class cifs_applier_user(applier_frontend):
|
||||
f.write(autofs_text)
|
||||
f.flush()
|
||||
|
||||
if self.is_changed_keys() or (self.drives and not self.is_mount_point_dirname()):
|
||||
self.restart_autofs()
|
||||
if self.username:
|
||||
self.update_drivemaps_home_links()
|
||||
|
||||
if self.username:
|
||||
self.update_drivemaps_home_links()
|
||||
|
||||
def restart_autofs(self):
|
||||
try:
|
||||
subprocess.check_call(['/bin/systemctl', 'restart', 'autofs'])
|
||||
except Exception as exc:
|
||||
log('E74', {'exc': exc})
|
||||
|
||||
|
||||
def unlink_symlink(self, symlink:Path, previous=None):
|
||||
try:
|
||||
if symlink.exists() and symlink.is_symlink() and symlink.owner() == 'root':
|
||||
symlink.unlink()
|
||||
elif symlink.is_symlink() and not symlink.exists():
|
||||
symlink.unlink()
|
||||
elif previous:
|
||||
symlink.unlink()
|
||||
except:
|
||||
pass
|
||||
|
||||
def del_previous_link(self, previous_value_link , mountpoint_dirname, prefix):
|
||||
d_previous = Path(self.homedir + ('/' if prefix else '/net.') + previous_value_link)
|
||||
if d_previous.name != mountpoint_dirname:
|
||||
dHide_previous = Path(self.homedir + ('/.' if prefix else '/.net.') + previous_value_link)
|
||||
self.unlink_symlink(d_previous, True)
|
||||
self.unlink_symlink(dHide_previous, True)
|
||||
|
||||
def update_drivemaps_home_links(self):
|
||||
if self.state_home_link_disable_net:
|
||||
prefix = ''
|
||||
else:
|
||||
prefix = 'net.'
|
||||
if self.state_home_link_disable_net_user:
|
||||
prefix_user = ''
|
||||
else:
|
||||
prefix_user = 'net.'
|
||||
|
||||
previous_value_link = self.keys_cifs_previous_values_machine.get(self.__name_value, self.__mountpoint_dirname)
|
||||
previous_state_home_link_disable_net_user = self.keys_cifs_previous_values_user.get(self.__key_link_prefix_user)
|
||||
previous_state_home_link_disable_net = self.keys_cifs_previous_values_user.get(self.__key_link_prefix)
|
||||
previous_value_link_user = self.keys_cifs_previous_values_user.get(self.__name_value_user, self.__mountpoint_dirname_user)
|
||||
|
||||
self.homedir = get_homedir(self.username)
|
||||
|
||||
dUser = Path(self.homedir + '/' + prefix_user + self.__mountpoint_dirname_user)
|
||||
dUserHide = Path(self.homedir + '/.' + prefix_user + self.__mountpoint_dirname_user)
|
||||
dMachine = Path(self.homedir+'/' + prefix + self.__mountpoint_dirname)
|
||||
dMachineHide = Path(self.homedir+'/.' + prefix + self.__mountpoint_dirname)
|
||||
dUser = Path(get_homedir(self.username)+'/net.' + self.__mountpoint_dirname_user)
|
||||
dUserHide = Path(get_homedir(self.username)+'/.net.' + self.__mountpoint_dirname_user)
|
||||
|
||||
if self.state_home_link_user:
|
||||
dUserMountpoint = Path(self.home).joinpath(self.__mountpoint_dirname_user)
|
||||
dUserMountpointHide = Path(self.home).joinpath('.' + self.__mountpoint_dirname_user)
|
||||
self.del_previous_link(previous_value_link_user, dUser.name, previous_state_home_link_disable_net_user)
|
||||
if not dUser.exists() and dUserMountpoint.exists():
|
||||
|
||||
if not dUser.exists():
|
||||
try:
|
||||
os.symlink(dUserMountpoint, dUser, True)
|
||||
except Exception as exc:
|
||||
log('D194', {'exc': exc})
|
||||
elif dUser.is_symlink() and not dUserMountpoint.exists():
|
||||
self.unlink_symlink(dUser)
|
||||
|
||||
if not dUserHide.exists() and dUserMountpointHide.exists():
|
||||
if not dUserHide.exists():
|
||||
try:
|
||||
os.symlink(dUserMountpointHide, dUserHide, True)
|
||||
except Exception as exc:
|
||||
log('D196', {'exc': exc})
|
||||
elif dUserHide.is_symlink() and not dUserMountpointHide.exists():
|
||||
self.unlink_symlink(dUserHide)
|
||||
else:
|
||||
self.del_previous_link(previous_value_link_user, dUser.name, previous_state_home_link_disable_net_user)
|
||||
self.unlink_symlink(dUser)
|
||||
self.unlink_symlink(dUserHide)
|
||||
if dUser.is_symlink() and dUser.owner() == 'root':
|
||||
dUser.unlink()
|
||||
if dUserHide.is_symlink() and dUserHide.owner() == 'root':
|
||||
dUserHide.unlink()
|
||||
|
||||
dMachine = Path(get_homedir(self.username)+'/net.' + self.__mountpoint_dirname)
|
||||
dMachineHide = Path(get_homedir(self.username)+'/.net.' + self.__mountpoint_dirname)
|
||||
|
||||
if self.state_home_link:
|
||||
dMachineMountpoint = Path(self.__target_mountpoint).joinpath(self.__mountpoint_dirname)
|
||||
dMachineMountpointHide = Path(self.__target_mountpoint).joinpath('.' + self.__mountpoint_dirname)
|
||||
self.del_previous_link(previous_value_link, dMachine.name, previous_state_home_link_disable_net)
|
||||
|
||||
if not dMachine.exists() and dMachineMountpoint.exists():
|
||||
if not dMachine.exists():
|
||||
try:
|
||||
os.symlink(dMachineMountpoint, dMachine, True)
|
||||
except Exception as exc:
|
||||
log('D195', {'exc': exc})
|
||||
elif dMachine.is_symlink() and not dMachineMountpoint.exists():
|
||||
self.unlink_symlink(dMachine)
|
||||
|
||||
if not dMachineHide.exists() and dMachineMountpointHide.exists():
|
||||
if not dMachineHide.exists():
|
||||
try:
|
||||
os.symlink(dMachineMountpointHide, dMachineHide, True)
|
||||
except Exception as exc:
|
||||
log('D197', {'exc': exc})
|
||||
elif dMachineHide.is_symlink() and not dMachineMountpointHide.exists():
|
||||
self.unlink_symlink(dMachineHide)
|
||||
else:
|
||||
self.del_previous_link(previous_value_link, dMachine.name, previous_state_home_link_disable_net)
|
||||
self.unlink_symlink(dMachine)
|
||||
self.unlink_symlink(dMachineHide)
|
||||
|
||||
|
||||
|
||||
if dMachine.is_symlink() and dMachine.owner() == 'root':
|
||||
dMachine.unlink()
|
||||
if dMachineHide.is_symlink() and dMachineHide.owner() == 'root':
|
||||
dMachineHide.unlink()
|
||||
|
||||
def admin_context_apply(self):
|
||||
if self.__module_enabled:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -21,8 +21,9 @@ from .applier_frontend import (
|
||||
, check_enabled
|
||||
)
|
||||
from .appliers.control import control
|
||||
from util.logging import log
|
||||
from util.logging import slogm, log
|
||||
|
||||
import logging
|
||||
|
||||
class control_applier(applier_frontend):
|
||||
__module_name = 'ControlApplier'
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -16,15 +16,19 @@
|
||||
# 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 logging
|
||||
import os
|
||||
import json
|
||||
|
||||
import cups
|
||||
|
||||
from .applier_frontend import (
|
||||
applier_frontend
|
||||
, check_enabled
|
||||
)
|
||||
from gpt.printers import json2printer
|
||||
from util.rpm import is_rpm_installed
|
||||
from util.logging import log
|
||||
from util.logging import slogm, log
|
||||
|
||||
def storage_get_printers(storage, sid):
|
||||
'''
|
||||
@@ -111,7 +115,7 @@ class cups_applier_user(applier_frontend):
|
||||
self.__module_enabled = check_enabled(
|
||||
self.storage
|
||||
, self.__module_name
|
||||
, self.__module_experimental
|
||||
, self.__module_enabled
|
||||
)
|
||||
|
||||
def user_context_apply(self):
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -21,8 +21,9 @@ from .applier_frontend import (
|
||||
, check_enabled
|
||||
)
|
||||
from .appliers.envvar import Envvar
|
||||
from util.logging import log
|
||||
from util.logging import slogm, log
|
||||
|
||||
import logging
|
||||
|
||||
class envvar_applier(applier_frontend):
|
||||
__module_name = 'EnvvarsApplier'
|
||||
@@ -33,8 +34,7 @@ class envvar_applier(applier_frontend):
|
||||
self.storage = storage
|
||||
self.sid = sid
|
||||
self.envvars = self.storage.get_envvars(self.sid)
|
||||
Envvar.clear_envvar_file()
|
||||
self.__module_enabled = check_enabled(self.storage, self.__module_name, self.__module_experimental)
|
||||
#self.__module_enabled = check_enabled(self.storage, self.__module_name, self.__module_enabled)
|
||||
|
||||
def apply(self):
|
||||
if self.__module_enabled:
|
||||
@@ -54,10 +54,12 @@ class envvar_applier_user(applier_frontend):
|
||||
self.sid = sid
|
||||
self.username = username
|
||||
self.envvars = self.storage.get_envvars(self.sid)
|
||||
Envvar.clear_envvar_file(username)
|
||||
self.__module_enabled = check_enabled(self.storage, self.__module_name, self.__module_experimental)
|
||||
#self.__module_enabled = check_enabled(self.storage, self.__module_name, self.__module_experimental)
|
||||
|
||||
def admin_context_apply(self):
|
||||
pass
|
||||
|
||||
def user_context_apply(self):
|
||||
if self.__module_enabled:
|
||||
log('D136')
|
||||
ev = Envvar(self.envvars, self.username)
|
||||
@@ -65,6 +67,3 @@ class envvar_applier_user(applier_frontend):
|
||||
else:
|
||||
log('D137')
|
||||
|
||||
def user_context_apply(self):
|
||||
pass
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -40,7 +40,8 @@ class firefox_applier(applier_frontend):
|
||||
__module_experimental = False
|
||||
__module_enabled = True
|
||||
__registry_branch = 'Software/Policies/Mozilla/Firefox'
|
||||
__firefox_policies = '/etc/firefox/policies'
|
||||
__firefox_installdir1 = '/usr/lib64/firefox/distribution'
|
||||
__firefox_installdir2 = '/etc/firefox/policies'
|
||||
|
||||
def __init__(self, storage, sid, username):
|
||||
self.storage = storage
|
||||
@@ -49,7 +50,8 @@ class firefox_applier(applier_frontend):
|
||||
self._is_machine_name = is_machine_name(self.username)
|
||||
self.policies = dict()
|
||||
self.policies_json = dict({ 'policies': self.policies })
|
||||
self.firefox_keys = self.storage.filter_hklm_entries(self.__registry_branch)
|
||||
firefox_filter = '{}%'.format(self.__registry_branch)
|
||||
self.firefox_keys = self.storage.filter_hklm_entries(firefox_filter)
|
||||
self.policies_gen = dict()
|
||||
self.__module_enabled = check_enabled(
|
||||
self.storage
|
||||
@@ -57,16 +59,88 @@ class firefox_applier(applier_frontend):
|
||||
, self.__module_experimental
|
||||
)
|
||||
|
||||
def get_boolean(self,data):
|
||||
if data in ['0', 'false', None, 'none', 0]:
|
||||
return False
|
||||
if data in ['1', 'true', 1]:
|
||||
return True
|
||||
|
||||
def get_parts(self, hivekeyname):
|
||||
'''
|
||||
Parse registry path string and leave key parameters
|
||||
'''
|
||||
parts = hivekeyname.replace(self.__registry_branch, '').split('/')
|
||||
return parts
|
||||
|
||||
def create_dict(self, firefox_keys):
|
||||
'''
|
||||
Collect dictionaries from registry keys into a general dictionary
|
||||
'''
|
||||
excp = ['SOCKSVersion']
|
||||
counts = dict()
|
||||
for it_data in firefox_keys:
|
||||
branch = counts
|
||||
try:
|
||||
if type(it_data.data) is bytes:
|
||||
it_data.data = it_data.data.decode(encoding='utf-16').replace('\x00','')
|
||||
json_data = try_dict_to_literal_eval(it_data.data)
|
||||
if json_data:
|
||||
it_data.data = json_data
|
||||
it_data.type = 7
|
||||
#Cases when it is necessary to create nested dictionaries
|
||||
if it_data.valuename != it_data.data:
|
||||
parts = self.get_parts(it_data.hive_key)
|
||||
#creating a nested dictionary from elements
|
||||
for part in parts[:-1]:
|
||||
branch = branch.setdefault(part, {})
|
||||
#dictionary key value initialization
|
||||
if it_data.type == 4:
|
||||
if it_data.valuename in excp:
|
||||
branch[parts[-1]] = int(it_data.data)
|
||||
else:
|
||||
branch[parts[-1]] = self.get_boolean(it_data.data)
|
||||
elif it_data.type == 7:
|
||||
branch[parts[-1]] = it_data.data
|
||||
else:
|
||||
branch[parts[-1]] = str(it_data.data).replace('\\', '/')
|
||||
#Cases when it is necessary to create lists in a dictionary
|
||||
else:
|
||||
parts = self.get_parts(it_data.keyname)
|
||||
for part in parts[:-1]:
|
||||
branch = branch.setdefault(part, {})
|
||||
if branch.get(parts[-1]) is None:
|
||||
branch[parts[-1]] = list()
|
||||
if it_data.type == 4:
|
||||
branch[parts[-1]].append(self.get_boolean(it_data.data))
|
||||
else:
|
||||
if os.path.isdir(str(it_data.data).replace('\\', '/')):
|
||||
branch[parts[-1]].append(str(it_data.data).replace('\\', '/'))
|
||||
else:
|
||||
branch[parts[-1]].append(str(it_data.data))
|
||||
except Exception as exc:
|
||||
logdata = dict()
|
||||
logdata['Exception'] = exc
|
||||
logdata['keyname'] = it_data.keyname
|
||||
log('W14', logdata)
|
||||
|
||||
self.policies_json = {'policies': dict_item_to_list(counts)}
|
||||
|
||||
def machine_apply(self):
|
||||
'''
|
||||
Write policies.json to Firefox.
|
||||
Write policies.json to Firefox installdir.
|
||||
'''
|
||||
excp = ['SOCKSVersion']
|
||||
self.policies_json = create_dict(self.firefox_keys, self.__registry_branch, excp)
|
||||
self.create_dict(self.firefox_keys)
|
||||
destfile = os.path.join(self.__firefox_installdir1, 'policies.json')
|
||||
|
||||
destfile = os.path.join(self.__firefox_policies, 'policies.json')
|
||||
os.makedirs(self.__firefox_policies, exist_ok=True)
|
||||
os.makedirs(self.__firefox_installdir1, exist_ok=True)
|
||||
with open(destfile, 'w') as f:
|
||||
json.dump(self.policies_json, f)
|
||||
logdata = dict()
|
||||
logdata['destfile'] = destfile
|
||||
log('D91', logdata)
|
||||
|
||||
destfile = os.path.join(self.__firefox_installdir2, 'policies.json')
|
||||
os.makedirs(self.__firefox_installdir2, exist_ok=True)
|
||||
with open(destfile, 'w') as f:
|
||||
json.dump(self.policies_json, f)
|
||||
logdata = dict()
|
||||
@@ -106,65 +180,3 @@ def dict_item_to_list(dictionary:dict) -> dict:
|
||||
else:
|
||||
dict_item_to_list(dictionary[key])
|
||||
return dictionary
|
||||
|
||||
def clean_data_firefox(data):
|
||||
return data.replace("'", '\"')
|
||||
|
||||
|
||||
|
||||
def create_dict(firefox_keys, registry_branch, excp=list()):
|
||||
'''
|
||||
Collect dictionaries from registry keys into a general dictionary
|
||||
'''
|
||||
get_boolean = lambda data: data in ['1', 'true', 'True', True, 1] if isinstance(data, (str, int)) else False
|
||||
get_parts = lambda hivekey, registry: hivekey.replace(registry, '').split('/')
|
||||
counts = dict()
|
||||
for it_data in firefox_keys:
|
||||
branch = counts
|
||||
try:
|
||||
if type(it_data.data) is bytes:
|
||||
it_data.data = it_data.data.decode(encoding='utf-16').replace('\x00','')
|
||||
json_data = try_dict_to_literal_eval(it_data.data)
|
||||
if json_data:
|
||||
it_data.data = json_data
|
||||
it_data.type = 7
|
||||
else:
|
||||
if it_data.type == 1:
|
||||
it_data.data = clean_data_firefox(it_data.data)
|
||||
#Cases when it is necessary to create nested dictionaries
|
||||
if it_data.valuename != it_data.data:
|
||||
parts = get_parts(it_data.hive_key, registry_branch)
|
||||
#creating a nested dictionary from elements
|
||||
for part in parts[:-1]:
|
||||
branch = branch.setdefault(part, {})
|
||||
#dictionary key value initialization
|
||||
if it_data.type == 4:
|
||||
if it_data.valuename in excp:
|
||||
branch[parts[-1]] = int(it_data.data)
|
||||
else:
|
||||
branch[parts[-1]] = get_boolean(it_data.data)
|
||||
elif it_data.type == 7:
|
||||
branch[parts[-1]] = it_data.data
|
||||
else:
|
||||
branch[parts[-1]] = str(it_data.data).replace('\\', '/')
|
||||
#Cases when it is necessary to create lists in a dictionary
|
||||
else:
|
||||
parts = get_parts(it_data.keyname, registry_branch)
|
||||
for part in parts[:-1]:
|
||||
branch = branch.setdefault(part, {})
|
||||
if branch.get(parts[-1]) is None:
|
||||
branch[parts[-1]] = list()
|
||||
if it_data.type == 4:
|
||||
branch[parts[-1]].append(get_boolean(it_data.data))
|
||||
else:
|
||||
if os.path.isdir(str(it_data.data).replace('\\', '/')):
|
||||
branch[parts[-1]].append(str(it_data.data).replace('\\', '/'))
|
||||
else:
|
||||
branch[parts[-1]].append(str(it_data.data))
|
||||
except Exception as exc:
|
||||
logdata = dict()
|
||||
logdata['Exception'] = exc
|
||||
logdata['keyname'] = it_data.keyname
|
||||
log('W14', logdata)
|
||||
|
||||
return {'policies': dict_item_to_list(counts)}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -17,9 +17,10 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import logging
|
||||
import subprocess
|
||||
|
||||
from util.logging import log
|
||||
from util.logging import slogm, log
|
||||
from .applier_frontend import (
|
||||
applier_frontend
|
||||
, check_enabled
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from .applier_frontend import (
|
||||
applier_frontend
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -26,7 +26,6 @@ from .polkit_applier import (
|
||||
)
|
||||
from .systemd_applier import systemd_applier
|
||||
from .firefox_applier import firefox_applier
|
||||
from .thunderbird_applier import thunderbird_applier
|
||||
from .chromium_applier import chromium_applier
|
||||
from .cups_applier import cups_applier
|
||||
from .package_applier import (
|
||||
@@ -148,7 +147,6 @@ class frontend_manager:
|
||||
self.machine_appliers['polkit'] = polkit_applier(self.storage)
|
||||
self.machine_appliers['systemd'] = systemd_applier(self.storage)
|
||||
self.machine_appliers['firefox'] = firefox_applier(self.storage, self.sid, self.username)
|
||||
self.machine_appliers['thunderbird'] = thunderbird_applier(self.storage, self.sid, self.username)
|
||||
self.machine_appliers['chromium'] = chromium_applier(self.storage, self.sid, self.username)
|
||||
self.machine_appliers['yandex_browser'] = yandex_browser_applier(self.storage, self.sid, self.username)
|
||||
self.machine_appliers['shortcuts'] = shortcut_applier(self.storage)
|
||||
@@ -163,6 +161,7 @@ class frontend_manager:
|
||||
self.machine_appliers['cups'] = cups_applier(self.storage)
|
||||
self.machine_appliers['firewall'] = firewall_applier(self.storage)
|
||||
self.machine_appliers['folders'] = folder_applier(self.storage, self.sid)
|
||||
self.machine_appliers['package'] = package_applier(self.storage)
|
||||
self.machine_appliers['ntp'] = ntp_applier(self.storage)
|
||||
self.machine_appliers['envvar'] = envvar_applier(self.storage, self.sid)
|
||||
self.machine_appliers['networkshare'] = networkshare_applier(self.storage, self.sid)
|
||||
@@ -170,7 +169,6 @@ class frontend_manager:
|
||||
self.machine_appliers['files'] = file_applier(self.storage, self.file_cache, self.sid)
|
||||
self.machine_appliers['ini'] = ini_applier(self.storage, self.sid)
|
||||
self.machine_appliers['kde'] = kde_applier(self.storage)
|
||||
self.machine_appliers['package'] = package_applier(self.storage)
|
||||
|
||||
def _init_user_appliers(self):
|
||||
# User appliers are expected to work with user-writable
|
||||
@@ -185,6 +183,7 @@ class frontend_manager:
|
||||
logdata['applier_name'] = 'cifs'
|
||||
logdata['msg'] = str(exc)
|
||||
log('E25', logdata)
|
||||
self.user_appliers['package'] = package_applier_user(self.storage, self.sid, self.username)
|
||||
self.user_appliers['polkit'] = polkit_applier_user(self.storage, self.sid, self.username)
|
||||
self.user_appliers['envvar'] = envvar_applier_user(self.storage, self.sid, self.username)
|
||||
self.user_appliers['networkshare'] = networkshare_applier(self.storage, self.sid, self.username)
|
||||
@@ -192,7 +191,6 @@ class frontend_manager:
|
||||
self.user_appliers['files'] = file_applier_user(self.storage, self.file_cache, self.sid, self.username)
|
||||
self.user_appliers['ini'] = ini_applier_user(self.storage, self.sid, self.username)
|
||||
self.user_appliers['kde'] = kde_applier_user(self.storage, self.sid, self.username, self.file_cache)
|
||||
self.user_appliers['package'] = package_applier_user(self.storage, self.sid, self.username)
|
||||
|
||||
def machine_apply(self):
|
||||
'''
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2021 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -21,8 +21,10 @@ import os
|
||||
import pwd
|
||||
import subprocess
|
||||
|
||||
from gi.repository import Gio
|
||||
from storage.dconf_registry import Dconf_registry
|
||||
from gi.repository import (
|
||||
Gio
|
||||
, GLib
|
||||
)
|
||||
|
||||
from .applier_frontend import (
|
||||
applier_frontend
|
||||
@@ -33,7 +35,7 @@ from .appliers.gsettings import (
|
||||
system_gsettings,
|
||||
user_gsettings
|
||||
)
|
||||
from util.logging import log
|
||||
from util.logging import slogm ,log
|
||||
|
||||
def uri_fetch(schema, path, value, cache):
|
||||
'''
|
||||
@@ -46,8 +48,6 @@ def uri_fetch(schema, path, value, cache):
|
||||
logdata['src'] = value
|
||||
try:
|
||||
retval = cache.get(value)
|
||||
if not retval:
|
||||
retval = ''
|
||||
logdata['dst'] = retval
|
||||
log('D90', logdata)
|
||||
except Exception as exc:
|
||||
@@ -137,7 +137,10 @@ class gsettings_applier(applier_frontend):
|
||||
log('E48')
|
||||
|
||||
# Update desktop configuration system backend
|
||||
Dconf_registry.dconf_update()
|
||||
try:
|
||||
proc = subprocess.run(args=['/usr/bin/dconf', "update"], capture_output=True, check=True)
|
||||
except Exception as exc:
|
||||
log('E49')
|
||||
|
||||
def apply(self):
|
||||
if self.__module_enabled:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2022 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from .appliers.ini_file import Ini_file
|
||||
from .applier_frontend import (
|
||||
|
@@ -24,14 +24,13 @@ import os
|
||||
import subprocess
|
||||
import re
|
||||
import dbus
|
||||
import shutil
|
||||
|
||||
class kde_applier(applier_frontend):
|
||||
__module_name = 'KdeApplier'
|
||||
__module_experimental = True
|
||||
__module_enabled = False
|
||||
__hklm_branch = 'Software/BaseALT/Policies/KDE/'
|
||||
__hklm_lock_branch = 'Software/BaseALT/Policies/KDELocks/'
|
||||
__hklm_branch = 'Software\\BaseALT\\Policies\\KDE\\'
|
||||
__hklm_lock_branch = 'Software\\BaseALT\\Policies\\KDELocks\\'
|
||||
|
||||
def __init__(self, storage):
|
||||
self.storage = storage
|
||||
@@ -62,10 +61,8 @@ class kde_applier_user(applier_frontend):
|
||||
__module_name = 'KdeApplierUser'
|
||||
__module_experimental = True
|
||||
__module_enabled = False
|
||||
kde_version = None
|
||||
__hkcu_branch = 'Software/BaseALT/Policies/KDE'
|
||||
__hkcu_lock_branch = 'Software/BaseALT/Policies/KDELocks'
|
||||
__plasma_update_entry = 'Software/BaseALT/Policies/KDE/Plasma/Update'
|
||||
__hkcu_branch = 'Software\\BaseALT\\Policies\\KDE\\'
|
||||
__hkcu_lock_branch = 'Software\\BaseALT\\Policies\\KDELocks\\'
|
||||
|
||||
def __init__(self, storage, sid=None, username=None, file_cache = None):
|
||||
self.storage = storage
|
||||
@@ -75,12 +72,9 @@ class kde_applier_user(applier_frontend):
|
||||
self.locks_dict = {}
|
||||
self.locks_data_dict = {}
|
||||
self.all_kde_settings = {}
|
||||
kde_applier_user.kde_version = get_kde_version()
|
||||
kde_filter = '{}%'.format(self.__hkcu_branch)
|
||||
locks_filter = '{}%'.format(self.__hkcu_lock_branch)
|
||||
self.locks_settings = self.storage.filter_hkcu_entries(self.sid, locks_filter)
|
||||
self.plasma_update = self.storage.get_entry(self.__plasma_update_entry)
|
||||
self.plasma_update_flag = self.plasma_update.data if self.plasma_update is not None else 0
|
||||
self.kde_settings = self.storage.filter_hkcu_entries(self.sid, kde_filter)
|
||||
self.__module_enabled = check_enabled(
|
||||
self.storage,
|
||||
@@ -89,16 +83,7 @@ class kde_applier_user(applier_frontend):
|
||||
)
|
||||
|
||||
def admin_context_apply(self):
|
||||
try:
|
||||
for setting in self.kde_settings:
|
||||
file_name = setting.keyname.split("/")[-2]
|
||||
if file_name == 'wallpaper':
|
||||
data = setting.data
|
||||
break
|
||||
self.file_cache.store(data)
|
||||
except Exception as exc:
|
||||
logdata = dict()
|
||||
logdata['exc'] = exc
|
||||
pass
|
||||
|
||||
def user_context_apply(self):
|
||||
'''
|
||||
@@ -106,43 +91,12 @@ class kde_applier_user(applier_frontend):
|
||||
'''
|
||||
if self.__module_enabled:
|
||||
log('D200')
|
||||
create_dict(self.kde_settings, self.all_kde_settings, self.locks_settings, self.locks_dict, self.file_cache, self.username, self.plasma_update_flag)
|
||||
create_dict(self.kde_settings, self.all_kde_settings, self.locks_settings, self.locks_dict, self.file_cache, self.username)
|
||||
apply(self.all_kde_settings, self.locks_dict, self.username)
|
||||
else:
|
||||
log('D201')
|
||||
|
||||
dbus_methods_mapping = {
|
||||
'kscreenlockerrc': {
|
||||
'dbus_service': 'org.kde.screensaver',
|
||||
'dbus_path': '/ScreenSaver',
|
||||
'dbus_interface': 'org.kde.screensaver',
|
||||
'dbus_method': 'configure'
|
||||
},
|
||||
'wallpaper': {
|
||||
'dbus_service': 'org.freedesktop.systemd1',
|
||||
'dbus_path': '/org/freedesktop/systemd1',
|
||||
'dbus_interface': 'org.freedesktop.systemd1.Manager',
|
||||
'dbus_method': 'RestartUnit',
|
||||
'dbus_args': ['plasma-plasmashell.service', 'replace']
|
||||
}
|
||||
}
|
||||
|
||||
def get_kde_version():
|
||||
try:
|
||||
kinfo_path = shutil.which("kinfo", path="/usr/lib/kf5/bin:/usr/bin")
|
||||
if not kinfo_path:
|
||||
raise FileNotFoundError("Unable to find kinfo")
|
||||
output = subprocess.check_output([kinfo_path], text=True, env={'LANG':'C'})
|
||||
for line in output.splitlines():
|
||||
if "KDE Frameworks Version" in line:
|
||||
frameworks_version = line.split(":", 1)[1].strip()
|
||||
major_frameworks_version = int(frameworks_version.split(".")[0])
|
||||
return major_frameworks_version
|
||||
except Exception as exc:
|
||||
raise exc
|
||||
|
||||
|
||||
def create_dict(kde_settings, all_kde_settings, locks_settings, locks_dict, file_cache = None, username = None, plasmaupdate = False):
|
||||
def create_dict(kde_settings, all_kde_settings, locks_settings, locks_dict, file_cache = None, username = None):
|
||||
for locks in locks_settings:
|
||||
locks_dict[locks.valuename] = locks.data
|
||||
for setting in kde_settings:
|
||||
@@ -150,9 +104,14 @@ def create_dict(kde_settings, all_kde_settings, locks_settings, locks_dict, file
|
||||
file_name, section, value = setting.keyname.split("/")[-2], setting.keyname.split("/")[-1], setting.valuename
|
||||
data = setting.data
|
||||
if file_name == 'wallpaper':
|
||||
apply_for_wallpaper(data, file_cache, username, plasmaupdate)
|
||||
apply_for_wallpaper(data, file_cache, username)
|
||||
else:
|
||||
all_kde_settings.setdefault(file_name, {}).setdefault(section, {})[value] = data
|
||||
if file_name not in all_kde_settings:
|
||||
all_kde_settings[file_name] = {}
|
||||
if section not in all_kde_settings[file_name]:
|
||||
all_kde_settings[file_name][section] = {}
|
||||
all_kde_settings[file_name][section][value] = data
|
||||
|
||||
except Exception as exc:
|
||||
logdata = dict()
|
||||
logdata['file_name'] = file_name
|
||||
@@ -164,7 +123,6 @@ def create_dict(kde_settings, all_kde_settings, locks_settings, locks_dict, file
|
||||
|
||||
def apply(all_kde_settings, locks_dict, username = None):
|
||||
logdata = dict()
|
||||
modified_files = set()
|
||||
if username is None:
|
||||
system_path_settings = '/etc/xdg/'
|
||||
system_files = [
|
||||
@@ -190,12 +148,11 @@ def apply(all_kde_settings, locks_dict, username = None):
|
||||
file.write(f'[{section}]\n')
|
||||
for key, value in keys.items():
|
||||
lock = f"{file_name}.{section}.{key}".replace('][', ')(')
|
||||
if locks_dict.get(lock) == 1:
|
||||
if lock in locks_dict and locks_dict[lock] == 1:
|
||||
file.write(f'{key}[$i]={value}\n')
|
||||
else:
|
||||
file.write(f'{key}={value}\n')
|
||||
file.write('\n')
|
||||
modified_files.add(file_name)
|
||||
else:
|
||||
for file_name, sections in all_kde_settings.items():
|
||||
path = f'{get_homedir(username)}/.config/{file_name}'
|
||||
@@ -205,11 +162,10 @@ def apply(all_kde_settings, locks_dict, username = None):
|
||||
pass
|
||||
for section, keys in sections.items():
|
||||
for key, value in keys.items():
|
||||
value = str(value)
|
||||
lock = f"{file_name}.{section}.{key}"
|
||||
if lock in locks_dict and locks_dict[lock] == 1:
|
||||
command = [
|
||||
f'kwriteconfig{kde_applier_user.kde_version}',
|
||||
'kwriteconfig5',
|
||||
'--file', file_name,
|
||||
'--group', section,
|
||||
'--key', key +'/$i/',
|
||||
@@ -218,7 +174,7 @@ def apply(all_kde_settings, locks_dict, username = None):
|
||||
]
|
||||
else:
|
||||
command = [
|
||||
f'kwriteconfig{kde_applier_user.kde_version}',
|
||||
'kwriteconfig5',
|
||||
'--file', file_name,
|
||||
'--group', section,
|
||||
'--key', key,
|
||||
@@ -227,9 +183,7 @@ def apply(all_kde_settings, locks_dict, username = None):
|
||||
]
|
||||
try:
|
||||
clear_locks_settings(username, file_name, key)
|
||||
env_path = dict(os.environ)
|
||||
env_path["PATH"] = "/usr/lib/kf5/bin:/usr/bin"
|
||||
subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env_path)
|
||||
subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except:
|
||||
logdata['command'] = command
|
||||
log('W22', logdata)
|
||||
@@ -247,9 +201,6 @@ def apply(all_kde_settings, locks_dict, username = None):
|
||||
except Exception as exc:
|
||||
logdata['exc'] = exc
|
||||
log('W19', logdata)
|
||||
modified_files.add(file_name)
|
||||
for file_name in modified_files:
|
||||
call_dbus_method(file_name)
|
||||
|
||||
def clear_locks_settings(username, file_name, key):
|
||||
'''
|
||||
@@ -268,60 +219,52 @@ def clear_locks_settings(username, file_name, key):
|
||||
logdata['line'] = line.strip()
|
||||
log('I10', logdata)
|
||||
|
||||
def apply_for_wallpaper(data, file_cache, username, plasmaupdate):
|
||||
def apply_for_wallpaper(data, file_cache, username):
|
||||
'''
|
||||
Method to change wallpaper
|
||||
'''
|
||||
logdata = dict()
|
||||
path_to_wallpaper = f'{get_homedir(username)}/.config/plasma-org.kde.plasma.desktop-appletsrc'
|
||||
id_desktop = get_id_desktop(path_to_wallpaper)
|
||||
try:
|
||||
try:
|
||||
data = str(file_cache.get(data))
|
||||
file_cache.store(data)
|
||||
data = file_cache.get(data)
|
||||
except NotUNCPathError:
|
||||
data = str(data)
|
||||
|
||||
with open(path_to_wallpaper, 'r') as file:
|
||||
current_wallpaper = file.read()
|
||||
match = re.search(rf'\[Containments\]\[{id_desktop}\]\[Wallpaper\]\[org\.kde\.image\]\[General\]\s+Image=(.*)', current_wallpaper)
|
||||
if match:
|
||||
current_wallpaper_path = match.group(1)
|
||||
flag = (current_wallpaper_path == data)
|
||||
else:
|
||||
flag = False
|
||||
|
||||
os.environ["LANGUAGE"] = os.environ["LANG"].split(".")[0]
|
||||
data = data
|
||||
os.environ["XDG_DATA_DIRS"] = "/usr/share/kf5:"
|
||||
#Variable for system detection of directories before files with .colors extension
|
||||
os.environ["DISPLAY"] = ":0"
|
||||
#Variable for command execution plasma-apply-colorscheme
|
||||
os.environ["XDG_RUNTIME_DIR"] = f"/run/user/{os.getuid()}"
|
||||
os.environ["PATH"] = "/usr/lib/kf5/bin:"
|
||||
os.environ["DBUS_SESSION_BUS_ADDRESS"] = f"unix:path=/run/user/{os.getuid()}/bus"#plasma-apply-wallpaperimage
|
||||
env_path = dict(os.environ)
|
||||
env_path["PATH"] = "/usr/lib/kf5/bin:/usr/bin"
|
||||
os.environ["PATH"] = "/usr/lib/kf5/bin:"
|
||||
#environment variable for accessing binary files without hard links
|
||||
if not flag:
|
||||
if os.path.isfile(path_to_wallpaper):
|
||||
command = [
|
||||
f'kwriteconfig{kde_applier_user.kde_version}',
|
||||
'--file', 'plasma-org.kde.plasma.desktop-appletsrc',
|
||||
'--group', 'Containments',
|
||||
'--group', id_desktop,
|
||||
'--group', 'Wallpaper',
|
||||
'--group', 'org.kde.image',
|
||||
'--group', 'General',
|
||||
'--key', 'Image',
|
||||
'--type', 'string',
|
||||
data
|
||||
]
|
||||
try:
|
||||
subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env_path)
|
||||
except:
|
||||
logdata['command'] = command
|
||||
log('E68', logdata)
|
||||
if plasmaupdate == 1:
|
||||
call_dbus_method("wallpaper")
|
||||
if os.path.isfile(path_to_wallpaper):
|
||||
id_desktop = get_id_desktop(path_to_wallpaper)
|
||||
command = [
|
||||
'kwriteconfig5',
|
||||
'--file', 'plasma-org.kde.plasma.desktop-appletsrc',
|
||||
'--group', 'Containments',
|
||||
'--group', id_desktop,
|
||||
'--group', 'Wallpaper',
|
||||
'--group', 'org.kde.image',
|
||||
'--group', 'General',
|
||||
'--key', 'Image',
|
||||
'--type', 'string',
|
||||
data
|
||||
]
|
||||
try:
|
||||
subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except:
|
||||
logdata['command'] = command
|
||||
log('E68', logdata)
|
||||
try:
|
||||
session_bus = dbus.SessionBus()
|
||||
plasma_shell = session_bus.get_object('org.kde.plasmashell', '/PlasmaShell', introspect='org.kde.PlasmaShell')
|
||||
plasma_shell_iface = dbus.Interface(plasma_shell, 'org.kde.PlasmaShell')
|
||||
plasma_shell_iface.refreshCurrentShell()
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
logdata['file'] = path_to_wallpaper
|
||||
log('W21', logdata)
|
||||
@@ -341,27 +284,9 @@ def get_id_desktop(path_to_wallpaper):
|
||||
with open(path_to_wallpaper, 'r') as file:
|
||||
file_content = file.read()
|
||||
match = re.search(pattern, file_content)
|
||||
return match.group(1) if match else None
|
||||
if match:
|
||||
return match.group(1)
|
||||
else:
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
||||
def call_dbus_method(file_name):
|
||||
'''
|
||||
Method to call D-Bus method based on the file name
|
||||
'''
|
||||
os.environ["DBUS_SESSION_BUS_ADDRESS"] = f"unix:path=/run/user/{os.getuid()}/bus"
|
||||
if file_name in dbus_methods_mapping:
|
||||
config = dbus_methods_mapping[file_name]
|
||||
try:
|
||||
session_bus = dbus.SessionBus()
|
||||
dbus_object = session_bus.get_object(config['dbus_service'], config['dbus_path'])
|
||||
dbus_iface = dbus.Interface(dbus_object, config['dbus_interface'])
|
||||
if 'dbus_args' in config:
|
||||
getattr(dbus_iface, config['dbus_method'])(*config['dbus_args'])
|
||||
else:
|
||||
getattr(dbus_iface, config['dbus_method'])()
|
||||
except dbus.exceptions.DBusException as e:
|
||||
logdata = dict({'error': str(exc)})
|
||||
log('E31', logdata)
|
||||
else:
|
||||
pass
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
import logging
|
||||
import subprocess
|
||||
from util.logging import log
|
||||
from util.logging import slogm, log
|
||||
from util.rpm import (
|
||||
update
|
||||
, install_rpm
|
||||
, remove_rpm
|
||||
)
|
||||
|
||||
from .applier_frontend import (
|
||||
applier_frontend
|
||||
|
@@ -95,6 +95,7 @@ class scripts_applier_user(applier_frontend):
|
||||
, self.__module_name
|
||||
, self.__module_experimental
|
||||
)
|
||||
self.filling_cache()
|
||||
|
||||
def cleaning_cache(self):
|
||||
log('D161')
|
||||
@@ -142,9 +143,7 @@ def install_script(storage_script_entry, script_dir, access_permissions):
|
||||
'''
|
||||
dir_cr = Path(script_dir)
|
||||
dir_cr.mkdir(parents=True, exist_ok=True)
|
||||
if storage_script_entry.number is None:
|
||||
return
|
||||
script_name = str(storage_script_entry.number).zfill(5) + '_' + os.path.basename(storage_script_entry.path)
|
||||
script_name = str(int(storage_script_entry.number)).zfill(5) + '_' + os.path.basename(storage_script_entry.path)
|
||||
script_file = os.path.join(script_dir, script_name)
|
||||
shutil.copyfile(storage_script_entry.path, script_file)
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -16,14 +16,16 @@
|
||||
# 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 logging
|
||||
import subprocess
|
||||
|
||||
from .applier_frontend import (
|
||||
applier_frontend
|
||||
, check_enabled
|
||||
)
|
||||
from gpt.shortcuts import json2sc
|
||||
from util.windows import expand_windows_var
|
||||
from util.logging import log
|
||||
from util.logging import slogm, log
|
||||
from util.util import (
|
||||
get_homedir,
|
||||
homedir_exists
|
||||
@@ -139,7 +141,6 @@ class shortcut_applier_user(applier_frontend):
|
||||
self.storage = storage
|
||||
self.sid = sid
|
||||
self.username = username
|
||||
self.__module_enabled = check_enabled(self.storage, self.__module_name, self.__module_experimental)
|
||||
|
||||
def run(self, in_usercontext):
|
||||
shortcuts = storage_get_shortcuts(self.storage, self.sid, self.username)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -21,8 +21,9 @@ from .applier_frontend import (
|
||||
, check_enabled
|
||||
)
|
||||
from .appliers.systemd import systemd_unit
|
||||
from util.logging import log
|
||||
from util.logging import slogm, log
|
||||
|
||||
import logging
|
||||
|
||||
class systemd_applier(applier_frontend):
|
||||
__module_name = 'SystemdApplier'
|
||||
@@ -42,14 +43,15 @@ class systemd_applier(applier_frontend):
|
||||
|
||||
def run(self):
|
||||
for setting in self.systemd_unit_settings:
|
||||
valuename = setting.hive_key.rpartition('/')[2]
|
||||
try:
|
||||
self.units.append(systemd_unit(setting.valuename, int(setting.data)))
|
||||
self.units.append(systemd_unit(valuename, int(setting.data)))
|
||||
logdata = dict()
|
||||
logdata['unit'] = format(setting.valuename)
|
||||
logdata['unit'] = format(valuename)
|
||||
log('I4', logdata)
|
||||
except Exception as exc:
|
||||
logdata = dict()
|
||||
logdata['unit'] = format(setting.valuename)
|
||||
logdata['unit'] = format(valuename)
|
||||
logdata['exc'] = exc
|
||||
log('I5', logdata)
|
||||
for unit in self.units:
|
||||
|
@@ -1,70 +0,0 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2024 BaseALT Ltd.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
from .applier_frontend import (
|
||||
applier_frontend
|
||||
, check_enabled
|
||||
)
|
||||
from util.logging import log
|
||||
from util.util import is_machine_name
|
||||
from .firefox_applier import create_dict
|
||||
|
||||
class thunderbird_applier(applier_frontend):
|
||||
__module_name = 'ThunderbirdApplier'
|
||||
__module_experimental = False
|
||||
__module_enabled = True
|
||||
__registry_branch = 'Software/Policies/Mozilla/Thunderbird'
|
||||
__thunderbird_policies = '/etc/thunderbird/policies'
|
||||
|
||||
def __init__(self, storage, sid, username):
|
||||
self.storage = storage
|
||||
self.sid = sid
|
||||
self.username = username
|
||||
self._is_machine_name = is_machine_name(self.username)
|
||||
self.policies = dict()
|
||||
self.policies_json = dict({ 'policies': self.policies })
|
||||
self.thunderbird_keys = self.storage.filter_hklm_entries(self.__registry_branch)
|
||||
self.policies_gen = dict()
|
||||
self.__module_enabled = check_enabled(
|
||||
self.storage
|
||||
, self.__module_name
|
||||
, self.__module_experimental
|
||||
)
|
||||
|
||||
|
||||
def machine_apply(self):
|
||||
'''
|
||||
Write policies.json to Thunderbird.
|
||||
'''
|
||||
self.policies_json = create_dict(self.thunderbird_keys, self.__registry_branch)
|
||||
|
||||
destfile = os.path.join(self.__thunderbird_policies, 'policies.json')
|
||||
os.makedirs(self.__thunderbird_policies, exist_ok=True)
|
||||
with open(destfile, 'w') as f:
|
||||
json.dump(self.policies_json, f)
|
||||
logdata = dict()
|
||||
logdata['destfile'] = destfile
|
||||
log('D212', logdata)
|
||||
|
||||
def apply(self):
|
||||
if self.__module_enabled:
|
||||
log('D213')
|
||||
self.machine_apply()
|
||||
else:
|
||||
log('D214')
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2022 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -39,7 +39,8 @@ class yandex_browser_applier(applier_frontend):
|
||||
self.sid = sid
|
||||
self.username = username
|
||||
self._is_machine_name = is_machine_name(self.username)
|
||||
self.yandex_keys = self.storage.filter_hklm_entries(self.__registry_branch)
|
||||
yandex_filter = '{}%'.format(self.__registry_branch)
|
||||
self.yandex_keys = self.storage.filter_hklm_entries(yandex_filter)
|
||||
|
||||
self.policies_json = dict()
|
||||
|
||||
|
@@ -27,7 +27,6 @@ from backend import backend_factory, save_dconf
|
||||
from frontend.frontend_manager import frontend_manager, determine_username
|
||||
from plugin import plugin_manager
|
||||
from messages import message_with_code
|
||||
from storage import Dconf_registry
|
||||
|
||||
from util.util import get_machine_name
|
||||
from util.users import (
|
||||
@@ -62,9 +61,6 @@ def parse_arguments():
|
||||
arguments.add_argument('--list-backends',
|
||||
action='store_true',
|
||||
help='Show list of available backends')
|
||||
arguments.add_argument('--force',
|
||||
action='store_true',
|
||||
help='Force GPT download')
|
||||
arguments.add_argument('--loglevel',
|
||||
type=int,
|
||||
default=4,
|
||||
@@ -124,7 +120,6 @@ class gpoa_controller:
|
||||
print('local')
|
||||
print('samba')
|
||||
return
|
||||
Dconf_registry._force = self.__args.force
|
||||
self.start_plugins()
|
||||
self.start_backend()
|
||||
|
||||
@@ -154,7 +149,6 @@ class gpoa_controller:
|
||||
back.retrieve_and_store()
|
||||
# Start frontend only on successful backend finish
|
||||
self.start_frontend()
|
||||
save_dconf(self.username, self.is_machine, nodomain)
|
||||
except Exception as exc:
|
||||
logdata = dict({'message': str(exc)})
|
||||
# In case we're handling "E3" - it means that
|
||||
@@ -165,6 +159,7 @@ class gpoa_controller:
|
||||
einfo = geterr()
|
||||
logdata.update(einfo)
|
||||
log('E3', logdata)
|
||||
save_dconf(self.username, self.is_machine)
|
||||
|
||||
def start_frontend(self):
|
||||
'''
|
||||
|
@@ -19,7 +19,7 @@
|
||||
import json
|
||||
from base64 import b64decode
|
||||
from Crypto.Cipher import AES
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
|
||||
from util.xml import get_xml_root
|
||||
|
||||
def decrypt_pass(cpassword):
|
||||
@@ -93,7 +93,7 @@ def json2drive(json_str):
|
||||
|
||||
return drive_obj
|
||||
|
||||
class drivemap(DynamicAttributes):
|
||||
class drivemap:
|
||||
def __init__(self):
|
||||
self.login = None
|
||||
self.password = None
|
||||
|
@@ -1,50 +0,0 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
#
|
||||
# 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/>.
|
||||
from enum import Enum
|
||||
|
||||
class DynamicAttributes:
|
||||
def __init__(self, **kwargs):
|
||||
self.policy_name = None
|
||||
for key, value in kwargs.items():
|
||||
self.__setattr__(key, value)
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if isinstance(value, Enum):
|
||||
value = str(value)
|
||||
if isinstance(value, str):
|
||||
for q in ["'", "\""]:
|
||||
if any(q in ch for ch in value):
|
||||
value = value.replace(q, "″")
|
||||
self.__dict__[key] = value
|
||||
|
||||
def items(self):
|
||||
return self.__dict__.items()
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.__dict__.items())
|
||||
|
||||
class RegistryKeyMetadata(DynamicAttributes):
|
||||
def __init__(self, policy_name, type, is_list=None, mod_previous_value=None):
|
||||
self.policy_name = policy_name
|
||||
self.type = type
|
||||
self.reloaded_with_policy_key = None
|
||||
self.is_list = is_list
|
||||
self.mod_previous_value = mod_previous_value
|
||||
|
||||
def __repr__(self):
|
||||
return str(dict(self))
|
@@ -17,8 +17,24 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from util.xml import get_xml_root
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
|
||||
from enum import Enum
|
||||
|
||||
class FileAction(Enum):
|
||||
CREATE = 'C'
|
||||
REPLACE = 'R'
|
||||
UPDATE = 'U'
|
||||
DELETE = 'D'
|
||||
|
||||
|
||||
def action_letter2enum(letter):
|
||||
if letter in ['C', 'R', 'U', 'D']:
|
||||
if letter == 'C': return FileAction.CREATE
|
||||
if letter == 'R': return FileAction.REPLACE
|
||||
if letter == 'U': return FileAction.UPDATE
|
||||
if letter == 'D': return FileAction.DELETE
|
||||
|
||||
return FileAction.CREATE
|
||||
|
||||
def read_envvars(envvars_file):
|
||||
variables = list()
|
||||
@@ -27,8 +43,8 @@ def read_envvars(envvars_file):
|
||||
props = var.find('Properties')
|
||||
name = props.get('name')
|
||||
value = props.get('value')
|
||||
action = props.get('action', default='C')
|
||||
var_obj = envvar(name, value, action)
|
||||
var_obj = envvar(name, value)
|
||||
var_obj.set_action(action_letter2enum(props.get('action', default='C')))
|
||||
|
||||
variables.append(var_obj)
|
||||
|
||||
@@ -38,9 +54,12 @@ def merge_envvars(storage, sid, envvar_objects, policy_name):
|
||||
for envv in envvar_objects:
|
||||
storage.add_envvar(sid, envv, policy_name)
|
||||
|
||||
class envvar(DynamicAttributes):
|
||||
def __init__(self, name, value, action):
|
||||
class envvar:
|
||||
def __init__(self, name, value):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.action = FileAction.CREATE
|
||||
|
||||
def set_action(self, action):
|
||||
self.action = action
|
||||
|
||||
|
@@ -17,7 +17,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from util.xml import get_xml_root
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
|
||||
def read_files(filesxml):
|
||||
files = list()
|
||||
@@ -40,7 +39,7 @@ def merge_files(storage, sid, file_objects, policy_name):
|
||||
for fileobj in file_objects:
|
||||
storage.add_file(sid, fileobj, policy_name)
|
||||
|
||||
class fileentry(DynamicAttributes):
|
||||
class fileentry:
|
||||
def __init__(self, fromPath):
|
||||
self.fromPath = fromPath
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -17,11 +17,28 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
from enum import Enum
|
||||
|
||||
|
||||
from util.xml import get_xml_root
|
||||
|
||||
|
||||
class FileAction(Enum):
|
||||
CREATE = 'C'
|
||||
REPLACE = 'R'
|
||||
UPDATE = 'U'
|
||||
DELETE = 'D'
|
||||
|
||||
|
||||
def action_letter2enum(letter):
|
||||
if letter in ['C', 'R', 'U', 'D']:
|
||||
if letter == 'C': return FileAction.CREATE
|
||||
if letter == 'R': return FileAction.REPLACE
|
||||
if letter == 'U': return FileAction.UPDATE
|
||||
if letter == 'D': return FileAction.DELETE
|
||||
|
||||
return FileAction.CREATE
|
||||
|
||||
|
||||
def action_enum2letter(enumitem):
|
||||
return enumitem.value
|
||||
@@ -44,9 +61,8 @@ def read_folders(folders_file):
|
||||
|
||||
for fld in get_xml_root(folders_file):
|
||||
props = fld.find('Properties')
|
||||
path = props.get('path')
|
||||
action = props.get('action', default='C')
|
||||
fld_obj = folderentry(path, action)
|
||||
fld_obj = folderentry(props.get('path'))
|
||||
fld_obj.set_action(action_letter2enum(props.get('action', default='C')))
|
||||
fld_obj.set_delete_folder(folder_int2bool(props.get('deleteFolder', default=1)))
|
||||
fld_obj.set_delete_sub_folders(folder_int2bool(props.get('deleteSubFolders', default=1)))
|
||||
fld_obj.set_delete_files(folder_int2bool(props.get('deleteFiles', default=1)))
|
||||
@@ -62,10 +78,10 @@ def merge_folders(storage, sid, folder_objects, policy_name):
|
||||
storage.add_folder(sid, folder, policy_name)
|
||||
|
||||
|
||||
class folderentry(DynamicAttributes):
|
||||
def __init__(self, path, action):
|
||||
class folderentry:
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self.action = action
|
||||
self.action = FileAction.CREATE
|
||||
self.delete_folder = False
|
||||
self.delete_sub_folders = False
|
||||
self.delete_files = False
|
||||
|
@@ -1,48 +0,0 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
|
||||
class GpoInfoDconf(DynamicAttributes):
|
||||
_counter = 0
|
||||
def __init__(self, gpo) -> None:
|
||||
GpoInfoDconf._counter += 1
|
||||
self.counter = GpoInfoDconf._counter
|
||||
self.display_name = None
|
||||
self.name = None
|
||||
self.version = None
|
||||
self.link = None
|
||||
self._fill_attributes(gpo)
|
||||
|
||||
def _fill_attributes(self, gpo):
|
||||
try:
|
||||
self.display_name = gpo.display_name
|
||||
except:
|
||||
self.display_name = "Unknown"
|
||||
try:
|
||||
self.name = gpo.name
|
||||
except:
|
||||
self.name = "Unknown"
|
||||
try:
|
||||
self.version = gpo.version
|
||||
except:
|
||||
self.version = "Unknown"
|
||||
try:
|
||||
self.link = gpo.link
|
||||
except:
|
||||
self.link = "Unknown"
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -23,7 +23,6 @@ from enum import Enum, unique
|
||||
from samba.gp_parse.gp_pol import GPPolParser
|
||||
|
||||
from storage import registry_factory
|
||||
from storage.dconf_registry import add_to_dict
|
||||
|
||||
from .polfile import (
|
||||
read_polfile
|
||||
@@ -154,14 +153,13 @@ def get_merger(preference_type):
|
||||
return mergers[preference_type]
|
||||
|
||||
class gpt:
|
||||
def __init__(self, gpt_path, sid, username='Machine', gpo_info=None):
|
||||
add_to_dict(gpt_path, username, gpo_info)
|
||||
def __init__(self, gpt_path, sid, username='Machine', version=None):
|
||||
self.path = gpt_path
|
||||
self.username = username
|
||||
self.sid = sid
|
||||
self.storage = registry_factory()
|
||||
self.storage._gpt_read_flag = True
|
||||
self.gpo_info = gpo_info
|
||||
self.version = version
|
||||
self.name = ''
|
||||
self.guid = self.path.rpartition('/')[2]
|
||||
if 'default' == self.guid:
|
||||
@@ -219,7 +217,7 @@ class gpt:
|
||||
if self.settings['machine']['regpol']:
|
||||
mlogdata = dict({'polfile': self.settings['machine']['regpol']})
|
||||
log('D34', mlogdata)
|
||||
util.preg.merge_polfile(self.settings['machine']['regpol'], policy_name=self.name, gpo_info=self.gpo_info)
|
||||
util.preg.merge_polfile(self.settings['machine']['regpol'], policy_name=self.name, version=self.version)
|
||||
# Merge machine preferences to registry if possible
|
||||
for preference_name, preference_path in self.settings['machine'].items():
|
||||
if preference_path:
|
||||
@@ -249,7 +247,7 @@ class gpt:
|
||||
sid=self.sid,
|
||||
policy_name=self.name,
|
||||
username=self.username,
|
||||
gpo_info=self.gpo_info)
|
||||
version=self.version)
|
||||
# Merge user preferences to registry if possible
|
||||
for preference_name, preference_path in self.settings['user'].items():
|
||||
if preference_path:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2022 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -17,7 +17,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from util.xml import get_xml_root
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
|
||||
def read_inifiles(inifiles_file):
|
||||
inifiles = list()
|
||||
@@ -28,7 +27,7 @@ def read_inifiles(inifiles_file):
|
||||
ini_obj.set_section(prors.get('section', default=None))
|
||||
ini_obj.set_property(prors.get('property', default=None))
|
||||
ini_obj.set_value(prors.get('value', default=None))
|
||||
ini_obj.set_action(prors.get('action', default='C'))
|
||||
ini_obj.set_action(prors.get('action'))
|
||||
|
||||
inifiles.append(ini_obj)
|
||||
|
||||
@@ -38,7 +37,7 @@ def merge_inifiles(storage, sid, inifile_objects, policy_name):
|
||||
for iniobj in inifile_objects:
|
||||
storage.add_ini(sid, iniobj, policy_name)
|
||||
|
||||
class inifile(DynamicAttributes):
|
||||
class inifile:
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2022 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -17,7 +17,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from util.xml import get_xml_root
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
from storage.dconf_registry import Dconf_registry
|
||||
|
||||
def read_networkshares(networksharesxml):
|
||||
networkshares = list()
|
||||
@@ -39,7 +39,7 @@ def merge_networkshares(storage, sid, networkshares_objects, policy_name):
|
||||
for networkshareobj in networkshares_objects:
|
||||
storage.add_networkshare(sid, networkshareobj, policy_name)
|
||||
|
||||
class networkshare(DynamicAttributes):
|
||||
class networkshare:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -17,7 +17,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import json
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
|
||||
from util.xml import get_xml_root
|
||||
|
||||
@@ -61,7 +60,7 @@ def json2printer(json_str):
|
||||
|
||||
return prn
|
||||
|
||||
class printer(DynamicAttributes):
|
||||
class printer:
|
||||
def __init__(self, ptype, name, status):
|
||||
'''
|
||||
ptype may be one of:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
import configparser
|
||||
import os
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
|
||||
|
||||
def read_scripts(scripts_file):
|
||||
scripts = Scripts_lists()
|
||||
@@ -115,7 +115,7 @@ class Scripts_lists:
|
||||
self.get_shutdown_scripts().append(script)
|
||||
|
||||
|
||||
class Script(DynamicAttributes):
|
||||
class Script:
|
||||
__logon_counter = 0
|
||||
__logoff_counter = 0
|
||||
__startup_counter = 0
|
||||
@@ -126,7 +126,6 @@ class Script(DynamicAttributes):
|
||||
self.action = action_upper
|
||||
self.path = os.path.join(script_dir, action_upper, script_filename.upper())
|
||||
if not os.path.isfile(self.path):
|
||||
self.number = None
|
||||
return None
|
||||
self.args = None
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -17,7 +17,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from util.xml import get_xml_root
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
|
||||
def read_services(service_file):
|
||||
'''
|
||||
@@ -44,7 +43,7 @@ def merge_services(storage, sid, service_objects, policy_name):
|
||||
for srv in service_objects:
|
||||
pass
|
||||
|
||||
class service(DynamicAttributes):
|
||||
class service:
|
||||
def __init__(self, name):
|
||||
self.unit = name
|
||||
self.servname = None
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -18,23 +18,21 @@
|
||||
|
||||
from pathlib import Path
|
||||
import stat
|
||||
import logging
|
||||
from enum import Enum
|
||||
|
||||
from xml.etree import ElementTree
|
||||
from xdg.DesktopEntry import DesktopEntry
|
||||
import json
|
||||
|
||||
from util.windows import transform_windows_path
|
||||
from util.xml import get_xml_root
|
||||
from util.paths import get_desktop_files_directory
|
||||
from .dynamic_attributes import DynamicAttributes
|
||||
|
||||
class TargetType(Enum):
|
||||
FILESYSTEM = 'FILESYSTEM'
|
||||
URL = 'URL'
|
||||
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
def get_ttype(targetstr):
|
||||
'''
|
||||
Validation function for targetType property
|
||||
@@ -45,7 +43,7 @@ def get_ttype(targetstr):
|
||||
'''
|
||||
ttype = TargetType.FILESYSTEM
|
||||
|
||||
if targetstr == 'URL'or targetstr == TargetType.URL:
|
||||
if targetstr == 'URL':
|
||||
ttype = TargetType.URL
|
||||
|
||||
return ttype
|
||||
@@ -99,6 +97,24 @@ def merge_shortcuts(storage, sid, shortcut_objects, policy_name):
|
||||
for shortcut in shortcut_objects:
|
||||
storage.add_shortcut(sid, shortcut, policy_name)
|
||||
|
||||
def json2sc(json_str):
|
||||
'''
|
||||
Build shortcut out of string-serialized JSON
|
||||
'''
|
||||
json_obj = json.loads(json_str)
|
||||
link_type = get_ttype(json_obj['type'])
|
||||
|
||||
sc = shortcut(json_obj['dest'], json_obj['path'], json_obj['arguments'], json_obj['name'], json_obj['action'], link_type)
|
||||
sc.set_changed(json_obj['changed'])
|
||||
sc.set_clsid(json_obj['clsid'])
|
||||
sc.set_guid(json_obj['guid'])
|
||||
sc.set_usercontext(json_obj['is_in_user_context'])
|
||||
if 'comment' in json_obj:
|
||||
sc.set_comment(json_obj['comment'])
|
||||
if 'icon' in json_obj:
|
||||
sc.set_icon(json_obj['icon'])
|
||||
|
||||
return sc
|
||||
|
||||
def find_desktop_entry(binary_path):
|
||||
desktop_dir = get_desktop_files_directory()
|
||||
@@ -113,7 +129,7 @@ def find_desktop_entry(binary_path):
|
||||
return None
|
||||
|
||||
|
||||
class shortcut(DynamicAttributes):
|
||||
class shortcut:
|
||||
def __init__(self, dest, path, arguments, name=None, action=None, ttype=TargetType.FILESYSTEM):
|
||||
'''
|
||||
:param dest: Path to resulting file on file system
|
||||
@@ -201,6 +217,30 @@ class shortcut(DynamicAttributes):
|
||||
def is_usercontext(self):
|
||||
return self.is_in_user_context
|
||||
|
||||
def to_json(self):
|
||||
'''
|
||||
Return shortcut's JSON for further serialization.
|
||||
'''
|
||||
content = dict()
|
||||
content['dest'] = self.dest
|
||||
content['path'] = self.path
|
||||
content['name'] = self.name
|
||||
content['arguments'] = self.arguments
|
||||
content['clsid'] = self.clsid
|
||||
content['guid'] = self.guid
|
||||
content['changed'] = self.changed
|
||||
content['action'] = self.action
|
||||
content['is_in_user_context'] = self.is_in_user_context
|
||||
content['type'] = ttype2str(self.type)
|
||||
if self.icon:
|
||||
content['icon'] = self.icon
|
||||
if self.comment:
|
||||
content['comment'] = self.comment
|
||||
result = self.desktop()
|
||||
result.content.update(content)
|
||||
|
||||
return json.dumps(result.content)
|
||||
|
||||
def desktop(self, dest=None):
|
||||
'''
|
||||
Returns desktop file object which may be written to disk.
|
||||
@@ -220,7 +260,7 @@ class shortcut(DynamicAttributes):
|
||||
'''
|
||||
Update desktop file object from internal data.
|
||||
'''
|
||||
if get_ttype(self.type) == TargetType.URL:
|
||||
if self.type == TargetType.URL:
|
||||
self.desktop_file.set('Type', 'Link')
|
||||
else:
|
||||
self.desktop_file.set('Type', 'Application')
|
||||
@@ -230,7 +270,7 @@ class shortcut(DynamicAttributes):
|
||||
desktop_path = self.path
|
||||
if self.expanded_path:
|
||||
desktop_path = self.expanded_path
|
||||
if get_ttype(self.type) == TargetType.URL:
|
||||
if self.type == TargetType.URL:
|
||||
self.desktop_file.set('URL', desktop_path)
|
||||
else:
|
||||
str2bool_lambda = (lambda boolstr: boolstr if isinstance(boolstr, bool)
|
||||
|
@@ -25,7 +25,6 @@ import os
|
||||
import sys
|
||||
import pwd
|
||||
import signal
|
||||
from storage import Dconf_registry
|
||||
|
||||
from util.users import (
|
||||
is_root
|
||||
@@ -84,11 +83,6 @@ def parse_cli_arguments():
|
||||
type=int,
|
||||
default=5,
|
||||
help='Set logging verbosity level')
|
||||
argparser.add_argument('-f',
|
||||
'--force',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Force GPT download')
|
||||
argparser.add_argument('-s',
|
||||
'--system',
|
||||
action='store_true',
|
||||
@@ -171,7 +165,6 @@ def main():
|
||||
gettext.bindtextdomain('gpoa', '/usr/lib/python3/site-packages/gpoa/locale')
|
||||
gettext.textdomain('gpoa')
|
||||
set_loglevel(args.loglevel)
|
||||
Dconf_registry._force = args.force
|
||||
gpo_appliers = runner_factory(args, process_target(args.target))
|
||||
|
||||
if gpo_appliers:
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -19,7 +19,9 @@
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import subprocess
|
||||
|
||||
from util.util import (
|
||||
runcmd
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -65,10 +65,6 @@ msgstr "Установка свойств для пользователя"
|
||||
msgid "The line in the configuration file was cleared"
|
||||
msgstr "В конфигурационном файле была очищена строка"
|
||||
|
||||
msgid "Found GPT in cache"
|
||||
msgstr "Найден GPT в кеше"
|
||||
|
||||
|
||||
# Error
|
||||
msgid "Insufficient permissions to run gpupdate"
|
||||
msgstr "Недостаточно прав для запуска gpupdate"
|
||||
@@ -256,12 +252,6 @@ msgstr "Не удалось обновить базу данных dconf"
|
||||
msgid "Exception occurred while updating dconf database"
|
||||
msgstr "Возникло исключение при обновлении базы данных dconf"
|
||||
|
||||
msgid "Failed to retrieve data from dconf database"
|
||||
msgstr "Не удалось получить данные из базы dconf"
|
||||
|
||||
msgid "Autofs restart failed"
|
||||
msgstr "Перезапуск Autofs не удался"
|
||||
|
||||
# Error_end
|
||||
|
||||
# Debug
|
||||
@@ -637,11 +627,11 @@ msgstr "Запуск применение настроек Envvar для маш
|
||||
msgid "Envvar applier for machine will not be started"
|
||||
msgstr "Применение настроек Envvar для машины не запускается"
|
||||
|
||||
msgid "Running Envvar applier for user in admin context"
|
||||
msgstr "Запуск применение настроек Envvar для пользователя в контексте администратора"
|
||||
msgid "Running Envvar applier for user in user context"
|
||||
msgstr "Запуск применение настроек Envvar для пользователя в контексте пользователя"
|
||||
|
||||
msgid "Envvar applier for user in admin context will not be started"
|
||||
msgstr "Применение настроек Envvar для пользователя в контексте администратора не запускается"
|
||||
msgid "Envvar applier for user in user context will not be started"
|
||||
msgstr "Применение настроек Envvar для пользователя в контексте пользователя не запускается"
|
||||
|
||||
msgid "Running Package applier for machine"
|
||||
msgstr "Запуск установки пакетов для машины"
|
||||
@@ -880,27 +870,6 @@ msgstr "Создание ini-файла с политиками для dconf"
|
||||
msgid "GPO version was not found"
|
||||
msgstr "Версия GPO не найдена"
|
||||
|
||||
msgid "SYSVOL entry found in cache"
|
||||
msgstr "Запись SYSVOL найдена в кеше"
|
||||
|
||||
msgid "Wrote Thunderbird preferences to"
|
||||
msgstr "Настройки Thunderbird записаны в"
|
||||
|
||||
msgid "Running Thunderbird applier for machine"
|
||||
msgstr "Запуск применение настроек Thunderbird для машины"
|
||||
|
||||
msgid "Thunderbird applier for machine will not be started"
|
||||
msgstr "Применение настроек Thunderbird для компьютера не запускается"
|
||||
|
||||
msgid "The environment file has been cleaned"
|
||||
msgstr "Файл environment очищен"
|
||||
|
||||
msgid "Cleanup of file environment failed"
|
||||
msgstr "Очистка файла environment не удалась"
|
||||
|
||||
msgid "Failed to get dictionary"
|
||||
msgstr "Не удалось получить словарь"
|
||||
|
||||
# Debug_end
|
||||
|
||||
# Warning
|
||||
@@ -953,8 +922,8 @@ msgstr "Не удалось скопировать файл"
|
||||
msgid "Failed to create KDE settings list"
|
||||
msgstr "Не удалось создать список настроек KDE"
|
||||
|
||||
msgid "Could not find tools to configure KDE"
|
||||
msgstr "Не удалось найти инструменты для настройки KDE"
|
||||
msgid "Could not find application tools"
|
||||
msgstr "Не удалось найти инструменты применения"
|
||||
|
||||
msgid "Failed to open KDE settings"
|
||||
msgstr "Не удалось открыть настройки KDE"
|
||||
@@ -977,12 +946,6 @@ msgstr "Не удалось выполнить действие для INI-фа
|
||||
msgid "Couldn't get the uid"
|
||||
msgstr "Не удалось получить uid"
|
||||
|
||||
msgid "Failed to load content from remote host"
|
||||
msgstr "Не удалось загрузить контент с удаленного узла"
|
||||
|
||||
msgid "Force mode activated"
|
||||
msgstr "Режим force задействован"
|
||||
|
||||
# Fatal
|
||||
msgid "Unable to refresh GPO list"
|
||||
msgstr "Невозможно обновить список объектов групповых политик"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -31,7 +31,6 @@ def info_code(code):
|
||||
info_ids[8] = 'Chromium policy'
|
||||
info_ids[9] = 'Set user property to'
|
||||
info_ids[10] = 'The line in the configuration file was cleared'
|
||||
info_ids[11] = 'Found GPT in cache'
|
||||
|
||||
return info_ids.get(code, 'Unknown info code')
|
||||
|
||||
@@ -108,8 +107,6 @@ def error_code(code):
|
||||
error_ids[70] = 'Error getting key value'
|
||||
error_ids[71] = 'Failed to update dconf database'
|
||||
error_ids[72] = 'Exception occurred while updating dconf database'
|
||||
error_ids[73] = 'Failed to retrieve data from dconf database'
|
||||
error_ids[74] = 'Autofs restart failed'
|
||||
return error_ids.get(code, 'Unknown error code')
|
||||
|
||||
def debug_code(code):
|
||||
@@ -249,8 +246,8 @@ def debug_code(code):
|
||||
debug_ids[133] = 'NTP applier for machine will not be started'
|
||||
debug_ids[134] = 'Running Envvar applier for machine'
|
||||
debug_ids[135] = 'Envvar applier for machine will not be started'
|
||||
debug_ids[136] = 'Running Envvar applier for user in admin context'
|
||||
debug_ids[137] = 'Envvar applier for user in admin context will not be started'
|
||||
debug_ids[136] = 'Running Envvar applier for user in user context'
|
||||
debug_ids[137] = 'Envvar applier for user in user context will not be started'
|
||||
debug_ids[138] = 'Running Package applier for machine'
|
||||
debug_ids[139] = 'Package applier for machine will not be started'
|
||||
debug_ids[140] = 'Running Package applier for user in administrator context'
|
||||
@@ -323,13 +320,7 @@ def debug_code(code):
|
||||
debug_ids[207] = 'Creating a dictionary with keys and values from the dconf database'
|
||||
debug_ids[208] = 'No entry found for the specified path'
|
||||
debug_ids[209] = 'Creating an ini file with policies for dconf'
|
||||
debug_ids[211] = 'SYSVOL entry found in cache'
|
||||
debug_ids[212] = 'Wrote Thunderbird preferences to'
|
||||
debug_ids[213] = 'Running Thunderbird applier for machine'
|
||||
debug_ids[214] = 'Thunderbird applier for machine will not be started'
|
||||
debug_ids[215] = 'The environment file has been cleaned'
|
||||
debug_ids[216] = 'Cleanup of file environment failed'
|
||||
debug_ids[217] = 'Failed to get dictionary'
|
||||
debug_ids[210] = 'GPO version was not found'
|
||||
|
||||
return debug_ids.get(code, 'Unknown debug code')
|
||||
|
||||
@@ -357,7 +348,7 @@ def warning_code(code):
|
||||
warning_ids[14] = 'Could not create a valid list of keys'
|
||||
warning_ids[15] = 'Failed to copy file'
|
||||
warning_ids[16] = 'Failed to create KDE settings list'
|
||||
warning_ids[17] = 'Could not find tools to configure KDE'
|
||||
warning_ids[17] = 'Could not find application tools'
|
||||
warning_ids[18] = 'Failed to open KDE settings'
|
||||
warning_ids[19] = 'Failed to change KDE configuration file'
|
||||
warning_ids[20] = 'Error connecting to server'
|
||||
@@ -365,8 +356,7 @@ def warning_code(code):
|
||||
warning_ids[22] = 'The user setting was not installed, conflict with computer setting'
|
||||
warning_ids[23] = 'Action for ini file failed'
|
||||
warning_ids[24] = 'Couldn\'t get the uid'
|
||||
warning_ids[25] = 'Failed to load content from remote host'
|
||||
warning_ids[26] = 'Force mode activated'
|
||||
|
||||
|
||||
return warning_ids.get(code, 'Unknown warning code')
|
||||
|
||||
|
@@ -20,13 +20,15 @@
|
||||
import rpm
|
||||
import subprocess
|
||||
from gpoa.storage import registry_factory
|
||||
from util.gpoa_ini_parsing import GpoaConfigObj
|
||||
from util.util import get_uid_by_username, string_to_literal_eval
|
||||
import logging
|
||||
from util.logging import log
|
||||
import argparse
|
||||
import gettext
|
||||
import locale
|
||||
from messages import message_with_code
|
||||
from util.arguments import (
|
||||
set_loglevel
|
||||
)
|
||||
|
||||
|
||||
def is_rpm_installed(rpm_name):
|
||||
@@ -43,32 +45,28 @@ def is_rpm_installed(rpm_name):
|
||||
class Pkcon_applier:
|
||||
|
||||
def __init__(self, user = None):
|
||||
install_key_name = 'Install'
|
||||
remove_key_name = 'Remove'
|
||||
hklm_branch = 'Software/BaseALT/Policies/Packages'
|
||||
self.__install_key_name = 'Install'
|
||||
self.__remove_key_name = 'Remove'
|
||||
self.__hklm_branch = '/Software/BaseALT/Policies/Packages'
|
||||
self.__install_command = ['/usr/bin/pkcon', '-y', 'install']
|
||||
self.__remove_command = ['/usr/bin/pkcon', '-y', 'remove']
|
||||
self.__reinstall_command = ['/usr/bin/pkcon', '-y', 'reinstall']
|
||||
self.install_packages = set()
|
||||
self.remove_packages = set()
|
||||
self.storage = registry_factory()
|
||||
if user:
|
||||
uid = get_uid_by_username(user)
|
||||
dict_dconf_db = self.storage.get_dictionary_from_dconf_file_db(uid)
|
||||
else:
|
||||
dict_dconf_db = self.storage.get_dictionary_from_dconf_file_db()
|
||||
dict_packages = dict_dconf_db.get(hklm_branch,{})
|
||||
self.install_packages_setting = string_to_literal_eval(dict_packages.get(install_key_name,[]))
|
||||
self.remove_packages_setting = string_to_literal_eval(dict_packages.get(remove_key_name,[]))
|
||||
|
||||
self.storage = registry_factory(username=user)
|
||||
self.storage.filling_storage_from_dconf()
|
||||
install_branch = '{}/{}'.format(self.__hklm_branch, self.__install_key_name)
|
||||
remove_branch = '{}/{}'.format(self.__hklm_branch, self.__remove_key_name)
|
||||
self.install_packages_setting = self.storage.filter_hklm_entries(install_branch)
|
||||
self.remove_packages_setting = self.storage.filter_hklm_entries(remove_branch)
|
||||
for package in self.install_packages_setting:
|
||||
if not is_rpm_installed(package):
|
||||
self.install_packages.add(package)
|
||||
if not is_rpm_installed(package.data):
|
||||
self.install_packages.add(package.data)
|
||||
for package in self.remove_packages_setting:
|
||||
if package in self.install_packages:
|
||||
self.install_packages.remove(package)
|
||||
if is_rpm_installed(package):
|
||||
self.remove_packages.add(package)
|
||||
if package.data in self.install_packages:
|
||||
self.install_packages.remove(package.data)
|
||||
if is_rpm_installed(package.data):
|
||||
self.remove_packages.add(package.data)
|
||||
|
||||
def apply(self):
|
||||
log('D142')
|
||||
|
@@ -35,6 +35,6 @@ class plugin_manager:
|
||||
logging.warning(slogm(str(exc)))
|
||||
|
||||
def run(self):
|
||||
#self.plugins.get('adp', plugin('adp')).run()
|
||||
self.plugins.get('adp', plugin('adp')).run()
|
||||
self.plugins.get('roles', plugin('roles')).run()
|
||||
|
||||
|
@@ -18,22 +18,9 @@
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from util.util import (string_to_literal_eval,
|
||||
try_dict_to_literal_eval,
|
||||
touch_file, get_uid_by_username,
|
||||
add_prefix_to_keys,
|
||||
remove_keys_with_prefix,
|
||||
clean_data)
|
||||
from util.paths import get_dconf_config_path
|
||||
from util.util import string_to_literal_eval, touch_file, get_uid_by_username
|
||||
from util.logging import log
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
import itertools
|
||||
from gpt.dynamic_attributes import RegistryKeyMetadata
|
||||
import gi
|
||||
gi.require_version("Gvdb", "1.0")
|
||||
gi.require_version("GLib", "2.0")
|
||||
from gi.repository import Gvdb, GLib
|
||||
|
||||
|
||||
class PregDconf():
|
||||
@@ -62,27 +49,19 @@ class Dconf_registry():
|
||||
'''
|
||||
A class variable that represents a global registry dictionary shared among instances of the class
|
||||
'''
|
||||
_GpoPriority = 'Software/BaseALT/Policies/GpoPriority'
|
||||
_gpo_name = set()
|
||||
global_registry_dict = dict({_GpoPriority:{}})
|
||||
previous_global_registry_dict = dict()
|
||||
_ReadQueue = 'Software/BaseALT/Policies/ReadQueue'
|
||||
global_registry_dict = dict({_ReadQueue:{}})
|
||||
__template_file = '/usr/share/dconf/user_mandatory.template'
|
||||
_policies_path = 'Software/'
|
||||
_policies_win_path = 'SOFTWARE/'
|
||||
_gpt_read_flag = False
|
||||
_force = False
|
||||
__dconf_dict_flag = False
|
||||
__dconf_dict = dict()
|
||||
_dconf_db = dict()
|
||||
_dict_gpo_name_version_cache = dict()
|
||||
_username = None
|
||||
_uid = None
|
||||
_envprofile = None
|
||||
_path_bin_system = "/etc/dconf/db/policy"
|
||||
|
||||
list_keys = list()
|
||||
_info = dict()
|
||||
_counter_gpt = itertools.count(0)
|
||||
|
||||
shortcuts = list()
|
||||
folders = list()
|
||||
@@ -96,18 +75,7 @@ class Dconf_registry():
|
||||
scripts = list()
|
||||
networkshares = list()
|
||||
|
||||
_true_strings = {
|
||||
"True",
|
||||
"true",
|
||||
"TRUE",
|
||||
"yes",
|
||||
"Yes",
|
||||
"enabled",
|
||||
"enable",
|
||||
"Enabled",
|
||||
"Enable",
|
||||
'1'
|
||||
}
|
||||
|
||||
|
||||
@classmethod
|
||||
def set_info(cls, key , data):
|
||||
@@ -118,9 +86,6 @@ class Dconf_registry():
|
||||
def get_info(cls, key):
|
||||
return cls._info.setdefault(key, None)
|
||||
|
||||
@staticmethod
|
||||
def get_next_number():
|
||||
return next(Dconf_registry._counter_gpt)
|
||||
|
||||
@staticmethod
|
||||
def get_matching_keys(path):
|
||||
@@ -175,12 +140,10 @@ class Dconf_registry():
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def dconf_update(uid=None):
|
||||
def dconf_update():
|
||||
logdata = dict()
|
||||
path_dconf_config = get_dconf_config_path(uid)
|
||||
db_file = path_dconf_config[:-3]
|
||||
try:
|
||||
process = subprocess.Popen(['dconf', 'compile', db_file, path_dconf_config],
|
||||
process = subprocess.Popen(['dconf', 'update'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
output, error = process.communicate()
|
||||
|
||||
@@ -201,12 +164,6 @@ class Dconf_registry():
|
||||
else:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def update_dict_to_previous(cls):
|
||||
dict_clean_previous = remove_keys_with_prefix(cls._dconf_db)
|
||||
dict_with_previous = add_prefix_to_keys(dict_clean_previous)
|
||||
cls.global_registry_dict.update(dict_with_previous)
|
||||
|
||||
@classmethod
|
||||
def apply_template(cls, uid):
|
||||
logdata = dict()
|
||||
@@ -249,62 +206,20 @@ class Dconf_registry():
|
||||
dconf_dict = self.get_key_values(self.get_matching_keys(startswith))
|
||||
for key, value in dconf_dict.items():
|
||||
keys_tmp = key.split('/')
|
||||
update_dict(output_dict.setdefault('/'.join(keys_tmp[:-1])[1:], {}), {keys_tmp[-1]: str(value)})
|
||||
update_dict(output_dict.setdefault('/'.join(keys_tmp[:-1])[1:], {}), {keys_tmp[-1]: value})
|
||||
|
||||
log('D207')
|
||||
return output_dict
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_dictionary_from_dconf_file_db(self, uid=None, path_bin=None, save_dconf_db=False):
|
||||
logdata = dict()
|
||||
error_skip = None
|
||||
if path_bin:
|
||||
error_skip = True
|
||||
elif not uid:
|
||||
path_bin = self._path_bin_system
|
||||
else:
|
||||
path_bin = self._path_bin_system + str(uid)
|
||||
output_dict = {}
|
||||
try:
|
||||
if (GLib.file_get_contents(path_bin)[0]):
|
||||
bytes1 = GLib.Bytes.new(GLib.file_get_contents(path_bin)[1])
|
||||
table = Gvdb.Table.new_from_bytes(bytes1, True)
|
||||
|
||||
name_list = Gvdb.Table.get_names(table)
|
||||
for name in name_list:
|
||||
value = Gvdb.Table.get_value(table, name)
|
||||
if value is None:
|
||||
continue
|
||||
list_path = name.split('/')
|
||||
if value.is_of_type(GLib.VariantType('s')):
|
||||
part = output_dict.setdefault('/'.join(list_path[1:-1]), {})
|
||||
part[list_path[-1]] = value.get_string()
|
||||
elif value.is_of_type(GLib.VariantType('i')):
|
||||
part = output_dict.setdefault('/'.join(list_path[1:-1]), {})
|
||||
part[list_path[-1]] = value.get_int32()
|
||||
except Exception as exc:
|
||||
logdata['exc'] = exc
|
||||
logdata['path_bin'] = path_bin
|
||||
if not error_skip:
|
||||
log('E73', logdata)
|
||||
else:
|
||||
log('D217', logdata)
|
||||
if save_dconf_db:
|
||||
Dconf_registry._dconf_db = output_dict
|
||||
return output_dict
|
||||
|
||||
|
||||
@classmethod
|
||||
def filter_entries(cls, startswith, registry_dict = None):
|
||||
if not registry_dict:
|
||||
registry_dict = cls.global_registry_dict
|
||||
def filter_entries(cls, startswith):
|
||||
if startswith[-1] == '%':
|
||||
startswith = startswith[:-1]
|
||||
if startswith[-1] == '/' or startswith[-1] == '\\':
|
||||
startswith = startswith[:-1]
|
||||
return filter_dict_keys(startswith, flatten_dictionary(registry_dict))
|
||||
return filter_dict_keys(startswith, flatten_dictionary(registry_dict))
|
||||
return filter_dict_keys(startswith, flatten_dictionary(cls.global_registry_dict))
|
||||
return filter_dict_keys(startswith, flatten_dictionary(cls.global_registry_dict))
|
||||
|
||||
|
||||
@classmethod
|
||||
@@ -319,7 +234,7 @@ class Dconf_registry():
|
||||
elif isinstance(value, list):
|
||||
for data in value:
|
||||
list_entiers.append(PregDconf(
|
||||
keyname, data, find_preg_type(data), data))
|
||||
keyname, convert_string_dconf(data), find_preg_type(data), data))
|
||||
else:
|
||||
list_entiers.append(PregDconf(
|
||||
'/'.join(keyname.split('/')[:-1]), convert_string_dconf(keyname.split('/')[-1]), find_preg_type(value), value))
|
||||
@@ -355,7 +270,7 @@ class Dconf_registry():
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_entry(cls, path, dictionary = None, preg = True):
|
||||
def get_entry(cls, path, dictionary = None):
|
||||
logdata = dict()
|
||||
result = Dconf_registry.get_storage(dictionary)
|
||||
|
||||
@@ -365,23 +280,12 @@ class Dconf_registry():
|
||||
if isinstance(result, dict) and key in result.keys():
|
||||
data = result.get(key).get(keys[-1])
|
||||
return PregDconf(
|
||||
key, convert_string_dconf(keys[-1]), find_preg_type(data), data) if preg else data
|
||||
key, convert_string_dconf(keys[-1]), find_preg_type(data), data)
|
||||
else:
|
||||
logdata['path'] = path
|
||||
log('D208', logdata)
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def check_enable_key(cls ,key):
|
||||
data = cls.get_entry(key, preg = False)
|
||||
if data:
|
||||
if isinstance(data, str):
|
||||
return True if data in cls._true_strings else False
|
||||
elif isinstance(data, int):
|
||||
return bool(data)
|
||||
else:
|
||||
return False
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_hkcu_entry(cls, sid, hive_key, dictionary = None):
|
||||
@@ -396,55 +300,46 @@ class Dconf_registry():
|
||||
|
||||
@classmethod
|
||||
def add_shortcut(cls, sid, sc_obj, policy_name):
|
||||
sc_obj.policy_name = policy_name
|
||||
cls.shortcuts.append(sc_obj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_printer(cls, sid, pobj, policy_name):
|
||||
pobj.policy_name = policy_name
|
||||
cls.printers.append(pobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_drive(cls, sid, dobj, policy_name):
|
||||
dobj.policy_name = policy_name
|
||||
cls.drives.append(dobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_folder(cls, sid, fobj, policy_name):
|
||||
fobj.policy_name = policy_name
|
||||
cls.folders.append(fobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_envvar(self, sid, evobj, policy_name):
|
||||
evobj.policy_name = policy_name
|
||||
self.environmentvariables.append(evobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_script(cls, sid, scrobj, policy_name):
|
||||
scrobj.policy_name = policy_name
|
||||
cls.scripts.append(scrobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_file(cls, sid, fileobj, policy_name):
|
||||
fileobj.policy_name = policy_name
|
||||
cls.files.append(fileobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_ini(cls, sid, iniobj, policy_name):
|
||||
iniobj.policy_name = policy_name
|
||||
cls.inifiles.append(iniobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_networkshare(cls, sid, networkshareobj, policy_name):
|
||||
networkshareobj.policy_name = policy_name
|
||||
cls.networkshares.append(networkshareobj)
|
||||
|
||||
|
||||
@@ -476,13 +371,13 @@ class Dconf_registry():
|
||||
def get_scripts(cls, sid, action):
|
||||
action_scripts = list()
|
||||
for part in cls.scripts:
|
||||
if action == 'LOGON' and part.action == 'LOGON':
|
||||
if action == 'LOGON':
|
||||
action_scripts.append(part)
|
||||
elif action == 'LOGOFF' and part.action == 'LOGOFF':
|
||||
elif action == 'LOGOFF':
|
||||
action_scripts.append(part)
|
||||
elif action == 'STARTUP' and part.action == 'STARTUP':
|
||||
elif action == 'STARTUP':
|
||||
action_scripts.append(part)
|
||||
elif action == 'SHUTDOWN' and part.action == 'SHUTDOWN':
|
||||
elif action == 'SHUTDOWN':
|
||||
action_scripts.append(part)
|
||||
return action_scripts
|
||||
|
||||
@@ -509,7 +404,7 @@ class Dconf_registry():
|
||||
|
||||
@classmethod
|
||||
def wipe_hklm(cls):
|
||||
cls.global_registry_dict = dict({cls._GpoPriority:{}})
|
||||
cls.global_registry_dict = dict({cls._ReadQueue:{}})
|
||||
|
||||
|
||||
def filter_dict_keys(starting_string, input_dict):
|
||||
@@ -530,7 +425,7 @@ def find_preg_type(argument):
|
||||
return 1
|
||||
|
||||
|
||||
def update_dict(dict1, dict2, save_key=None):
|
||||
def update_dict(dict1, dict2):
|
||||
'''
|
||||
Updates dict1 with the key-value pairs from dict2
|
||||
'''
|
||||
@@ -538,144 +433,74 @@ def update_dict(dict1, dict2, save_key=None):
|
||||
if key in dict1:
|
||||
# If both values are dictionaries, recursively call the update_dict function
|
||||
if isinstance(dict1[key], dict) and isinstance(value, dict):
|
||||
save_key = key
|
||||
update_dict(dict1[key], value, save_key)
|
||||
update_dict(dict1[key], value)
|
||||
# If the value in dict1 is a list, extend it with unique values from value
|
||||
elif isinstance(dict1[key], list):
|
||||
dict1[key].extend(set(value) - set(dict1[key]))
|
||||
else:
|
||||
# If the value in dict1 is not a dictionary or the value in dict2 is not a dictionary,
|
||||
# replace the value in dict1 with the value from dict2
|
||||
if save_key and save_key.startswith('Source'):
|
||||
value.reloaded_with_policy_key = [dict1[key].policy_name]
|
||||
if dict1[key].reloaded_with_policy_key:
|
||||
value.reloaded_with_policy_key += dict1[key].reloaded_with_policy_key
|
||||
dict1[key] = value
|
||||
else:
|
||||
dict1[key] = value
|
||||
dict1[key] = value
|
||||
else:
|
||||
# If the key does not exist in dict1, add the key-value pair from dict2 to dict1
|
||||
dict1[key] = value
|
||||
|
||||
|
||||
def add_to_dict(string, username, gpo_info):
|
||||
if gpo_info:
|
||||
counter = gpo_info.counter
|
||||
display_name = gpo_info.display_name
|
||||
name = gpo_info.name
|
||||
version = gpo_info.version
|
||||
else:
|
||||
counter = 0
|
||||
display_name = 'Local Policy'
|
||||
name = None
|
||||
version = None
|
||||
|
||||
if username is None or username == 'Machine':
|
||||
machine= '{}/Machine/{}'.format(Dconf_registry._GpoPriority, counter)
|
||||
def add_to_dict(string, policy_name, username, version):
|
||||
if username is None:
|
||||
correct_path = '/'.join(string.split('/')[:-2])
|
||||
machine= '{}/Machine'.format(Dconf_registry._ReadQueue)
|
||||
dictionary = Dconf_registry.global_registry_dict.setdefault(machine, dict())
|
||||
else:
|
||||
if name in Dconf_registry._gpo_name:
|
||||
return
|
||||
user = '{}/User/{}'.format(Dconf_registry._GpoPriority, counter)
|
||||
correct_path = '/'.join(string.split('/')[:-2])
|
||||
user = '{}/User'.format(Dconf_registry._ReadQueue)
|
||||
dictionary = Dconf_registry.global_registry_dict.setdefault(user, dict())
|
||||
Dconf_registry._gpo_name.add(name)
|
||||
|
||||
dictionary['display_name'] = display_name
|
||||
dictionary['name'] = name
|
||||
dictionary['version'] = str(version)
|
||||
dictionary['correct_path'] = string
|
||||
dictionary[len(dictionary)] = (policy_name, correct_path, version)
|
||||
|
||||
def get_mod_previous_value(key_source, key_valuename):
|
||||
previous_sourc = try_dict_to_literal_eval(Dconf_registry._dconf_db
|
||||
.get(key_source, {})
|
||||
.get(key_valuename, {}))
|
||||
return previous_sourc.get('mod_previous_value') if previous_sourc else None
|
||||
|
||||
def get_previous_value(key_source, key_valuename):
|
||||
previous = key_source.replace('Source', 'Previous')
|
||||
return (Dconf_registry._dconf_db
|
||||
.get(previous, {})
|
||||
.get(key_valuename, None))
|
||||
|
||||
def load_preg_dconf(pregfile, pathfile, policy_name, username, gpo_info):
|
||||
def load_preg_dconf(pregfile, pathfile, policy_name, username, version=None):
|
||||
'''
|
||||
Loads the configuration from preg registry into a dictionary
|
||||
'''
|
||||
# Prefix for storing key data
|
||||
source_pre = "Source"
|
||||
dd = dict()
|
||||
for i in pregfile.entries:
|
||||
# Skip this entry if the valuename starts with '**del'
|
||||
if i.valuename.lower().startswith('**del'):
|
||||
if i.valuename.startswith('**del'):
|
||||
continue
|
||||
valuename = convert_string_dconf(i.valuename)
|
||||
data = check_data(i.data, i.type)
|
||||
if i.valuename != i.data and i.valuename:
|
||||
key_registry_source = f"{source_pre}/{i.keyname}".replace('\\', '/')
|
||||
key_registry = f"{i.keyname}".replace('\\', '/')
|
||||
key_valuename = valuename.replace('\\', '/')
|
||||
if i.keyname.replace('\\', '/') in dd:
|
||||
# If the key exists in dd, update its value with the new key-value pair
|
||||
dd[i.keyname.replace('\\', '/')].update({key_valuename:data})
|
||||
mod_previous_value = get_mod_previous_value(key_registry_source, key_valuename)
|
||||
previous_value = get_previous_value(key_registry, key_valuename)
|
||||
if previous_value != data:
|
||||
(dd[key_registry_source]
|
||||
.update({key_valuename:RegistryKeyMetadata(policy_name, i.type, mod_previous_value=previous_value)}))
|
||||
else:
|
||||
(dd[key_registry_source]
|
||||
.update({key_valuename:RegistryKeyMetadata(policy_name, i.type, mod_previous_value=mod_previous_value)}))
|
||||
dd[i.keyname.replace('\\', '/')].update({valuename.replace('\\', '/'):data})
|
||||
else:
|
||||
# If the key does not exist in dd, create a new key-value pair
|
||||
dd[i.keyname.replace('\\', '/')] = {key_valuename:data}
|
||||
mod_previous_value = get_mod_previous_value(key_registry_source, key_valuename)
|
||||
previous_value = get_previous_value(key_registry, key_valuename)
|
||||
if previous_value != data:
|
||||
dd[key_registry_source] = {key_valuename:RegistryKeyMetadata(policy_name, i.type, mod_previous_value=previous_value)}
|
||||
else:
|
||||
dd[key_registry_source] = {key_valuename:RegistryKeyMetadata(policy_name, i.type, mod_previous_value=mod_previous_value)}
|
||||
dd[i.keyname.replace('\\', '/')] = {valuename.replace('\\', '/'):data}
|
||||
|
||||
elif not i.valuename:
|
||||
keyname_tmp = i.keyname.replace('\\', '/').split('/')
|
||||
keyname = '/'.join(keyname_tmp[:-1])
|
||||
mod_previous_value = get_mod_previous_value(f"{source_pre}/{keyname}", keyname_tmp[-1])
|
||||
previous_value = get_previous_value(f"{keyname}", keyname_tmp[-1])
|
||||
if keyname in dd:
|
||||
# If the key exists in dd, update its value with the new key-value pair
|
||||
dd[keyname].update({keyname_tmp[-1]:data})
|
||||
if previous_value != data:
|
||||
dd[f"{source_pre}/{keyname}"].update({keyname_tmp[-1]:RegistryKeyMetadata(policy_name, i.type, mod_previous_value=previous_value)})
|
||||
else:
|
||||
dd[f"{source_pre}/{keyname}"].update({keyname_tmp[-1]:RegistryKeyMetadata(policy_name, i.type, mod_previous_value=mod_previous_value)})
|
||||
else:
|
||||
# If the key does not exist in dd, create a new key-value pair
|
||||
dd[keyname] = {keyname_tmp[-1]:data}
|
||||
if previous_value != data:
|
||||
dd[f"{source_pre}/{keyname}"] = {keyname_tmp[-1]:RegistryKeyMetadata(policy_name, i.type, mod_previous_value=previous_value)}
|
||||
else:
|
||||
dd[f"{source_pre}/{keyname}"] = {keyname_tmp[-1]:RegistryKeyMetadata(policy_name, i.type, mod_previous_value=mod_previous_value)}
|
||||
|
||||
else:
|
||||
# If the value name is the same as the data,
|
||||
# split the keyname and add the data to the appropriate location in dd.
|
||||
all_list_key = i.keyname.split('\\')
|
||||
key_d ='/'.join(all_list_key[:-1])
|
||||
dd_target = dd.setdefault(key_d,{})
|
||||
key_source = f"Source/{key_d}"
|
||||
dd_target_source = dd.setdefault(key_source, {})
|
||||
data_list = dd_target.setdefault(all_list_key[-1], []).append(data)
|
||||
mod_previous_value = get_mod_previous_value(key_source, all_list_key[-1])
|
||||
previous_value = get_previous_value(key_d, all_list_key[-1])
|
||||
if previous_value != str(data_list):
|
||||
dd_target_source[all_list_key[-1]] = RegistryKeyMetadata(policy_name, i.type, is_list=True, mod_previous_value=previous_value)
|
||||
else:
|
||||
dd_target_source[all_list_key[-1]] = RegistryKeyMetadata(policy_name, i.type, is_list=True, mod_previous_value=mod_previous_value)
|
||||
dd_target = dd.setdefault('/'.join(all_list_key[:-1]),{})
|
||||
dd_target.setdefault(all_list_key[-1], []).append(data)
|
||||
|
||||
# Update the global registry dictionary with the contents of dd
|
||||
add_to_dict(pathfile, policy_name, username, version)
|
||||
update_dict(Dconf_registry.global_registry_dict, dd)
|
||||
|
||||
|
||||
def create_dconf_ini_file(filename, data, uid=None, nodomain=None):
|
||||
def create_dconf_ini_file(filename, data):
|
||||
'''
|
||||
Create an ini-file based on a dictionary of dictionaries.
|
||||
Args:
|
||||
@@ -686,7 +511,7 @@ def create_dconf_ini_file(filename, data, uid=None, nodomain=None):
|
||||
Raises:
|
||||
None
|
||||
'''
|
||||
with open(filename, 'a' if nodomain else 'w') as file:
|
||||
with open(filename, 'w') as file:
|
||||
for section, section_data in data.items():
|
||||
file.write(f'[{section}]\n')
|
||||
for key, value in section_data.items():
|
||||
@@ -698,8 +523,15 @@ def create_dconf_ini_file(filename, data, uid=None, nodomain=None):
|
||||
logdata = dict()
|
||||
logdata['path'] = filename
|
||||
log('D209', logdata)
|
||||
Dconf_registry.dconf_update(uid)
|
||||
Dconf_registry.dconf_update()
|
||||
|
||||
def clean_data(data):
|
||||
try:
|
||||
cleaned_string = data.replace('\n', '').replace('\r', '')
|
||||
cleaned_string = cleaned_string.replace('"', "'")
|
||||
return cleaned_string
|
||||
except:
|
||||
return None
|
||||
|
||||
def check_data(data, t_data):
|
||||
if isinstance(data, bytes):
|
||||
@@ -715,8 +547,7 @@ def convert_string_dconf(input_string):
|
||||
macros = {
|
||||
'#': '%sharp%',
|
||||
';': '%semicolon%',
|
||||
'//': '%doubleslash%',
|
||||
'/': '%oneslash%'
|
||||
'//': '%doubleslash%'
|
||||
}
|
||||
output_string = input_string
|
||||
for key, value in macros.items():
|
||||
@@ -758,54 +589,3 @@ def get_dconf_envprofile():
|
||||
|
||||
profile = '/run/dconf/user/{}'.format(get_uid_by_username(Dconf_registry._username))
|
||||
return {'DCONF_PROFILE': profile}
|
||||
|
||||
|
||||
def convert_elements_to_list_dicts(elements):
|
||||
return list(map(lambda x: dict(x), elements))
|
||||
|
||||
def remove_duplicate_dicts_in_list(list_dict):
|
||||
return convert_elements_to_list_dicts(list(OrderedDict((tuple(sorted(d.items())), d) for d in list_dict).values()))
|
||||
|
||||
def add_preferences_to_global_registry_dict(username, is_machine):
|
||||
if is_machine:
|
||||
prefix = 'Software/BaseALT/Policies/Preferences/Machine'
|
||||
else:
|
||||
prefix = f'Software/BaseALT/Policies/Preferences/{username}'
|
||||
|
||||
preferences_global = [('Shortcuts',remove_duplicate_dicts_in_list(Dconf_registry.shortcuts)),
|
||||
('Folders',remove_duplicate_dicts_in_list(Dconf_registry.folders)),
|
||||
('Files',remove_duplicate_dicts_in_list(Dconf_registry.files)),
|
||||
('Drives',remove_duplicate_dicts_in_list(Dconf_registry.drives)),
|
||||
('Scheduledtasks',remove_duplicate_dicts_in_list(Dconf_registry.scheduledtasks)),
|
||||
('Environmentvariables',remove_duplicate_dicts_in_list(Dconf_registry.environmentvariables)),
|
||||
('Inifiles',remove_duplicate_dicts_in_list(Dconf_registry.inifiles)),
|
||||
('Services',remove_duplicate_dicts_in_list(Dconf_registry.services)),
|
||||
('Printers',remove_duplicate_dicts_in_list(Dconf_registry.printers)),
|
||||
('Scripts',remove_duplicate_dicts_in_list(Dconf_registry.scripts)),
|
||||
('Networkshares',remove_duplicate_dicts_in_list(Dconf_registry.networkshares))]
|
||||
|
||||
preferences_global_dict = dict()
|
||||
preferences_global_dict[prefix] = dict()
|
||||
|
||||
for key, val in preferences_global:
|
||||
preferences_global_dict[prefix].update({key:clean_data(str(val))})
|
||||
|
||||
update_dict(Dconf_registry.global_registry_dict, preferences_global_dict)
|
||||
|
||||
def extract_display_name_version(data, username):
|
||||
policy_force = data.get('Software/BaseALT/Policies/GPUpdate', {}).get('Force', False)
|
||||
if Dconf_registry._force or policy_force:
|
||||
logdata = dict({'username': username})
|
||||
log('W26', logdata)
|
||||
return {}
|
||||
result = {}
|
||||
tmp = {}
|
||||
if isinstance(data, dict):
|
||||
for key in data.keys():
|
||||
if key.startswith(Dconf_registry._GpoPriority+'/'):
|
||||
tmp[key] = data[key]
|
||||
for value in tmp.values():
|
||||
if isinstance(value, dict) and value.get('version', 'None')!='None' and value.get('display_name'):
|
||||
result[value['display_name']] = {'version': value['version'], 'correct_path': value['correct_path']}
|
||||
Dconf_registry._dict_gpo_name_version_cache = result
|
||||
return result
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2021-2024 BaseALT Ltd. <org@basealt.ru>
|
||||
# Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
|
||||
# Copyright (C) 2021 Igor Chudov <nir@nir.org.ru>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -27,15 +27,14 @@ import smbc
|
||||
from util.logging import log
|
||||
from util.paths import file_cache_dir, file_cache_path_home, UNCPath
|
||||
from util.exceptions import NotUNCPathError
|
||||
from util.util import get_machine_name
|
||||
|
||||
|
||||
class fs_file_cache:
|
||||
__read_blocksize = 4096
|
||||
|
||||
def __init__(self, cache_name, username = None):
|
||||
self.cache_name = cache_name
|
||||
self.username = username
|
||||
if username and username != get_machine_name():
|
||||
if username:
|
||||
try:
|
||||
self.storage_uri = file_cache_path_home(username)
|
||||
except:
|
||||
@@ -86,9 +85,7 @@ class fs_file_cache:
|
||||
df.close()
|
||||
os.rename(tmpfile, destfile)
|
||||
os.chmod(destfile, 0o644)
|
||||
except Exception as exc:
|
||||
logdata = dict({'exception': str(exc)})
|
||||
log('W25', logdata)
|
||||
except:
|
||||
tmppath = Path(tmpfile)
|
||||
if tmppath.exists():
|
||||
tmppath.unlink()
|
||||
@@ -109,10 +106,8 @@ class fs_file_cache:
|
||||
logdata = dict({'exception': str(exc)})
|
||||
log('E36', logdata)
|
||||
raise exc
|
||||
if Path(destfile).exists():
|
||||
return str(destfile)
|
||||
else:
|
||||
return None
|
||||
|
||||
return str(destfile)
|
||||
|
||||
def get_ls_smbdir(self, uri):
|
||||
type_file_smb = 8
|
||||
|
309
gpoa/storage/record_types.py
Normal file
309
gpoa/storage/record_types.py
Normal file
@@ -0,0 +1,309 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
class samba_preg(object):
|
||||
'''
|
||||
Object mapping representing HKLM entry (registry key without SID)
|
||||
'''
|
||||
def __init__(self, preg_obj, policy_name):
|
||||
self.policy_name = policy_name
|
||||
self.keyname = preg_obj.keyname
|
||||
self.valuename = preg_obj.valuename
|
||||
self.hive_key = '{}\\{}'.format(self.keyname, self.valuename)
|
||||
self.type = preg_obj.type
|
||||
self.data = preg_obj.data
|
||||
|
||||
def update_fields(self):
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['type'] = self.type
|
||||
fields['data'] = self.data
|
||||
|
||||
return fields
|
||||
|
||||
class samba_hkcu_preg(object):
|
||||
'''
|
||||
Object mapping representing HKCU entry (registry key with SID)
|
||||
'''
|
||||
def __init__(self, sid, preg_obj, policy_name):
|
||||
self.sid = sid
|
||||
self.policy_name = policy_name
|
||||
self.keyname = preg_obj.keyname
|
||||
self.valuename = preg_obj.valuename
|
||||
self.hive_key = '{}\\{}'.format(self.keyname, self.valuename)
|
||||
self.type = preg_obj.type
|
||||
self.data = preg_obj.data
|
||||
|
||||
def update_fields(self):
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['type'] = self.type
|
||||
fields['data'] = self.data
|
||||
|
||||
return fields
|
||||
|
||||
class ad_shortcut(object):
|
||||
'''
|
||||
Object mapping representing Windows shortcut.
|
||||
'''
|
||||
def __init__(self, sid, sc, policy_name):
|
||||
self.sid = sid
|
||||
self.policy_name = policy_name
|
||||
self.path = sc.dest
|
||||
self.shortcut = sc.to_json()
|
||||
|
||||
def update_fields(self):
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['path'] = self.path
|
||||
fields['shortcut'] = self.shortcut
|
||||
|
||||
return fields
|
||||
|
||||
class info_entry(object):
|
||||
def __init__(self, name, value):
|
||||
self.name = name
|
||||
self.value = value
|
||||
|
||||
def update_fields(self):
|
||||
fields = dict()
|
||||
fields['value'] = self.value
|
||||
|
||||
return fields
|
||||
|
||||
class printer_entry(object):
|
||||
'''
|
||||
Object mapping representing Windows printer of some type.
|
||||
'''
|
||||
def __init__(self, sid, pobj, policy_name):
|
||||
self.sid = sid
|
||||
self.policy_name = policy_name
|
||||
self.name = pobj.name
|
||||
self.printer = pobj.to_json()
|
||||
|
||||
def update_fields(self):
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['name'] = self.name
|
||||
fields['printer'] = self.printer.to_json()
|
||||
|
||||
return fields
|
||||
|
||||
class drive_entry(object):
|
||||
'''
|
||||
Object mapping representing Samba share bound to drive letter
|
||||
'''
|
||||
def __init__(self, sid, dobj, policy_name):
|
||||
self.sid = sid
|
||||
self.policy_name = policy_name
|
||||
self.login = dobj.login
|
||||
self.password = dobj.password
|
||||
self.dir = dobj.dir
|
||||
self.path = dobj.path
|
||||
self.action = dobj.action
|
||||
self.thisDrive = dobj.thisDrive
|
||||
self.allDrives = dobj.allDrives
|
||||
self.label = dobj.label
|
||||
self.persistent = dobj.persistent
|
||||
self.useLetter = dobj.useLetter
|
||||
|
||||
|
||||
def update_fields(self):
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['login'] = self.login
|
||||
fields['password'] = self.password
|
||||
fields['dir'] = self.dir
|
||||
fields['path'] = self.path
|
||||
fields['action'] = self.action
|
||||
fields['thisDrive'] = self.thisDrive
|
||||
fields['allDrives'] = self.allDrives
|
||||
fields['label'] = self.label
|
||||
fields['persistent'] = self.persistent
|
||||
fields['useLetter'] = self.useLetter
|
||||
|
||||
return fields
|
||||
|
||||
class folder_entry(object):
|
||||
'''
|
||||
Object mapping representing file system directory
|
||||
'''
|
||||
def __init__(self, sid, fobj, policy_name):
|
||||
self.sid = sid
|
||||
self.policy_name = policy_name
|
||||
self.path = fobj.path
|
||||
self.action = fobj.action.value
|
||||
self.delete_folder = str(fobj.delete_folder)
|
||||
self.delete_sub_folders = str(fobj.delete_sub_folders)
|
||||
self.delete_files = str(fobj.delete_files)
|
||||
self.hidden_folder = str(fobj.hidden_folder)
|
||||
|
||||
def update_fields(self):
|
||||
'''
|
||||
Return list of fields to update
|
||||
'''
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['action'] = self.action
|
||||
fields['delete_folder'] = self.delete_folder
|
||||
fields['delete_sub_folders'] = self.delete_sub_folders
|
||||
fields['delete_files'] = self.delete_files
|
||||
fields['hidden_folder'] = self.hidden_folder
|
||||
|
||||
|
||||
return fields
|
||||
|
||||
class envvar_entry(object):
|
||||
'''
|
||||
Object mapping representing environment variables
|
||||
'''
|
||||
def __init__(self, sid, evobj, policy_name):
|
||||
self.sid = sid
|
||||
self.policy_name = policy_name
|
||||
self.name = evobj.name
|
||||
self.value = evobj.value
|
||||
self.action = evobj.action.value
|
||||
|
||||
def update_fields(self):
|
||||
'''
|
||||
Return list of fields to update
|
||||
'''
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['action'] = self.action
|
||||
fields['value'] = self.value
|
||||
|
||||
return fields
|
||||
|
||||
class script_entry(object):
|
||||
'''
|
||||
Object mapping representing scripts.ini
|
||||
'''
|
||||
def __init__(self, sid, scrobj, policy_name):
|
||||
self.sid = sid
|
||||
self.policy_name = policy_name
|
||||
self.action = scrobj.action
|
||||
self.number = scrobj.number
|
||||
self.path = scrobj.path
|
||||
self.arg = scrobj.args
|
||||
|
||||
def update_fields(self):
|
||||
'''
|
||||
Return list of fields to update
|
||||
'''
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['action'] = self.action
|
||||
fields['number'] = self.number
|
||||
fields['path'] = self.path
|
||||
fields['arg'] = self.arg
|
||||
|
||||
return fields
|
||||
|
||||
class file_entry(object):
|
||||
'''
|
||||
Object mapping representing FILES.XML
|
||||
'''
|
||||
def __init__(self, sid, fileobj, policy_name):
|
||||
self.sid = sid
|
||||
self.policy_name = policy_name
|
||||
self.action = fileobj.action
|
||||
self.fromPath = fileobj.fromPath
|
||||
self.targetPath = fileobj.targetPath
|
||||
self.readOnly = fileobj.readOnly
|
||||
self.archive = fileobj.archive
|
||||
self.hidden = fileobj.hidden
|
||||
self.suppress = fileobj.suppress
|
||||
self.executable = fileobj.executable
|
||||
|
||||
def update_fields(self):
|
||||
'''
|
||||
Return list of fields to update
|
||||
'''
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['action'] = self.action
|
||||
fields['fromPath'] = self.fromPath
|
||||
fields['targetPath'] = self.targetPath
|
||||
fields['readOnly'] = self.readOnly
|
||||
fields['archive'] = self.archive
|
||||
fields['hidden'] = self.hidden
|
||||
fields['suppress'] = self.suppress
|
||||
fields['executable'] = self.executable
|
||||
|
||||
return fields
|
||||
|
||||
class ini_entry(object):
|
||||
'''
|
||||
Object mapping representing INIFILES.XML
|
||||
'''
|
||||
def __init__(self, sid, iniobj, policy_name):
|
||||
self.sid = sid
|
||||
self.policy_name = policy_name
|
||||
self.action = iniobj.action
|
||||
self.path = iniobj.path
|
||||
self.section = iniobj.section
|
||||
self.property = iniobj.property
|
||||
self.value = iniobj.value
|
||||
|
||||
|
||||
def update_fields(self):
|
||||
'''
|
||||
Return list of fields to update
|
||||
'''
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['action'] = self.action
|
||||
fields['path'] = self.path
|
||||
fields['section'] = self.section
|
||||
fields['property'] = self.property
|
||||
fields['value'] = self.value
|
||||
|
||||
return fields
|
||||
|
||||
class networkshare_entry(object):
|
||||
'''
|
||||
Object mapping representing NETWORKSHARES.XML
|
||||
'''
|
||||
def __init__(self, sid, networkshareobj, policy_name):
|
||||
self.sid = sid
|
||||
self.policy_name = policy_name
|
||||
self.name = networkshareobj.name
|
||||
self.action = networkshareobj.action
|
||||
self.path = networkshareobj.path
|
||||
self.allRegular = networkshareobj.allRegular
|
||||
self.comment = networkshareobj.comment
|
||||
self.limitUsers = networkshareobj.limitUsers
|
||||
self.abe = networkshareobj.abe
|
||||
|
||||
|
||||
def update_fields(self):
|
||||
'''
|
||||
Return list of fields to update
|
||||
'''
|
||||
fields = dict()
|
||||
fields['policy_name'] = self.policy_name
|
||||
fields['name'] = self.name
|
||||
fields['action'] = self.action
|
||||
fields['path'] = self.path
|
||||
fields['allRegular'] = self.allRegular
|
||||
fields['comment'] = self.comment
|
||||
fields['limitUsers'] = self.limitUsers
|
||||
fields['abe'] = self.abe
|
||||
|
||||
return fields
|
101
gpoa/storage/sqlite_cache.py
Normal file
101
gpoa/storage/sqlite_cache.py
Normal file
@@ -0,0 +1,101 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
from .cache import cache
|
||||
|
||||
import os
|
||||
|
||||
from sqlalchemy import (
|
||||
create_engine,
|
||||
Table,
|
||||
Column,
|
||||
Integer,
|
||||
String,
|
||||
)
|
||||
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from .sqlite_registry_compat import sqlite_registry_compat
|
||||
|
||||
from util.logging import log
|
||||
from util.paths import cache_dir
|
||||
|
||||
def mapping_factory(mapper_suffix):
|
||||
exec(
|
||||
'''
|
||||
class mapped_id_{}(object):
|
||||
def __init__(self, str_id, value):
|
||||
self.str_id = str_id
|
||||
self.value = str(value)
|
||||
'''.format(mapper_suffix)
|
||||
)
|
||||
return eval('mapped_id_{}'.format(mapper_suffix))
|
||||
|
||||
class sqlite_cache(cache):
|
||||
def __init__(self, cache_name):
|
||||
self.cache_name = cache_name
|
||||
self.mapper_obj = mapping_factory(self.cache_name)
|
||||
self.storage_uri = os.path.join('sqlite:///{}/{}.sqlite'.format(cache_dir(), self.cache_name))
|
||||
logdata = dict({'cache_file': self.storage_uri})
|
||||
log('D20', logdata)
|
||||
self.db_cnt = create_engine(self.storage_uri, echo=False)
|
||||
self.__compat = sqlite_registry_compat(self.db_cnt)
|
||||
self.__metadata = self.__compat.metadata()
|
||||
self.cache_table = Table(
|
||||
self.cache_name,
|
||||
self.__metadata,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('str_id', String(65536), unique=True),
|
||||
Column('value', String)
|
||||
)
|
||||
|
||||
self.__metadata.create_all(self.db_cnt)
|
||||
Session = sessionmaker(bind=self.db_cnt)
|
||||
self.db_session = Session()
|
||||
mapper_reg = self.__compat
|
||||
mapper_reg.map_imperatively(self.mapper_obj, self.cache_table)
|
||||
|
||||
def store(self, str_id, value):
|
||||
obj = self.mapper_obj(str_id, value)
|
||||
self._upsert(obj)
|
||||
|
||||
def get(self, obj_id):
|
||||
result = self.db_session.query(self.mapper_obj).filter(self.mapper_obj.str_id == obj_id).first()
|
||||
return result
|
||||
|
||||
def get_default(self, obj_id, default_value):
|
||||
result = self.get(obj_id)
|
||||
if result == None:
|
||||
logdata = dict()
|
||||
logdata['object'] = obj_id
|
||||
log('D43', logdata)
|
||||
self.store(obj_id, default_value)
|
||||
return str(default_value)
|
||||
return result.value
|
||||
|
||||
def _upsert(self, obj):
|
||||
try:
|
||||
self.db_session.add(obj)
|
||||
self.db_session.commit()
|
||||
except Exception as exc:
|
||||
self.db_session.rollback()
|
||||
logdata = dict()
|
||||
logdata['msg'] = str(exc)
|
||||
log('D44', logdata)
|
||||
self.db_session.query(self.mapper_obj).filter(self.mapper_obj.str_id == obj.str_id).update({ 'value': obj.value })
|
||||
self.db_session.commit()
|
||||
|
621
gpoa/storage/sqlite_registry.py
Normal file
621
gpoa/storage/sqlite_registry.py
Normal file
@@ -0,0 +1,621 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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 os
|
||||
|
||||
from sqlalchemy import (
|
||||
create_engine,
|
||||
Table,
|
||||
Column,
|
||||
Integer,
|
||||
String,
|
||||
UniqueConstraint
|
||||
)
|
||||
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from .sqlite_registry_compat import sqlite_registry_compat
|
||||
|
||||
from util.logging import log
|
||||
from util.paths import cache_dir
|
||||
from .registry import registry
|
||||
from .record_types import (
|
||||
samba_preg
|
||||
, samba_hkcu_preg
|
||||
, ad_shortcut
|
||||
, info_entry
|
||||
, printer_entry
|
||||
, drive_entry
|
||||
, folder_entry
|
||||
, envvar_entry
|
||||
, script_entry
|
||||
, file_entry
|
||||
, ini_entry
|
||||
, networkshare_entry
|
||||
)
|
||||
|
||||
class sqlite_registry(registry):
|
||||
def __init__(self, db_name, registry_cache_dir=None):
|
||||
self.db_name = db_name
|
||||
cdir = registry_cache_dir
|
||||
if cdir == None:
|
||||
cdir = cache_dir()
|
||||
self.db_path = os.path.join('sqlite:///{}/{}.sqlite'.format(cdir, self.db_name))
|
||||
self.db_cnt = create_engine(self.db_path, echo=False)
|
||||
self.__compat = sqlite_registry_compat(self.db_cnt)
|
||||
self.__metadata = self.__compat.metadata()
|
||||
self.__info = Table(
|
||||
'info',
|
||||
self.__metadata,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('name', String(65536), unique=True),
|
||||
Column('value', String(65536))
|
||||
)
|
||||
self.__hklm = Table(
|
||||
'HKLM'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('hive_key', String(65536, collation='NOCASE'),
|
||||
unique=True)
|
||||
, Column('keyname', String(collation='NOCASE'))
|
||||
, Column('valuename', String(collation='NOCASE'))
|
||||
, Column('policy_name', String)
|
||||
, Column('type', Integer)
|
||||
, Column('data', String)
|
||||
)
|
||||
self.__hkcu = Table(
|
||||
'HKCU'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('sid', String)
|
||||
, Column('hive_key', String(65536, collation='NOCASE'))
|
||||
, Column('keyname', String(collation='NOCASE'))
|
||||
, Column('valuename', String(collation='NOCASE'))
|
||||
, Column('policy_name', String)
|
||||
, Column('type', Integer)
|
||||
, Column('data', String)
|
||||
, UniqueConstraint('sid', 'hive_key')
|
||||
)
|
||||
self.__shortcuts = Table(
|
||||
'Shortcuts'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('sid', String)
|
||||
, Column('path', String)
|
||||
, Column('policy_name', String)
|
||||
, Column('shortcut', String)
|
||||
, UniqueConstraint('sid', 'path')
|
||||
)
|
||||
self.__printers = Table(
|
||||
'Printers'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('sid', String)
|
||||
, Column('name', String)
|
||||
, Column('policy_name', String)
|
||||
, Column('printer', String)
|
||||
, UniqueConstraint('sid', 'name')
|
||||
)
|
||||
self.__drives = Table(
|
||||
'Drives'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('sid', String)
|
||||
, Column('login', String)
|
||||
, Column('password', String)
|
||||
, Column('dir', String)
|
||||
, Column('policy_name', String)
|
||||
, Column('path', String)
|
||||
, Column('action', String)
|
||||
, Column('thisDrive', String)
|
||||
, Column('allDrives', String)
|
||||
, Column('label', String)
|
||||
, Column('persistent', String)
|
||||
, Column('useLetter', String)
|
||||
, UniqueConstraint('sid', 'dir')
|
||||
)
|
||||
self.__folders = Table(
|
||||
'Folders'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('sid', String)
|
||||
, Column('path', String)
|
||||
, Column('policy_name', String)
|
||||
, Column('action', String)
|
||||
, Column('delete_folder', String)
|
||||
, Column('delete_sub_folders', String)
|
||||
, Column('delete_files', String)
|
||||
, Column('hidden_folder', String)
|
||||
, UniqueConstraint('sid', 'path')
|
||||
)
|
||||
self.__envvars = Table(
|
||||
'Envvars'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('sid', String)
|
||||
, Column('name', String)
|
||||
, Column('policy_name', String)
|
||||
, Column('action', String)
|
||||
, Column('value', String)
|
||||
, UniqueConstraint('sid', 'name')
|
||||
)
|
||||
self.__scripts = Table(
|
||||
'Scripts'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('sid', String)
|
||||
, Column('policy_name', String)
|
||||
, Column('number', String)
|
||||
, Column('action', String)
|
||||
, Column('path', String)
|
||||
, Column('arg', String)
|
||||
, UniqueConstraint('sid', 'path', 'arg')
|
||||
)
|
||||
self.__files = Table(
|
||||
'Files'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('sid', String)
|
||||
, Column('policy_name', String)
|
||||
, Column('action', String)
|
||||
, Column('fromPath', String)
|
||||
, Column('targetPath', String)
|
||||
, Column('readOnly', String)
|
||||
, Column('archive', String)
|
||||
, Column('hidden', String)
|
||||
, Column('suppress', String)
|
||||
, Column('executable', String)
|
||||
, UniqueConstraint('sid', 'policy_name', 'targetPath', 'fromPath')
|
||||
)
|
||||
self.__ini = Table(
|
||||
'Ini'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('sid', String)
|
||||
, Column('policy_name', String)
|
||||
, Column('action', String)
|
||||
, Column('path', String)
|
||||
, Column('section', String)
|
||||
, Column('property', String)
|
||||
, Column('value', String)
|
||||
, UniqueConstraint('sid', 'action', 'path', 'section', 'property', 'value')
|
||||
)
|
||||
self.__networkshare = Table(
|
||||
'Networkshare'
|
||||
, self.__metadata
|
||||
, Column('id', Integer, primary_key=True)
|
||||
, Column('sid', String)
|
||||
, Column('policy_name', String)
|
||||
, Column('name', String)
|
||||
, Column('action', String)
|
||||
, Column('path', String)
|
||||
, Column('allRegular', String)
|
||||
, Column('comment', String)
|
||||
, Column('limitUsers', String)
|
||||
, Column('abe', String)
|
||||
, UniqueConstraint('sid', 'name', 'path')
|
||||
)
|
||||
|
||||
self.__metadata.create_all(self.db_cnt)
|
||||
Session = sessionmaker(bind=self.db_cnt)
|
||||
self.db_session = Session()
|
||||
mapper_reg = self.__compat
|
||||
try:
|
||||
mapper_reg.map_imperatively(info_entry, self.__info)
|
||||
mapper_reg.map_imperatively(samba_preg, self.__hklm)
|
||||
mapper_reg.map_imperatively(samba_hkcu_preg, self.__hkcu)
|
||||
mapper_reg.map_imperatively(ad_shortcut, self.__shortcuts)
|
||||
mapper_reg.map_imperatively(printer_entry, self.__printers)
|
||||
mapper_reg.map_imperatively(drive_entry, self.__drives)
|
||||
mapper_reg.map_imperatively(folder_entry, self.__folders)
|
||||
mapper_reg.map_imperatively(envvar_entry, self.__envvars)
|
||||
mapper_reg.map_imperatively(script_entry, self.__scripts)
|
||||
mapper_reg.map_imperatively(file_entry, self.__files)
|
||||
mapper_reg.map_imperatively(ini_entry, self.__ini)
|
||||
mapper_reg.map_imperatively(networkshare_entry, self.__networkshare)
|
||||
except:
|
||||
pass
|
||||
#logging.error('Error creating mapper')
|
||||
|
||||
def _add(self, row):
|
||||
try:
|
||||
self.db_session.add(row)
|
||||
self.db_session.commit()
|
||||
except Exception as exc:
|
||||
self.db_session.rollback()
|
||||
raise exc
|
||||
|
||||
def _info_upsert(self, row):
|
||||
try:
|
||||
self._add(row)
|
||||
except:
|
||||
(self
|
||||
.db_session.query(info_entry)
|
||||
.filter(info_entry.name == row.name)
|
||||
.update(row.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
def _hklm_upsert(self, row):
|
||||
try:
|
||||
self._add(row)
|
||||
except:
|
||||
(self
|
||||
.db_session
|
||||
.query(samba_preg)
|
||||
.filter(samba_preg.hive_key == row.hive_key)
|
||||
.update(row.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
def _hkcu_upsert(self, row):
|
||||
try:
|
||||
self._add(row)
|
||||
except Exception as exc:
|
||||
(self
|
||||
.db_session
|
||||
.query(samba_hkcu_preg)
|
||||
.filter(samba_hkcu_preg.sid == row.sid)
|
||||
.filter(samba_hkcu_preg.hive_key == row.hive_key)
|
||||
.update(row.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
def _shortcut_upsert(self, row):
|
||||
try:
|
||||
self._add(row)
|
||||
except:
|
||||
(self
|
||||
.db_session
|
||||
.query(ad_shortcut)
|
||||
.filter(ad_shortcut.sid == row.sid)
|
||||
.filter(ad_shortcut.path == row.path)
|
||||
.update(row.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
def _printer_upsert(self, row):
|
||||
try:
|
||||
self._add(row)
|
||||
except:
|
||||
(self
|
||||
.db_session
|
||||
.query(printer_entry)
|
||||
.filter(printer_entry.sid == row.sid)
|
||||
.filter(printer_entry.name == row.name)
|
||||
.update(row.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
def _drive_upsert(self, row):
|
||||
try:
|
||||
self._add(row)
|
||||
except:
|
||||
(self
|
||||
.db_session
|
||||
.query(drive_entry)
|
||||
.filter(drive_entry.sid == row.sid)
|
||||
.filter(drive_entry.dir == row.dir)
|
||||
.update(row.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
def set_info(self, name, value):
|
||||
ientry = info_entry(name, value)
|
||||
logdata = dict()
|
||||
logdata['varname'] = name
|
||||
logdata['value'] = value
|
||||
log('D19', logdata)
|
||||
self._info_upsert(ientry)
|
||||
|
||||
def _delete_hklm_keyname(self, keyname):
|
||||
'''
|
||||
Delete PReg hive_key from HKEY_LOCAL_MACHINE
|
||||
'''
|
||||
logdata = dict({'keyname': keyname})
|
||||
try:
|
||||
(self
|
||||
.db_session
|
||||
.query(samba_preg)
|
||||
.filter(samba_preg.keyname == keyname)
|
||||
.delete(synchronize_session=False))
|
||||
self.db_session.commit()
|
||||
log('D65', logdata)
|
||||
except Exception as exc:
|
||||
log('D63', logdata)
|
||||
|
||||
def add_hklm_entry(self, preg_entry, policy_name):
|
||||
'''
|
||||
Write PReg entry to HKEY_LOCAL_MACHINE
|
||||
'''
|
||||
pentry = samba_preg(preg_entry, policy_name)
|
||||
if not pentry.valuename.startswith('**'):
|
||||
self._hklm_upsert(pentry)
|
||||
else:
|
||||
logdata = dict({'key': pentry.hive_key})
|
||||
if pentry.valuename.lower() == '**delvals.':
|
||||
self._delete_hklm_keyname(pentry.keyname)
|
||||
else:
|
||||
log('D27', logdata)
|
||||
|
||||
def _delete_hkcu_keyname(self, keyname, sid):
|
||||
'''
|
||||
Delete PReg hive_key from HKEY_CURRENT_USER
|
||||
'''
|
||||
logdata = dict({'sid': sid, 'keyname': keyname})
|
||||
try:
|
||||
(self
|
||||
.db_session
|
||||
.query(samba_hkcu_preg)
|
||||
.filter(samba_hkcu_preg.sid == sid)
|
||||
.filter(samba_hkcu_preg.keyname == keyname)
|
||||
.delete(synchronize_session=False))
|
||||
self.db_session.commit()
|
||||
log('D66', logdata)
|
||||
except:
|
||||
log('D64', logdata)
|
||||
|
||||
def add_hkcu_entry(self, preg_entry, sid, policy_name):
|
||||
'''
|
||||
Write PReg entry to HKEY_CURRENT_USER
|
||||
'''
|
||||
hkcu_pentry = samba_hkcu_preg(sid, preg_entry, policy_name)
|
||||
logdata = dict({'sid': sid, 'policy': policy_name, 'key': hkcu_pentry.hive_key})
|
||||
if not hkcu_pentry.valuename.startswith('**'):
|
||||
log('D26', logdata)
|
||||
self._hkcu_upsert(hkcu_pentry)
|
||||
else:
|
||||
if hkcu_pentry.valuename.lower() == '**delvals.':
|
||||
self._delete_hkcu_keyname(hkcu_pentry.keyname, sid)
|
||||
else:
|
||||
log('D51', logdata)
|
||||
|
||||
def add_shortcut(self, sid, sc_obj, policy_name):
|
||||
'''
|
||||
Store shortcut information in the database
|
||||
'''
|
||||
sc_entry = ad_shortcut(sid, sc_obj, policy_name)
|
||||
logdata = dict()
|
||||
logdata['link'] = sc_entry.path
|
||||
logdata['sid'] = sid
|
||||
log('D41', logdata)
|
||||
self._shortcut_upsert(sc_entry)
|
||||
|
||||
def add_printer(self, sid, pobj, policy_name):
|
||||
'''
|
||||
Store printer configuration in the database
|
||||
'''
|
||||
prn_entry = printer_entry(sid, pobj, policy_name)
|
||||
logdata = dict()
|
||||
logdata['printer'] = prn_entry.name
|
||||
logdata['sid'] = sid
|
||||
log('D40', logdata)
|
||||
self._printer_upsert(prn_entry)
|
||||
|
||||
def add_drive(self, sid, dobj, policy_name):
|
||||
drv_entry = drive_entry(sid, dobj, policy_name)
|
||||
logdata = dict()
|
||||
logdata['uri'] = drv_entry.path
|
||||
logdata['sid'] = sid
|
||||
log('D39', logdata)
|
||||
self._drive_upsert(drv_entry)
|
||||
|
||||
def add_folder(self, sid, fobj, policy_name):
|
||||
fld_entry = folder_entry(sid, fobj, policy_name)
|
||||
logdata = dict()
|
||||
logdata['folder'] = fld_entry.path
|
||||
logdata['sid'] = sid
|
||||
log('D42', logdata)
|
||||
try:
|
||||
self._add(fld_entry)
|
||||
except Exception as exc:
|
||||
(self
|
||||
._filter_sid_obj(folder_entry, sid)
|
||||
.filter(folder_entry.path == fld_entry.path)
|
||||
.update(fld_entry.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
def add_envvar(self, sid, evobj, policy_name):
|
||||
ev_entry = envvar_entry(sid, evobj, policy_name)
|
||||
logdata = dict()
|
||||
logdata['envvar'] = ev_entry.name
|
||||
logdata['sid'] = sid
|
||||
log('D53', logdata)
|
||||
try:
|
||||
self._add(ev_entry)
|
||||
except Exception as exc:
|
||||
(self
|
||||
._filter_sid_obj(envvar_entry, sid)
|
||||
.filter(envvar_entry.name == ev_entry.name)
|
||||
.update(ev_entry.update_fields()))
|
||||
self.db_session.commit()
|
||||
def add_script(self, sid, scrobj, policy_name):
|
||||
scr_entry = script_entry(sid, scrobj, policy_name)
|
||||
logdata = dict()
|
||||
logdata['script path'] = scrobj.path
|
||||
logdata['sid'] = sid
|
||||
log('D153', logdata)
|
||||
try:
|
||||
self._add(scr_entry)
|
||||
except Exception as exc:
|
||||
(self
|
||||
._filter_sid_obj(script_entry, sid)
|
||||
.filter(script_entry.path == scr_entry.path)
|
||||
.update(scr_entry.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
def add_file(self, sid, fileobj, policy_name):
|
||||
f_entry = file_entry(sid, fileobj, policy_name)
|
||||
logdata = dict()
|
||||
logdata['targetPath'] = f_entry.targetPath
|
||||
logdata['fromPath'] = f_entry.fromPath
|
||||
log('D162', logdata)
|
||||
try:
|
||||
self._add(f_entry)
|
||||
except Exception as exc:
|
||||
(self
|
||||
._filter_sid_obj(file_entry, sid)
|
||||
.filter(file_entry.targetPath == f_entry.targetPath)
|
||||
.update(f_entry.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
|
||||
def add_ini(self, sid, iniobj, policy_name):
|
||||
inientry = ini_entry(sid, iniobj, policy_name)
|
||||
logdata = dict()
|
||||
logdata['path'] = inientry.path
|
||||
logdata['action'] = inientry.action
|
||||
log('D177', logdata)
|
||||
try:
|
||||
self._add(inientry)
|
||||
except Exception as exc:
|
||||
(self
|
||||
._filter_sid_obj(ini_entry, sid)
|
||||
.filter(ini_entry.path == inientry.path)
|
||||
.update(inientry.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
def add_networkshare(self, sid, networkshareobj, policy_name):
|
||||
networkshareentry = networkshare_entry(sid, networkshareobj, policy_name)
|
||||
logdata = dict()
|
||||
logdata['name'] = networkshareentry.name
|
||||
logdata['path'] = networkshareentry.path
|
||||
logdata['action'] = networkshareentry.action
|
||||
log('D186', logdata)
|
||||
try:
|
||||
self._add(networkshareentry)
|
||||
except Exception as exc:
|
||||
(self
|
||||
._filter_sid_obj(networkshare_entry, sid)
|
||||
.filter(networkshare_entry.path == networkshareentry.path)
|
||||
.update(networkshareentry.update_fields()))
|
||||
self.db_session.commit()
|
||||
|
||||
|
||||
def _filter_sid_obj(self, row_object, sid):
|
||||
res = (self
|
||||
.db_session
|
||||
.query(row_object)
|
||||
.filter(row_object.sid == sid))
|
||||
return res
|
||||
|
||||
def _filter_sid_list(self, row_object, sid):
|
||||
res = (self
|
||||
.db_session
|
||||
.query(row_object)
|
||||
.filter(row_object.sid == sid)
|
||||
.order_by(row_object.id)
|
||||
.all())
|
||||
return res
|
||||
|
||||
def get_shortcuts(self, sid):
|
||||
return self._filter_sid_list(ad_shortcut, sid)
|
||||
|
||||
def get_printers(self, sid):
|
||||
return self._filter_sid_list(printer_entry, sid)
|
||||
|
||||
def get_drives(self, sid):
|
||||
return self._filter_sid_list(drive_entry, sid)
|
||||
|
||||
def get_folders(self, sid):
|
||||
return self._filter_sid_list(folder_entry, sid)
|
||||
|
||||
def get_envvars(self, sid):
|
||||
return self._filter_sid_list(envvar_entry, sid)
|
||||
|
||||
def _filter_scripts_list(self, row_object, sid, action):
|
||||
res = (self
|
||||
.db_session
|
||||
.query(row_object)
|
||||
.filter(row_object.sid == sid)
|
||||
.filter(row_object.action == action)
|
||||
.order_by(row_object.id)
|
||||
.all())
|
||||
return res
|
||||
|
||||
def get_scripts(self, sid, action):
|
||||
return self._filter_scripts_list(script_entry, sid, action)
|
||||
|
||||
def get_files(self, sid):
|
||||
return self._filter_sid_list(file_entry, sid)
|
||||
|
||||
def get_networkshare(self, sid):
|
||||
return self._filter_sid_list(networkshare_entry, sid)
|
||||
|
||||
def get_ini(self, sid):
|
||||
return self._filter_sid_list(ini_entry, sid)
|
||||
|
||||
def get_hkcu_entry(self, sid, hive_key):
|
||||
res = (self
|
||||
.db_session
|
||||
.query(samba_hkcu_preg)
|
||||
.filter(samba_hkcu_preg.sid == sid)
|
||||
.filter(samba_hkcu_preg.hive_key == hive_key)
|
||||
.first())
|
||||
# Try to get the value from machine SID as a default if no option is set.
|
||||
if not res:
|
||||
machine_sid = self.get_info('machine_sid')
|
||||
res = self.db_session.query(samba_hkcu_preg).filter(samba_hkcu_preg.sid == machine_sid).filter(samba_hkcu_preg.hive_key == hive_key).first()
|
||||
return res
|
||||
|
||||
def filter_hkcu_entries(self, sid, startswith):
|
||||
res = (self
|
||||
.db_session
|
||||
.query(samba_hkcu_preg)
|
||||
.filter(samba_hkcu_preg.sid == sid)
|
||||
.filter(samba_hkcu_preg.hive_key.like(startswith)))
|
||||
return res
|
||||
|
||||
def get_info(self, name):
|
||||
res = (self
|
||||
.db_session
|
||||
.query(info_entry)
|
||||
.filter(info_entry.name == name)
|
||||
.first())
|
||||
return res.value
|
||||
|
||||
def get_hklm_entry(self, hive_key):
|
||||
res = (self
|
||||
.db_session
|
||||
.query(samba_preg)
|
||||
.filter(samba_preg.hive_key == hive_key)
|
||||
.first())
|
||||
return res
|
||||
|
||||
def filter_hklm_entries(self, startswith):
|
||||
res = (self
|
||||
.db_session
|
||||
.query(samba_preg)
|
||||
.filter(samba_preg.hive_key.like(startswith)))
|
||||
return res
|
||||
|
||||
def wipe_user(self, sid):
|
||||
self._wipe_sid(samba_hkcu_preg, sid)
|
||||
self._wipe_sid(ad_shortcut, sid)
|
||||
self._wipe_sid(printer_entry, sid)
|
||||
self._wipe_sid(drive_entry, sid)
|
||||
self._wipe_sid(script_entry, sid)
|
||||
self._wipe_sid(file_entry, sid)
|
||||
self._wipe_sid(ini_entry, sid)
|
||||
self._wipe_sid(networkshare_entry, sid)
|
||||
|
||||
def _wipe_sid(self, row_object, sid):
|
||||
(self
|
||||
.db_session
|
||||
.query(row_object)
|
||||
.filter(row_object.sid == sid)
|
||||
.delete())
|
||||
self.db_session.commit()
|
||||
|
||||
def wipe_hklm(self):
|
||||
self.db_session.query(samba_preg).delete()
|
||||
self.db_session.commit()
|
||||
|
45
gpoa/storage/sqlite_registry_compat.py
Normal file
45
gpoa/storage/sqlite_registry_compat.py
Normal file
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2024 BaseALT Ltd.
|
||||
# Copyright (C) 2024 Evgeny SInelnikov <sin@altlinux.org>.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
__compat__ = False
|
||||
|
||||
from sqlalchemy import MetaData
|
||||
|
||||
try:
|
||||
from sqlalchemy.orm import registry
|
||||
except:
|
||||
from sqlalchemy.orm import mapper
|
||||
__compat__ = True
|
||||
|
||||
class sqlite_registry_compat:
|
||||
def __init__(self, db_cnt):
|
||||
if not __compat__:
|
||||
self.__registry = registry()
|
||||
self.__metadata = MetaData()
|
||||
else:
|
||||
self.__metadata = MetaData(db_cnt)
|
||||
|
||||
def metadata(self):
|
||||
return self.__metadata
|
||||
|
||||
def map_imperatively(self, obj, table):
|
||||
if __compat__:
|
||||
mapper(obj, table)
|
||||
else:
|
||||
self.__registry.map_imperatively(obj, table)
|
@@ -16,5 +16,5 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
{{ home_dir }}/{{mntTarget}} {{ mount_file }} -t {{timeout}} --browse
|
||||
{{ home_dir }}/{{mntTarget}} {{ mount_file }} -t 120 --browse
|
||||
|
||||
|
@@ -16,5 +16,5 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
{{ home_dir }}/.{{mntTarget}} {{ mount_file }} -t {{timeout}}
|
||||
{{ home_dir }}/.{{mntTarget}} {{ mount_file }} -t 120
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -18,9 +18,10 @@
|
||||
|
||||
import logging
|
||||
import logging.handlers
|
||||
from enum import IntEnum, Enum
|
||||
from enum import IntEnum
|
||||
|
||||
from .logging import log
|
||||
from messages import message_with_code
|
||||
from .logging import slogm
|
||||
|
||||
|
||||
def set_loglevel(loglevel_num=None):
|
||||
@@ -69,7 +70,7 @@ def process_target(target_name=None):
|
||||
target = target_name
|
||||
|
||||
logdata = dict({'target': target})
|
||||
log('D10', logdata)
|
||||
logging.debug(slogm(message_with_code('D10'), logdata))
|
||||
|
||||
return target.upper()
|
||||
|
||||
@@ -83,20 +84,3 @@ class ExitCodeUpdater(IntEnum):
|
||||
FAIL_GPUPDATE_USER_NOREPLY = 3
|
||||
EXIT_SIGINT = 130
|
||||
|
||||
class FileAction(Enum):
|
||||
CREATE = 'C'
|
||||
REPLACE = 'R'
|
||||
UPDATE = 'U'
|
||||
DELETE = 'D'
|
||||
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
def action_letter2enum(letter):
|
||||
if letter in ['C', 'R', 'U', 'D']:
|
||||
if letter == 'C': return FileAction.CREATE
|
||||
if letter == 'R': return FileAction.REPLACE
|
||||
if letter == 'U': return FileAction.UPDATE
|
||||
if letter == 'D': return FileAction.DELETE
|
||||
|
||||
return FileAction.CREATE
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -20,7 +20,6 @@ import dbus
|
||||
|
||||
from .logging import log
|
||||
from .users import is_root
|
||||
from storage import Dconf_registry
|
||||
|
||||
|
||||
class dbus_runner:
|
||||
@@ -73,7 +72,6 @@ class dbus_runner:
|
||||
if self.username:
|
||||
logdata = dict({'username': self.username})
|
||||
log('D6', logdata)
|
||||
gpupdate = 'gpupdate' if not Dconf_registry._force else 'gpupdate_force'
|
||||
if is_root():
|
||||
# oddjobd-gpupdate's ACL allows access to this method
|
||||
# only for superuser. This method is called via PAM
|
||||
@@ -97,7 +95,7 @@ class dbus_runner:
|
||||
result = self.system_bus.call_blocking(self.bus_name,
|
||||
self._object_path,
|
||||
self.interface_name,
|
||||
gpupdate,
|
||||
'gpupdate',
|
||||
None,
|
||||
[],
|
||||
timeout=self._synchronous_timeout)
|
||||
@@ -108,12 +106,11 @@ class dbus_runner:
|
||||
raise exc
|
||||
else:
|
||||
log('D11')
|
||||
gpupdate_computer = 'gpupdate_computer' if not Dconf_registry._force else 'gpupdate_computer_force'
|
||||
try:
|
||||
result = self.system_bus.call_blocking(self.bus_name,
|
||||
self._object_path,
|
||||
self.interface_name,
|
||||
gpupdate_computer,
|
||||
'gpupdate_computer',
|
||||
None,
|
||||
# The following positional parameter is called "args".
|
||||
# There is no official documentation for it.
|
||||
@@ -121,6 +118,7 @@ class dbus_runner:
|
||||
timeout=self._synchronous_timeout)
|
||||
print_dbus_result(result)
|
||||
except dbus.exceptions.DBusException as exc:
|
||||
print(exc)
|
||||
logdata = dict({'error': str(exc)})
|
||||
log('E22', logdata)
|
||||
raise exc
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd. <org@basealt.ru>
|
||||
# Copyright (C) 2019-2021 BaseALT Ltd. <org@basealt.ru>
|
||||
# Copyright (C) 2019-2021 Igor Chudov <nir@nir.org.ru>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -93,14 +93,7 @@ def local_policy_cache():
|
||||
|
||||
return lpcache
|
||||
|
||||
|
||||
def get_dconf_config_path(uid = None):
|
||||
if uid:
|
||||
return f'/etc/dconf/db/policy{uid}.d/'
|
||||
else:
|
||||
return '/etc/dconf/db/policy.d/'
|
||||
|
||||
def get_dconf_config_file(uid = None):
|
||||
if uid:
|
||||
return f'/etc/dconf/db/policy{uid}.d/policy{uid}.ini'
|
||||
else:
|
||||
@@ -123,7 +116,7 @@ class UNCPath:
|
||||
def get_uri(self):
|
||||
path = self.path
|
||||
if self.type == 'unc':
|
||||
path = self.path.replace('\\\\', '/')
|
||||
path = self.path.replace('\\', '/')
|
||||
path = path.replace('//', 'smb://')
|
||||
else:
|
||||
pass
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
|
||||
from xml.etree import ElementTree
|
||||
from storage import registry_factory
|
||||
from storage.dconf_registry import load_preg_dconf
|
||||
|
||||
from samba.gp_parse.gp_pol import GPPolParser
|
||||
@@ -80,15 +81,22 @@ def preg_keymap(preg):
|
||||
return keymap
|
||||
|
||||
|
||||
def merge_polfile(preg, sid=None, reg_name='registry', reg_path=None, policy_name='Unknown', username='Machine', gpo_info=None):
|
||||
def merge_polfile(preg, sid=None, reg_name='registry', reg_path=None, policy_name='Unknown', username='Machine', version=None):
|
||||
pregfile = load_preg(preg)
|
||||
if sid is None and username == 'Machine':
|
||||
load_preg_dconf(pregfile, preg, policy_name, None, gpo_info)
|
||||
load_preg_dconf(pregfile, preg, policy_name, None, version)
|
||||
else:
|
||||
load_preg_dconf(pregfile, preg, policy_name, username, gpo_info)
|
||||
load_preg_dconf(pregfile, preg, policy_name, username, version)
|
||||
logdata = dict({'pregfile': preg})
|
||||
log('D32', logdata)
|
||||
|
||||
#log dconf
|
||||
return
|
||||
storage = registry_factory(reg_name, reg_path)
|
||||
for entry in pregfile.entries:
|
||||
if not sid:
|
||||
storage.add_hklm_entry(entry, policy_name)
|
||||
else:
|
||||
storage.add_hkcu_entry(entry, sid, policy_name)
|
||||
|
||||
|
||||
class entry:
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -20,6 +20,7 @@
|
||||
from enum import Enum
|
||||
|
||||
import pwd
|
||||
import logging
|
||||
import subprocess
|
||||
import pysss_nss_idmap
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2021 BaseALT Ltd.
|
||||
#
|
||||
# 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
|
||||
@@ -19,6 +19,8 @@
|
||||
import os
|
||||
import pwd
|
||||
|
||||
from .logging import log
|
||||
|
||||
|
||||
def is_root():
|
||||
'''
|
||||
|
@@ -196,43 +196,3 @@ def get_uid_by_username(username):
|
||||
return user_info.pw_uid
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def add_prefix_to_keys(dictionary: dict, prefix: str='Previous/') -> dict:
|
||||
"""
|
||||
Adds a prefix to each key in the dictionary.
|
||||
Args: Input dictionary whose keys need to be modified
|
||||
prefix string to be added to each key. Defaults to 'Previous/'
|
||||
Returns: New dictionary with modified keys having the specified prefix
|
||||
"""
|
||||
result = {}
|
||||
for key, value in dictionary.items():
|
||||
new_key = f'{prefix}{key}'
|
||||
if isinstance(value, dict):
|
||||
result[new_key] = {deep_key:clean_data(val) if isinstance(val, str) else val for deep_key, val in value.items()}
|
||||
else:
|
||||
result[new_key] = value
|
||||
return result
|
||||
|
||||
|
||||
def remove_keys_with_prefix(dictionary: dict, prefix: tuple=('Previous/', 'Source/')) -> dict:
|
||||
"""
|
||||
Removes all keys that start with the specified prefix from the dictionary.
|
||||
By default, removes keys starting with 'Previous/' and 'Source/' prefix.
|
||||
"""
|
||||
return {key: value for key, value in dictionary.items() if not key.startswith(prefix)}
|
||||
|
||||
|
||||
def get_trans_table():
|
||||
return str.maketrans({
|
||||
'\n': '',
|
||||
'\r': '',
|
||||
'"': "'",
|
||||
'\\': '\\\\'
|
||||
})
|
||||
|
||||
def clean_data(data):
|
||||
try:
|
||||
cleaned_string = data.translate(get_trans_table())
|
||||
return cleaned_string
|
||||
except:
|
||||
return None
|
||||
|
@@ -18,7 +18,7 @@
|
||||
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
from samba import getopt as options
|
||||
from samba import NTSTATUSError
|
||||
|
||||
@@ -28,13 +28,12 @@ except ImportError:
|
||||
from samba.gp.gpclass import get_dc_hostname, check_refresh_gpo_list
|
||||
|
||||
from samba.netcmd.common import netcmd_get_domain_infos_via_cldap
|
||||
from storage.dconf_registry import Dconf_registry, extract_display_name_version
|
||||
import samba.gpo
|
||||
|
||||
from .xdg import (
|
||||
xdg_get_desktop
|
||||
)
|
||||
from .util import get_homedir, get_uid_by_username
|
||||
from .util import get_homedir
|
||||
from .exceptions import GetGPOListFail
|
||||
from .logging import log
|
||||
from .samba import smbopts
|
||||
@@ -110,11 +109,7 @@ class smbcreds (smbopts):
|
||||
hostname
|
||||
'''
|
||||
gpos = list()
|
||||
if Dconf_registry.get_info('machine_name') == username:
|
||||
dconf_dict = Dconf_registry.get_dictionary_from_dconf_file_db(save_dconf_db=True)
|
||||
else:
|
||||
dconf_dict = Dconf_registry.get_dictionary_from_dconf_file_db(get_uid_by_username(username), save_dconf_db=True)
|
||||
dict_gpo_name_version = extract_display_name_version(dconf_dict, username)
|
||||
|
||||
try:
|
||||
log('D48')
|
||||
ads = samba.gpo.ADS_STRUCT(self.selected_dc, self.lp, self.creds)
|
||||
@@ -126,19 +121,13 @@ class smbcreds (smbopts):
|
||||
for gpo in gpos:
|
||||
# These setters are taken from libgpo/pygpo.c
|
||||
# print(gpo.ds_path) # LDAP entry
|
||||
if gpo.display_name in dict_gpo_name_version.keys() and dict_gpo_name_version.get(gpo.display_name, {}).get('version') == str(getattr(gpo, 'version', None)):
|
||||
if Path(dict_gpo_name_version.get(gpo.display_name, {}).get('correct_path')).exists():
|
||||
gpo.file_sys_path = ''
|
||||
ldata = dict({'gpo_name': gpo.display_name, 'gpo_uuid': gpo.name, 'file_sys_path_cache': True})
|
||||
log('I11', ldata)
|
||||
continue
|
||||
ldata = dict({'gpo_name': gpo.display_name, 'gpo_uuid': gpo.name, 'file_sys_path': gpo.file_sys_path})
|
||||
log('I2', ldata)
|
||||
|
||||
except Exception as exc:
|
||||
if self.selected_dc != self.pdc_emulator_server:
|
||||
raise GetGPOListFail(exc)
|
||||
logdata = dict({'username': username, 'dc': self.selected_dc, 'exc': exc})
|
||||
logdata = dict({'username': username, 'dc': self.selected_dc})
|
||||
log('E17', logdata)
|
||||
|
||||
return gpos
|
||||
|
@@ -8,10 +8,7 @@
|
||||
%add_python3_req_skip gpt.gpt
|
||||
%add_python3_req_skip gpt.printers
|
||||
%add_python3_req_skip gpt.shortcuts
|
||||
%add_python3_req_skip gpt.gpo_dconf_mapping
|
||||
%add_python3_req_skip gpt.dynamic_attributes
|
||||
%add_python3_req_skip messages
|
||||
%add_python3_req_skip plugin
|
||||
%add_python3_req_skip storage
|
||||
%add_python3_req_skip storage.fs_file_cache
|
||||
%add_python3_req_skip storage.dconf_registry
|
||||
@@ -36,7 +33,7 @@
|
||||
%add_python3_req_skip util.gpoa_ini_parsing
|
||||
|
||||
Name: gpupdate
|
||||
Version: 0.12.2
|
||||
Version: 0.10.3
|
||||
Release: alt1
|
||||
|
||||
Summary: GPT applier
|
||||
@@ -52,13 +49,12 @@ BuildRequires: gettext-tools
|
||||
Requires: python3-module-rpm
|
||||
Requires: python3-module-dbus
|
||||
Requires: python3-module-configobj
|
||||
Requires: oddjob-%name >= 0.2.3
|
||||
Requires: oddjob-%name >= 0.2.0
|
||||
Requires: libnss-role >= 0.5.0
|
||||
Requires: local-policy >= 0.4.9
|
||||
Requires: pam-config >= 1.9.0
|
||||
Requires: autofs
|
||||
Requires: dconf-profile
|
||||
Requires: libgvdb-gir
|
||||
# This is needed by shortcuts_applier
|
||||
Requires: desktop-file-utils
|
||||
# This is needed for smb file cache support
|
||||
@@ -195,66 +191,6 @@ fi
|
||||
%exclude %python3_sitelibdir/gpoa/test
|
||||
|
||||
%changelog
|
||||
* Tue Jan 14 2025 Valery Sinelnikov <greh@altlinux.org> 0.12.2-alt1
|
||||
- Fixed interpretation of boolean values (closes:52683)
|
||||
|
||||
* Fri Jan 10 2025 Valery Sinelnikov <greh@altlinux.org> 0.12.1-alt1
|
||||
- Fixed checking the path for existence (closes:52597)
|
||||
|
||||
* Tue Dec 10 2024 Valery Sinelnikov <greh@altlinux.org> 0.12.0-alt1
|
||||
- Special thanks to Andrey Belgorodtsev (andrey@net55.su)
|
||||
for valuable pre-release testing and feedback
|
||||
- Added applier thunderbird
|
||||
- Added environment file cleaning (closes: 51016)
|
||||
- Added the ability to set the name of the directory to automount
|
||||
- Added the ability to remove the prefix from a sylink
|
||||
to the catalog in automount
|
||||
- Added the ability to set the timeout in automount
|
||||
- Added messages using the force mode
|
||||
- Improved KDE update logic
|
||||
- Added preservation of previous keys
|
||||
|
||||
* Fri Oct 11 2024 Valery Sinelnikov <greh@altlinux.org> 0.11.4-alt1
|
||||
- Added skip plugin (closes: 51631)
|
||||
- Fixed getting the network path (closes:51606)
|
||||
- The _appliers sequence has been changed,
|
||||
package_applier has been moved to the end
|
||||
|
||||
* Fri Sep 06 2024 Valery Sinelnikov <greh@altlinux.org> 0.11.3-alt1
|
||||
- Optimized string cleaning using str.translate()
|
||||
|
||||
* Wed Sep 04 2024 Valery Sinelnikov <greh@altlinux.org> 0.11.2-alt1
|
||||
- Fixed data type handling in kde_applier
|
||||
- Removing legacy unused code
|
||||
- Added saving policy data without polfile
|
||||
- Added escaping of special characters in data (closes: 51201)
|
||||
|
||||
* Tue Aug 27 2024 Valery Sinelnikov <greh@altlinux.org> 0.11.1-alt1
|
||||
- Fixed setting links in shortcuts (closes: 51275)
|
||||
|
||||
* Fri Aug 09 2024 Valery Sinelnikov <greh@altlinux.org> 0.11.0-alt1
|
||||
- Added saving preferences in dconf
|
||||
- Added versioning support for gpt
|
||||
- Added the ability to force gpt download
|
||||
- Added completions for --force
|
||||
- Added new exceptions for Chromium 126
|
||||
- Added information to the man pages
|
||||
- Fixed handling of incorrect valuename
|
||||
|
||||
* Mon Jul 08 2024 Valery Sinelnikov <greh@altlinux.org> 0.10.6-alt1
|
||||
- Fixed firefox_applier errors
|
||||
|
||||
* Fri Jun 28 2024 Valery Sinelnikov <greh@altlinux.org> 0.10.5-alt1
|
||||
- Correction of missing entries with a upper case
|
||||
- Fixed string processing in date (closes: 50782)
|
||||
- Fixed getting correct data for the user for pkcon_runner
|
||||
|
||||
* Thu Jun 27 2024 Valery Sinelnikov <greh@altlinux.org> 0.10.4-alt1
|
||||
- Fixed the definition of the module activation check (closes: 50755)
|
||||
- Fixed sorting of scripts (closes: 50756)
|
||||
- Fixed reading key values from dconf
|
||||
- Changed the method for getting the list of packages for pkcon_runner
|
||||
|
||||
* Wed Jun 19 2024 Valery Sinelnikov <greh@altlinux.org> 0.10.3-alt1
|
||||
- Added autocompletion for gpoa, gpupdate, gpupdate-setup
|
||||
- Added correct work with json data in keys for the Firefox browser
|
||||
|
Reference in New Issue
Block a user