modify CSC schema instead of using inetOrgPerson
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Max Erenberg 2021-10-28 21:33:32 -04:00
parent 02aff43e7f
commit 2493bb1a6b
5 changed files with 22 additions and 42 deletions

View File

@ -27,7 +27,8 @@ attributetype ( 1.3.6.1.4.1.27934.1.1.6 NAME 'isClubRep'
objectclass ( 1.3.6.1.4.1.27934.1.2.1 NAME 'member' objectclass ( 1.3.6.1.4.1.27934.1.2.1 NAME 'member'
SUP top AUXILIARY SUP top AUXILIARY
MUST ( cn $ uid ) MUST ( cn $ uid )
MAY ( studentid $ program $ term $ nonMemberTerm $ description $ position $ isClubRep ) ) MAY ( studentid $ program $ term $ nonMemberTerm $ description $ position $
isClubRep $ sn $ givenName ) )
objectclass ( 1.3.6.1.4.1.27934.1.2.2 NAME 'club' objectclass ( 1.3.6.1.4.1.27934.1.2.2 NAME 'club'
SUP top AUXILIARY SUP top AUXILIARY

View File

@ -89,9 +89,7 @@ uid: ctdalek
uidNumber: 20001 uidNumber: 20001
gidNumber: 20001 gidNumber: 20001
objectClass: top objectClass: top
objectClass: person objectClass: account
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount objectClass: posixAccount
objectClass: shadowAccount objectClass: shadowAccount
objectClass: member objectClass: member
@ -116,9 +114,7 @@ uid: regular1
uidNumber: 20002 uidNumber: 20002
gidNumber: 20002 gidNumber: 20002
objectClass: top objectClass: top
objectClass: person objectClass: account
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount objectClass: posixAccount
objectClass: shadowAccount objectClass: shadowAccount
objectClass: member objectClass: member
@ -143,9 +139,7 @@ uid: exec1
uidNumber: 20003 uidNumber: 20003
gidNumber: 20003 gidNumber: 20003
objectClass: top objectClass: top
objectClass: person objectClass: account
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount objectClass: posixAccount
objectClass: shadowAccount objectClass: shadowAccount
objectClass: member objectClass: member

1
.gitignore vendored
View File

@ -14,6 +14,7 @@ __pycache__/
/docs/*.5 /docs/*.5
/debian/ceo/ /debian/ceo/
/debian/ceod/ /debian/ceod/
/debian/ceo-common/
/debian/tmp/ /debian/tmp/
/debian/ceo.substvars /debian/ceo.substvars
/debian/files /debian/files

View File

@ -164,19 +164,15 @@ class LDAPService:
conn.delete(dn) conn.delete(dn)
def add_user(self, user: IUser): def add_user(self, user: IUser):
object_classes = ['top', 'account', 'posixAccount', 'shadowAccount']
if user.is_club(): if user.is_club():
min_id, max_id = self.club_min_id, self.club_max_id min_id, max_id = self.club_min_id, self.club_max_id
object_classes = [ object_classes.append('club')
'top', 'account', 'posixAccount', 'shadowAccount', 'club',
]
else: else:
assert user.given_name and user.sn, \ assert user.given_name and user.sn, \
'First name and last name must be specified for new members' 'First name and last name must be specified for new members'
min_id, max_id = self.member_min_id, self.member_max_id min_id, max_id = self.member_min_id, self.member_max_id
object_classes = [ object_classes.append('member')
'top', 'person', 'organizationalPerson', 'inetOrgPerson',
'posixAccount', 'shadowAccount', 'member',
]
if user.mail_local_addresses: if user.mail_local_addresses:
object_classes.append('inetLocalMailRecipient') object_classes.append('inetLocalMailRecipient')
conn = self._get_ldap_conn() conn = self._get_ldap_conn()

View File

@ -1,8 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
This is a script which converts each user record in CSC LDAP from the This is a script which adds 'sn' and 'givenName' attributes to each user record.
'account' to the 'inetOrgPerson' objectClass. It pulls first/last name It pulls first/last name information from UWLDAP.
information from UWLDAP.
GSSAPI is used for LDAP authentication, so make sure to run `kinit` first. GSSAPI is used for LDAP authentication, so make sure to run `kinit` first.
""" """
@ -21,8 +20,10 @@ csc_conn = ldap3.Connection(
LDAP_URI, authentication=ldap3.SASL, sasl_mechanism=ldap3.KERBEROS, LDAP_URI, authentication=ldap3.SASL, sasl_mechanism=ldap3.KERBEROS,
auto_bind=True, raise_exceptions=True) auto_bind=True, raise_exceptions=True)
uw_conn = ldap3.Connection(UWLDAP_URI, auto_bind=True, raise_exceptions=True) uw_conn = ldap3.Connection(UWLDAP_URI, auto_bind=True, raise_exceptions=True)
csc_conn.search(LDAP_MEMBERS_BASE, '(&(objectClass=member)(objectClass=account))', csc_conn.search(
attributes=ldap3.ALL_ATTRIBUTES) LDAP_MEMBERS_BASE,
'(&(objectClass=member)(!(|(sn=*)(givenName=*))))',
attributes=['uid', 'cn'])
total_records_updated = 0 total_records_updated = 0
for csc_entry in csc_conn.entries: for csc_entry in csc_conn.entries:
uid = csc_entry.uid.value uid = csc_entry.uid.value
@ -32,7 +33,7 @@ for csc_entry in csc_conn.entries:
try: try:
uw_conn.search( uw_conn.search(
f'uid={uid},{UWLDAP_MEMBERS_BASE}', '(objectClass=*)', f'uid={uid},{UWLDAP_MEMBERS_BASE}', '(objectClass=*)',
attributes=ldap3.ALL_ATTRIBUTES, search_scope=ldap3.BASE) attributes=['sn', 'givenName'], search_scope=ldap3.BASE)
uw_entry = uw_conn.entries[0] uw_entry = uw_conn.entries[0]
sn = uw_entry.sn.value sn = uw_entry.sn.value
given_name = uw_entry.givenName.value given_name = uw_entry.givenName.value
@ -42,24 +43,11 @@ for csc_entry in csc_conn.entries:
print(f'WARNING: could not retrieve first and last names for {uid}; inferring from whitespace instead') print(f'WARNING: could not retrieve first and last names for {uid}; inferring from whitespace instead')
words = cn.split() words = cn.split()
given_name, sn = words[0], words[-1] given_name, sn = words[0], words[-1]
old_object_classes = csc_entry.objectClass.values.copy() changes = {
old_object_classes.remove('account') 'givenName': [(ldap3.MODIFY_ADD, [given_name])],
new_object_classes = old_object_classes + [ 'sn': [(ldap3.MODIFY_ADD, [sn])],
'person', 'organizationalPerson', 'inetOrgPerson', }
] csc_conn.modify(csc_entry.entry_dn, changes)
attrs = csc_entry.entry_attributes_as_dict.copy() print(f'Updated record for {uid}')
attrs['objectClass'] = new_object_classes
attrs['givenName'] = [given_name]
attrs['sn'] = [sn]
csc_conn.delete(csc_entry.entry_dn)
try:
csc_conn.add(csc_entry.entry_dn, attributes=attrs)
except Exception:
print(traceback.format_exc())
print(f"!!! ERROR !!! We weren't able to create a new record for {uid}.")
print('You need to add the old record back in. Here it is:')
print(csc_entry)
sys.exit(1)
print(f'Created new record for {uid}')
total_records_updated += 1 total_records_updated += 1
print(f'Total records updated: {total_records_updated}') print(f'Total records updated: {total_records_updated}')