11import configparser
22import json
3+
4+ import jinja2
35import ldap
46import ldap .modlist as modlist
57from sys import stdin
@@ -16,7 +18,12 @@ def config(key,default=''):
1618 c = __CONFIG__ ['config' ]
1719 return c .get (key ,default )
1820
19-
21+ def get_config ():
22+ items = __CONFIG__ .items ('config' )
23+ data = {}
24+ for k , v in items :
25+ data [k ] = v
26+ return data
2027def connect_ldap (url ,dn ,password ):
2128 try :
2229 l = ldap .initialize (url )
@@ -77,33 +84,60 @@ def make_entry_array(entity):
7784 additionalFields = entity ['payload' ]['additionalFields' ]['attributes' ]
7885 #inetOrgPerson
7986 for k ,v in inetOrgPerson .items ():
80- data [k ]= str (v )
87+ if type (v ) is int :
88+ v = str (v )
89+ data [k .lower ()]= v
8190
8291 for obj in objectclasses :
8392 #recherche si l objectclass est exclu
8493 exclusions = config ('excludedObjectclasses' ).lower ()
8594 if exclusions .find (obj .lower ()) == - 1 :
86- for k ,v in additionalFields [obj ].items ():
87- data [k ]= str (v )
95+ if obj in additionalFields .keys ():
96+ for k ,v in additionalFields [obj ].items ():
97+ if type (v ) is int :
98+ v = str (v )
99+ data [k .lower ()]= v
88100 return data
89101
90102
91- def make_objectclass (entity ):
103+ def make_objectclass (entity , entry ):
92104 data = {}
105+ objectclasses = []
106+ if entry :
107+ current = entry [0 ][1 ]['objectClass' ]
108+ for k in current :
109+ x = k .decode ('UTF-8' ).lower ()
110+ objectclasses .append (x )
111+ else :
112+ objectclasses .append ('top' )
113+ objectclasses .append ('inetOrgPerson' )
93114 if "identity" in entity ['payload' ]:
94- objectclasses = entity ['payload' ]['identity' ]['identity' ]['additionalFields' ]['objectClasses' ]
115+ new_objectclasses = entity ['payload' ]['identity' ]['identity' ]['additionalFields' ]['objectClasses' ]
95116 else :
96- objectclasses = entity ['payload' ]['additionalFields' ]['objectClasses' ]
117+ new_objectclasses = entity ['payload' ]['additionalFields' ]['objectClasses' ]
118+
119+ for k in new_objectclasses :
120+ if k .lower () not in objectclasses :
121+ objectclasses .append (k )
97122
98- return [ 'top' , 'inetOrgPerson' ] + objectclasses
123+ return objectclasses
99124
100125
101126def make_entry_array_without_empty (entity ):
102127 data = {}
103128 data1 = make_entry_array (entity )
104129 for k ,v in data1 .items ():
105- if str (v ) != "" :
106- data [k ]= v
130+ if type (v ) is list and len (k ) > 0 :
131+ l = []
132+ for i in v :
133+ if i != '' :
134+ l .append (i )
135+ if len (l )> 0 :
136+ data [k .lower ()] = l
137+ if type (v ) is int :
138+ v = str (v )
139+ if type (v ) is str and str (v ) != "" :
140+ data [k .lower ()]= v
107141 return data
108142
109143def convert_to_utf8 (entry ):
@@ -121,27 +155,35 @@ def compose_rdn(entity):
121155 rdn = config ('rdnAttribute' , 'uid' )
122156 rdnValue = find_key (entity , rdn )
123157 return rdn + '=' + rdnValue
124-
125158def compose_dn (entity ):
126- rdn = config ('rdnAttribute' ,'uid' )
159+ """Compose the DN of a identity"""
160+ rdn = config ('rdnAttribute' , 'uid' )
127161 rdnValue = find_key (entity ,rdn )
162+ data = {
163+ 'e' : make_entry_array (entity ),
164+ 'config' : get_config (),
165+ 'rdnValue' : rdnValue
166+ }
167+
168+ x = type (rdnValue )
169+ if rdnValue is None :
170+ rdnValue = 'test'
128171 branchAttr = config ('branchAttr' ,'' )
129- branch = ''
172+ data [ 'rdnValue' ] = rdnValue
130173 if branchAttr != '' :
131174 branchValue = find_key (entity ,branchAttr )
132-
133- match branchValue :
134- case 'etd' :
135- branch = config ('branchForEtd' ,'' )
136- case 'esn' :
137- branch = config ('branchForEsn' , '' )
138- case 'adm' :
139- branch = config ('branchForAdm' , '' )
140- if branch != '' :
141- return rdn + '=' + rdnValue + ',' + branch + "," + config ('userbase' )
175+ key_branch = 'branchFor' + branchValue
176+ branch = config (key_branch ,'' )
177+ data ['branch' ]= branch
178+ template_string = '{{ config.rdnattribute}}={{rdnValue}},{{ branch }},{{ config.userbase }}'
142179 else :
143- return rdn + '=' + rdnValue + "," + config ('userbase' )
144-
180+ if config ('userbase' ,'' ) != '' :
181+ template_string = '{{config.rdnattribute}}={{ rdnValue}},{{ config.userbase }}'
182+ else :
183+ template_string = '{{config.rdnattribute}}={{ rdnValue}},{{ config.base }}'
184+ template = jinja2 .Environment (loader = jinja2 .BaseLoader ()).from_string (config ('dnTemplate' ,template_string ))
185+ content = template .render (data )
186+ return content
145187def dn_superior (dn ):
146188 tab = dn .split (',' )
147189 tab .pop (0 )
@@ -153,13 +195,22 @@ def search_entity(l,entity):
153195 employeeNumber = find_key (entity ,'employeeNumber' )
154196 employeeType = find_key (entity ,'employeeType' )
155197 base = config ('base' )
156- filter = '(&(employeeNumber=' + employeeNumber + ')(employeeType=' + employeeType + '))'
198+ if config ('searchFilter' ,'' ):
199+ data = {
200+ 'e' : make_entry_array (entity ),
201+ }
202+ template = jinja2 .Environment (loader = jinja2 .BaseLoader ()).from_string (config ('searchFilter' ))
203+ filter = template .render (data )
204+
205+
206+ else :
207+ filter = '(&(employeeNumber=' + employeeNumber + ')(employeeType=' + employeeType + '))'
157208 try :
158209 r = l .search_s (base ,ldap .SCOPE_SUBTREE ,filter )
159210 return r
160211 except ldap .LDAPError as e :
161212 e_dict = e .args [0 ]
162- print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" )))
213+ print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" ) + " " + e_dict . get ( "info" ) ))
163214 exit (1 )
164215
165216def upsert_entry (l ,entity ):
@@ -170,44 +221,50 @@ def upsert_entry(l,entity):
170221 #creation de la liste
171222 entry = make_entry_array_without_empty (entity )
172223 ## Ajout objectclass
173- entry ['objectclass' ]= make_objectclass (entity )
224+ entry ['objectclass' ]= make_objectclass (entity , r )
174225 dn = compose_dn (entity )
175226 ldif = modlist .addModlist (convert_to_utf8 (entry ))
176227 try :
177228 action = "add"
178229 l .add_s (dn , ldif )
179230 except ldap .LDAPError as e :
180231 e_dict = e .args [0 ]
181- print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" )))
232+ print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" ) + " " + e_dict . get ( "info" ) ))
182233 exit (1 )
183234 else :
184235 if len (r ) > 1 :
185236 print (returncode (1 ,"many identities found" ))
186237 exit (1 )
187238 entry = make_entry_array_without_empty (entity );
188- entry ['objectclass' ] = make_objectclass (entity )
239+ entry = complete_entry (entry ,r );
240+
241+ entry ['objectclass' ] = make_objectclass (entity ,r )
189242 entry = convert_to_utf8 (entry )
190- ldif = modlist .modifyModlist (r [0 ][1 ],entry )
243+ old_entry = normalize_entry (r [0 ][1 ])
244+ ldif = modlist .modifyModlist (old_entry ,entry )
191245 dn = compose_dn (entity )
192- if dn == r [0 ][0 ]:
246+ #dn= r[0][0]
247+ if dn_superior (dn ) == dn_superior (r [0 ][0 ]):
193248 try :
194249 action = "mod"
195- l .modify_s (dn ,ldif )
250+ l .modify_s (r [ 0 ][ 0 ] ,ldif )
196251 except ldap .LDAPError as e :
197252 e_dict = e .args [0 ]
198- print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" )))
253+ print (returncode (1 , 'mod ' + str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" ) + " " + e_dict . get ( "info " )))
199254 exit (1 )
200255 else :
201256 ## changement du DN
202257 oldDn = r [0 ][0 ]
203- rdn = compose_rdn (entity )
258+ rdn = get_rdn_attribure (oldDn )
259+ rdnValue = entry [rdn ][0 ].decode ('UTF-8' )
260+ new_rdn = rdn + "=" + rdnValue
204261 newSuperior = dn_superior (compose_dn (entity ))
205262 try :
206263 action = "rename"
207- l .rename_s (oldDn ,rdn ,newSuperior )
264+ l .rename_s (oldDn ,new_rdn ,newSuperior )
208265 except ldap .LDAPError as e :
209266 e_dict = e .args [0 ]
210- print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" )))
267+ print (returncode (1 , 'rename ' + str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" ) + " " + e_dict . get ( "info " )))
211268 exit (1 )
212269 return returncode (0 ,"Entree " + dn + " " + action )
213270
@@ -226,15 +283,15 @@ def change_password(l,uid,old,new):
226283 l .passwd_s (r [0 ][0 ],old ,new )
227284 except ldap .LDAPError as e :
228285 e_dict = e .args [0 ]
229- print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" )))
286+ print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" ) + " " + e_dict . get ( "info" ) ))
230287 exit (1 )
231288 else :
232289 ldif = [(ldap .MOD_REPLACE , 'userPassword' , [new .encode ('utf-8' )])]
233290 try :
234291 l .modify_s (r [0 ][0 ], ldif )
235292 except ldap .LDAPError as e :
236293 e_dict = e .args [0 ]
237- print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" )))
294+ print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" ) + " " + e_dict . get ( "info" ) ))
238295 exit (1 )
239296
240297def change_entity_password (l ,entity ):
@@ -271,9 +328,31 @@ def delete_entity(l,entity):
271328 return returncode (0 , "user : " + r [0 ][0 ] + " deleted" )
272329 except ldap .LDAPError as e :
273330 e_dict = e .args [0 ]
274- print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" )))
331+ print (returncode (1 , str (e_dict .get ("result" )) + ' ' + e_dict .get ("desc" ) + " " + e_dict . get ( "info" ) ))
275332 exit (1 )
276333 else :
277334 print (returncode (1 , "User not found" ))
278335 exit (1 )
336+ def complete_entry (entry ,r ):
337+ for cle ,valeur in r [0 ][1 ].items ():
338+ if cle .lower () != 'objectclass' :
339+ if cle not in entry :
340+ if type (valeur ) is list :
341+ for i in valeur :
342+ x = i .decode ('UTF-8' )
343+ if len (x ) == 1 :
344+ v = x [0 ]
345+ else :
346+ v = x
347+ entry [cle .lower ()]= v
348+ return entry
279349
350+ def normalize_entry (entry ):
351+ e = {}
352+ for cle , valeur in entry .items ():
353+ e [cle .lower ()]= valeur
354+ return e
355+ def get_rdn_attribure (dn ):
356+ dnTab = dn .split (',' )
357+ attr = dnTab [0 ].split ('=' )
358+ return attr [0 ]
0 commit comments