1
0
mirror of https://github.com/altlinux/gpupdate.git synced 2025-03-21 18:50:38 +03:00

Merge pull request #108 from altlinux/freeipa_backend_stub

gpupdate-setup and other improvements
This commit is contained in:
Evgeny Sinelnikov 2020-09-02 20:31:40 +04:00 committed by GitHub
commit a9f9689032
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 530 additions and 251 deletions

233
dist/gpupdate-setup vendored
View File

@ -1,233 +0,0 @@
#! /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 smbopts().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_default = subparsers.add_parser('default-policy',
help='Show name of default policy')
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_name():
etc_policy_dir = '/etc/local-policy'
actual_policy_name = 'unknown'
active_policy_path = os.path.join(etc_policy_dir, 'active')
if os.path.islink(active_policy_path):
active_policy_path = os.path.realpath(active_policy_path)
if os.path.isdir(active_policy_path):
actual_policy_name = os.path.basename(active_policy_path)
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_name())
if arguments.action == 'default-policy':
print(get_default_policy_name())
if __name__ == '__main__':
main()

4
dist/gpupdate.ini vendored Normal file
View File

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

View File

@ -21,6 +21,7 @@ from util.windows import smbcreds
from .samba_backend import samba_backend
from .nodomain_backend import nodomain_backend
from util.logging import log
from util.config import GPConfig
def backend_factory(dc, username, is_machine, no_domain = False):
'''
@ -30,12 +31,11 @@ def backend_factory(dc, username, is_machine, no_domain = False):
policies enforced by domain administrators.
'''
back = None
domain = None
if not no_domain:
config = GPConfig()
if config.get_backend() == 'samba' and not no_domain:
sc = smbcreds(dc)
domain = sc.get_domain()
if domain:
ldata = dict({'domain': domain})
log('D9', ldata)
try:
@ -43,7 +43,8 @@ def backend_factory(dc, username, is_machine, no_domain = False):
except Exception as exc:
logdata = dict({'error': str(exc)})
log('E7', logdata)
else:
if config.get_backend() == 'local' or no_domain:
log('D8')
try:
back = nodomain_backend()

View File

@ -0,0 +1,25 @@
#
# 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_backend import applier_backend
class freeipa_backend(applier_backend):
def __init__(self):
pass

View File

@ -27,6 +27,10 @@ from util.util import (
get_machine_name,
is_machine_name
)
from util.kerberos import (
machine_kinit
, machine_kdestroy
)
from util.windows import get_sid
import util.preg
from util.logging import log
@ -34,6 +38,8 @@ from util.logging import log
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)
self.storage = registry_factory('registry')
self.storage.set_info('domain', domain)
machine_name = get_machine_name()
@ -59,6 +65,10 @@ class samba_backend(applier_backend):
logdata = dict({'cachedir': self.cache_dir})
log('D7', logdata)
def __del__(self):
if self.__kinit_successful:
machine_kdestroy()
def retrieve_and_store(self):
'''
Retrieve settings and strore it in a database

View File

@ -29,10 +29,6 @@ from plugin import plugin_manager
from messages import message_with_code
from util.util import get_machine_name
from util.kerberos import (
machine_kinit
, machine_kdestroy
)
from util.users import (
is_root,
get_process_user
@ -62,6 +58,9 @@ def parse_arguments():
arguments.add_argument('--noplugins',
action='store_true',
help='Don\'t start plugins')
arguments.add_argument('--list-backends',
action='store_true',
help='Show list of available backends')
arguments.add_argument('--loglevel',
type=int,
default=4,
@ -69,7 +68,6 @@ def parse_arguments():
return arguments.parse_args()
class gpoa_controller:
__kinit_successful = False
__args = None
def __init__(self):
@ -79,7 +77,6 @@ class gpoa_controller:
user = get_machine_name()
self.is_machine = True
set_loglevel(self.__args.loglevel)
self.cache_path = '/var/cache/gpupdate/creds/krb5cc_{}'.format(os.getpid())
locale.bindtextdomain('gpoa', '/usr/lib/python3/site-packages/gpoa/locale')
gettext.bindtextdomain('gpoa', '/usr/lib/python3/site-packages/gpoa/locale')
gettext.textdomain('gpoa')
@ -100,11 +97,12 @@ class gpoa_controller:
'''
GPOA controller entry point
'''
self.__kinit_successful = machine_kinit(self.cache_path)
if self.__args.list_backends:
print('local')
print('samba')
return
self.start_plugins()
self.start_backend()
if self.__kinit_successful:
machine_kdestroy()
def start_backend(self):
'''

305
gpoa/gpupdate-setup Executable file
View File

