1
0
mirror of https://github.com/altlinux/gpupdate.git synced 2025-10-15 15:33:49 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
81b215003a Manpage for gpupdate-setup added 2020-09-11 18:17:06 +04:00
51 changed files with 375 additions and 2109 deletions

View File

@@ -1,19 +0,0 @@
#!/bin/sh
. /etc/control.d/functions
CONFIG=/etc/pam.d/system-policy-gpupdate
new_subst disabled \
'^[[:space:]]*session[[:space:]]+\[.*default=1.*\][[:space:]]+pam_succeed_if.so user ingroup users.*' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)default=[[:alnum:]]\+\(.*pam_succeed_if.so user ingroup users.*\)$,\1default=1\2,'
new_subst enabled \
'^[[:space:]]*session[[:space:]]+\[.*default=ignore.*\][[:space:]]+pam_succeed_if.so user ingroup users.*' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)default=[[:alnum:]]\+\(.*pam_succeed_if.so user ingroup users.*\)$,\1default=ignore\2,'
new_help disabled "Disable group policy applying for users in 'users' group only"
new_help enabled "Enable group policy applying for users in 'users' group only"
new_summary "Group policy applying for users in 'users' group only"
control_subst "$CONFIG" "$*"

View File

@@ -1,19 +0,0 @@
#!/bin/sh
. /etc/control.d/functions
CONFIG=/etc/pam.d/system-policy-gpupdate
new_subst disabled \
'^[[:space:]]*session[[:space:]]+\[.*success=2.*\][[:space:]]+pam_localuser.so' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)success=[[:alnum:]]\+\(.*pam_localuser.so.*\)$,\1success=2\2,'
new_subst enabled \
'^[[:space:]]*session[[:space:]]+\[.*success=1.*\][[:space:]]+pam_localuser.so' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)success=[[:alnum:]]\+\(.*pam_localuser.so.*\)$,\1success=1\2,'
new_help disabled 'Disable group policy applying for local users'
new_help enabled 'Enable group policy applying for local users'
new_summary 'Group policy applying for local users'
control_subst "$CONFIG" "$*"

View File

@@ -1,19 +0,0 @@
#!/bin/sh
. /etc/control.d/functions
CONFIG=/etc/pam.d/system-policy-gpupdate
new_subst disabled \
'^[[:space:]]*session[[:space:]]+\[.*default=1.*\][[:space:]]+pam_succeed_if.so uid >= 500.*' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)default=[[:alnum:]]\+\(.*pam_succeed_if.so uid >= 500.*\)$,\1default=1\2,'
new_subst enabled \
'^[[:space:]]*session[[:space:]]+\[.*default=ignore.*\][[:space:]]+pam_succeed_if.so uid >= 500.*' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)default=[[:alnum:]]\+\(.*pam_succeed_if.so uid >= 500.*\)$,\1default=ignore\2,'
new_help disabled "Disable group policy applying for users with not system uids only"
new_help enabled "Enable group policy applying for users with not system uids only"
new_summary "Group policy applying for users with not system uids (greater or equal 500) only"
control_subst "$CONFIG" "$*"

4
dist/gpupdate.ini vendored
View File

@@ -1,4 +1,4 @@
[gpoa]
backend = local
local-policy = default
backend = samba
local-policy = auto

View File

@@ -1,6 +1,6 @@
[Unit]
Description=Group policy update for machine
After=syslog.target network-online.target sssd.service
After=sssd.service
[Service]
Environment="PATH=/bin:/sbin:/usr/bin:/usr/sbin"

View File

@@ -1,12 +1,4 @@
#%PAM-1.0
session [success=2 perm_denied=ignore default=die] pam_localuser.so
session required pam_mkhomedir.so silent
session [default=1] pam_permit.so
session [default=6] pam_permit.so
session [success=1 default=ignore] pam_succeed_if.so user ingroup users quiet
session [default=4] pam_permit.so
session [success=1 default=ignore] pam_succeed_if.so uid >= 500 quiet
session [default=2] pam_permit.so
-session required pam_oddjob_gpupdate.so
session optional pam_env.so user_readenv=1 conffile=/etc/gpupdate/environment user_envfile=.gpupdate_environment
session required pam_permit.so

View File

@@ -54,12 +54,15 @@ behavioral defaults for machine in AD domain.
All data is located in \fB/var/cache/gpupdate\fR. Also domain GPTs are
taken from Samba's \fB/var/cache/samba\fR.
.
The configuration file for \fBgpoa\fP is located in
\fB/etc/gpupdate/gpupdate.ini\fP.
.
The settings read from Samba are stored in
\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)
gpupdate(1) gpupdate-setup(1)
.SH BUGS
Tons of it.
Tons of it. Report at \fBhttps://github.com/altlinux/gpupdate\fP.

View File

@@ -61,7 +61,7 @@ No reply from \fID-Bus\fR when starting \fBgpoa\fR for user using
\fBoddjobd\fR via \fID-Bus\fR.
.
.SH "SEE ALSO"
gpoa(1)
gpoa(1) gpupdate-setup(1)
.SH BUGS
There is tons of bugs since it tries to mimic behavior of Windows
machines.

View File

@@ -41,7 +41,7 @@ def backend_factory(dc, username, is_machine, no_domain = False):
log('D52', ld)
sc = smbcreds(dc)
domain = sc.get_domain()
ldata = dict({'domain': domain, "username": username, 'is_machine': is_machine})
ldata = dict({'domain': domain})
log('D9', ldata)
try:
back = samba_backend(sc, username, domain, is_machine)

View File

@@ -40,8 +40,6 @@ class samba_backend(applier_backend):
def __init__(self, sambacreds, username, domain, is_machine):
self.cache_path = '/var/cache/gpupdate/creds/krb5cc_{}'.format(os.getpid())
self.__kinit_successful = machine_kinit(self.cache_path)
if not self.__kinit_successful:
raise Exception('kinit is not successful')
self.storage = registry_factory('registry')
self.storage.set_info('domain', domain)
machine_name = get_machine_name()
@@ -126,7 +124,7 @@ class samba_backend(applier_backend):
def _get_gpts(self, username, sid):
gpts = list()
log('D45', {'username': username, 'sid': sid})
log('D45')
# util.windows.smbcreds
gpos = self.sambacreds.update_gpos(username)
log('D46')

View File

@@ -32,17 +32,6 @@ def check_experimental_enabled(storage):
return result
def check_windows_mapping_enabled(storage):
windows_mapping_enable_flag = 'Software\\BaseALT\\Policies\\GPUpdate\\WindowsPoliciesMapping'
flag = storage.get_hklm_entry(windows_mapping_enable_flag)
result = True
if flag and '0' == flag.data:
result = False
return result
def check_module_enabled(storage, module_name):
gpupdate_module_enable_branch = 'Software\\BaseALT\\Policies\\GPUpdate'
gpupdate_module_flag = '{}\\{}'.format(gpupdate_module_enable_branch, module_name)

View File

@@ -19,29 +19,13 @@
import subprocess
import threading
import logging
from util.logging import slogm, log
def control_subst(preg_name):
'''
This is a workaround for control names which can't be used in
PReg/ADMX files.
'''
control_triggers = dict()
control_triggers['dvd_rw-format'] = 'dvd+rw-format'
control_triggers['dvd_rw-mediainfo'] = 'dvd+rw-mediainfo'
control_triggers['dvd_rw-booktype'] = 'dvd+rw-booktype'
result = preg_name
if preg_name in control_triggers:
result = control_triggers[preg_name]
return result
from util.logging import slogm
class control:
def __init__(self, name, value):
if type(value) != int and type(value) != str:
raise Exception('Unknown type of value for control')
self.control_name = control_subst(name)
self.control_name = name
self.control_value = value
self.possible_values = self._query_control_values()
if self.possible_values == None:
@@ -68,11 +52,7 @@ class control:
try:
str_status = self.possible_values[int_status]
except IndexError as exc:
logdata = dict()
logdata['control'] = self.control_name
logdata['value from'] = self.possible_values
logdata['by index'] = int_status
log('E41', )
logging.error(slogm('Error getting control ({}) value from {} by index {}'.format(self.control_name, self.possible_values, int_status)))
str_status = None
return str_status
@@ -97,30 +77,20 @@ class control:
if type(self.control_value) == int:
status = self._map_control_status(self.control_value)
if status == None:
logdata = dict()
logdata['control'] = self.control_name
logdata['inpossible values'] = self.self.control_value
log('E42', logdata)
logging.error(slogm('\'{}\' is not in possible values for control {}'.format(self.control_value, self.control_name)))
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.self.control_value
log('E42', logdata)
logging.error(slogm('\'{}\' is not in possible values for control {}'.format(self.control_value, self.control_name)))
return
status = self.control_value
logdata = dict()
logdata['control'] = self.control_name
logdata['status'] = status
log('D68', logdata)
logging.debug(slogm('Setting control {} to {}'.format(self.control_name, status)))
try:
popen_call = ['/usr/sbin/control', self.control_name, status]
with subprocess.Popen(popen_call, stdout=subprocess.PIPE) as proc:
proc.wait()
except:
logdata = dict()
logdata['control'] = self.control_name
logdata['status'] = status
log('E43', logdata)
logging.error(slogm('Unable to set {} to {}'.format(self.control_name, status)))

View File

@@ -1,118 +0,0 @@
#
# 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 os.path import isfile
from util.logging import slogm
import logging
from gpt.envvars import (
FileAction
, action_letter2enum
)
from util.windows import expand_windows_var
from util.util import (
get_homedir,
homedir_exists
)
class Envvar:
def __init__(self, envvars, username=''):
self.username = username
self.envvars = envvars
if self.username == 'root':
self.envvar_file_path = '/etc/gpupdate/environment'
else:
self.envvar_file_path = get_homedir(self.username) + '/.gpupdate_environment'
def _open_envvar_file(self):
fd = None
if isfile(self.envvar_file_path):
fd = open(self.envvar_file_path, 'r+')
else:
fd = open(self.envvar_file_path, 'w')
fd.close()
fd = open(self.envvar_file_path, 'r+')
return fd
def _create_action(self, create_dict, envvar_file):
lines_old = envvar_file.readlines()
lines_new = list()
for name in create_dict:
exist = False
for line in lines_old:
if line.startswith(name + '='):
exist = True
break
if not exist:
lines_new.append(name + '=' + create_dict[name] + '\n')
if len(lines_new) > 0:
envvar_file.writelines(lines_new)
def _delete_action(self, delete_dict, envvar_file):
lines = envvar_file.readlines()
deleted = False
for name in delete_dict:
for line in lines:
if line.startswith(name + '='):
lines.remove(line)
deleted = True
break
if deleted:
envvar_file.writelines(lines)
def act(self):
if isfile(self.envvar_file_path):
with open(self.envvar_file_path, 'r') as f:
lines = f.readlines()
else:
lines = list()
file_changed = False
for envvar_object in self.envvars:
action = action_letter2enum(envvar_object.action)
name = envvar_object.name
value = expand_windows_var(envvar_object.value, self.username)
if value != envvar_object.value:
#slashes are replaced only if the change of variables was performed and we consider the variable as a path to a file or directory
value = value.replace('\\', '/')
exist_line = None
for line in lines:
if line.split()[0] == name:
exist_line = line
break
if exist_line != None:
if action == FileAction.CREATE:
pass
if action == FileAction.DELETE:
lines.remove(exist_line)
file_changed = True
if action == FileAction.UPDATE or action == FileAction.REPLACE:
if exist_line.split()[1].split('=')[1].replace('"', '') != value: #from 'NAME DEFAULT=value' cut value and compare, don`t change if it matches
lines.remove(exist_line)
lines.append(name + ' ' + 'DEFAULT=\"' + value + '\"\n')
file_changed = True
else:
if action == FileAction.CREATE or action == FileAction.UPDATE or action == FileAction.REPLACE:
lines.append(name + ' ' + 'DEFAULT=\"' + value + '\"\n')
file_changed = True
if action == FileAction.DELETE:
pass
if file_changed:
with open(self.envvar_file_path, 'w') as f:
f.writelines(lines)

View File

@@ -1,7 +1,7 @@
#
# GPOA - GPO Applier for Linux
#
# Copyright (C) 2019-2021 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,116 +21,67 @@ import os
import logging
from gi.repository import Gio, GLib
from util.logging import slogm, log
from util.logging import slogm
class system_gsetting:
def __init__(self, schema, path, value, lock, helper_function=None):
__global_schema = '/usr/share/glib-2.0/schemas'
def __init__(self, schema, path, value, override_priority='0'):
self.schema = schema
self.path = path
self.value = value
self.lock = lock
self.helper_function = helper_function
def apply(self, settings, config, locks):
try:
config.add_section(self.schema)
except configparser.DuplicateSectionError:
pass
value = self.value
if self.helper_function:
value = self.helper_function(self.schema, self.path, value)
result = glib_value(self.schema, self.path, value, settings)
config.set(self.schema, self.path, str(result))
if self.lock:
lock_path = dconf_path(settings, self.path)
locks.append(lock_path)
class system_gsettings:
__path_local_dir = '/etc/dconf/db/local.d'
__path_locks = '/etc/dconf/db/policy.d/locks/policy'
__path_profile = '/etc/dconf/profile/user'
__profile_data = 'user-db:user\nsystem-db:policy\nsystem-db:local\n'
def __init__(self, override_file_path):
self.gsettings = list()
self.locks = list()
self.override_file_path = override_file_path
def append(self, schema, path, data, lock, helper):
self.gsettings.append(system_gsetting(schema, path, data, lock, helper))
self.override_priority = override_priority
self.filename = '{}_policy.gschema.override'.format(self.override_priority)
self.file_path = os.path.join(self.__global_schema, self.filename)
def apply(self):
config = configparser.ConfigParser()
for gsetting in self.gsettings:
settings = Gio.Settings(schema=gsetting.schema)
logdata = dict()
logdata['gsetting.schema'] = gsetting.schema
logdata['gsetting.path'] = gsetting.path
logdata['gsetting.value'] = gsetting.value
logdata['gsetting.lock'] = gsetting.lock
log('D89', logdata)
gsetting.apply(settings, config, self.locks)
with open(self.override_file_path, 'w') as f:
config.write(f)
os.makedirs(self.__path_local_dir, mode=0o755, exist_ok=True)
os.makedirs(os.path.dirname(self.__path_locks), mode=0o755, exist_ok=True)
os.makedirs(os.path.dirname(self.__path_profile), mode=0o755, exist_ok=True)
try:
os.remove(self.__path_locks)
except OSError as error:
pass
config.read(self.file_path)
except Exception as exc:
logging.error(slogm(exc))
config.add_section(self.schema)
config.set(self.schema, self.path, self.value)
file_locks = open(self.__path_locks,'w')
for lock in self.locks:
file_locks.write(lock +'\n')
file_locks.close()
profile = open(self.__path_profile ,'w')
profile.write(self.__profile_data)
profile.close()
with open(self.file_path, 'w') as f:
config.write(f)
def glib_map(value, glib_type):
result_value = value
if glib_type == 'i' or glib_type == 'b':
if glib_type == 'i':
result_value = GLib.Variant(glib_type, int(value))
else:
result_value = GLib.Variant(glib_type, value)
return result_value
def dconf_path(settings, path):
return settings.get_property("path") + path
def glib_value(schema, path, value, settings):
# Get the key to modify
key = settings.get_value(path)
# Query the data type for the key
glib_value_type = key.get_type_string()
# Build the new value with the determined type
return glib_map(value, glib_value_type)
class user_gsetting:
def __init__(self, schema, path, value, helper_function=None):
logging.debug('Creating GSettings element {} (in {}) with value {}'.format(path, schema, value))
self.schema = schema
self.path = path
self.value = value
self.helper_function = helper_function
def apply(self):
# Access the current schema
settings = Gio.Settings(schema=self.schema)
# Update result with helper function
value = self.value
logging.debug('Setting GSettings key {} (in {}) to {}'.format(self.path, self.schema, self.value))
if self.helper_function:
value = self.helper_function(self.schema, self.path, value)
# Get typed value by schema
result = glib_value(self.schema, self.path, value, settings)
self.helper_function(self.schema, self.path, self.value)
# Access the current schema
settings = Gio.Settings(self.schema)
# Get the key to modify
key = settings.get_value(self.path)
# Query the data type for the key
glib_value_type = key.get_type_string()
# Build the new value with the determined type
val = glib_map(self.value, glib_value_type)
# Set the value
settings.set_value(self.path, result)
settings.sync()
settings.set_value(self.path, val)
#gso = Gio.Settings.new(self.schema)
#variants = gso.get_property(self.path)
#if (variants.has_key(self.path)):
# key = variants.get_key(self.path)
# print(key.get_range())

