View | Details | Raw Unified | Return to bug 50280
Collapse All | Expand All

(-)ucs-school-import/debian/control (+2 lines)
 Lines 26-31   Depends: univention-directory-manager, Link Here 
26
 python-univention,
26
 python-univention,
27
 python-univention-lib,
27
 python-univention-lib,
28
 python-lazy-object-proxy,
28
 python-lazy-object-proxy,
29
 python-ldap,
30
 python-univention-config-registry,
29
Description: UCS@school: Importing objects like users and computers
31
Description: UCS@school: Importing objects like users and computers
30
 This package provides scripts for importing objects like users, groups,
32
 This package provides scripts for importing objects like users, groups,
31
 networks and computers.
33
 networks and computers.
(-)ucs-school-import/usr/share/ucs-school-import/scripts/fix_ucsschool_slaves (-30 / +56 lines)
 Lines 29-39    Link Here 
29
# <http://www.gnu.org/licenses/>.
29
# <http://www.gnu.org/licenses/>.
30
30
31
from __future__ import absolute_import
31
from __future__ import absolute_import
32
33
import urllib
32
import logging
34
import logging
33
from optparse import OptionParser
35
from optparse import OptionParser
36
37
import ldap
38
from ldap.filter import filter_format
39
40
import univention.uldap
34
from univention.admin.uldap import getAdminConnection
41
from univention.admin.uldap import getAdminConnection
42
from univention.config_registry import ConfigRegistry
35
from ucsschool.lib.models.utils import get_stream_handler, get_file_handler
43
from ucsschool.lib.models.utils import get_stream_handler, get_file_handler
36
import subprocess
37
44
38
LOG_FILE = '/var/log/univention/ucsschool-fix-slave-objects.log'
45
LOG_FILE = '/var/log/univention/ucsschool-fix-slave-objects.log'
39
LOG_DEBUG_FMT = '%(asctime)s %(levelname)-5s %(funcName)s:%(lineno)d  %(message)s'
46
LOG_DEBUG_FMT = '%(asctime)s %(levelname)-5s %(funcName)s:%(lineno)d  %(message)s'
 Lines 43-56   LOG_DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S' Link Here 
43
logger = logging.getLogger('main')
50
logger = logging.getLogger('main')
44
51
45
52
46
def fix_slave(lo, slave_dn, slave_attrs, dry_run=True):
53
def get_s4_lo():
54
	ucr = ConfigRegistry()
55
	ucr.load()
56
	tls_mode = 0 if ucr.get('connector/s4/ldap/ssl') == "no" else 2
57
58
	protocol = ucr.get('connector/s4/ldap/protocol', 'ldap').lower()
59
	ldap_host_s4 = ucr.get('connector/s4/ldap/host')
60
	ldap_port_s4 = int(ucr.get('connector/s4/ldap/port'))
61
	ldap_base_s4 = ucr.get('connector/s4/ldap/base')
62
	ldap_binddn_s4 = ucr.get('connector/s4/ldap/binddn')
63
	ldap_bindpw_s4 = None
64
	if ucr.get('connector/s4/ldap/bindpw'):
65
		ldap_bindpw_s4 = open(ucr['connector/s4/ldap/bindpw']).read().strip('\n')
66
	ldap_certificate_s4 = ucr.get('connector/s4/ldap/certificate')
67
	if protocol == 'ldapi':
68
		socket = urllib.quote(ucr.get('connector/s4/ldap/socket', ''), '')
69
		ldap_uri_s4 = "%s://%s" % (protocol, socket)
70
	else:
71
		ldap_uri_s4 = "%s://%s:%d" % (protocol, ldap_host_s4, ldap_port_s4)
72
73
	lo_s4 = univention.uldap.access(host=ldap_host_s4, port=ldap_port_s4, base=ldap_base_s4, binddn=ldap_binddn_s4, bindpw=ldap_bindpw_s4, start_tls=tls_mode, ca_certfile=ldap_certificate_s4, uri=ldap_uri_s4)
74
	lo_s4.lo.set_option(ldap.OPT_REFERRALS, 0)
75
	return lo_s4
76
77
78
def fix_slave(lo, lo_s4, slave_dn, slave_attrs, dry_run=True):
47
	logger.debug('Checking %r', slave_dn)
79
	logger.debug('Checking %r', slave_dn)
48
	logger.debug('Attributes: %r', slave_attrs)
80
	logger.debug('Attributes: %r', slave_attrs)
49
	roles = slave_attrs.get('ucsschoolRole', [])
81
	roles = slave_attrs.get('ucsschoolRole', [])
50
	object_classes = slave_attrs.get('objectClass', [])
82
	object_classes = slave_attrs.get('objectClass', [])
51
	slave_cn = slave_attrs.get('cn', [])
83
	slave_cn = slave_attrs.get('cn', [''])[0]
52
	slave_s4_dn = ''
53
	slave_uAC = ''
