mirror of
https://github.com/altlinux/gpupdate.git
synced 2025-08-23 09:49:29 +03:00
Compare commits
55 Commits
0.4.3-alt1
...
binary_mod
Author | SHA1 | Date | |
---|---|---|---|
8292aa69b3
|
|||
aa03e6dfa4
|
|||
0328afa788 | |||
edead53d7e
|
|||
db1a82f930
|
|||
fd7cfe2b83
|
|||
b3694a8b4d
|
|||
060f125258
|
|||
1f4960cb48
|
|||
a0c5b1a2b1 | |||
2f7e6f3a98 | |||
393529f0af | |||
ccf73c4fc6 | |||
a7aa12d42d | |||
d12d4c4227 | |||
e8833ddee0
|
|||
18e1911bb5
|
|||
fa34dc9e96
|
|||
34ed296546
|
|||
8b63d294d3 | |||
d38e937e22 | |||
c70280a964 | |||
41e950172b
|
|||
25381e1a04
|
|||
f7233c539e
|
|||
0b3c004d0b
|
|||
ac37d736cb
|
|||
91da6ff912
|
|||
ae7d1ed0dc
|
|||
ce0e3f1901
|
|||
edfca0e31d
|
|||
77da991c6f
|
|||
d61583e704
|
|||
1d31f17bb3
|
|||
3276be53cc
|
|||
442e7986d5
|
|||
faa0265fd7 | |||
0150e60f3d
|
|||
7572fa1ed7 | |||
1fa9b67fb2 | |||
0be9e4b317 | |||
c16312161f | |||
ed9477c0fc | |||
75485eeb62 | |||
633637bee2 | |||
7d46cd69e0 | |||
2901f54830 | |||
8f349a96c7 | |||
ebbdf7c033
|
|||
4e8888086f
|
|||
2571e27235
|
|||
207b7eb029
|
|||
5668dae81e
|
|||
ce9891802f
|
|||
d0ff27c45c
|
228
dist/gpupdate-setup
vendored
Executable file
228
dist/gpupdate-setup
vendored
Executable file
@ -0,0 +1,228 @@
|
||||
#! /usr/bin/env 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 os
|
||||
import sys
|
||||
import argparse
|
||||
import subprocess
|
||||
|
||||
import re
|
||||
|
||||
from gpoa.util.samba import smbopts
|
||||
|
||||
|
||||
def command(args):
|
||||
try:
|
||||
subprocess.check_call(args.split())
|
||||
except:
|
||||
print ('command: \'%s\' error' % args)
|
||||
|
||||
def from_command(args):
|
||||
try:
|
||||
with subprocess.Popen(args.split(), stdout=subprocess.PIPE) as proc:
|
||||
value = proc.stdout.readline().decode('utf-8')
|
||||
proc.wait()
|
||||
except:
|
||||
print ('from_command: \'%s\' error' % args)
|
||||
return 'local'
|
||||
|
||||
return value.strip()
|
||||
|
||||
def get_default_policy_name():
|
||||
localpolicy = 'workstation'
|
||||
dcpolicy = 'ad-domain-controller'
|
||||
|
||||
try:
|
||||
if smbopt.get_server_role() == 'active directory domain controller':
|
||||
return dcpolicy
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
release = '/etc/altlinux-release'
|
||||
if os.path.isfile(release):
|
||||
f = open(release)
|
||||
s = f.readline()
|
||||
if re.search('server', s, re.I):
|
||||
localpolicy = 'server'
|
||||
except:
|
||||
pass
|
||||
|
||||
return localpolicy
|
||||
|
||||
def parse_arguments():
|
||||
'''
|
||||
Parse CLI arguments.
|
||||
'''
|
||||
parser = argparse.ArgumentParser(prog='gpupdate-setup')
|
||||
subparsers = parser.add_subparsers(dest='action',
|
||||
metavar='action',
|
||||
help='Group Policy management actions (default action is status)')
|
||||
|
||||
parser_list = subparsers.add_parser('list',
|
||||
help='List avalable types of local policy')
|
||||
parser_status = subparsers.add_parser('status',
|
||||
help='Show current Group Policy status')
|
||||
parser_enable = subparsers.add_parser('enable',
|
||||
help='Enable Group Policy subsystem')
|
||||
parser_disable = subparsers.add_parser('disable',
|
||||
help='Disable Group Policy subsystem')
|
||||
parser_write = subparsers.add_parser('write',
|
||||
help='Operate on Group Policies (enable or disable)')
|
||||
parser_active = subparsers.add_parser('active-policy',
|
||||
help='Show name of policy enabled')
|
||||
|
||||
parser_write.add_argument('status',
|
||||
choices=['enable', 'disable'],
|
||||
help='Enable or disable Group Policies')
|
||||
parser_write.add_argument('localpolicy',
|
||||
default=None,
|
||||
nargs='?',
|
||||
help='Name of local policy to enable')
|
||||
|
||||
parser_enable.add_argument('localpolicy',
|
||||
default=None,
|
||||
nargs='?',
|
||||
help='Name of local policy to enable')
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def get_policy_entries(directory):
|
||||
filtered_entries = list()
|
||||
if os.path.isdir(directory):
|
||||
entries = [os.path.join(directory, entry) for entry in os.listdir(directory)]
|
||||
|
||||
for entry in entries:
|
||||
if os.path.isdir(os.path.join(entry)):
|
||||
if not os.path.islink(os.path.join(entry)):
|
||||
if not entry.rpartition('/')[2] == 'default':
|
||||
filtered_entries.append(entry)
|
||||
|
||||
return filtered_entries
|
||||
|
||||
|
||||
def get_policy_variants():
|
||||
'''
|
||||
Get the list of local policy variants deployed on this system.
|
||||
Please note that is case overlapping names the names in
|
||||
/etc/local-policy must override names in /usr/share/local-policy
|
||||
'''
|
||||
policy_dir = '/usr/share/local-policy'
|
||||
etc_policy_dir = '/etc/local-policy'
|
||||
|
||||
system_policies = get_policy_entries(policy_dir)
|
||||
user_policies = get_policy_entries(etc_policy_dir)
|
||||
|
||||
general_listing = list()
|
||||
general_listing.extend(system_policies)
|
||||
general_listing.extend(user_policies)
|
||||
|
||||
return general_listing
|
||||
|
||||
def validate_policy_name(policy_name):
|
||||
return policy_name in [os.path.basename(d) for d in get_policy_variants()]
|
||||
|
||||
def get_status():
|
||||
systemd_unit_link = '/etc/systemd/system/multi-user.target.wants/gpupdate.service'
|
||||
|
||||
return os.path.islink(systemd_unit_link)
|
||||
|
||||
def get_active_policy():
|
||||
policy_dir = '/usr/share/local-policy'
|
||||
etc_policy_dir = '/etc/local-policy'
|
||||
default_policy_name = os.path.join(policy_dir, get_default_policy_name())
|
||||
|
||||
active_policy_name = os.path.join(etc_policy_dir, 'active')
|
||||
|
||||
actual_policy_name = os.path.realpath(default_policy_name)
|
||||
|
||||
if os.path.isdir(active_policy_name):
|
||||
actual_policy_name = os.path.realpath(active_policy_name)
|
||||
|
||||
return actual_policy_name
|
||||
|
||||
|
||||
def disable_gp():
|
||||
if from_command('/usr/sbin/control system-auth') != 'local':
|
||||
command('/usr/sbin/control system-policy global')
|
||||
else:
|
||||
command('/usr/sbin/control system-policy local')
|
||||
command('systemctl disable gpupdate.service')
|
||||
command('systemctl --global disable gpupdate-user.service')
|
||||
|
||||
def enable_gp(policy_name):
|
||||
policy_dir = '/usr/share/local-policy'
|
||||
etc_policy_dir = '/etc/local-policy'
|
||||
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)
|
||||
default_policy_name = os.path.join(policy_dir, target_policy_name)
|
||||
active_policy_name = os.path.join(etc_policy_dir, 'active')
|
||||
|
||||
if not os.path.isdir(etc_policy_dir):
|
||||
os.makedirs(etc_policy_dir)
|
||||
|
||||
if not os.path.islink(active_policy_name):
|
||||
os.symlink(default_policy_name, active_policy_name)
|
||||
else:
|
||||
os.unlink(active_policy_name)
|
||||
os.symlink(default_policy_name, active_policy_name)
|
||||
|
||||
# Enable oddjobd_gpupdate in PAM config
|
||||
command('/usr/sbin/control system-policy gpupdate')
|
||||
# Bootstrap the Group Policy engine
|
||||
command('/usr/sbin/gpoa --nodomain --loglevel 5')
|
||||
# Enable gpupdate-setup.service for all users
|
||||
command('systemctl --global enable gpupdate-user.service')
|
||||
|
||||
def main():
|
||||
arguments = parse_arguments()
|
||||
|
||||
if arguments.action == 'list':
|
||||
for entry in get_policy_variants():
|
||||
print(entry.rpartition('/')[2])
|
||||
|
||||
if arguments.action == 'status' or arguments.action == None:
|
||||
if get_status():
|
||||
print('enabled')
|
||||
else:
|
||||
print('disabled')
|
||||
|
||||
if arguments.action == 'write':
|
||||
if arguments.status == 'enable' or arguments.status == '#t':
|
||||
enable_gp(arguments.localpolicy)
|
||||
if arguments.status == 'disable' or arguments.status == '#f':
|
||||
disable_gp()
|
||||
|
||||
if arguments.action == "enable":
|
||||
enable_gp(arguments.localpolicy)
|
||||
|
||||
if arguments.action == "disable":
|
||||
disable_gp()
|
||||
|
||||
if arguments.action == 'active-policy':
|
||||
print(get_active_policy())
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -41,8 +41,13 @@ from util.users import (
|
||||
with_privileges
|
||||
)
|
||||
from util.logging import slogm
|
||||
from util.paths import (
|
||||
frontend_module_dir
|
||||
)
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def determine_username(username=None):
|
||||
'''
|
||||
@ -72,6 +77,12 @@ class frontend_manager:
|
||||
'''
|
||||
|
||||
def __init__(self, username, is_machine):
|
||||
frontend_module_files = frontend_module_dir().glob('**/*')
|
||||
self.frontend_module_binaries = list()
|
||||
for exe in frontend_module_files:
|
||||
if (exe.is_file() and os.access(exe.resolve(), os.X_OK)):
|
||||
self.frontend_module_binaries.append(exe)
|
||||
|
||||
self.storage = registry_factory('registry')
|
||||
self.username = determine_username(username)
|
||||
self.is_machine = is_machine
|
||||
@ -105,6 +116,10 @@ class frontend_manager:
|
||||
logging.error('Not sufficient privileges to run machine appliers')
|
||||
return
|
||||
logging.debug(slogm('Applying computer part of settings'))
|
||||
|
||||
for exe in self.frontend_module_binaries:
|
||||
subprocess.check_call([exe.resolve()])
|
||||
|
||||
self.machine_appliers['systemd'].apply()
|
||||
self.machine_appliers['control'].apply()
|
||||
self.machine_appliers['polkit'].apply()
|
||||
|
@ -273,7 +273,7 @@ def lp2gpt():
|
||||
'''
|
||||
Convert local-policy to full-featured GPT.
|
||||
'''
|
||||
lppath = os.path.join(default_policy_path(), 'local.xml')
|
||||
lppath = os.path.join(default_policy_path(), 'Machine/Registry.pol.xml')
|
||||
|
||||
# Load settings from XML PolFile
|
||||
polparser = GPPolParser()
|
||||
|
@ -22,6 +22,6 @@ from .sqlite_cache import sqlite_cache
|
||||
def cache_factory(cache_name):
|
||||
return sqlite_cache(cache_name)
|
||||
|
||||
def registry_factory(registry_name):
|
||||
return sqlite_registry(registry_name)
|
||||
def registry_factory(registry_name='registry', registry_dir=None):
|
||||
return sqlite_registry(registry_name, registry_dir)
|
||||
|
||||
|
59
gpoa/storage/record_types.py
Normal file
59
gpoa/storage/record_types.py
Normal file
@ -0,0 +1,59 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
class samba_preg(object):
|
||||
'''
|
||||
Object mapping representing HKLM entry (registry key without SID)
|
||||
'''
|
||||
def __init__(self, preg_obj):
|
||||
self.hive_key = '{}\\{}'.format(preg_obj.keyname, preg_obj.valuename)
|
||||
self.type = preg_obj.type
|
||||
self.data = preg_obj.data
|
||||
|
||||
class samba_hkcu_preg(object):
|
||||
'''
|
||||
Object mapping representing HKCU entry (registry key with SID)
|
||||
'''
|
||||
def __init__(self, sid, preg_obj):
|
||||
self.sid = sid
|
||||
self.hive_key = '{}\\{}'.format(preg_obj.keyname, preg_obj.valuename)
|
||||
self.type = preg_obj.type
|
||||
self.data = preg_obj.data
|
||||
|
||||
class ad_shortcut(object):
|
||||
'''
|
||||
Object mapping representing Windows shortcut.
|
||||
'''
|
||||
def __init__(self, sid, sc):
|
||||
self.sid = sid
|
||||
self.path = sc.dest
|
||||
self.shortcut = sc.to_json()
|
||||
|
||||
class info_entry(object):
|
||||
def __init__(self, name, value):
|
||||
self.name = name
|
||||
self.value = value
|
||||
|
||||
class printer_entry(object):
|
||||
'''
|
||||
Object mapping representing Windows printer of some type.
|
||||
'''
|
||||
def __init__(self, sid, pobj):
|
||||
self.sid = sid
|
||||
self.name = pobj.name
|
||||
self.printer = pobj.to_json()
|
@ -36,53 +36,21 @@ from sqlalchemy.orm import (
|
||||
from util.logging import slogm
|
||||
from util.paths import cache_dir
|
||||
from .registry import registry
|
||||
|
||||
class samba_preg(object):
|
||||
'''
|
||||
Object mapping representing HKLM entry (registry key without SID)
|
||||
'''
|
||||
def __init__(self, preg_obj):
|
||||
self.hive_key = '{}\\{}'.format(preg_obj.keyname, preg_obj.valuename)
|
||||
self.type = preg_obj.type
|
||||
self.data = preg_obj.data
|
||||
|
||||
class samba_hkcu_preg(object):
|
||||
'''
|
||||
Object mapping representing HKCU entry (registry key with SID)
|
||||
'''
|
||||
def __init__(self, sid, preg_obj):
|
||||
self.sid = sid
|
||||
self.hive_key = '{}\\{}'.format(preg_obj.keyname, preg_obj.valuename)
|
||||
self.type = preg_obj.type
|
||||
self.data = preg_obj.data
|
||||
|
||||
class ad_shortcut(object):
|
||||
'''
|
||||
Object mapping representing Windows shortcut.
|
||||
'''
|
||||
def __init__(self, sid, sc):
|
||||
self.sid = sid
|
||||
self.path = sc.dest
|
||||
self.shortcut = sc.to_json()
|
||||
|
||||
class info_entry(object):
|
||||
def __init__(self, name, value):
|
||||
self.name = name
|
||||
self.value = value
|
||||
|
||||
class printer_entry(object):
|
||||
'''
|
||||
Object mapping representing Windows printer of some type.
|
||||
'''
|
||||
def __init__(self, sid, pobj):
|
||||
self.sid = sid
|
||||
self.name = pobj.name
|
||||
self.printer = pobj.to_json()
|
||||
from .record_types import (
|
||||
samba_preg
|
||||
, samba_hkcu_preg
|
||||
, ad_shortcut
|
||||
, info_entry
|
||||
, printer_entry
|
||||
)
|
||||
|
||||
class sqlite_registry(registry):
|
||||
def __init__(self, db_name):
|
||||
def __init__(self, db_name, registry_cache_dir=None):
|
||||
self.db_name = db_name
|
||||
self.db_path = os.path.join('sqlite:///{}/{}.sqlite'.format(cache_dir(), self.db_name))
|
||||
cdir = registry_cache_dir
|
||||
if cdir == None:
|
||||
cdir = cache_dir()
|
||||
self.db_path = os.path.join('sqlite:///{}/{}.sqlite'.format(cdir, self.db_name))
|
||||
self.db_cnt = create_engine(self.db_path, echo=False)
|
||||
self.__metadata = MetaData(self.db_cnt)
|
||||
self.__info = Table(
|
||||
@ -221,15 +189,21 @@ class sqlite_registry(registry):
|
||||
Write PReg entry to HKEY_LOCAL_MACHINE
|
||||
'''
|
||||
pentry = samba_preg(preg_entry)
|
||||
self._hklm_upsert(pentry)
|
||||
if not pentry.hive_key.rpartition('\\')[2].startswith('**'):
|
||||
self._hklm_upsert(pentry)
|
||||
else:
|
||||
logging.warning(slogm('Skipping branch deletion key: {}'.format(pentry.hive_key)))
|
||||
|
||||
def add_hkcu_entry(self, preg_entry, sid):
|
||||
'''
|
||||
Write PReg entry to HKEY_CURRENT_USER
|
||||
'''
|
||||
hkcu_pentry = samba_hkcu_preg(sid, preg_entry)
|
||||
logging.debug(slogm('Adding HKCU entry for {}'.format(sid)))
|
||||
self._hkcu_upsert(hkcu_pentry)
|
||||
if not hkcu_pentry.hive_key.rpartition('\\')[2].startswith('**'):
|
||||
logging.debug(slogm('Adding HKCU entry for {}'.format(sid)))
|
||||
self._hkcu_upsert(hkcu_pentry)
|
||||
else:
|
||||
logging.warning(slogm('Skipping branch deletion key: {}'.format(hkcu_pentry.hive_key)))
|
||||
|
||||
def add_shortcut(self, sid, sc_obj):
|
||||
'''
|
||||
|
18
gpoa/test/storage/__init__.py
Normal file
18
gpoa/test/storage/__init__.py
Normal file
@ -0,0 +1,18 @@
|
||||
#
|
||||
# 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/>.
|
||||
|
18
gpoa/test/storage/data/Registry.pol.xml
Normal file
18
gpoa/test/storage/data/Registry.pol.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PolFile num_entries="3" signature="PReg" version="1">
|
||||
<Entry type="1" type_name="REG_SZ">
|
||||
<Key>Software\BaseALT\Policies\Control</Key>
|
||||
<ValueName>**del.cups</ValueName>
|
||||
<Value> </Value>
|
||||
</Entry>
|
||||
<Entry type="1" type_name="REG_SZ">
|
||||
<Key>Software\BaseALT\Policies\Control</Key>
|
||||
<ValueName>**del.postfix</ValueName>
|
||||
<Value> </Value>
|
||||
</Entry>
|
||||
<Entry type="1" type_name="REG_SZ">
|
||||
<Key>Software\BaseALT\Policies\Control</Key>
|
||||
<ValueName>**del.postqueue</ValueName>
|
||||
<Value> </Value>
|
||||
</Entry>
|
||||
</PolFile>
|
47
gpoa/test/storage/test_preg_special_values.py
Normal file
47
gpoa/test/storage/test_preg_special_values.py
Normal file
@ -0,0 +1,47 @@
|
||||
#
|
||||
# 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 unittest
|
||||
import unittest.mock
|
||||
|
||||
import os
|
||||
|
||||
|
||||
class StorageTestCase(unittest.TestCase):
|
||||
preg_xml_path = '{}/test/storage/data/Registry.pol.xml'.format(os.getcwd())
|
||||
reg_name = 'registry'
|
||||
# Run destructive storage tests in current directory
|
||||
reg_path = '{}/test/tmp'.format(os.getcwd())
|
||||
|
||||
@unittest.mock.patch('util.paths.cache_dir')
|
||||
def test_add_hklm_entry(self, cdir_mock):
|
||||
test_sid = None
|
||||
|
||||
from util.preg import merge_polfile
|
||||
|
||||
merge_polfile(self.preg_xml_path, test_sid, self.reg_name, self.reg_path)
|
||||
|
||||
@unittest.mock.patch('util.paths.cache_dir')
|
||||
def test_add_hkcu_entry(self, cdir_mock):
|
||||
test_sid = 'test_sid'
|
||||
|
||||
from util.preg import merge_polfile
|
||||
|
||||
merge_polfile(self.preg_xml_path, test_sid, self.reg_name, self.reg_path)
|
||||
|
5
gpoa/test/tmp/.gitignore
vendored
Normal file
5
gpoa/test/tmp/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
|
37
gpoa/test/util/test_rpm.py
Normal file
37
gpoa/test/util/test_rpm.py
Normal file
@ -0,0 +1,37 @@
|
||||
#
|
||||
# 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 unittest
|
||||
|
||||
from util.rpm import (
|
||||
install_rpms
|
||||
, remove_rpms
|
||||
)
|
||||
|
||||
class RPMTestCase(unittest.TestCase):
|
||||
@unittest.skip('test_install_rpm is not unit test')
|
||||
def test_install_rpm(self):
|
||||
test_package_names = ['tortoisehg', 'csync']
|
||||
install_rpms(test_package_names)
|
||||
|
||||
@unittest.skip('test_remove_rpm is not unit test')
|
||||
def test_remove_rpm(self):
|
||||
test_package_names = ['tortoisehg', 'csync']
|
||||
remove_rpms(test_package_names)
|
||||
|
@ -17,13 +17,22 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pathlib
|
||||
import os
|
||||
|
||||
|
||||
def default_policy_path():
|
||||
'''
|
||||
Returns path pointing to Default Policy directory.
|
||||
'''
|
||||
return pathlib.Path('/usr/share/local-policy/default')
|
||||
local_policy_default = '/usr/share/local-policy/default'
|
||||
etc_local_policy_default = '/etc/local-policy/active'
|
||||
|
||||
result_path = pathlib.Path(local_policy_default)
|
||||
|
||||
if os.path.exists(etc_local_policy_default):
|
||||
result_path = pathlib.Path(etc_local_policy_default)
|
||||
|
||||
return pathlib.Path(result_path)
|
||||
|
||||
|
||||
def cache_dir():
|
||||
@ -50,3 +59,31 @@ def local_policy_cache():
|
||||
|
||||
return lpcache
|
||||
|
||||
def backend_module_dir():
|
||||
backend_dir = '/usr/lib/gpoa/backend'
|
||||
return pathlib.Path(backend_dir)
|
||||
|
||||
def frontend_module_dir():
|
||||
frontend_dir = '/usr/lib/gpoa/frontend'
|
||||
return pathlib.Path(frontend_dir)
|
||||
|
||||
def storage_module_dir():
|
||||
storage_dir = '/usr/lib/gpoa/storage'
|
||||
return pathlib.Path(storage_dir)
|
||||
|
||||
def pre_backend_plugin_dir():
|
||||
pre_backend_dir = '/usr/lib/gpoa/backend_pre'
|
||||
return pathlib.Path(pre_backend_dir)
|
||||
|
||||
def post_backend_plugin_dir():
|
||||
post_backend_dir = '/usr/lib/gpoa/backend_post'
|
||||
return pathlib.Path(post_backend_dir)
|
||||
|
||||
def pre_frontend_plugin_dir():
|
||||
pre_forntend_dir = '/usr/lib/gpoa/frontend_pre'
|
||||
return pathlib.Path(pre_frontend_dir)
|
||||
|
||||
def post_frontend_plugin_dir():
|
||||
post_frontend_dir = '/usr/lib/gpoa/frontend_post'
|
||||
return pathlib.Path(post_frontend_dir)
|
||||
|
||||
|
@ -76,11 +76,10 @@ def preg_keymap(preg):
|
||||
return keymap
|
||||
|
||||
|
||||
def merge_polfile(preg, sid=None):
|
||||
def merge_polfile(preg, sid=None, reg_name='registry', reg_path=None):
|
||||
pregfile = load_preg(preg)
|
||||
logging.info(slogm('Loaded PReg {}'.format(preg)))
|
||||
key_map = dict()
|
||||
storage = registry_factory('registry')
|
||||
storage = registry_factory(reg_name, reg_path)
|
||||
for entry in pregfile.entries:
|
||||
if not sid:
|
||||
storage.add_hklm_entry(entry)
|
||||
|
@ -33,6 +33,64 @@ def is_rpm_installed(rpm_name):
|
||||
|
||||
return False
|
||||
|
||||
class Package:
|
||||
__install_command = ['/usr/bin/apt-get', '-y', 'install']
|
||||
__remove_command = ['/usr/bin/apt-get', '-y', 'remove']
|
||||
__reinstall_command = ['/usr/bin/apt-get', '-y', 'reinstall']
|
||||
|
||||
def __init__(self, package_name):
|
||||
self.package_name = package_name
|
||||
self.for_install = True
|
||||
|
||||
if package_name.endswith('-'):
|
||||
self.package_name = package_name[:-1]
|
||||
self.for_install = False
|
||||
|
||||
self.installed = is_rpm_installed(self.package_name)
|
||||
|
||||
def mark_for_install(self):
|
||||
self.for_install = True
|
||||
|
||||
def mark_for_removal(self):
|
||||
self.for_install = False
|
||||
|
||||
def is_installed(self):
|
||||
return self.installed
|
||||
|
||||
def is_for_install(self):
|
||||
return self.for_install
|
||||
|
||||
def is_for_removal(self):
|
||||
return (not self.for_install)
|
||||
|
||||
def action(self):
|
||||
if self.for_install:
|
||||
if not self.is_installed():
|
||||
return self.install()
|
||||
else:
|
||||
if self.is_installed():
|
||||
return self.remove()
|
||||
|
||||
def install(self):
|
||||
fullcmd = self.__install_command
|
||||
fullcmd.append(self.package_name)
|
||||
return subprocess.check_call(fullcmd)
|
||||
|
||||
def reinstall(self):
|
||||
fullcmd = self.__reinstall_command
|
||||
fullcmd.append(self.package_name)
|
||||
return subprocess.check_call(fullcmd)
|
||||
|
||||
def remove(self):
|
||||
fullcmd = self.__remove_command
|
||||
fullcmd.append(self.package_name)
|
||||
return subprocess.check_call(fullcmd)
|
||||
|
||||
def __repr__(self):
|
||||
return self.package_name
|
||||
|
||||
def __str__(self):
|
||||
return self.package_name
|
||||
|
||||
def update():
|
||||
'''
|
||||
@ -40,18 +98,40 @@ def update():
|
||||
'''
|
||||
subprocess.check_call(['/usr/bin/apt-get', 'update'])
|
||||
|
||||
|
||||
def install_rpm(rpm_name):
|
||||
'''
|
||||
Install RPM from APT-RPM sources.
|
||||
Install single RPM
|
||||
'''
|
||||
update()
|
||||
subprocess.check_call(['/usr/bin/apt-get', '-y', 'install', rpm_name])
|
||||
|
||||
rpm = Package(rpm_name)
|
||||
return rpm.install()
|
||||
|
||||
def remove_rpm(rpm_name):
|
||||
'''
|
||||
Remove RPM from file system.
|
||||
Remove single RPM
|
||||
'''
|
||||
subprocess.check_call(['/usr/bin/apt-get', '-y', 'remove', rpm_name])
|
||||
rpm = Package(rpm_name)
|
||||
return rpm.remove()
|
||||
|
||||
def install_rpms(rpm_names):
|
||||
'''
|
||||
Install set of RPMs sequentially
|
||||
'''
|
||||
result = list()
|
||||
|
||||
for package in rpm_names:
|
||||
result.append(install_rpm(package))
|
||||
|
||||
return result
|
||||
|
||||
def remove_rpms(rpm_names):
|
||||
'''
|
||||
Remove set of RPMs requentially
|
||||
'''
|
||||
result = list()
|
||||
|
||||
for package in rpm_names:
|
||||
result.append(remove_rpm(package))
|
||||
|
||||
return result
|
||||
|
||||
|
38
gpoa/util/samba.py
Normal file
38
gpoa/util/samba.py
Normal file
@ -0,0 +1,38 @@
|
||||
#
|
||||
# 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 optparse
|
||||
from samba import getopt as options
|
||||
|
||||
|
||||
class smbopts:
|
||||
|
||||
def __init__(self, prog=None):
|
||||
self.parser = optparse.OptionParser(prog)
|
||||
self.sambaopts = options.SambaOptions(self.parser)
|
||||
self.lp = self.sambaopts.get_loadparm()
|
||||
|
||||
def get_cache_dir(self):
|
||||
return self._get_prop('cache directory')
|
||||
|
||||
def get_server_role(self):
|
||||
return self._get_prop('server role')
|
||||
|
||||
def _get_prop(self, property_name):
|
||||
return self.lp.get(property_name)
|
@ -21,7 +21,6 @@ import logging
|
||||
import os
|
||||
import pwd
|
||||
|
||||
import optparse
|
||||
from samba import getopt as options
|
||||
|
||||
from samba.gpclass import get_dc_hostname, check_refresh_gpo_list
|
||||
@ -33,15 +32,14 @@ from storage import cache_factory
|
||||
from .xdg import get_user_dir
|
||||
from .util import get_homedir
|
||||
from .logging import slogm
|
||||
from .samba import smbopts
|
||||
|
||||
|
||||
class smbcreds:
|
||||
class smbcreds (smbopts):
|
||||
|
||||
def __init__(self, dc_fqdn=None):
|
||||
self.parser = optparse.OptionParser('GPO Applier')
|
||||
self.sambaopts = options.SambaOptions(self.parser)
|
||||
smbopts.__init__(self, 'GPO Applier')
|
||||
self.credopts = options.CredentialsOptions(self.parser)
|
||||
self.lp = self.sambaopts.get_loadparm()
|
||||
self.creds = self.credopts.get_credentials(self.lp, fallback_machine=True)
|
||||
self.selected_dc = self.set_dc(dc_fqdn)
|
||||
|
||||
@ -87,9 +85,6 @@ class smbcreds:
|
||||
|
||||
return dns_domainname
|
||||
|
||||
def get_cache_dir(self):
|
||||
return self._get_prop('cache directory')
|
||||
|
||||
def get_gpos(self, username):
|
||||
'''
|
||||
Get GPO list for the specified username for the specified DC
|
||||
@ -125,9 +120,6 @@ class smbcreds:
|
||||
username, self.selected_dc)))
|
||||
return gpos
|
||||
|
||||
def _get_prop(self, property_name):
|
||||
return self.lp.get(property_name)
|
||||
|
||||
|
||||
def wbinfo_getsid(domain, user):
|
||||
'''
|
||||
|
@ -1,13 +1,13 @@
|
||||
%define _unpackaged_files_terminate_build 1
|
||||
|
||||
Name: gpupdate
|
||||
Version: 0.4.3
|
||||
Version: 0.5.0
|
||||
Release: alt1
|
||||
|
||||
Summary: GPT applier
|
||||
License: GPLv3+
|
||||
Group: Other
|
||||
Url: http://git.altlinux.org/
|
||||
Url: https://github.com/altlinux/gpupdate
|
||||
BuildArch: noarch
|
||||
|
||||
Requires: control
|
||||
@ -15,8 +15,13 @@ Requires: local-policy >= 0.1.0
|
||||
|
||||
BuildRequires: rpm-build-python3
|
||||
Requires: python3-module-rpm
|
||||
Requires: python3-module-dbus
|
||||
Requires: oddjob-%name >= 0.2.0
|
||||
Requires: libnss-role
|
||||
Requires: libnss-role >= 0.5.0
|
||||
Requires: local-policy >= 0.3.0
|
||||
Requires: pam-config >= 1.8
|
||||
# This is needed by shortcuts_applier
|
||||
Requires: desktop-file-utils
|
||||
|
||||
Source0: %name-%version.tar
|
||||
|
||||
@ -42,14 +47,16 @@ ln -s %python3_sitelibdir/gpoa/gpoa \
|
||||
%buildroot%_sbindir/gpoa
|
||||
ln -s %python3_sitelibdir/gpoa/gpupdate \
|
||||
%buildroot%_bindir/gpupdate
|
||||
cp dist/gpupdate-setup \
|
||||
%buildroot%_sbindir/gpupdate-setup
|
||||
|
||||
mkdir -p %buildroot%_datadir/%name
|
||||
mv %buildroot%python3_sitelibdir/gpoa/templates \
|
||||
%buildroot%_datadir/%name/
|
||||
|
||||
install -Dm0644 %name.service %buildroot%_unitdir/%name.service
|
||||
install -Dm0644 %name.service %{buildroot}/usr/lib/systemd/user/%{name}-user.service
|
||||
install -Dm0644 system-policy-%name %buildroot%_sysconfdir/pam.d/system-policy-%name
|
||||
install -Dm0644 dist/%name.service %buildroot%_unitdir/%name.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 doc/gpoa.1 %buildroot/%{_man1dir}/gpoa.1
|
||||
install -Dm0644 doc/gpupdate.1 %buildroot/%{_man1dir}/gpupdate.1
|
||||
|
||||
@ -61,19 +68,31 @@ install -Dm0644 doc/gpupdate.1 %buildroot/%{_man1dir}/gpupdate.1
|
||||
|
||||
%files
|
||||
%_sbindir/gpoa
|
||||
%_sbindir/gpupdate-setup
|
||||
%_bindir/gpupdate
|
||||
%attr(755,root,root) %python3_sitelibdir/gpoa/gpoa
|
||||
%attr(755,root,root) %python3_sitelibdir/gpoa/gpupdate
|
||||
%python3_sitelibdir/gpoa
|
||||
%_datadir/%name
|
||||
%_unitdir/%name.service
|
||||
%{_man1dir}/gpoa.1.xz
|
||||
%{_man1dir}/gpupdate.1.xz
|
||||
/usr/lib/systemd/user/%{name}-user.service
|
||||
%_man1dir/gpoa.1.*
|
||||
%_man1dir/gpupdate.1.*
|
||||
/usr/lib/systemd/user/%name-user.service
|
||||
%_sysconfdir/pam.d/system-policy-%name
|
||||
%dir %_cachedir/%name
|
||||
|
||||
%changelog
|
||||
* Wed Apr 22 2020 Evgeny Sinelnikov <sin@altlinux.org> 0.5.0-alt1
|
||||
- Update samba format: local.xml -> Machine/Registry.pol.xml
|
||||
- Add support of ad-domain-controller local policy profile
|
||||
- Set properly URL of project
|
||||
|
||||
* Mon Apr 20 2020 Evgeny Sinelnikov <sin@altlinux.org> 0.4.5-alt1
|
||||
- Add support for control system-policy and requires to new pam-config
|
||||
|
||||
* Sun Apr 19 2020 Evgeny Sinelnikov <sin@altlinux.org> 0.4.4-alt1
|
||||
- Add gpupdate-setup initialization script supported local-policy profiles
|
||||
|
||||
* Fri Mar 06 2020 Evgeny Sinelnikov <sin@altlinux.org> 0.4.3-alt1
|
||||
- Fix polfile merging
|
||||
- Add support controls with strings values
|
||||
|
Reference in New Issue
Block a user