View File

@@ -20,7 +20,7 @@ import os
import jinja2
import logging
from util.logging import slogm, log
from util.logging import slogm
class polkit:
__template_path = '/usr/share/gpupdate/templates'
@@ -46,13 +46,7 @@ class polkit:
with open(self.outfile, 'w') as f:
f.write(text)
logdata = dict()
logdata['file'] = self.outfile
logdata['arguments'] = self.args
log('D77', logdata)
logging.debug(slogm('Generated file {} with arguments {}'.format(self.outfile, self.args)))
except Exception as exc:
logdata = dict()
logdata['file'] = self.outfile
logdata['arguments'] = self.args
log('E44', logdata)
logging.error(slogm('Unable to generate file {} from {}'.format(self.outfile, self.infilename)))

View File

@@ -19,7 +19,7 @@
import dbus
import logging
from util.logging import slogm, log
from util.logging import slogm
class systemd_unit:
def __init__(self, unit_name, state):
@@ -39,9 +39,7 @@ class systemd_unit:
self.manager.UnmaskUnitFiles([self.unit_name], dbus.Boolean(False))
self.manager.EnableUnitFiles([self.unit_name], dbus.Boolean(False), dbus.Boolean(True))
self.manager.StartUnit(self.unit_name, 'replace')
logdata = dict()
logdata['unit'] = self.unit_name
log('I6', logdata)
logging.info(slogm('Starting systemd unit: {}'.format(self.unit_name)))
# In case the service has 'RestartSec' property set it
# switches to 'activating (auto-restart)' state instead of
@@ -49,23 +47,17 @@ class systemd_unit:
service_state = self._get_state()
if not service_state in ['active', 'activating']:
logdata = dict()
logdata['unit'] = self.unit_name
log('E46', logdata)
logging.error(slogm('Unable to start systemd unit {}'.format(self.unit_name)))
else:
self.manager.StopUnit(self.unit_name, 'replace')
self.manager.DisableUnitFiles([self.unit_name], dbus.Boolean(False))
self.manager.MaskUnitFiles([self.unit_name], dbus.Boolean(False), dbus.Boolean(True))
logdata = dict()
logdata['unit'] = self.unit_name
log('I6', logdata)
logging.info(slogm('Stopping systemd unit: {}'.format(self.unit_name)))
service_state = self._get_state()
if not service_state in ['stopped']:
logdata = dict()
logdata['unit'] = self.unit_name
log('E46', logdata)
logging.error(slogm('Unable to stop systemd unit {}'.format(self.unit_name)))
def _get_state(self):
'''

View File

@@ -25,13 +25,13 @@ import logging
import json
import os
from util.logging import slogm, log
from util.logging import slogm
from util.util import is_machine_name
class chromium_applier(applier_frontend):
__module_name = 'ChromiumApplier'
__module_enabled = True
__module_experimental = False
__module_enabled = False
__module_experimental = True
__registry_branch = 'Software\\Policies\\Google\\Chrome'
__managed_policies_path = '/etc/chromium/policies/managed'
__recommended_policies_path = '/etc/chromium/policies/recommended'
@@ -83,10 +83,7 @@ class chromium_applier(applier_frontend):
def set_policy(self, name, obj):
if obj:
self.policies[name] = obj
logdata = dict()
logdata['name'] = name
logdata['set to'] = obj
log('I8', logdata)
logging.info(slogm('Chromium policy \'{}\' set to {}'.format(name, obj)))
def set_user_policy(self, name, obj):
'''
@@ -104,24 +101,16 @@ class chromium_applier(applier_frontend):
with open(prefpath, 'r') as f:
settings = json.load(f)
except FileNotFoundError as exc:
logdata = dict()
logdata['prefpath'] = prefpath
log('E51', logdata)
logging.error(slogm('Chromium preferences file {} does not exist at the moment'.format(prefpath)))
except:
logdata = dict()
logdata['username'] = self.username
log('E51', logdata)
logging.error(slogm('Error during attempt to read Chromium preferences for user {}'.format(self.username)))
if obj:
settings[name] = obj
with open(prefpath, 'w') as f:
json.dump(settings, f)
logdata = dict()
logdata['user'] = self.username
logdata['name'] = name
logdata['set to'] = obj
log('I9', logdata)
logging.info(slogm('Set user ({}) property \'{}\' to {}'.format(self.username, name, obj)))
def get_home_page(self, hkcu=False):
response = self.get_hklm_string_entry('HomepageLocation')
@@ -141,9 +130,7 @@ class chromium_applier(applier_frontend):
os.makedirs(self.__managed_policies_path, exist_ok=True)
with open(destfile, 'w') as f:
json.dump(self.policies, f)
logdata = dict()
logdata['destfile'] = destfile
log('D97', logdata)
logging.debug(slogm('Wrote Chromium preferences to {}'.format(destfile)))
def user_apply(self):
'''
@@ -156,10 +143,10 @@ class chromium_applier(applier_frontend):
All actual job done here.
'''
if self.__module_enabled:
log('D95')
logging.debug(slogm('Running Chromium applier for machine'))
self.machine_apply()
else:
log('D96')
logging.debug(slogm('Chromium applier for machine will not be started'))
#if not self._is_machine_name:
# logging.debug('Running user applier for Chromium')
# self.user_apply()

View File

@@ -21,7 +21,7 @@ from .applier_frontend import (
, check_enabled
)
from .appliers.control import control
from util.logging import slogm, log
from util.logging import slogm
import logging
@@ -46,21 +46,12 @@ class control_applier(applier_frontend):
valuename = setting.hive_key.rpartition('\\')[2]
try:
self.controls.append(control(valuename, int(setting.data)))
logdata = dict()
logdata['control'] = valuename
logdata['value'] = setting.data
log('I3', logdata)
logging.info(slogm('Working with control {}'.format(valuename)))
except ValueError as exc:
self.controls.append(control(valuename, setting.data))
logdata = dict()
logdata['control'] = valuename
logdata['with string value'] = setting.data
log('I3', logdata)
logging.info(slogm('Working with control {} with string value'.format(valuename)))
except Exception as exc:
logdata = dict()
logdata['control'] = valuename
logdata['exc'] = exc
log('E39', logdata)
logging.info(slogm('Unable to work with control {}: {}'.format(valuename, exc)))
#for e in polfile.pol_file.entries:
# print('{}:{}:{}:{}:{}'.format(e.type, e.data, e.valuename, e.keyname))
for cont in self.controls:
@@ -71,7 +62,8 @@ class control_applier(applier_frontend):
Trigger control facility invocation.
'''
if self.__module_enabled:
log('D67')
logging.debug(slogm('Running Control applier for machine'))
self.run()
else:
log('E40')
logging.debug(slogm('Control applier for machine will not be started'))

View File

@@ -28,7 +28,7 @@ from .applier_frontend import (
)
from gpt.printers import json2printer
from util.rpm import is_rpm_installed
from util.logging import slogm, log
from util.logging import slogm
def storage_get_printers(storage, sid):
'''
@@ -79,7 +79,7 @@ class cups_applier(applier_frontend):
def run(self):
if not is_rpm_installed('cups'):
log('W9')
logging.warning(slogm('CUPS is not installed: no printer settings will be deployed'))
return
self.cups_connection = cups.Connection()
@@ -94,10 +94,10 @@ class cups_applier(applier_frontend):
Perform configuration of printer which is assigned to computer.
'''
if self.__module_enabled:
log('D113')
logging.debug(slogm('Running CUPS applier for machine'))
self.run()
else:
log('D114')
logging.debug(slogm('CUPS applier for machine will not be started'))
class cups_applier_user(applier_frontend):
__module_name = 'CUPSApplierUser'
@@ -123,7 +123,7 @@ class cups_applier_user(applier_frontend):
def run(self):
if not is_rpm_installed('cups'):
log('W9')
logging.warning(slogm('CUPS is not installed: no printer settings will be deployed'))
return
self.cups_connection = cups.Connection()
@@ -138,8 +138,8 @@ class cups_applier_user(applier_frontend):
Perform printer configuration assigned for user.
'''
if self.__module_enabled:
log('D115')
logging.debug(slogm('Running CUPS applier for user in administrator context'))
self.run()
else:
log('D116')
logging.debug(slogm('CUPS applier for user in administrator context will not be started'))

View File

@@ -1,69 +0,0 @@
#
# 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 .applier_frontend import (
applier_frontend
, check_enabled
)
from .appliers.envvar import Envvar
from util.logging import slogm
import logging
class envvar_applier(applier_frontend):
__module_name = 'EnvvarsApplier'
__module_experimental = False
__module_enabled = True
def __init__(self, storage, sid):
self.storage = storage
self.sid = sid
self.envvars = self.storage.get_envvars(self.sid)
#self.__module_enabled = check_enabled(self.storage, self.__module_name, self.__module_enabled)
def apply(self):
if self.__module_enabled:
logging.debug(slogm('Running Envvar applier for machine'))
ev = Envvar(self.envvars, 'root')
ev.act()
else:
logging.debug(slogm('Envvar applier for machine will not be started'))
class envvar_applier_user(applier_frontend):
__module_name = 'EnvvarsApplierUser'
__module_experimental = False
__module_enabled = True
def __init__(self, storage, sid, username):
self.storage = storage
self.sid = sid
self.username = username
self.envvars = self.storage.get_envvars(self.sid)
#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:
logging.debug(slogm('Running Envvar applier for user in user context'))
ev = Envvar(self.envvars, self.username)
ev.act()
else:
logging.debug(slogm('Envvar applier for user in user context will not be started'))

View File