54
84
55
	mod_role = {
85
	mod_role = {
56
		'old': roles,
86
		'old': roles,
 Lines 61-98   def fix_slave(lo, slave_dn, slave_attrs, dry_run=True): Link Here 
61
		'new': [oc for oc in object_classes if oc not in ('univentionWindows', 'ucsschoolComputer')],
91
		'new': [oc for oc in object_classes if oc not in ('univentionWindows', 'ucsschoolComputer')],
62
	}
92
	}
63
93
64
	output = subprocess.check_output(['univention-s4search', '--cross-ncs', '(&(cn=%s)(userAccountControl:1.2.840.113556.1.4.803:=4096))' % slave_cn[0]])
65
	for line in output.splitlines():
66
		if 'dn:' in line:
67
			slave_s4_dn = line.split(': ')[1]
68
		if 'userAccountControl' in line:
69
			slave_uAC = int(line.split(': ')[1])
70
71
	if mod_role['old'] != mod_role['new'] or mod_oc['old'] != mod_oc['new']:
94
	if mod_role['old'] != mod_role['new'] or mod_oc['old'] != mod_oc['new']:
72
		logger.info('Will modify: %s', slave_dn)
95
		logger.info('Will modify: %s', slave_dn)
73
		logger.info('Roles: %r', mod_role)
96
		logger.info('Roles: %r', mod_role)
74
		logger.info('ObjectClass: %r', mod_oc)
97
		logger.info('ObjectClass: %r', mod_oc)
75
		if slave_uAC:
98
		if not dry_run:
76
			new_slave_uAC = int(slave_uAC) - 4096 + 532480
77
			mod_uAC = {
78
				'old': [slave_uAC],
79
				'new': [new_slave_uAC],
80
			}
81
			logger.info('userAccountControl: %r', mod_uAC)
82
		if dry_run:
83
			logger.info('DRY-RUN: skipping modification')
84
		else:
85
			lo.modify(slave_dn, (
99
			lo.modify(slave_dn, (
86
				('ucsschoolRole', mod_role['old'], mod_role['new']),
100
				('ucsschoolRole', mod_role['old'], mod_role['new']),
87
				('objectClass', mod_oc['old'], mod_oc['new']),
101
				('objectClass', mod_oc['old'], mod_oc['new']),
88
			))
102
			))
89
			if slave_s4_dn and slave_uAC:
103
90
				# reset userAccountControl from workstation/server (4096) to DC (532480)
104
		for slave_s4_dn, slave_s4_attr in lo_s4.search(filter_format('(&(cn=%s)(userAccountControl:1.2.840.113556.1.4.803:=4096))', [slave_cn]), attr=['userAccountControl']):
91
				mod_str = 'dn: %s\nchangetype: modify\nreplace: userAccountControl\nuserAccountControl: %s\n\n' % (slave_s4_dn, new_slave_uAC)
105
			if slave_s4_dn is None:
92
				p1 = subprocess.Popen(['ldbmodify', '-H', '/var/lib/samba/private/sam.ldb'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=False)
106
				continue  # referals
93
				(stdout, stderr) = p1.communicate(mod_str)
107
			slave_account_control = int(slave_s4_attr['userAccountControl'][0])
94
				if p1.returncode != 0:
108
			new_slave_account_control = int(slave_account_control) & ~4096 | 8192 | 524288
95
					logger.error('Failed to set userAccountControl for Samba 4 object (%s)\n%s' % (slave_s4_dn, stderr))
109
			if slave_account_control == new_slave_account_control:
110
				continue
111
112
			mod_account_control = [('userAccountControl', slave_s4_attr['userAccountControl'], [str(new_slave_account_control)])]
113
			logger.info('userAccountControl: %r', mod_account_control)
114
115
			# reset userAccountControl from workstation/server (4096) to DC (532480)
116
			if not dry_run:
117
				lo_s4.modify(slave_s4_dn, mod_account_control)
118
119
		if dry_run:
120
			logger.info('DRY-RUN: skipping modification')
96
121
97
122
98
def main():
123
def main():
 Lines 110-121   the wrong object class will be removed and the ucsschoolRole attribute corrected Link Here 
110
135
111
	logger.info('Looking for affected domaincontroller_slave objects...')
136
	logger.info('Looking for affected domaincontroller_slave objects...')
112
	lo, po = getAdminConnection()
137
	lo, po = getAdminConnection()
138
	lo_s4 = get_s4_lo()
113
	slaves = lo.search(
139
	slaves = lo.search(
114
		filter='(univentionObjectType=computers/domaincontroller_slave)',
140
		filter='(univentionObjectType=computers/domaincontroller_slave)',
115
		attr=['objectClass', 'ucsschoolRole', 'cn']
141
		attr=['objectClass', 'ucsschoolRole', 'cn']
116
	)
142
	)
117
	for slave_dn, slave_attrs in slaves:
143
	for slave_dn, slave_attrs in slaves:
118
		fix_slave(lo, slave_dn, slave_attrs, dry_run=options.dry_run)
144
		fix_slave(lo, lo_s4, slave_dn, slave_attrs, dry_run=options.dry_run)
119
145
120
146
121
if __name__ == '__main__':
147
if __name__ == '__main__':

Return to bug 50280