@ -0,0 +1,305 @@
#! /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 util.util import (
runcmd
, get_backends
, get_default_policy_name
, get_policy_entries
, get_policy_variants
)
from util.config import GPConfig
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():
'''
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_list = subparsers.add_parser('list-backends',
help='Show list of available backends')
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_default = subparsers.add_parser('default-policy',
help='Show name of default policy')
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_write.add_argument('backend',
default='samba',
type=str,
nargs='?',
const='backend',
choices=['local', 'samba'],
help='Backend (source of settings) name')
parser_enable.add_argument('localpolicy',
default=None,
nargs='?',
help='Name of local policy to enable')
parser_enable.add_argument('backend',
default='samba',
type=str,
nargs='?',
const='backend',
choices=['local', 'samba'],
help='Backend (source of settings) name')
return parser.parse_args()
def validate_policy_name(policy_name):
return policy_name in [os.path.basename(d) for d in get_policy_variants()]
def is_unit_enabled(unit_name, unit_global=False):
'''
Check that designated systemd unit is enabled
'''
command = ['/bin/systemctl', 'is-enabled', unit_name]
if unit_global:
command = ['/bin/systemctl', '--global', 'is-enabled', unit_name]
value = runcmd(command)
# If first line of stdout is equal to "enabled" and return code
# is zero then unit is considered enabled.
rc = value[0]
result = []
try:
result = value[1].replace('\n', '')
except IndexError as exc:
return False
if result == 'enabled' and rc == 0:
return True
return False
def get_status():
'''
Check that gpupdate.service and gpupdate-user.service are enabled.
'''
is_gpupdate = is_unit_enabled('gpupdate.service')
is_gpupdate_user = is_unit_enabled('gpupdate-user.service', unit_global=True)
if is_gpupdate and is_gpupdate_user:
return True
return False
def get_active_policy_name():
'''
Show the name of an active Local Policy template
'''
config = GPConfig()
return os.path.basename(config.get_local_policy_template())
def rollback_on_error(command_name):
'''
Disable group policy services in case command returns error code
'''
if 0 != runcmd(command_name)[0]:
disable_gp()
return False
return True
def disable_gp():
'''
Consistently disable group policy services
'''
cmd_set_global_policy = ['/usr/sbin/control', 'system-policy', 'global']
cmd_set_local_policy = ['/usr/sbin/control', 'system-policy', 'local']
cmd_disable_gpupdate_service = ['/bin/systemctl', 'disable', 'gpupdate.service']
cmd_disable_gpupdate_user_service = ['/bin/systemctl', '--global', 'disable', 'gpupdate-user.service']
cmd_control_system_auth = ['/usr/sbin/control', 'system-auth']
config = GPConfig()
auth_result = 'local'
try:
auth_result = runcmd(cmd_control_system_auth)[1][0]
except Exception as exc:
print(str(exc))
if auth_result != 'local':
runcmd(cmd_set_global_policy)
else:
runcmd(cmd_set_local_policy)
runcmd(cmd_disable_gpupdate_service)
runcmd(cmd_disable_gpupdate_user_service)
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']
cmd_enable_gpupdate_user_service = ['/bin/systemctl', '--global', 'enable', 'gpupdate-user.service']
config = GPConfig()
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)
if not os.path.isdir(etc_policy_dir):
os.makedirs(etc_policy_dir)
config.set_local_policy_template(default_policy_name)
# Enable oddjobd_gpupdate in PAM config
if not rollback_on_error(cmd_set_gpupdate_policy):
return
# Bootstrap the Group Policy engine
if not rollback_on_error(cmd_gpoa_nodomain):
return
# Enable gpupdate.service
if not rollback_on_error(cmd_enable_gpupdate_service):
return
if not is_unit_enabled('gpupdate.service'):
disable_gp()
return
# Enable gpupdate-setup.service for all users
if not rollback_on_error(cmd_enable_gpupdate_user_service):
return
if not is_unit_enabled('gpupdate-user.service', unit_global=True):
disable_gp()
return
def act_list():
'''
Show list of available templates of Local Policy
'''
for entry in get_policy_variants():
print(entry.rpartition('/')[2])
def act_list_backends():
'''
List backends supported by GPOA
'''
backends = get_backends()
for backend in backends:
print(backend)
def act_status():
'''
Check that group policy services are enabled
'''
if get_status():
print('enabled')
else:
print('disabled')
def act_write(localpolicy, backend):
'''
Enable or disable group policy services
'''
if arguments.status == 'enable' or arguments.status == '#t':
enable_gp(localpolicy, backend)
if arguments.status == 'disable' or arguments.status == '#f':
disable_gp()
def act_enable(localpolicy, backend):
'''
Enable group policy services
'''
enable_gp(localpolicy, backend)
def act_active_policy():
'''
Print active Local Policy template name to stdout
'''
print(get_active_policy_name())
def act_default_policy():
'''
Print default Local Policy template name to stdout
'''
print(get_default_policy_name())
def main():
arguments = parse_arguments()
action = dict()
action['list'] = act_list
action['list-backends'] = act_list_backends
action['status'] = act_status
action['write'] = act_write
action['enable'] = act_enable
action['disable'] = disable_gp
action['active-policy'] = act_active_policy
action['default-policy'] = act_default_policy
if arguments.action == None:
action['status']()
elif arguments.action == 'enable':
action[arguments.action](arguments.localpolicy, arguments.backend)
elif arguments.action == 'write':
action[arguments.action](arguments.localpolicy)
else:
action[arguments.action]()
if __name__ == '__main__':
main()

70
gpoa/util/config.py Normal file
View File

@ -0,0 +1,70 @@
#
# 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 configparser import ConfigParser
from .util import (
get_backends
, get_default_policy_name
)
class GPConfig:
__config_path = '/etc/gpupdate/gpupdate.ini'
def __init__(self, config_path=None):
if config_path:
self.__config_path = config_path
self.full_config = ConfigParser()
self.full_config.read(self.__config_path)
def get_backend(self):
'''
Fetch the name of the backend from configuration file.
'''
if 'gpoa' in self.full_config:
if 'backend' in self.full_config['gpoa']:
if self.full_config['gpoa']['backend'] in get_backends():
return self.full_config['gpoa']['backend']
return 'local'
def set_backend(self, backend_name):
self.full_config['gpoa']['backend'] = backend_name
self.write_config()
def get_local_policy_template(self):
'''
Fetch the name of chosen Local Policy template from
configuration file.
'''
if 'gpoa' in self.full_config:
if 'local-policy' in self.full_config['gpoa']:
return self.full_config['gpoa']['local-policy']
return get_default_policy_name()
def set_local_policy_template(self, template_name):
self.full_config['gpoa']['local-policy'] = template_name
self.write_config()
def write_config(self):
with open(self.__config_path, 'w') as config_file:
self.full_config.write(config_file)

View File

@ -19,18 +19,20 @@
import pathlib
import os
from .config import GPConfig
def default_policy_path():
'''
Returns path pointing to Default Policy directory.
'''
local_policy_default = '/usr/share/local-policy/default'
etc_local_policy_default = '/etc/local-policy/active'
config = GPConfig()
result_path = pathlib.Path(local_policy_default)
if os.path.exists(etc_local_policy_default):
result_path = pathlib.Path(etc_local_policy_default)
if os.path.exists(config.get_local_policy_template()):
result_path = pathlib.Path(config.get_local_policy_template())
return pathlib.Path(result_path)

View File

@ -20,7 +20,9 @@
import socket
import os
import pwd
import subprocess
from pathlib import Path
from .samba import smbopts
def get_machine_name():
@ -83,3 +85,95 @@ def mk_homedir_path(username, homedir_path):
os.chown(homedir, uid=uid, gid=gid)
longer_path = os.path.join(longer_path, elem)
def runcmd(command_name):
'''
Run application.
'''
try:
with subprocess.Popen(command_name, stdout=subprocess.PIPE) as proc:
value = proc.stdout.read().decode('utf-8')
proc.wait()
rc = proc.returncode
return (rc, value)
except Exception as exc:
print(str(exc))
def get_backends():
'''
Get the list of backends supported by GPOA
'''
command = ['/usr/sbin/gpoa', '--list-backends']
backends = list()
out = list()
with subprocess.Popen(command, stdout=subprocess.PIPE) as proc:
out = proc.stdout.read().decode('utf-8')
proc.wait()
out = out.split('\n')
for line in out:
tmpline = line.replace('\n', '')
if tmpline != '':
backends.append(tmpline)
return backends
def get_default_policy_name():
'''
Determine the preferred Local Policy template name according to
ALT distribution type
'''
localpolicy = 'workstation'
dcpolicy = 'ad-domain-controller'
try:
if smbopts().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 get_policy_entries(directory):
'''
Get list of directories representing "Local Policy" templates.
'''
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

View File

@ -54,7 +54,7 @@ ln -s %python3_sitelibdir/gpoa/gpoa \
%buildroot%_sbindir/gpoa
ln -s %python3_sitelibdir/gpoa/gpupdate \
%buildroot%_bindir/gpupdate
cp dist/gpupdate-setup \
ln -s %python3_sitelibdir/gpoa/gpupdate-setup \
%buildroot%_sbindir/gpupdate-setup
mkdir -p %buildroot%_datadir/%name
@ -67,6 +67,7 @@ touch %buildroot%_sysconfdir/%name/environment
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 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
@ -87,6 +88,7 @@ rm -f %_cachedir/%name/registry.sqlite
%_bindir/gpupdate
%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
%python3_sitelibdir/gpoa
%_datadir/%name
%_unitdir/%name.service
@ -95,6 +97,7 @@ rm -f %_cachedir/%name/registry.sqlite
/usr/lib/systemd/user/%name-user.service
%dir %_sysconfdir/%name
%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(0700, root, root) %_cachedir/%name/creds