@@ -34,16 +34,15 @@ from .applier_frontend import (
applier_frontend
, check_enabled
)
from util.logging import slogm, log
from util.logging import slogm
from util.util import is_machine_name
class firefox_applier(applier_frontend):
__module_name = 'FirefoxApplier'
__module_experimental = False
__module_enabled = True
__module_experimental = True
__module_enabled = False
__registry_branch = 'Software\\Policies\\Mozilla\\Firefox'
__firefox_installdir1 = '/usr/lib64/firefox/distribution'
__firefox_installdir2 = '/etc/firefox/policies'
__firefox_installdir = '/usr/lib64/firefox/distribution'
__user_settings_dir = '.mozilla/firefox'
def __init__(self, storage, sid, username):
@@ -98,10 +97,7 @@ class firefox_applier(applier_frontend):
'''
if obj:
self.policies[name] = obj
logdata = dict()
logdata['name'] = name
logdata['set to'] = obj
log('I7', logdata)
logging.info(slogm('Firefox policy \'{}\' set to {}'.format(name, obj)))
def get_home_page(self):
'''
@@ -118,105 +114,45 @@ class firefox_applier(applier_frontend):
return homepage
return None
def get_boolean_config(self, name):
def get_block_about_config(self):
'''
Query boolean property from the storage.
Query BlockAboutConfig boolean property from the storage.
'''
response = self.get_hklm_string_entry(name)
response = self.get_hklm_string_entry('BlockAboutConfig')
if response:
data = response.data if isinstance(response.data, int) else str(response.data).lower()
if data in ['0', 'false', None, 'none', 0]:
if response.data.lower() in ['0', 'false', False, None, 'None']:
return False
if data in ['1', 'true', 1]:
return True
return True
return None
def set_boolean_policy(self, name):
'''
Add boolean entry to policy set.
'''
obj = self.get_boolean_config(name)
if obj is not None:
self.policies[name] = obj
logdata = dict()
logdata['name'] = name
logdata['set to'] = obj
log('I7', logdata)
def machine_apply(self):
'''
Write policies.json to Firefox installdir.
'''
self.set_policy('Homepage', self.get_home_page())
self.set_boolean_policy('BlockAboutConfig')
self.set_boolean_policy('BlockAboutProfiles')
self.set_boolean_policy('BlockAboutSupport')
self.set_boolean_policy('CaptivePortal')
self.set_boolean_policy('DisableSetDesktopBackground')
self.set_boolean_policy('DisableMasterPasswordCreation')
self.set_boolean_policy('DisableBuiltinPDFViewer')
self.set_boolean_policy('DisableDeveloperTools')
self.set_boolean_policy('DisableFeedbackCommands')
self.set_boolean_policy('DisableFirefoxScreenshots')
self.set_boolean_policy('DisableFirefoxAccounts')
self.set_boolean_policy('DisableFirefoxStudies')
self.set_boolean_policy('DisableForgetButton')
self.set_boolean_policy('DisableFormHistory')
self.set_boolean_policy('DisablePasswordReveal')
self.set_boolean_policy('DisablePocket')
self.set_boolean_policy('DisablePrivateBrowsing')
self.set_boolean_policy('DisableProfileImport')
self.set_boolean_policy('DisableProfileRefresh')
self.set_boolean_policy('DisableSafeMode')
self.set_boolean_policy('DisableSystemAddonUpdate')
self.set_boolean_policy('DisableTelemetry')
self.set_boolean_policy('DontCheckDefaultBrowser')
self.set_boolean_policy('ExtensionUpdate')
self.set_boolean_policy('HardwareAcceleration')
self.set_boolean_policy('PrimaryPassword')
self.set_boolean_policy('NetworkPrediction')
self.set_boolean_policy('NewTabPage')
self.set_boolean_policy('NoDefaultBookmarks')
self.set_boolean_policy('OfferToSaveLogins')
self.set_boolean_policy('PasswordManagerEnabled')
self.set_boolean_policy('PromptForDownloadLocation')
self.set_boolean_policy('SanitizeOnShutdown')
self.set_boolean_policy('SearchSuggestEnabled')
self.set_policy('BlockAboutConfig', self.get_block_about_config())
destfile = os.path.join(self.__firefox_installdir1, 'policies.json')
destfile = os.path.join(self.__firefox_installdir, 'policies.json')
os.makedirs(self.__firefox_installdir1, exist_ok=True)
os.makedirs(self.__firefox_installdir, 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()
logdata['destfile'] = destfile
log('D91', logdata)
logging.debug(slogm('Wrote Firefox preferences to {}'.format(destfile)))
def user_apply(self):
profiles = self.get_profiles()
profiledir = os.path.join(util.get_homedir(self.username), self.__user_settings_dir)
for profile in profiles:
logdata = dict()
logdata['profiledir'] = profiledir
logdata['profile'] = profile
log('D92', logdata)
logging.debug(slogm('Found Firefox profile in {}/{}'.format(profiledir, profile)))
def apply(self):
if self.__module_enabled:
log('D93')
logging.debug(slogm('Running Firefox applier for machine'))
self.machine_apply()
else:
log('D94')
logging.debug(slogm('Firefox applier for machine will not be started'))
#if not self._is_machine_name:
# logging.debug('Running user applier for Firefox')
# self.user_apply()

View File

@@ -20,7 +20,7 @@
import logging
import subprocess
from util.logging import slogm, log
from util.logging import slogm
from .applier_frontend import (
applier_frontend
, check_enabled
@@ -52,14 +52,14 @@ class firewall_applier(applier_frontend):
def apply(self):
if self.__module_enabled:
log('D117')
logging.debug(slogm('Running Firewall applier for machine'))
if '1' == self.firewall_enabled:
log('D118')
logging.debug(slogm('Firewall is enabled'))
self.run()
else:
log('D119')
logging.debug(slogm('Firewall is disabled, settings will be reset'))
proc = subprocess.Popen(self.__firewall_reset_cmd)
proc.wait()
else:
log('D120')
logging.debug(slogm('Firewall applier will not be started'))

View File

@@ -23,7 +23,7 @@ from .applier_frontend import (
, check_enabled
)
from .appliers.folder import Folder
from util.logging import slogm, log
from util.logging import slogm
import logging
@@ -40,12 +40,12 @@ class folder_applier(applier_frontend):
def apply(self):
if self.__module_enabled:
log('D107')
logging.debug(slogm('Running Folder applier for machine'))
for directory_obj in self.folders:
fld = Folder(directory_obj)
fld.action()
else:
log('D108')
logging.debug(slogm('Folder applier for machine will not be started'))
class folder_applier_user(applier_frontend):
__module_name = 'FoldersApplierUser'
@@ -70,15 +70,15 @@ class folder_applier_user(applier_frontend):
def admin_context_apply(self):
if self.__module_enabled:
log('D109')
logging.debug(slogm('Running Folder applier for user in administrator context'))
self.run()
else:
log('D110')
logging.debug(slogm('Folder applier for user in administrator context will not be started'))
def user_context_apply(self):
if self.__module_enabled:
log('D111')
logging.debug(slogm('Running Folder applier for user in user context'))
self.run()
else:
log('D112')
logging.debug(slogm('Folder applier for user administrator context will not be started'))

View File

@@ -17,7 +17,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from storage import registry_factory
from storage.fs_file_cache import fs_file_cache
from .control_applier import control_applier
from .polkit_applier import (
@@ -47,18 +46,14 @@ from .folder_applier import (
)
from .cifs_applier import cifs_applier_user
from .ntp_applier import ntp_applier
from .envvar_applier import (
envvar_applier
, envvar_applier_user
)
from util.windows import get_sid
from util.users import (
is_root,
get_process_user,
username_match_uid,
with_privileges
)
from util.logging import log
from util.system import with_privileges
def determine_username(username=None):
@@ -84,18 +79,6 @@ def determine_username(username=None):
return name
def apply_user_context(user_appliers):
for applier_name, applier_object in user_appliers.items():
log('D55', {'name': applier_name})
try:
applier_object.user_context_apply()
except Exception as exc:
logdata = dict()
logdata['applier'] = applier_name
logdata['exception'] = str(exc)
log('E20', logdata)
class frontend_manager:
'''
The frontend_manager class decides when and how to run appliers
@@ -108,7 +91,6 @@ class frontend_manager:
self.is_machine = is_machine
self.process_uname = get_process_user()
self.sid = get_sid(self.storage.get_info('domain'), self.username, is_machine)
self.file_cache = fs_file_cache('file_cache')
self.machine_appliers = dict()
self.machine_appliers['control'] = control_applier(self.storage)
@@ -117,20 +99,19 @@ class frontend_manager:
self.machine_appliers['firefox'] = firefox_applier(self.storage, self.sid, self.username)
self.machine_appliers['chromium'] = chromium_applier(self.storage, self.sid, self.username)
self.machine_appliers['shortcuts'] = shortcut_applier(self.storage)
self.machine_appliers['gsettings'] = gsettings_applier(self.storage, self.file_cache)
self.machine_appliers['gsettings'] = gsettings_applier(self.storage)
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)
# User appliers are expected to work with user-writable
# files and settings, mostly in $HOME.
self.user_appliers = dict()
self.user_appliers['shortcuts'] = shortcut_applier_user(self.storage, self.sid, self.username)
self.user_appliers['folders'] = folder_applier_user(self.storage, self.sid, self.username)
self.user_appliers['gsettings'] = gsettings_applier_user(self.storage, self.file_cache, self.sid, self.username)
self.user_appliers['gsettings'] = gsettings_applier_user(self.storage, self.sid, self.username)
try:
self.user_appliers['cifs'] = cifs_applier_user(self.storage, self.sid, self.username)
except Exception as exc:
@@ -140,7 +121,6 @@ class frontend_manager:
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)
def machine_apply(self):
'''
@@ -150,7 +130,6 @@ class frontend_manager:
log('E13')
return
log('D16')
for applier_name, applier_object in self.machine_appliers.items():
try:
applier_object.apply()
@@ -174,13 +153,13 @@ class frontend_manager:
logdata['exception'] = str(exc)
log('E19', logdata)
try:
with_privileges(self.username, lambda: apply_user_context(self.user_appliers))
except Exception as exc:
logdata = dict()
logdata['username'] = self.username
logdata['exception'] = str(exc)
log('E30', logdata)
try:
with_privileges(self.username, applier_object.user_context_apply)
except Exception as exc:
logdata = dict()
logdata['applier'] = applier_name
logdata['exception'] = str(exc)
log('E20', logdata)
else:
for applier_name, applier_object in self.user_appliers.items():
try:

View File

@@ -1,7 +1,7 @@
#
# GPOA - GPO Applier for Linux
#
# Copyright (C) 2019-2021 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
@@ -29,121 +29,62 @@ from gi.repository import (
from .applier_frontend import (
applier_frontend
, check_enabled
, check_windows_mapping_enabled
)
from .appliers.gsettings import (
system_gsettings,
system_gsetting,
user_gsetting
)
from util.logging import slogm ,log
def uri_fetch(schema, path, value, cache):
'''
Function to fetch and cache uri
'''
retval = value
logdata = dict()
logdata['schema'] = schema
logdata['path'] = path
logdata['src'] = value
try:
retval = cache.get(value)
logdata['dst'] = retval
log('D90', logdata)
except Exception as exc:
pass
return retval
from util.logging import slogm
class gsettings_applier(applier_frontend):
__module_name = 'GSettingsApplier'
__module_experimental = False
__module_enabled = True
__registry_branch = 'Software\\BaseALT\\Policies\\GSettings\\'
__registry_locks_branch = 'Software\\BaseALT\\Policies\\GSettingsLocks\\'
__wallpaper_entry = 'Software\\BaseALT\\Policies\\GSettings\\org.mate.background.picture-filename'
__module_experimental = True
__module_enabled = False
__registry_branch = 'Software\\BaseALT\\Policies\\gsettings'
__global_schema = '/usr/share/glib-2.0/schemas'
__override_priority_file = 'zzz_policy.gschema.override'
__override_old_file = '0_policy.gschema.override'
__windows_settings = dict()
def __init__(self, storage, file_cache):
def __init__(self, storage):
self.storage = storage
self.file_cache = file_cache
gsettings_filter = '{}%'.format(self.__registry_branch)
gsettings_locks_filter = '{}%'.format(self.__registry_locks_branch)
self.gsettings_keys = self.storage.filter_hklm_entries(gsettings_filter)
self.gsettings_locks = self.storage.filter_hklm_entries(gsettings_locks_filter)
self.override_file = os.path.join(self.__global_schema, self.__override_priority_file)
self.override_old_file = os.path.join(self.__global_schema, self.__override_old_file)
self.gsettings = system_gsettings(self.override_file)
self.locks = dict()
self.gsettings = list()
self.override_file = os.path.join(self.__global_schema, '0_policy.gschema.override')
self.__module_enabled = check_enabled(
self.storage
, self.__module_name
, self.__module_experimental
)
def update_file_cache(self, data):
try:
self.file_cache.store(data)
except Exception as exc:
logdata = dict()
logdata['exception'] = str(exc)
log('E47', logdata)
def uri_fetch_helper(self, schema, path, value):
return uri_fetch(schema, path, value, self.file_cache)
def run(self):
# Compatility cleanup of old settings
if os.path.exists(self.override_old_file):
os.remove(self.override_old_file)
# Cleanup settings from previous run
if os.path.exists(self.override_file):
log('D82')
logging.debug(slogm('Removing GSettings policy file from previous run'))
os.remove(self.override_file)
# Get all configured gsettings locks
for lock in self.gsettings_locks:
valuename = lock.hive_key.rpartition('\\')[2]
self.locks[valuename] = int(lock.data)
# Calculate all configured gsettings
for setting in self.gsettings_keys:
helper = None
valuename = setting.hive_key.rpartition('\\')[2]
rp = valuename.rpartition('.')
schema = rp[0]
path = rp[2]
lock = bool(self.locks[valuename]) if valuename in self.locks else None
if setting.hive_key.lower() == self.__wallpaper_entry.lower():
self.update_file_cache(setting.data)
helper = self.uri_fetch_helper
self.gsettings.append(schema, path, setting.data, lock, helper)
self.gsettings.append(system_gsetting(schema, path, setting.data))
# Create GSettings policy with highest available priority
self.gsettings.apply()
for gsetting in self.gsettings:
gsetting.apply()
# Recompile GSettings schemas with overrides
try:
proc = subprocess.run(args=['/usr/bin/glib-compile-schemas', self.__global_schema], capture_output=True, check=True)
except Exception as exc:
log('E48')
# Update desktop configuration system backend
try:
proc = subprocess.run(args=['/usr/bin/dconf', "update"], capture_output=True, check=True)
except Exception as exc:
log('E49')
logging.debug(slogm('Error recompiling global GSettings schemas'))
def apply(self):
if self.__module_enabled:
log('D80')
self.run()
logging.debug(slogm('Running GSettings applier for machine'))
else:
log('D81')
logging.debug(slogm('GSettings applier for machine will not be started'))
class GSettingsMapping:
def __init__(self, hive_key, gsettings_schema, gsettings_key):
@@ -161,7 +102,7 @@ class GSettingsMapping:
logdata['hive_key'] = self.hive_key
logdata['gsettings_schema'] = self.gsettings_schema
logdata['gsettings_key'] = self.gsettings_key
log('W6', logdata)
logging.warning(slogm('Unable to resolve GSettings parameter {}.{}'.format(self.gsettings_schema, self.gsettings_key)))
def preg2gsettings(self):
'''
@@ -178,21 +119,18 @@ class GSettingsMapping:
class gsettings_applier_user(applier_frontend):
__module_name = 'GSettingsApplierUser'
__module_experimental = False
__module_enabled = True
__registry_branch = 'Software\\BaseALT\\Policies\\GSettings\\'
__wallpaper_entry = 'Software\\BaseALT\\Policies\\GSettings\\org.mate.background.picture-filename'
__module_experimental = True
__module_enabled = False
__registry_branch = 'Software\\BaseALT\\Policies\\gsettings'
def __init__(self, storage, file_cache, sid, username):
def __init__(self, storage, sid, username):
self.storage = storage
self.file_cache = file_cache
self.sid = sid
self.username = username
gsettings_filter = '{}%'.format(self.__registry_branch)
self.gsettings_keys = self.storage.filter_hkcu_entries(self.sid, gsettings_filter)
self.gsettings = list()
self.__module_enabled = check_enabled(self.storage, self.__module_name, self.__module_enabled)
self.__windows_mapping_enabled = check_windows_mapping_enabled(self.storage)
self.__windows_settings = dict()
self.windows_settings = list()
@@ -228,23 +166,6 @@ class gsettings_applier_user(applier_frontend):
self.__windows_settings[element.hive_key] = element
def windows_mapping_append(self):
for setting_key in self.__windows_settings.keys():
value = self.storage.get_hkcu_entry(self.sid, setting_key)
if value:
logdata = dict()
logdata['setting_key'] = setting_key
logdata['value.data'] = value.data
log('D86', logdata)
mapping = self.__windows_settings[setting_key]
try:
self.gsettings.append(user_gsetting(mapping.gsettings_schema, mapping.gsettings_key, value.data))
except Exception as exc:
print(exc)
def uri_fetch_helper(self, schema, path, value):
return uri_fetch(schema, path, value, self.file_cache)
def run(self):
#for setting in self.gsettings_keys:
# valuename = setting.hive_key.rpartition('\\')[2]
@@ -253,49 +174,34 @@ class gsettings_applier_user(applier_frontend):
# path = rp[2]
# self.gsettings.append(user_gsetting(schema, path, setting.data))
os.environ['DBUS_SESSION_BUS_ADDRESS'] = 'unix:path=/run/user/{}/bus'.format(pwd.getpwnam(self.username).pw_uid)
# Calculate all mapped gsettings if mapping enabled
if self.__windows_mapping_enabled:
log('D83')
self.windows_mapping_append()
else:
log('D84')
for setting_key in self.__windows_settings.keys():
logging.debug('Checking for GSettings mapping {}'.format(setting_key))
value = self.storage.get_hkcu_entry(self.sid, setting_key)
if value:
logging.debug('Found GSettings mapping {} to {}'.format(setting_key, value.data))
mapping = self.__windows_settings[setting_key]
self.gsettings.append(user_gsetting(mapping.gsettings_schema, mapping.gsettings_key, value.data))
else:
logging.debug('GSettings mapping of {} to {} not found'.format(setting_key, value.data))
# Calculate all configured gsettings
for setting in self.gsettings_keys:
valuename = setting.hive_key.rpartition('\\')[2]
rp = valuename.rpartition('.')
schema = rp[0]
path = rp[2]
helper = self.uri_fetch_helper if setting.hive_key.lower() == self.__wallpaper_entry.lower() else None
self.gsettings.append(user_gsetting(schema, path, setting.data, helper))
# Create GSettings policy with highest available priority
for gsetting in self.gsettings:
logdata = dict()
logdata['gsetting.schema'] = gsetting.schema
logdata['gsetting.path'] = gsetting.path
logdata['gsetting.value'] = gsetting.value
log('D85', logdata)
logging.debug('Applying setting {}/{}'.format(gsetting.schema, gsetting.path))
gsetting.apply()
del os.environ['DBUS_SESSION_BUS_ADDRESS']
def user_context_apply(self):
if self.__module_enabled:
log('D87')
logging.debug(slogm('Running GSettings applier for user in user context'))
self.run()
else:
log('D88')
logging.debug(slogm('GSettings applier for user in user context will not be started'))
def admin_context_apply(self):
# Cache files on remote locations
try:
entry = self.__wallpaper_entry
filter_result = self.storage.get_hkcu_entry(self.sid, entry)
if filter_result:
self.file_cache.store(filter_result.data)
except Exception as exc:
logdata = dict()
logdata['exception'] = str(exc)
log('E50', logdata)
'''
Not implemented because there is no point of doing so.
'''
pass

View File

@@ -17,7 +17,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
import subprocess
from util.logging import slogm
from util.rpm import (
update
@@ -36,7 +35,6 @@ class package_applier(applier_frontend):
__module_enabled = False
__install_key_name = 'Install'
__remove_key_name = 'Remove'
__sync_key_name = 'Sync'
__hklm_branch = 'Software\\BaseALT\\Policies\\Packages'
def __init__(self, storage):
@@ -44,47 +42,30 @@ class package_applier(applier_frontend):
install_branch = '{}\\{}%'.format(self.__hklm_branch, self.__install_key_name)
remove_branch = '{}\\{}%'.format(self.__hklm_branch, self.__remove_key_name)
sync_branch = '{}\\{}%'.format(self.__hklm_branch, self.__sync_key_name)
self.fulcmd = list()
self.fulcmd.append('/usr/libexec/gpupdate/pkcon_runner')
self.install_packages_setting = self.storage.filter_hklm_entries(install_branch)
self.remove_packages_setting = self.storage.filter_hklm_entries(remove_branch)
self.sync_packages_setting = self.storage.filter_hklm_entries(sync_branch)
self.flagSync = False
self.__module_enabled = check_enabled(
self.storage
, self.__module_name
, self.__module_experimental
)
def run(self):
for flag in self.sync_packages_setting:
if flag.data:
self.flagSync = bool(int(flag.data))
if 0 < self.install_packages_setting.count() or 0 < self.remove_packages_setting.count():
if not self.flagSync:
update()
for package in self.install_packages_setting:
try:
subprocess.check_call(self.fulcmd)
install_rpm(package.data)
except Exception as exc:
logging.error(exc)
else:
try:
subprocess.Popen(self.fulcmd,close_fds=False)
except Exception as exc:
logging.error(exc)
#update()
#for package in self.install_packages_setting:
#try:
# install_rpm(package.data)
#except Exception as exc:
# logging.error(exc)
#for package in self.remove_packages_setting:
# try:
# remove_rpm(package.data)
# except Exception as exc:
# logging.error(exc)
for package in self.remove_packages_setting:
try:
remove_rpm(package.data)
except Exception as exc:
logging.error(exc)
def apply(self):
if self.__module_enabled:
@@ -100,25 +81,18 @@ class package_applier_user(applier_frontend):
__module_enabled = False
__install_key_name = 'Install'
__remove_key_name = 'Remove'
__sync_key_name = 'Sync'
__hkcu_branch = 'Software\\BaseALT\\Policies\\Packages'
def __init__(self, storage, sid, username):
self.storage = storage
self.sid = sid
self.username = username
self.fulcmd = list()
self.fulcmd.append('/usr/libexec/gpupdate/pkcon_runner')
self.fulcmd.append(self.sid)
install_branch = '{}\\{}%'.format(self.__hkcu_branch, self.__install_key_name)
remove_branch = '{}\\{}%'.format(self.__hkcu_branch, self.__remove_key_name)
sync_branch = '{}\\{}%'.format(self.__hkcu_branch, self.__sync_key_name)
self.install_packages_setting = self.storage.filter_hkcu_entries(self.sid, install_branch)
self.remove_packages_setting = self.storage.filter_hkcu_entries(self.sid, remove_branch)
self.sync_packages_setting = self.storage.filter_hkcu_entries(self.sid, sync_branch)
self.flagSync = True
self.__module_enabled = check_enabled(self.storage, self.__module_name, self.__module_enabled)
@@ -129,32 +103,19 @@ class package_applier_user(applier_frontend):
pass
def run(self):
for flag in self.sync_packages_setting:
if flag.data:
self.flagSync = bool(int(flag.data))
if 0 < self.install_packages_setting.count() or 0 < self.remove_packages_setting.count():
if self.flagSync:
update()
for package in self.install_packages_setting:
try:
subprocess.check_call(self.fulcmd)
install_rpm(package.data)
except Exception as exc:
logging.error(exc)
else:
logging.debug(exc)
for package in self.remove_packages_setting:
try:
subprocess.Popen(self.fulcmd,close_fds=False)
remove_rpm(package.data)
except Exception as exc:
logging.error(exc)
# update()
# for package in self.install_packages_setting:
# try:
# install_rpm(package.data)
# except Exception as exc:
# logging.debug(exc)
# for package in self.remove_packages_setting:
# try:
# remove_rpm(package.data)
# except Exception as exc:
# logging.debug(exc)
logging.debug(exc)
def admin_context_apply(self):
'''

View File

@@ -21,7 +21,7 @@ from .applier_frontend import (
, check_enabled
)
from .appliers.polkit import polkit
from util.logging import slogm, log
from util.logging import slogm
import logging
@@ -41,12 +41,10 @@ class polkit_applier(applier_frontend):
template_file = self.__polkit_map[self.__deny_all][0]
template_vars = self.__polkit_map[self.__deny_all][1]
if deny_all:
logdata = dict()
logdata['Deny_All'] = deny_all.data
log('D69', logdata)
logging.debug(slogm('Deny_All setting found: {}'.format(deny_all.data)))
self.__polkit_map[self.__deny_all][1]['Deny_All'] = deny_all.data
else:
log('D71')
logging.debug(slogm('Deny_All setting not found'))
self.policies = []
self.policies.append(polkit(template_file, template_vars))
self.__module_enabled = check_enabled(
@@ -60,11 +58,11 @@ class polkit_applier(applier_frontend):
Trigger control facility invocation.
'''
if self.__module_enabled:
log('D73')
logging.debug(slogm('Running Polkit applier for machine'))
for policy in self.policies:
policy.generate()
else:
log('D75')
logging.debug(slogm('Polkit applier for machine will not be started'))
class polkit_applier_user(applier_frontend):
__module_name = 'PolkitApplierUser'
@@ -85,14 +83,11 @@ class polkit_applier_user(applier_frontend):
template_file = self.__polkit_map[self.__deny_all][0]
template_vars = self.__polkit_map[self.__deny_all][1]
if deny_all:
logdata = dict()
logdata['user'] = self.username
logdata['Deny_All'] = deny_all.data
log('D70', logdata)
logging.debug(slogm('Deny_All setting for user {} found: {}'.format(self.username, deny_all.data)))
self.__polkit_map[self.__deny_all][1]['Deny_All'] = deny_all.data
self.__polkit_map[self.__deny_all][1]['User'] = self.username
else:
log('D72')
logging.debug(slogm('Deny_All setting not found'))
self.policies = []
self.policies.append(polkit(template_file, template_vars, self.username))
self.__module_enabled = check_enabled(
@@ -109,10 +104,9 @@ class polkit_applier_user(applier_frontend):
Trigger control facility invocation.
'''
if self.__module_enabled:
log('D74')
logging.debug(slogm('Running Polkit applier for user in administrator context'))
for policy in self.policies:
policy.generate()
else:
log('D76')
logging.debug(slogm('Polkit applier for user in administrator context will not be started'))

View File

@@ -25,13 +25,13 @@ from .applier_frontend import (
)
from gpt.shortcuts import json2sc
from util.windows import expand_windows_var
from util.logging import slogm, log
from util.logging import slogm
from util.util import (
get_homedir,
homedir_exists
)
def storage_get_shortcuts(storage, sid, username=None):
def storage_get_shortcuts(storage, sid):
'''
Query storage for shortcuts' rows for specified SID.
'''
@@ -40,25 +40,21 @@ def storage_get_shortcuts(storage, sid, username=None):
for sc_obj in shortcut_objs:
sc = json2sc(sc_obj.shortcut)
if username:
sc.set_expanded_path(expand_windows_var(sc.path, username))
shortcuts.append(sc)
return shortcuts
def apply_shortcut(shortcut, username=None):
def write_shortcut(shortcut, username=None):
'''
Apply the single shortcut file to the disk.
Write the single shortcut file to the disk.
:username: None means working with machine variables and paths
'''
dest_abspath = shortcut.dest
if not dest_abspath.startswith('/') and not dest_abspath.startswith('%'):
dest_abspath = '%HOME%/' + dest_abspath
logdata = dict()
logdata['shortcut'] = dest_abspath
logdata['for'] = username
log('D105', logdata)
logging.debug(slogm('Try to expand path for shortcut: {} for {}'.format(dest_abspath, username)))
dest_abspath = expand_windows_var(dest_abspath, username).replace('\\', '/') + '.desktop'
# Check that we're working for user, not on global system level
@@ -68,34 +64,22 @@ def apply_shortcut(shortcut, username=None):
if dest_abspath.startswith(get_homedir(username)):
# Don't try to operate on non-existent directory
if not homedir_exists(username):
logdata = dict()
logdata['user'] = username
logdata['dest_abspath'] = dest_abspath
log('W7', logdata)
logging.warning(slogm('No home directory exists for user {}: will not create link {}'.format(username, dest_abspath)))
return None
else:
logdata = dict()
logdata['user'] = username
logdata['bad path'] = dest_abspath
log('W8', logdata)
logging.warning(slogm('User\'s shortcut not placed to home directory for {}: bad path {}'.format(username, dest_abspath)))
return None
if '%' in dest_abspath:
logdata = dict()
logdata['dest_abspath'] = dest_abspath
log('E53', logdata)
logging.debug(slogm('Fail for writing shortcut to file with \'%\': {}'.format(dest_abspath)))
return None
if not dest_abspath.startswith('/'):
logdata = dict()
logdata['dest_abspath'] = dest_abspath
log('E54', logdata)
logging.debug(slogm('Fail for writing shortcut to not absolute path \'%\': {}'.format(dest_abspath)))
return None
logdata = dict()
logdata['file'] = dest_abspath
logdata['with_action'] = shortcut.action
log('D106', logdata)
shortcut.apply_desktop(dest_abspath)
logging.debug(slogm('Writing shortcut file to {}'.format(dest_abspath)))
shortcut.write_desktop(dest_abspath)
class shortcut_applier(applier_frontend):
__module_name = 'ShortcutsApplier'
@@ -114,7 +98,7 @@ class shortcut_applier(applier_frontend):
shortcuts = storage_get_shortcuts(self.storage, self.storage.get_info('machine_sid'))
if shortcuts:
for sc in shortcuts:
apply_shortcut(sc)
write_shortcut(sc)
if len(shortcuts) > 0:
# According to ArchWiki - this thing is needed to rebuild MIME
# type cache in order file bindings to work. This rebuilds
@@ -122,16 +106,14 @@ class shortcut_applier(applier_frontend):
# /usr/local/share/applications
subprocess.check_call(['/usr/bin/update-desktop-database'])
else:
logdata = dict()
logdata['machine_sid'] = self.storage.get_info('machine_sid')
log('D100', logdata)
logging.debug(slogm('No shortcuts to process for {}'.format(self.storage.get_info('machine_sid'))))
def apply(self):
if self.__module_enabled:
log('D98')
logging.debug(slogm('Running Shortcut applier for machine'))
self.run()
else:
log('D99')
logging.debug(slogm('Shortcut applier for machine will not be started'))
class shortcut_applier_user(applier_frontend):
__module_name = 'ShortcutsApplierUser'
@@ -143,31 +125,27 @@ class shortcut_applier_user(applier_frontend):
self.sid = sid
self.username = username
def run(self, in_usercontext):
shortcuts = storage_get_shortcuts(self.storage, self.sid, self.username)
def run(self):
shortcuts = storage_get_shortcuts(self.storage, self.sid)
if shortcuts:
for sc in shortcuts:
if in_usercontext and sc.is_usercontext():
apply_shortcut(sc, self.username)
if not in_usercontext and not sc.is_usercontext():
apply_shortcut(sc, self.username)
if sc.is_usercontext():
write_shortcut(sc, self.username)
else:
logdata = dict()
logdata['sid'] = self.sid
log('D100', logdata)
logging.debug(slogm('No shortcuts to process for {}'.format(self.sid)))
def user_context_apply(self):
if self.__module_enabled:
log('D101')
self.run(True)
logging.debug(slogm('Running Shortcut applier for user in user context'))
self.run()
else:
log('D102')
logging.debug(slogm('Shortcut applier for user in user context will not be started'))
def admin_context_apply(self):
if self.__module_enabled:
log('D103')
self.run(False)
logging.debug(slogm('Running Shortcut applier for user in administrator context'))
self.run()
else:
log('D104')
logging.debug(slogm('Shortcut applier for user in administrator context will not be started'))

View File

@@ -21,7 +21,7 @@ from .applier_frontend import (
, check_enabled
)
from .appliers.systemd import systemd_unit
from util.logging import slogm, log
from util.logging import slogm
import logging
@@ -46,31 +46,24 @@ class systemd_applier(applier_frontend):
valuename = setting.hive_key.rpartition('\\')[2]
try:
self.units.append(systemd_unit(valuename, int(setting.data)))
logdata = dict()
logdata['unit'] = format(valuename)
log('I4', logdata)
logging.info(slogm('Working with systemd unit {}'.format(valuename)))
except Exception as exc:
logdata = dict()
logdata['unit'] = format(valuename)
logdata['exc'] = exc
log('I5', logdata)
logging.info(slogm('Unable to work with systemd unit {}: {}'.format(valuename, exc)))
for unit in self.units:
try:
unit.apply()
except:
logdata = dict()
logdata['unit'] = unit.unit_name
log('E45', logdata)
logging.error(slogm('Failed applying unit {}'.format(unit.unit_name)))
def apply(self):
'''
Trigger control facility invocation.
'''
if self.__module_enabled:
log('D78')
logging.debug(slogm('Running systemd applier for machine'))
self.run()
else:
log('D79')
logging.debug(slogm('systemd applier for machine will not be started'))
class systemd_applier_user(applier_frontend):
__module_name = 'SystemdApplierUser'

View File

@@ -73,44 +73,25 @@ class gpoa_controller:
def __init__(self):
self.__args = parse_arguments()
self.is_machine = False
self.noupdate = self.__args.noupdate
if not self.__args.user:
user = get_machine_name()
self.is_machine = True
set_loglevel(self.__args.loglevel)
locale.bindtextdomain('gpoa', '/usr/lib/python3/site-packages/gpoa/locale')
gettext.bindtextdomain('gpoa', '/usr/lib/python3/site-packages/gpoa/locale')
gettext.textdomain('gpoa')
if not self.__args.user:
self.username = get_machine_name()
self.is_machine = True
else:
self.username = self.__args.user
uname = get_process_user()
uid = os.getuid()
logdata = dict()
logdata['username'] = self.username
logdata['is_machine'] = self.is_machine
logdata['process_username'] = uname
logdata['process_uid'] = uid
if self.is_machine:
log('D61', logdata)
else:
log('D1', logdata)
self.username = determine_username(self.username)
logdata['username'] = uname
logdata['uid'] = uid
log('D1', logdata)
if not is_root():
self.noupdate = True
if self.is_machine:
msgtext = message_with_code('E34')
log('E34', {'username': self.username})
raise Exception(msgtext)
log('D59', {'username': self.username})
self.username = uname
else:
log('D60', {'username': self.username})
self.username = determine_username(self.__args.user)
def run(self):
'''
@@ -132,7 +113,7 @@ class gpoa_controller:
if self.__args.nodomain:
nodomain = True
if not self.noupdate:
if not self.__args.noupdate:
if is_root():
back = None
try:

View File

@@ -18,48 +18,21 @@
from util.xml import get_xml_root
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()
for var in get_xml_root(envvars_file):
props = var.find('Properties')
name = props.get('name')
value = props.get('value')
var_obj = envvar(name, value)
var_obj.set_action(action_letter2enum(props.get('action', default='C')))
var_obj = envvar()
variables.append(var_obj)
return variables
def merge_envvars(storage, sid, envvar_objects, policy_name):
for envv in envvar_objects:
storage.add_envvar(sid, envv, policy_name)
def merge_envvars(storage, sid, envvars_objects, policy_name):
for envvar in envvar_objects:
pass
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
def __init__(self):
pass

View File

@@ -68,7 +68,7 @@ from .tasks import (
import util
import util.preg
from util.paths import (
local_policy_path,
default_policy_path,
cache_dir,
local_policy_cache
)
@@ -326,7 +326,7 @@ def lp2gpt():
'''
Convert local-policy to full-featured GPT.
'''
lppath = os.path.join(local_policy_path(), 'Machine/Registry.pol.xml')
lppath = os.path.join(default_policy_path(), 'Machine/Registry.pol.xml')
# Load settings from XML PolFile
polparser = GPPolParser()

View File

@@ -79,7 +79,7 @@ def read_shortcuts(shortcuts_file):
# URL or FILESYSTEM
target_type = get_ttype(props.get('targetType'))
sc = shortcut(dest, path, arguments, link.get('name'), props.get('action'), target_type)
sc = shortcut(dest, path, arguments, link.get('name'), target_type)
sc.set_changed(link.get('changed'))
sc.set_clsid(link.get('clsid'))
sc.set_guid(link.get('uid'))
@@ -100,7 +100,7 @@ def json2sc(json_str):
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 = shortcut(json_obj['dest'], json_obj['path'], json_obj['arguments'], json_obj['name'], link_type)
sc.set_changed(json_obj['changed'])
sc.set_clsid(json_obj['clsid'])
sc.set_guid(json_obj['guid'])
@@ -111,7 +111,7 @@ def json2sc(json_str):
return sc
class shortcut:
def __init__(self, dest, path, arguments, name=None, action=None, ttype=TargetType.FILESYSTEM):
def __init__(self, dest, path, arguments, name=None, ttype=TargetType.FILESYSTEM):
'''
:param dest: Path to resulting file on file system
:param path: Path where the link should point to
@@ -121,10 +121,8 @@ class shortcut:
'''
self.dest = dest
self.path = path
self.expanded_path = None
self.arguments = arguments
self.name = name
self.action = action
self.changed = ''
self.icon = None
self.is_in_user_context = self.set_usercontext()
@@ -168,12 +166,6 @@ class shortcut:
self.is_in_user_context = ctx
def set_expanded_path(self, path):
'''
Adjust shortcut path with expanding windows variables
'''
self.expanded_path = path
def is_usercontext(self):
return self.is_in_user_context
@@ -189,7 +181,6 @@ class shortcut:
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:
@@ -199,78 +190,39 @@ class shortcut:
return json.dumps(result.content)
def desktop(self, dest=None):
def desktop(self):
'''
Returns desktop file object which may be written to disk.
'''
if dest:
self.desktop_file = DesktopEntry(dest)
else:
self.desktop_file = DesktopEntry()
self.desktop_file.addGroup('Desktop Entry')
self.desktop_file.set('Version', '1.0')
self._update_desktop()
self.desktop_file = DesktopEntry()
self.desktop_file.addGroup('Desktop Entry')
return self.desktop_file
def _update_desktop(self):
'''
Update desktop file object from internal data.
'''
if self.type == TargetType.URL:
self.desktop_file.set('Type', 'Link')
else:
self.desktop_file.set('Type', 'Application')
self.desktop_file.set('Version', '1.0')
self.desktop_file.set('Name', self.name)
desktop_path = self.path
if self.expanded_path:
desktop_path = self.expanded_path
if self.type == TargetType.URL:
self.desktop_file.set('URL', desktop_path)
self.desktop_file.set('URL', self.path)
else:
self.desktop_file.set('Terminal', 'false')
self.desktop_file.set('Exec', '{} {}'.format(desktop_path, self.arguments))
self.desktop_file.set('Exec', '{} {}'.format(self.path, self.arguments))
if self.icon:
self.desktop_file.set('Icon', self.icon)
def _write_desktop(self, dest, create_only=False, read_firstly=False):
return self.desktop_file
def write_desktop(self, dest):
'''
Write .desktop file to disk using path 'dest'. Please note that
.desktop files must have executable bit set in order to work in
GUI.
'''
self.desktop().write(dest)
sc = Path(dest)
if sc.exists() and create_only:
return
if sc.exists() and read_firstly:
self.desktop(dest).write(dest)
else:
self.desktop().write(dest)
sc.chmod(sc.stat().st_mode | stat.S_IEXEC)
def _remove_desktop(self, dest):
'''
Remove .desktop file fromo disk using path 'dest'.
'''
sc = Path(dest)
if sc.exists():
sc.unlink()
def apply_desktop(self, dest):
'''
Apply .desktop file by action.
'''
if self.action == 'U':
self._write_desktop(dest, read_firstly=True)
elif self.action == 'D':
self._remove_desktop(dest)
elif self.action == 'R':
self._remove_desktop(dest)
self._write_desktop(dest)
elif self.action == 'C':
self._write_desktop(dest, create_only=True)

View File

@@ -23,6 +23,8 @@ import sys
import argparse
import subprocess
import re
from util.util import (
runcmd
, get_backends
@@ -31,14 +33,17 @@ from util.util import (
, get_policy_variants
)
from util.config import GPConfig
from util.paths import get_custom_policy_dir
class Runner:
__control_path = '/usr/sbin/control'
__systemctl_path = '/bin/systemctl'
__etc_policy_dir = '/etc/local-policy'
__usr_policy_dir = '/usr/share/local-policy'
def __init__(self):
self.etc_policies = get_policy_entries(self.__etc_policy_dir)
self.usr_policies = get_policy_entries(self.__usr_policy_dir)
self.arguments = parse_arguments()
def parse_arguments():
@@ -189,13 +194,13 @@ def disable_gp():
runcmd(cmd_set_local_policy)
runcmd(cmd_disable_gpupdate_service)
runcmd(cmd_disable_gpupdate_user_service)
config.set_local_policy_template()
config.set_backend()
def enable_gp(policy_name, backend_type):
'''
Consistently enable group policy services
'''
policy_dir = '/usr/share/local-policy'
etc_policy_dir = '/etc/local-policy'
cmd_set_gpupdate_policy = ['/usr/sbin/control', 'system-policy', 'gpupdate']
cmd_gpoa_nodomain = ['/usr/sbin/gpoa', '--nodomain', '--loglevel', '5']
cmd_enable_gpupdate_service = ['/bin/systemctl', 'enable', 'gpupdate.service']
@@ -203,17 +208,18 @@ def enable_gp(policy_name, backend_type):
config = GPConfig()
custom_policy_dir = get_custom_policy_dir()
if not os.path.isdir(custom_policy_dir):
os.makedirs(custom_policy_dir)
target_policy_name = get_default_policy_name()
if policy_name:
if validate_policy_name(policy_name):
target_policy_name = policy_name
print (target_policy_name)
config.set_local_policy_template(target_policy_name)
print (target_policy_name)
default_policy_name = os.path.join(policy_dir, target_policy_name)
if not os.path.isdir(etc_policy_dir):
os.makedirs(etc_policy_dir)
config.set_local_policy_template(default_policy_name)
config.set_backend(backend_type)
# Enable oddjobd_gpupdate in PAM config

View File

@@ -41,27 +41,6 @@ msgstr "Получен объект групповой политики"
msgid "Unknown info code"
msgstr "Неизвестный код информационного сообщения"
msgid "Working with control"
msgstr "Применение настроек control"
msgid "Working with systemd"
msgstr "Работа с systemd"
msgid "Unable to work with systemd unit"
msgstr "Невозможно создать оъект для unit systemd"
msgid "Starting systemd unit"
msgstr "Запуск unit systemd"
msgid "Firefox policy"
msgstr "Политика Firefox"
msgid "Chromium policy"
msgstr "Политика Chromium"
msgid "Set user property to"
msgstr "Установка свойств для пользователя"
# Error
msgid "Insufficient permissions to run gpupdate"
msgstr "Недостаточно прав для запуска gpupdate"
@@ -153,59 +132,6 @@ msgstr "Ошибка слияния пользовательской части
msgid "Unknown error code"
msgstr "Неизвестный код ошибки"
msgid "Unable to work with control"
msgstr "Не удалось применить настройки control"
msgid "Control applier for machine will not be started"
msgstr "Приминение Control для машины не удалось"
msgid "Error getting control"
msgstr "Ошибка установки control"
msgid "Is not in possible values for control"
msgstr "Не входит в возможные значения для control"
msgid "Unable to set"
msgstr "Невозможно установить"
msgid "Unable to generate file"
msgstr "Невозможно создать файл"
msgid "Failed applying unit"
msgstr "Не удалось применить настройки"
msgid "Unable to start systemd unit"
msgstr "Невозможно запустить systemd unit"
msgid "Unable to cache specified URI"
msgstr "Невозможно кэшировать указанный URI"
msgid "Unable to cache specified URI for machine"
msgstr "Невозможно кэшировать указанный URI для компьютера"
msgid "Error recompiling global GSettings schemas"
msgstr "Ошибка перекомпиляции глобальных GSettings schemas"
msgid "Error update configuration dconf"
msgstr "Ошибка обновления конфигурации dconf"
msgid "Unable to cache specified URI for user"
msgstr "Невозможно кэшировать указанный URI для пользователя"
msgid "Chromium preferences file does not exist at the moment"
msgstr "Файл настроек Chromium в данный момент не существует"
msgid "Error during attempt to read Chromium preferences for user"
msgstr "Ошибка при попытке прочитать настройки Chromium для пользователя"
msgid "Fail for applying shortcut to file with %"
msgstr "Не удалось применить ярлык к файлу с %"
msgid "Fail for applying shortcut to not absolute path"
msgstr "Не удалось применить ярлык к не абсолютному пути"
# Error_end
# Debug
msgid "The GPOA process was started for user"
msgstr "Произведён запуск GPOA для обновления политик пользователя"
@@ -363,179 +289,9 @@ msgstr "Пропускаем специальный ключ удаления в
msgid "Read domain name from configuration file"
msgstr "Имя контроллера домена для репликации прочитано из файла конфигурации"
msgid "Saving information about environment variables"
msgstr "Сохранение информации о переменных окружения"
msgid "Unknown debug code"
msgstr "Неизвестный отладочный код"
msgid "Running Control applier for machine"
msgstr "Начато применение Control для машины"
msgid "Setting control"
msgstr "Установка control"
msgid "Deny_All setting found"
msgstr "Deny_All настройка найдена"
msgid "Deny_All setting for user"
msgstr "Deny_All настройка для пользователя"
msgid "Deny_All setting not found"
msgstr "Deny_All настройка не найдена"
msgid "Deny_All setting not found for user"
msgstr "Deny_All настройка не найдена для пользователя"
msgid "Running Polkit applier for machine"
msgstr "Начато применение настроек Polkit для машины"
msgid "Running Polkit applier for user in administrator context"
msgstr "Начато применение настроек Polkit пользователя в контексте администратора"
msgid "Polkit applier for machine will not be started"
msgstr "Polkit для машины не запускается"
msgid "Polkit applier for user in administrator context will not be started"
msgstr "Polkit для пользователя в контексте администратора не запускается"
msgid "Generated file"
msgstr "Созданный файл"
msgid "Running systemd applier for machine"
msgstr "Начато применение настроек systemd для машины"
msgid "Running systemd applier for machine will not be started"
msgstr "Применение настроек systemd для машины не удалось"
msgid "Running GSettings applier for machine"
msgstr "Запуск применение настроек GSettings для машины"
msgid "GSettings applier for machine will not be started"
msgstr "Применение настроек GSettings для машины не удалось"
msgid "Removing GSettings policy file from previous run"
msgstr "Удаление файла политики GSettings от предыдущего запуска"
msgid "Mapping Windows policies to GSettings policies"
msgstr "Сопоставление политик Windows с политиками GSettings"
msgid "GSettings windows policies mapping not enabled"
msgstr "Сопоставление политик Windows GSettings не включено"
msgid "Applying user setting"
msgstr "Применение пользовательских настроек"
msgid "Found GSettings windows mapping"
msgstr "Найдены соответствия настроек windows-GSettings"
msgid "Running GSettings applier for user in user context"
msgstr "Запуск применение настроек GSettings в контексте пользователя"
msgid "GSettings applier for user in user context will not be started"
msgstr "GSettings в контексте пользователя не запускается"
msgid "Applying machine setting"
msgstr "Применение настроек машины"
msgid "Path not resolved as UNC URI"
msgstr "Путь не разрешен"
msgid "Getting cached file for URI"
msgstr "Получение кешированного файла для URI"
msgid "Wrote Firefox preferences to"
msgstr "Настройки Firefox записаны в"
msgid "Found Firefox profile in"
msgstr "Найден профиль Firefox в"
msgid "Running Firefox applier for machine"
msgstr "Запуск применение настроек Firefox для машины"
msgid "Firefox applier for machine will not be started"
msgstr "Применение настроек Firefox для компьютера не запускается"
msgid "Running Chromium applier for machine"
msgstr "Запуск применение настроек Chromium для машины"
msgid "Chromium applier for machine will not be started"
msgstr "Применение настроек Chromium для компьютера не запускается"
msgid "Wrote Chromium preferences to"
msgstr "Настройки Chromium записаны в"
msgid "Running Shortcut applier for machine"
msgstr "Запуск применение ярлыков для машины"
msgid "Shortcut applier for machine will not be started"
msgstr "Применение ярлыков для компьютера не запускается"
msgid "No shortcuts to process for"
msgstr "Нет ярлыков для обработки"
msgid "Running Shortcut applier for user in user context"
msgstr "Запуск применение ярлыков в контексте пользователя"
msgid "Shortcut applier for user in user context will not be started"
msgstr "Применение ярлыков в контексте пользователя не запускается"
msgid "Running Shortcut applier for user in administrator context"
msgstr "Запуск применение ярлыков в контексте администратора"
msgid "Shortcut applier for user in administrator context will not be started"
msgstr "Применение ярлыков в контексте администратора не запускается"
msgid "Try to expand path for shortcut"
msgstr "Попытка расширить путь для ярлыка"
msgid "Applying shortcut file to"
msgstr "Применение ярлыка к файлу"
msgid "Running Folder applier for machine"
msgstr "Запуск применение папок для машины"
msgid "Folder applier for machine will not be started"
msgstr "Применение папок для машины не запускается"
msgid "Running Folder applier for user in administrator context"
msgstr "Запуск применение папок в контексте администратора"
msgid "Folder applier for user in administrator context will not be started"
msgstr "Применение папок в контексте администратора не запускается"
msgid "Running Folder applier for user in user context"
msgstr "Запуск применение папок в контексте пользователя"
msgid "Folder applier for user in user context will not be started"
msgstr "Применение папок в контексте пользователя не запускается"
msgid "Running CUPS applier for machine"
msgstr "Запуск применение настроек CUPS для машины"
msgid "CUPS applier for machine will not be started"
msgstr "Применение настроек CUPS для машины не запускается"
msgid "Running CUPS applier for user in administrator context"
msgstr "Запуск применение настроек CUPS в контексте пользователя"
msgid "CUPS applier for user in administrator context will not be started"
msgstr "Применение настроек CUPS в контексте пользователя не запускается"
msgid "Running Firewall applier for machine"
msgstr "Запуск применение настроек Firewall для машины"
msgid "Firewall is enabled"
msgstr "Firewall включен"
msgid "Firewall is disabled, settings will be reset"
msgstr "Firewall отключен, настройки будут сброшены"
msgid "Firewall applier will not be started"
msgstr "Применение настроек Firewall не запускается"
# Debug_end
# Warning
msgid "Unable to perform gpupdate for non-existent user, will update machine settings"
msgstr "Невозможно запустить gpupdate для несуществующего пользователя, будут обновлены настройки машины"
@@ -556,18 +312,6 @@ msgstr "Пакет ADP не установлен, плагин не будет
msgid "Unknown warning code"
msgstr "Неизвестный код предупреждения"
msgid "Unable to resolve GSettings parameter"
msgstr "Не удалось установить параметр GSettings"
msgid "No home directory exists for user"
msgstr "Для пользователя не существует домашнего каталога"
msgid "User's shortcut not placed to home directory"
msgstr "Ярлык пользователя не помещен в домашний каталог"
msgid "CUPS is not installed: no printer settings will be deployed"
msgstr "CUPS не установлен: настройки принтера не будут развернуты"
# Fatal
msgid "Unable to refresh GPO list"
msgstr "Невозможно обновить список объектов групповых политик"

View File

@@ -23,13 +23,6 @@ def info_code(code):
info_ids = dict()
info_ids[1] = 'Got GPO list for username'
info_ids[2] = 'Got GPO'
info_ids[3] = 'Working with control'
info_ids[4] = 'Working with systemd'
info_ids[5] = 'Unable to work with systemd unit'
info_ids[6] = 'Starting systemd unit'
info_ids[7] = 'Firefox policy'
info_ids[8] = 'Chromium policy'
info_ids[9] = 'Set user property to'
return info_ids.get(code, 'Unknown info code')
@@ -64,31 +57,6 @@ def error_code(code):
error_ids[27] = 'Error merging user GPT'
error_ids[28] = 'Error merging machine part of GPT'
error_ids[29] = 'Error merging user part of GPT'
error_ids[30] = 'Error occured while running dropped privileges process for user context appliers'
error_ids[31] = 'Error connecting to DBus Session daemon'
error_ids[32] = 'No reply from DBus Session'
error_ids[33] = 'Error occured while running forked process with dropped privileges'
error_ids[34] = 'Error running GPOA directly for computer'
error_ids[35] = 'Error caching URI to file'
error_ids[36] = 'Error getting cached file for URI'
error_ids[37] = 'Error caching file URIs'
error_ids[38] = 'Unable to cache specified URI'
error_ids[39] = 'Unable to work with control'
error_ids[40] = 'Control applier for machine will not be started'
error_ids[41] = 'Error getting control'
error_ids[42] = 'Is not in possible values for control'
error_ids[43] = 'Unable to set'
error_ids[44] = 'Unable to generate file'
error_ids[45] = 'Failed applying unit'
error_ids[46] = 'Unable to start systemd unit'
error_ids[47] = 'Unable to cache specified URI for machine'
error_ids[48] = 'Error recompiling global GSettings schemas'
error_ids[49] = 'Error update configuration dconf'
error_ids[50] = 'Unable to cache specified URI for user'
error_ids[51] = 'Chromium preferences file does not exist at the moment'
error_ids[52] = 'Error during attempt to read Chromium preferences for user'
error_ids[53] = 'Fail for applying shortcut to file with \'%\''
error_ids[54] = 'Fail for applying shortcut to not absolute path'
return error_ids.get(code, 'Unknown error code')
@@ -146,74 +114,6 @@ def debug_code(code):
debug_ids[50] = 'Finished GPO replication from AD DC'
debug_ids[51] = 'Skipping HKCU branch deletion key'
debug_ids[52] = 'Read domain name from configuration file'
debug_ids[53] = 'Saving information about environment variables'
debug_ids[54] = 'Run forked process with droped privileges'
debug_ids[55] = 'Run user context applier with dropped privileges'
debug_ids[56] = 'Kill dbus-daemon and dconf-service in user context'
debug_ids[57] = 'Found connection by org.freedesktop.DBus.GetConnectionUnixProcessID'
debug_ids[58] = 'Connection search return org.freedesktop.DBus.Error.NameHasNoOwner'
debug_ids[59] = 'Running GPOA without GPT update directly for user'
debug_ids[60] = 'Running GPOA by root for user'
debug_ids[61] = 'The GPOA process was started for computer'
debug_ids[62] = 'Path not resolved as UNC URI'
debug_ids[63] = 'Delete HKLM branch key'
debug_ids[64] = 'Delete HKCU branch key'
debug_ids[65] = 'Delete HKLM branch key error'
debug_ids[66] = 'Delete HKCU branch key error'
debug_ids[67] = 'Running Control applier for machine'
debug_ids[68] = 'Setting control'
debug_ids[69] = 'Deny_All setting found'
debug_ids[70] = 'Deny_All setting for user'
debug_ids[71] = 'Deny_All setting not found'
debug_ids[72] = 'Deny_All setting not found for user'
debug_ids[73] = 'Running Polkit applier for machine'
debug_ids[74] = 'Running Polkit applier for user in administrator context'
debug_ids[75] = 'Polkit applier for machine will not be started'
debug_ids[76] = 'Polkit applier for user in administrator context will not be started'
debug_ids[77] = 'Generated file'
debug_ids[78] = 'Running systemd applier for machine'
debug_ids[79] = 'Running systemd applier for machine will not be started'
debug_ids[80] = 'Running GSettings applier for machine'
debug_ids[81] = 'GSettings applier for machine will not be started'
debug_ids[82] = 'Removing GSettings policy file from previous run'
debug_ids[83] = 'Mapping Windows policies to GSettings policies'
debug_ids[84] = 'GSettings windows policies mapping not enabled'
debug_ids[85] = 'Applying user setting'
debug_ids[86] = 'Found GSettings windows mapping'
debug_ids[87] = 'Running GSettings applier for user in user context'
debug_ids[88] = 'GSettings applier for user in user context will not be started'
debug_ids[89] = 'Applying machine setting'
debug_ids[90] = 'Getting cached file for URI'
debug_ids[91] = 'Wrote Firefox preferences to'
debug_ids[92] = 'Found Firefox profile in'
debug_ids[93] = 'Running Firefox applier for machine'
debug_ids[94] = 'Firefox applier for machine will not be started'
debug_ids[95] = 'Running Chromium applier for machine'
debug_ids[96] = 'Chromium applier for machine will not be started'
debug_ids[97] = 'Wrote Chromium preferences to'
debug_ids[98] = 'Running Shortcut applier for machine'
debug_ids[99] = 'Shortcut applier for machine will not be started'
debug_ids[100] = 'No shortcuts to process for'
debug_ids[101] = 'Running Shortcut applier for user in user context'
debug_ids[102] = 'Shortcut applier for user in user context will not be started'
debug_ids[103] = 'Running Shortcut applier for user in administrator context'
debug_ids[104] = 'Shortcut applier for user in administrator context will not be started'
debug_ids[105] = 'Try to expand path for shortcut'
debug_ids[106] = 'Applying shortcut file to'
debug_ids[107] = 'Running Folder applier for machine'
debug_ids[108] = 'Folder applier for machine will not be started'
debug_ids[109] = 'Running Folder applier for user in administrator context'
debug_ids[110] = 'Folder applier for user in administrator context will not be started'
debug_ids[111] = 'Running Folder applier for user in user context'
debug_ids[112] = 'Folder applier for user in user context will not be started'
debug_ids[113] = 'Running CUPS applier for machine'
debug_ids[114] = 'CUPS applier for machine will not be started'
debug_ids[115] = 'Running CUPS applier for user in administrator context'
debug_ids[116] = 'CUPS applier for user in administrator context will not be started'
debug_ids[117] = 'Running Firewall applier for machine'
debug_ids[118] = 'Firewall is enabled'
debug_ids[119] = 'Firewall is disabled, settings will be reset'
debug_ids[120] = 'Firewall applier will not be started'
return debug_ids.get(code, 'Unknown debug code')
@@ -230,11 +130,6 @@ def warning_code(code):
warning_ids[3] = 'oddjobd is inaccessible'
warning_ids[4] = 'No SYSVOL entry assigned to GPO'
warning_ids[5] = 'ADP package is not installed - plugin will not be initialized'
warning_ids[6] = 'Unable to resolve GSettings parameter'
warning_ids[7] = 'No home directory exists for user'
warning_ids[8] = 'User\'s shortcut not placed to home directory'
warning_ids[9] = 'CUPS is not installed: no printer settings will be deployed'
return warning_ids.get(code, 'Unknown warning code')

View File

@@ -1,120 +0,0 @@
#!/usr/bin/python3
#
# 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 rpm
import subprocess
from gpoa.storage import registry_factory
import logging
import argparse
def is_rpm_installed(rpm_name):
'''
Check if the package named 'rpm_name' is installed
'''
ts = rpm.TransactionSet()
pm = ts.dbMatch('name', rpm_name)
if pm.count() > 0:
return True
return False
class Pkcon_applier:
def __init__(self, sid = None):
self.sid = sid
self.__install_key_name = 'Install'
self.__remove_key_name = 'Remove'
self.__hkcu_branch = 'Software\\BaseALT\\Policies\\Packages'
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 = list()
self.remove_packages = list()
self.storage = registry_factory('registry')
if sid:
install_branch_user = '{}\\{}%'.format(self.__hkcu_branch, self.__install_key_name)
remove_branch_user = '{}\\{}%'.format(self.__hkcu_branch, self.__remove_key_name)
self.install_packages_setting = self.storage.filter_hkcu_entries(self.sid, install_branch_user)
self.remove_packages_setting = self.storage.filter_hkcu_entries(self.sid, remove_branch_user)
else:
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 is_rpm_installed(package.data) == False:
self.install_packages.append(package.data)
for package in self.remove_packages_setting:
if is_rpm_installed(package.data):
self.remove_packages.append(package.data)
self.install_packages = list(set(self.install_packages) - set(self.remove_packages))
def run(self):
self.update()
for package in self.remove_packages:
try:
self.remove_pkg(package)
except Exception as exc:
logging.debug(exc)
for package in self.install_packages:
try:
self.install_pkg(package)
except Exception as exc:
logging.debug(exc)
def apply(self):
self.run()
def install_pkg(self, package_name):
fullcmd = list(self.__install_command)
fullcmd.append(package_name)
return subprocess.check_call(fullcmd)
def reinstall_pkg(self, package_name):
fullcmd = list(self.__reinstall_command)
fullcmd.append(self.package_name)
return subprocess.check_call(fullcmd)
def remove_pkg(self, package_name):
fullcmd = self.__remove_command
fullcmd.append(package_name)
return subprocess.check_call(fullcmd)
def update(self):
'''
Update APT-RPM database.
'''
try:
subprocess.check_call(['/usr/bin/apt-get', 'update'])
except Exception as exc:
logging.debug(exc)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Package applier')
parser.add_argument('sid', type = str, help = 'sid', nargs = '?', default = None)
args = parser.parse_args()
if args.sid:
applier = Pkcon_applier(args.sid)
else:
applier = Pkcon_applier()
applier.apply()

View File

@@ -1,97 +0,0 @@
#
# GPOA - GPO Applier for Linux
#
# 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
# 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
import os.path
from pathlib import Path
import smbc
from util.logging import log
from util.paths import file_cache_dir, UNCPath
from util.exceptions import NotUNCPathError
class fs_file_cache:
__read_blocksize = 4096
def __init__(self, cache_name):
self.cache_name = cache_name
self.storage_uri = file_cache_dir()
logdata = dict({'cache_file': self.storage_uri})
log('D20', logdata)
self.samba_context = smbc.Context(use_kerberos=1)
#, debug=10)
def store(self, uri):
destdir = uri
try:
uri_path = UNCPath(uri)
file_name = os.path.basename(uri_path.get_path())
file_path = os.path.dirname(uri_path.get_path())
destdir = Path('{}/{}/{}'.format(self.storage_uri,
uri_path.get_domain(),
file_path))
except Exception as exc:
logdata = dict({'exception': str(exc)})
log('E38', logdata)
raise exc
if not destdir.exists():
destdir.mkdir(parents=True, exist_ok=True)
destfile = Path('{}/{}/{}'.format(self.storage_uri,
uri_path.get_domain(),
uri_path.get_path()))
with open(destfile, 'wb') as df:
df.truncate()
df.flush()
try:
file_handler = self.samba_context.open(str(uri_path), os.O_RDONLY)
while True:
data = file_handler.read(self.__read_blocksize)
if not data:
break
df.write(data)
df.flush()
except Exception as exc:
logdata = dict({'exception': str(exc)})
log('E35', logdata)
raise exc
def get(self, uri):
destfile = uri
try:
uri_path = UNCPath(uri)
file_name = os.path.basename(uri_path.get_path())
file_path = os.path.dirname(uri_path.get_path())
destfile = Path('{}/{}/{}'.format(self.storage_uri,
uri_path.get_domain(),
uri_path.get_path()))
except NotUNCPathError as exc:
logdata = dict({'path': str(exc)})
log('D62', logdata)
except Exception as exc:
logdata = dict({'exception': str(exc)})
log('E36', logdata)
raise exc
return str(destfile)

View File

@@ -22,9 +22,7 @@ class samba_preg(object):
'''
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.hive_key = '{}\\{}'.format(preg_obj.keyname, preg_obj.valuename)
self.type = preg_obj.type
self.data = preg_obj.data
@@ -43,9 +41,7 @@ class samba_hkcu_preg(object):
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.hive_key = '{}\\{}'.format(preg_obj.keyname, preg_obj.valuename)
self.type = preg_obj.type
self.data = preg_obj.data
@@ -152,25 +148,3 @@ class folder_entry(object):
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

View File

@@ -43,7 +43,6 @@ from .record_types import (
, printer_entry
, drive_entry
, folder_entry
, envvar_entry
)
class sqlite_registry(registry):
@@ -66,10 +65,7 @@ class sqlite_registry(registry):
'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('hive_key', String(65536), unique=True)
, Column('policy_name', String)
, Column('type', Integer)
, Column('data', String)
@@ -79,9 +75,7 @@ class sqlite_registry(registry):
, 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('hive_key', String(65536))
, Column('policy_name', String)
, Column('type', Integer)
, Column('data', String)
@@ -132,17 +126,6 @@ class sqlite_registry(registry):
, Column('delete_files', 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.__metadata.create_all(self.db_cnt)
Session = sessionmaker(bind=self.db_cnt)
self.db_session = Session()
@@ -154,7 +137,6 @@ class sqlite_registry(registry):
mapper(printer_entry, self.__printers)
mapper(drive_entry, self.__drives)
mapper(folder_entry, self.__folders)
mapper(envvar_entry, self.__envvars)
except:
pass
#logging.error('Error creating mapper')
@@ -244,52 +226,16 @@ class sqlite_registry(registry):
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('**'):
if not pentry.hive_key.rpartition('\\')[2].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)
log('D27', logdata)
def add_hkcu_entry(self, preg_entry, sid, policy_name):
'''
@@ -297,14 +243,11 @@ class sqlite_registry(registry):
'''
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('**'):
if not hkcu_pentry.hive_key.rpartition('\\')[2].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)
log('D51', logdata)
def add_shortcut(self, sid, sc_obj, policy_name):
'''
@@ -351,21 +294,6 @@ class sqlite_registry(registry):
.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 _filter_sid_obj(self, row_object, sid):
res = (self
.db_session
@@ -378,7 +306,6 @@ class sqlite_registry(registry):
.db_session
.query(row_object)
.filter(row_object.sid == sid)
.order_by(row_object.id)
.all())
return res
@@ -394,9 +321,6 @@ class sqlite_registry(registry):
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 get_hkcu_entry(self, sid, hive_key):
res = (self
.db_session

View File

@@ -45,7 +45,7 @@ class GPConfig:
return 'samba'
def set_backend(self, backend_name='local'):
def set_backend(self, backend_name):
self.full_config['gpoa']['backend'] = backend_name
self.write_config()
@@ -71,7 +71,7 @@ class GPConfig:
return get_default_policy_name()
def set_local_policy_template(self, template_name='default'):
def set_local_policy_template(self, template_name):
self.full_config['gpoa']['local-policy'] = template_name
self.write_config()

View File

@@ -29,38 +29,22 @@ class dbus_runner:
'''
_bus_name = 'com.redhat.oddjob_gpupdate'
# Interface name is equal to bus name.
_interface_name = 'com.redhat.oddjob_gpupdate'
_object_path = '/'
# The timeout is in milliseconds. The default is -1 which is
# DBUS_TIMEOUT_USE_DEFAULT which is 25 seconds. There is also
# DBUS_TIMEOUT_INFINITE constant which is equal to INT32_MAX or
# 0x7ffffff (largest 32-bit integer).
#
# It was decided to set the timeout to 10 minutes which must be
# sufficient to replicate and apply all recognizable GPOs.
_synchronous_timeout = 600000
def __init__(self, username=None):
self.username = username
self.system_bus = dbus.SystemBus()
system_bus = dbus.SystemBus()
obj = system_bus.get_object(self._bus_name, self._object_path)
self.interface = dbus.Interface(obj, self._bus_name)
def run(self):
#print(obj.Introspect()[0])
if self.username:
logdata = dict({'username': self.username})
log('D6', logdata)
if is_root():
# oddjobd-gpupdate's ACL allows access to this method
# only for superuser. This method is called via PAM
# when user logs in.
try:
result = self.system_bus.call_blocking(self._bus_name,
self._object_path,
self._interface_name,
'gpupdatefor',
(username),
(dbus.String(self.username)),
timeout=self._synchronous_timeout)
result = self.interface.gpupdatefor(dbus.String(self.username))
print_dbus_result(result)
except dbus.exceptions.DBusException as exc:
logdata = dict()
@@ -69,36 +53,20 @@ class dbus_runner:
raise exc
else:
try:
result = self.system_bus.call_blocking(self._bus_name,
self._object_path,
self._interface_name,
'gpupdate',
None,
(),
timeout=self._synchronous_timeout)
result = self.interface.gpupdate()
print_dbus_result(result)
except dbus.exceptions.DBusException as exc:
logdata = dict({'error': str(exc)})
log('E21', logdata)
log('E21')
raise exc
else:
log('D11')
try:
result = self.system_bus.call_blocking(self._bus_name,
self._object_path,
self._interface_name,
'gpupdate_computer',
None,
# The following positional parameter is called "args".
# There is no official documentation for it.
(),
timeout=self._synchronous_timeout)
result = self.interface.gpupdate_computer()
print_dbus_result(result)
except dbus.exceptions.DBusException as exc:
print(exc)
logdata = dict({'error': str(exc)})
log('E22', logdata)
log('E22')
raise exc
#self.interface.Quit()
def start_gpupdate_user():
@@ -170,27 +138,3 @@ def print_dbus_result(result):
for line in message:
print(str(line))
class dbus_session:
def __init__(self):
try:
self.session_bus = dbus.SessionBus()
self.session_dbus = self.session_bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
self.session_iface = dbus.Interface(self.session_dbus, 'org.freedesktop.DBus')
except dbus.exceptions.DBusException as exc:
logdata = dict({'error': str(exc)})
log('E31', logdata)
raise exc
def get_connection_pid(self, connection):
pid = -1
try:
pid = self.session_iface.GetConnectionUnixProcessID(connection)
log('D57', {"pid": pid})
except dbus.exceptions.DBusException as exc:
if exc.get_dbus_name() != 'org.freedesktop.DBus.Error.NameHasNoOwner':
logdata = dict({'error': str(exc)})
log('E32', logdata)
raise exc
log('D58', {'connection': connection})
return int(pid)

View File

@@ -39,10 +39,3 @@ def geterr():
return traceinfo
class NotUNCPathError(Exception):
def __init__(self, path):
self.path = path
def __str__(self):
return self.path

View File

@@ -21,19 +21,15 @@ import subprocess
from .util import get_machine_name
from .logging import log
from .samba import smbopts
def machine_kinit(cache_name=None):
'''
Perform kinit with machine credentials
'''
opts = smbopts()
host = get_machine_name()
realm = opts.get_realm()
with_realm = '{}@{}'.format(host, realm)
os.environ['KRB5CCNAME'] = 'FILE:{}'.format(cache_name)
kinit_cmd = ['kinit', '-k', with_realm]
kinit_cmd = ['kinit', '-k', host]
if cache_name:
kinit_cmd.extend(['-c', cache_name])
proc = subprocess.Popen(kinit_cmd)
@@ -59,9 +55,8 @@ def machine_kdestroy(cache_name=None):
if cache_name:
kdestroy_cmd.extend(['-c', cache_name])
if cache_name or 'KRB5CCNAME' in os.environ:
proc = subprocess.Popen(kdestroy_cmd, stderr=subprocess.DEVNULL)
proc.wait()
proc = subprocess.Popen(kdestroy_cmd, stderr=subprocess.DEVNULL)
proc.wait()
if cache_name and os.path.exists(cache_name):
os.unlink(cache_name)
@@ -79,13 +74,10 @@ def check_krb_ticket():
try:
subprocess.check_call(['klist', '-s'])
output = subprocess.check_output('klist', stderr=subprocess.STDOUT).decode()
logging.info(output)
result = True
logdata = dict()
logdata['output'] = output
log('D17', logdata)
except Exception as exc:
logdata = dict()
logdata['krb-exc'] = exc
log('E14', logdata)
log('D17')
except:
log('E14')
return result

View File

@@ -1,8 +1,7 @@
#
# GPOA - GPO Applier for Linux
#
# Copyright (C) 2019-2021 BaseALT Ltd. <org@basealt.ru>
# Copyright (C) 2019-2021 Igor Chudov <nir@nir.org.ru>
# 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,38 +18,25 @@
import pathlib
import os
from pathlib import Path
from urllib.parse import urlparse
from .config import GPConfig
from .exceptions import NotUNCPathError
def get_custom_policy_dir():
def default_policy_path():
'''
Returns path pointing to Custom Policy directory.
Returns path pointing to Default Policy directory.
'''
return '/etc/local-policy'
def local_policy_path(default_template_name="default"):
'''
Returns path pointing to Local Policy template directory.
'''
local_policy_dir = '/usr/share/local-policy'
local_policy_default = '/usr/share/local-policy/default'
config = GPConfig()
local_policy_template = config.get_local_policy_template()
local_policy_template_path = os.path.join(local_policy_dir, local_policy_template)
local_policy_default = os.path.join(local_policy_dir, default_template_name)
result_path = pathlib.Path(local_policy_default)
if os.path.exists(local_policy_template):
result_path = pathlib.Path(local_policy_template)
elif os.path.exists(local_policy_template_path):
result_path = pathlib.Path(local_policy_template_path)
if os.path.exists(config.get_local_policy_template()):
result_path = pathlib.Path(config.get_local_policy_template())
return pathlib.Path(result_path)
def cache_dir():
'''
Returns path pointing to gpupdate's cache directory
@@ -62,16 +48,6 @@ def cache_dir():
return cachedir
def file_cache_dir():
'''
Returns path pointing to gpupdate's cache directory
'''
cachedir = pathlib.Path('/var/cache/gpupdate_file_cache')
if not cachedir.exists():
cachedir.mkdir(parents=True, exist_ok=True)
return cachedir
def local_policy_cache():
'''
@@ -85,46 +61,3 @@ def local_policy_cache():
return lpcache
class UNCPath:
def __init__(self, path):
self.path = path
self.type = None
if self.path.startswith(r'smb://'):
self.type = 'uri'
if self.path.startswith(r'\\'):
self.type = 'unc'
if not self.type:
raise NotUNCPathError(path)
def get_uri(self):
path = self.path
if self.type == 'unc':
path = self.path.replace('\\', '/')
path = path.replace('//', 'smb://')
else:
pass
return path
def get_unc(self):
path = self.path
if self.type == 'uri':
path = self.path.replace('//', '\\\\')
path = path.replace('smb:\\\\', '\\\\')
path = path.replace('/', '\\')
else:
pass
return path
def get_domain(self):
schema_struct = urlparse(self.get_uri())
return schema_struct.netloc
def get_path(self):
schema_struct = urlparse(self.get_uri())
return schema_struct.path
def __str__(self):
return self.get_uri()

View File

@@ -18,7 +18,6 @@
import optparse
import socket
from samba import getopt as options
@@ -29,32 +28,11 @@ class smbopts:
self.sambaopts = options.SambaOptions(self.parser)
self.lp = self.sambaopts.get_loadparm()
def get_realm(self):
'''
Get the default realm specified in smb.conf file.
'''
return self._get_prop('realm')
def get_cache_dir(self):
return self._get_prop('cache directory')
def get_server_role(self):
return self._get_prop('server role')
def get_machine_name(self):
'''
Get localhost name looking like DC0$
'''
nb_name = self.get_netbios_name()
result = nb_name + "$"
if result == '':
result = socket.gethostname().split('.', 1)[0].upper() + "$"
return result
def get_netbios_name(self):
return self._get_prop('netbios name')
def _get_prop(self, property_name):
return self.lp.get(property_name)

View File

@@ -1,141 +0,0 @@
#
# GPOA - GPO Applier for Linux
#
# Copyright (C) 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
# 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
import sys
import pwd
import signal
import subprocess
from .logging import log
from .dbus import dbus_session
def set_privileges(username, uid, gid, groups, home):
'''
Set current process privileges
'''
os.environ.clear()
os.environ['HOME'] = home
os.environ['USER'] = username
os.environ['USERNAME'] = username
try:
os.setgid(gid)
except Exception as exc:
raise Exception('Error setgid() for drop privileges: {}'.format(str(exc)))
try:
os.setgroups(groups)
except Exception as exc:
raise Exception('Error setgroups() for drop privileges: {}'.format(str(exc)))
try:
os.setuid(uid)
except Exception as exc:
raise Exception('Error setuid() for drop privileges: {}'.format(str(exc)))
os.chdir(home)
logdata = dict()
logdata['uid'] = uid
logdata['gid'] = gid
logdata['username'] = username
log('D37', logdata)
def with_privileges(username, func):
'''
Run supplied function with privileges for specified username.
'''
if not os.getuid() == 0:
raise Exception('Not enough permissions to drop privileges')
user_pw = pwd.getpwnam(username)
user_uid = user_pw.pw_uid
user_gid = user_pw.pw_gid
user_groups = os.getgrouplist(username, user_gid)
user_home = user_pw.pw_dir
if not os.path.isdir(user_home):
raise Exception('User home directory not exists')
pid = os.fork()
if pid > 0:
log('D54', {'pid': pid})
waitpid, status = os.waitpid(pid, 0)
code = os.WEXITSTATUS(status)
if code != 0:
raise Exception('Error in forked process ({})'.format(status))
return
# We need to return child error code to parent
result = 0
dbus_pid = -1
dconf_pid = -1
try:
# Drop privileges
set_privileges(username, user_uid, user_gid, user_groups, user_home)
# Run the D-Bus session daemon in order D-Bus calls to work
proc = subprocess.Popen(
'dbus-launch',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
for var in proc.stdout:
sp = var.decode('utf-8').split('=', 1)
os.environ[sp[0]] = sp[1][:-1]
# Save pid of dbus-daemon
dbus_pid = int(os.environ['DBUS_SESSION_BUS_PID'])
# Run user appliers
func()
# Save pid of dconf-service
dconf_connection = "ca.desrt.dconf"
try:
session = dbus_session()
dconf_pid = session.get_connection_pid(dconf_connection)
except Exception:
pass
except Exception as exc:
logdata = dict()
logdata['msg'] = str(exc)
log('E33', logdata)
result = 1;
finally:
logdata = dict()
logdata['dbus_pid'] = dbus_pid
logdata['dconf_pid'] = dconf_pid
log('D56', logdata)
if dbus_pid > 0:
os.kill(dbus_pid, signal.SIGHUP)
if dconf_pid > 0:
os.kill(dconf_pid, signal.SIGTERM)
if dbus_pid > 0:
os.kill(dbus_pid, signal.SIGTERM)
sys.exit(result)

View File

@@ -1,7 +1,7 @@
#
# GPOA - GPO Applier for Linux
#
# Copyright (C) 2019-2021 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
@@ -55,3 +55,59 @@ def username_match_uid(username):
return False
def set_privileges(username, uid, gid, groups=list()):
'''
Set current process privileges
'''
try:
os.setegid(gid)
except Exception as exc:
print('setegid')
try:
os.seteuid(uid)
except Exception as exc:
print('seteuid')
#try:
# os.setgroups(groups)
#except Exception as exc:
# print('setgroups')
logdata = dict()
logdata['uid'] = uid
logdata['gid'] = gid
logdata['username'] = username
log('D37', logdata)
def with_privileges(username, func):
'''
Run supplied function with privileges for specified username.
'''
current_uid = os.getuid()
current_groups = os.getgrouplist('root', 0)
if not current_uid == 0:
raise Exception('Not enough permissions to drop privileges')
user_uid = pwd.getpwnam(username).pw_uid
user_gid = pwd.getpwnam(username).pw_gid
user_groups = os.getgrouplist(username, user_gid)
# Drop privileges
set_privileges(username, user_uid, user_gid, user_groups)
# We need to catch exception in order to be able to restore
# privileges later in this function
out = None
try:
out = func()
except Exception as exc:
log(str(exc))
# Restore privileges
set_privileges('root', current_uid, 0, current_groups)
return out

View File

@@ -17,10 +17,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import socket
import os
import pwd
import subprocess
import re
from pathlib import Path
from .samba import smbopts
@@ -29,10 +29,7 @@ def get_machine_name():
'''
Get localhost name looking like DC0$
'''
loadparm = smbopts()
result = loadparm.get_machine_name()
return result
return socket.gethostname().split('.', 1)[0].upper() + "$"
def is_machine_name(name):

View File

@@ -105,7 +105,7 @@ class smbcreds (smbopts):
for gpo in gpos:
# These setters are taken from libgpo/pygpo.c
# print(gpo.ds_path) # LDAP entry
ldata = dict({'gpo_name': gpo.display_name, 'gpo_uuid': gpo.name, 'file_sys_path': gpo.file_sys_path})
ldata = dict({'gpo_name': gpo.display_name, 'gpo_uuid': gpo.name})
log('I2', ldata)
except Exception as exc:
@@ -192,7 +192,6 @@ def expand_windows_var(text, username=None):
variables['DesktopDir'] = xdg_get_desktop(username, variables['HOME'])
if username:
variables['LogonUser'] = username
variables['HOME'] = get_homedir(username)
variables['StartMenuDir'] = os.path.join(

View File

@@ -1,8 +1,8 @@
%define _unpackaged_files_terminate_build 1
Name: gpupdate
Version: 0.9.8
Release: alt0.dev1
Version: 0.8.0
Release: alt1
Summary: GPT applier
License: GPLv3+
@@ -13,18 +13,16 @@ BuildArch: noarch
Requires: control
BuildRequires: rpm-build-python3
BuildRequires: gettext-tools
BuildRequires: python-tools-i18n
Requires: python3-module-rpm
Requires: python3-module-dbus
Requires: oddjob-%name >= 0.2.0
Requires: libnss-role >= 0.5.0
Requires: local-policy >= 0.4.9
Requires: local-policy >= 0.4.0
Requires: pam-config >= 1.9.0
Requires: autofs
# This is needed by shortcuts_applier
Requires: desktop-file-utils
# This is needed for smb file cache support
Requires: python3-module-smbc >= 1.0.23-alt3
Source0: %name-%version.tar
@@ -42,7 +40,7 @@ cp -r gpoa \
%buildroot%python3_sitelibdir/
# Generate translations
msgfmt \
pymsgfmt \
-o %buildroot%python3_sitelibdir/gpoa/locale/ru_RU/LC_MESSAGES/gpoa.mo \
%buildroot%python3_sitelibdir/gpoa/locale/ru_RU/LC_MESSAGES/gpoa.po
@@ -50,7 +48,6 @@ mkdir -p \
%buildroot%_bindir/ \
%buildroot%_sbindir/ \
%buildroot%_cachedir/%name/ \
%buildroot%_cachedir/%{name}_file_cache/ \
%buildroot%_cachedir/%name/creds
ln -s %python3_sitelibdir/gpoa/gpoa \
@@ -60,12 +57,6 @@ ln -s %python3_sitelibdir/gpoa/gpupdate \
ln -s %python3_sitelibdir/gpoa/gpupdate-setup \
%buildroot%_sbindir/gpupdate-setup
mkdir -p \
%buildroot%_prefix/libexec/%name
ln -s %python3_sitelibdir/gpoa/pkcon_runner \
%buildroot%_prefix/libexec/%name/pkcon_runner
mkdir -p %buildroot%_datadir/%name
mv %buildroot%python3_sitelibdir/gpoa/templates \
%buildroot%_datadir/%name/
@@ -74,20 +65,12 @@ mkdir -p %buildroot%_sysconfdir/%name
touch %buildroot%_sysconfdir/%name/environment
install -Dm0644 dist/%name.service %buildroot%_unitdir/%name.service
install -Dm0644 dist/%name-user.service %buildroot/usr/lib/systemd/user/%name-user.service
install -Dm0644 dist/%name.service %buildroot/usr/lib/systemd/user/%name-user.service
install -Dm0644 dist/system-policy-%name %buildroot%_sysconfdir/pam.d/system-policy-%name
install -Dm0644 dist/%name.ini %buildroot%_sysconfdir/%name/%name.ini
install -Dm0644 doc/gpoa.1 %buildroot/%_man1dir/gpoa.1
install -Dm0644 doc/gpupdate.1 %buildroot/%_man1dir/gpupdate.1
for i in gpupdate-localusers \
gpupdate-group-users \
gpupdate-system-uids
do
install -pD -m755 "dist/$i" \
"%buildroot%_sysconfdir/control.d/facilities/$i"
done
%preun
%preun_service gpupdate
@@ -96,23 +79,16 @@ done
# Remove storage in case we've lost compatibility between versions.
# The storage will be regenerated on GPOA start.
%define active_policy %_sysconfdir/local-policy/active
%triggerpostun -- %name < 0.9.6
%triggerpostun -- %name > 0.7
rm -f %_cachedir/%name/registry.sqlite
if test -L %active_policy; then
sed -i "s|^\s*local-policy\s*=.*|local-policy = $(readlink -f %active_policy)|" \
%_sysconfdir/%name/%name.ini
fi
%files
%_sbindir/gpoa
%_sbindir/gpupdate-setup
%_bindir/gpupdate
%_prefix/libexec/%name/pkcon_runner
%attr(755,root,root) %python3_sitelibdir/gpoa/gpoa
%attr(755,root,root) %python3_sitelibdir/gpoa/gpupdate
%attr(755,root,root) %python3_sitelibdir/gpoa/gpupdate-setup
%attr(755,root,root) %python3_sitelibdir/gpoa/pkcon_runner
%python3_sitelibdir/gpoa
%_datadir/%name
%_unitdir/%name.service
@@ -120,12 +96,10 @@ fi
%_man1dir/gpupdate.1.*
/usr/lib/systemd/user/%name-user.service
%dir %_sysconfdir/%name
%_sysconfdir/control.d/facilities/*
%config(noreplace) %_sysconfdir/%name/environment
%config(noreplace) %_sysconfdir/%name/%name.ini
%config(noreplace) %_sysconfdir/pam.d/system-policy-%name
%dir %attr(0700, root, root) %_cachedir/%name
%dir %attr(0755, root, root) %_cachedir/%{name}_file_cache
%dir %attr(0700, root, root) %_cachedir/%name/creds
%exclude %python3_sitelibdir/gpoa/.pylintrc
%exclude %python3_sitelibdir/gpoa/.prospector.yaml
@@ -133,68 +107,6 @@ fi
%exclude %python3_sitelibdir/gpoa/test
%changelog
* Wed Sep 29 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.7-alt1
- Fix regression with kestroy for user credential cache
- Update system-policy-gpupdate PAM-rules to ignore applying group policies
for local users and system users with uid less than 500
- Add control facilities to rule system-policy-gpupdate rules:
+ gpupdate-group-users
+ gpupdate-localusers
+ gpupdate-system-uids
* Mon Sep 20 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.6-alt1
- Add support changed GPO List Processing for '**DelVals.' value name
* Tue Sep 14 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.5-alt1
- Refix local policy path detection
- gpupdate-setup: revert settings to default when disabled
* Tue Sep 14 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.4-alt1
- Add improvement with new local-policy system-policy control
- Fix gpupdate-setup and user service installation regressions
- Set empty local policy and local backend by default
- Fix local policy path detection
* Mon Sep 06 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.3-alt1
- Use NetBIOS name for Kerberos authentification
- Add support actions (create, update, delete, replace) for Shortcuts
- Add support GSettings with locks feature
- Add support file cache for special GSettings policy:
Software\BaseALT\Policies\GSettings\org.mate.background.picture-filename
(requires python smbc module with use_kerberos option support)
* Wed Jul 28 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.2-alt1
- Fix Shortcuts applier double running in user context
- Add LogonUser variable to expand_windows_var() function
- Add support of path variable expansion to Shortcuts applier
* Sun Jul 18 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.1-alt1
- Fix GSettings applier user part support
- Add support additional firefox appliers
- Add new windows policies mapping capability feature ruled by:
Software\BaseALT\Policies\GPUpdate\WindowsPoliciesMapping
- Improve drop privileges mechanism with fork and dbus session
* Fri Jun 25 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.0-alt1
- Change policies.json location for Firefox
- Set GSettings, Chromium and Firefox appliers
not experimental and enabled by default
* Tue Dec 22 2020 Igor Chudov <nir@altlinux.org> 0.8.2-alt1
- Increased D-Bus timeouts on calls
- Minor logging fixes
* Wed Oct 07 2020 Evgeny Sinelnikov <sin@altlinux.org> 0.8.1-alt3
- Fixed compatibility upgrade trigger condition
* Wed Oct 07 2020 Evgeny Sinelnikov <sin@altlinux.org> 0.8.1-alt2
- Fixed compatibility upgrade trigger from 0.7 releases for update
active local-policy in new gpupdate.ini configuartion file
* Fri Sep 11 2020 Evgeny Sinelnikov <sin@altlinux.org> 0.8.1-alt1
- Workaround for control names with special symbols
- Improved logging on Kerberos errors
* Fri Sep 04 2020 Evgeny Sinelnikov <sin@altlinux.org> 0.8.0-alt1
- Improve gpo applier logging
- Add new configuration file /etc/gpupdate/gpupdate.ini