Skip to content

Commit fd24d2c

Browse files
committed
more work
1 parent 3153def commit fd24d2c

12 files changed

Lines changed: 403 additions & 29 deletions

‎src/bin/activation.py‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/python3
2+
import sys
3+
sys.path.append('../lib')
4+
import backend_sambaad_utils as smb
5+
import backend_utils as u
6+
import argparse
7+
8+
def main():
9+
parser = argparse.ArgumentParser()
10+
parser.add_argument('--active', help='0 | 1 ', default='1')
11+
args = parser.parse_args()
12+
json=u.readjsoninput()
13+
config=u.read_config('../etc/config.conf')
14+
smb.set_config(config)
15+
if u.is_backend_concerned(json) == False:
16+
print(u.returncode(0, "not concerned"))
17+
exit(0)
18+
l=smb.connect_sambaad(u.config('host'),u.config('dn'),u.config('password'))
19+
if args.active == "1":
20+
ret=l.activate_entry(l,json,True)
21+
else:
22+
ret = l.activate_entry(l, json, False)
23+
print(ret)
24+
exit(0)
25+
26+
if __name__ == '__main__':
27+
main()

‎src/bin/changepwd.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/python3
2+
import sys
3+
sys.path.append('../lib')
4+
import backend_sambaad_utils as smb
5+
import backend_utils as u
6+
import json
7+
def main():
8+
js=u.readjsoninput()
9+
config= u.read_config('../etc/config.conf')
10+
smb.set_config(config)
11+
if u.is_backend_concerned(js):
12+
l=smb.connect_sambaad(u.config('host'),u.config('user'),u.config('password'))
13+
ret=smb.change_entity_password(l,js)
14+
result=json.loads(ret)
15+
print(ret)
16+
exit(result['status'])
17+
else:
18+
print(u.returncode(0,'not concerned'))
19+
20+
if __name__ == '__main__':
21+
main()
22+

‎src/bin/delentity.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/usr/bin/python3
2+
import sys
3+
sys.path.append('../lib')
4+
import backend_sambaad_utils as smb
5+
import backend_utils as u
6+
def main():
7+
json=u.readjsoninput()
8+
config=u.read_config('../etc/config.conf')
9+
smb.set_config(config)
10+
if u.is_backend_concerned(json):
11+
l=smb.connect_sambaad(u.config('host'),u.config('user'),u.config('password'))
12+
print(smb.delete_entity(l,json))
13+
else:
14+
print(u.returncode(0, "not concerned"))
15+
16+
if __name__ == '__main__':
17+
main()

‎src/bin/lifecycle.py‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/python3
2+
# Recherche un script nommé 'lifecycle' (.py/.sh/.pl) dans src/lifecycle/.
3+
# Avant d'exécuter lifecycle.py, vérifie s'il existe un script nommé
4+
# {before.lifecycle}_{after.lifecycle}+extension et l'exécute à la place si trouvé.
5+
# Si aucun script lifecycle n'est trouvé, retourne "not concerned".
6+
import json
7+
import os
8+
import subprocess
9+
import sys
10+
11+
sys.path.append('../lib')
12+
import backend_utils as u
13+
14+
15+
EXTENSIONS = ['', '.py', '.sh', '.pl']
16+
17+
18+
def run_backend(script, content):
19+
ret = subprocess.run(script, input=content.encode(), capture_output=True)
20+
return {"returncode": ret.returncode, "stdout": ret.stdout.decode()}
21+
22+
23+
def find_script(lifecycle_dir, names):
24+
for name in names:
25+
for ext in EXTENSIONS:
26+
candidate = lifecycle_dir + '/' + name + ext
27+
if os.path.isfile(candidate):
28+
return candidate
29+
return None
30+
31+
32+
def main():
33+
lifecycle_dir = '../lifecycle'
34+
raw = sys.stdin.read()
35+
content = raw.replace("\n", "")
36+
config = u.read_config('../etc/config.conf')
37+
try:
38+
data = json.loads(content)
39+
before = data['payload']['before']['lifecycle']
40+
after = data['payload']['after']['lifecycle']
41+
specific_name = before + '_' + after if before and after else None
42+
except (json.JSONDecodeError, Exception):
43+
specific_name = None
44+
if u.is_backend_concerned(data) == False:
45+
print(u.returncode(0, "not concerned"))
46+
exit(0)
47+
script = None
48+
if specific_name:
49+
script = find_script(lifecycle_dir, [specific_name])
50+
51+
if script is None:
52+
script = find_script(lifecycle_dir, ['lifecycle'])
53+
54+
if script is None:
55+
print(u.returncode(0, "not concerned"))
56+
exit(0)
57+
58+
ret = run_backend(script, content)
59+
print(ret['stdout'])
60+
exit(ret['returncode'])
61+
62+
63+
if __name__ == '__main__':
64+
main()

‎src/bin/ping.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/usr/bin/python3
2+
import sys
3+
import ldb
4+
sys.path.append('../lib')
5+
import backend_sambaad_utils as smb
6+
import backend_utils as u
7+
def main():
8+
config=u.read_config('../etc/config.conf')
9+
smb.set_config(config)
10+
samdb = smb.connect_sambaad(u.config('host'), u.config('user'), u.config('password'))
11+
if samdb:
12+
print(u.returncode(0,'I m alive'))
13+
return 0
14+
15+
16+
if __name__ == '__main__':
17+
main()

‎src/bin/resetpwd.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/python3
2+
import sys
3+
sys.path.append('../lib')
4+
import backend_sambaad_utils as smb
5+
import backend_utils as u
6+
7+
def main():
8+
json=u.readjsoninput()
9+
config=u.read_config('../etc/config.conf')
10+
smb.set_config(config)
11+
if u.is_backend_concerned(json):
12+
l=smb.connect_sambaad(u.config('host'),u.config('user'),u.config('password'))
13+
print(smb.reset_entity_password(l,json))
14+
else:
15+
print(u.returncode(0,'not concerned'))
16+
17+
18+
if __name__ == '__main__':
19+
main()

‎src/bin/upsertidentity.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77

88
def main():
99
json=u.readjsoninput()
10+
#json=u.readjsonfile('../../unittest/backend_ad_files/identity1.json')
1011
config=u.read_config('../etc/config.conf')
1112
smb.set_config(config)
1213
if u.is_backend_concerned(json):
13-
l=smb.connect_sambaad(u.config('host'),u.config('dn'),u.config('password'))
14+
l=smb.connect_sambaad(u.config('host'),u.config('user'),u.config('password'))
1415
print(smb.upsert_entry(l,json))
1516
else:
1617
print(u.returncode(0,'not concerned'))

‎src/lib/backend_sambaad_utils.py‎

Lines changed: 138 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1-
import configparser
2-
import json
3-
import os
4-
import jinja2
51
import sys
6-
import getpass
72
import ldb
3+
import secrets
4+
import string
5+
from samba import samdb
86
from samba.auth import system_session
97
from samba.credentials import Credentials
10-
from samba.dcerpc import security
11-
from samba.dcerpc.security import dom_sid
12-
from samba.ndr import ndr_pack, ndr_unpack
138
from samba.param import LoadParm
149
from samba.samdb import SamDB
15-
from sys import stdin
1610
sys.path.append('.')
1711
import backend_utils as u
1812
__LIFECYLE_DIR__="../lifecycle"
@@ -21,37 +15,153 @@ def set_config(config):
2115
u.__CONFIG__ = config
2216

2317
def connect_sambaad(url,user,password):
18+
lp = LoadParm()
2419
creds = Credentials()
2520
creds.guess(lp)
2621
creds.set_username(user)
2722
creds.set_password(password)
2823
try:
29-
samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp)
30-
return (1)
31-
except samdb.error.SamDBError as e:
32-
print(u.returncode(1, e))
33-
return (1)
24+
samdb = SamDB(url=url, session_info=system_session(),credentials=creds, lp=lp)
25+
result = samdb.search(
26+
base=u.config('base'),
27+
scope=ldb.SCOPE_BASE,
28+
attrs=["objectClass"]
29+
)
30+
return samdb
31+
except ldb.LdbError as e:
32+
code, message = e.args
33+
print(u.returncode(1,f"Erreur {code} : {message}"))
34+
return(None)
3435

35-
def upsert_entry(l,entity):
36-
return (1)
3736

38-
def search_entity(l,entity):
39-
return (1)
37+
def upsert_entry(samdb,entity):
38+
# test si l'entree existe
39+
result=search_entity(samdb,entity)
40+
if len(result) == 0:
41+
entry=u.make_entry_array_without_empty(entity)
42+
pwd=generate_password()
43+
try:
44+
uid=entry['uid']
45+
samdb.newuser(
46+
username=uid,
47+
givenname=entry['givenName'],
48+
surname=entry['sn'],
49+
mailaddress=entry['mail'],
50+
password=pwd
51+
)
52+
query = (f"(sAMAccountName={uid})")
53+
samdb.setexpiry(query,0,True)
54+
samdb.disable_account(query)
55+
return(u.returncode(0,'Entry added'))
56+
except ldb.LdbError as e:
57+
code, message = e.args
58+
print(u.returncode(1, f"Erreur {code} : {message}"))
59+
return (None)
60+
else:
61+
try:
62+
entry = result[0]
63+
msg = ldb.Message()
64+
msg.dn = entry.dn
65+
msg["sn"] = ldb.MessageElement(
66+
entry['sn'],
67+
ldb.FLAG_MOD_REPLACE,
68+
"sn"
69+
)
70+
msg["givenName"] = ldb.MessageElement(
71+
entry['givenName'],
72+
ldb.FLAG_MOD_REPLACE,
73+
"givenName"
74+
)
75+
msg["mail"] = ldb.MessageElement(
76+
entry['mail'],
77+
ldb.FLAG_MOD_REPLACE,
78+
"mail"
79+
)
80+
samdb.modify(msg)
81+
return (u.returncode(0, 'Entry modified'))
82+
except ldb.LdbError as e:
83+
code, message = e.args
84+
print(u.returncode(1, f"Erreur {code} : {message}"))
85+
return (None)
4086

41-
def delete_entity(l,entity):
42-
return (1)
4387

44-
def update_entity(l,entity):
45-
return (1)
88+
def search_entity(samdb,entity):
89+
uid = u.find_key(entity, 'uid')
90+
query = (f"(sAMAccountName={uid})")
91+
result=samdb.search(u.config('base'), expression=query, scope=ldb.SCOPE_SUBTREE)
92+
return (result)
4693

47-
def activate_entry(l,entity,activate):
48-
return (1)
94+
def delete_entity(samdb,entity):
95+
uid = u.find_key(entity, 'uid')
96+
try:
97+
samdb.deleteuser(uid)
98+
return(u.returncode(0, 'Entry deleted'))
99+
except ldb.LdbError as e:
100+
code, message = e.args
101+
print(u.returncode(1, f"Erreur {code} : {message}"))
102+
return (None)
49103

50-
def change_entity_password(l,entity):
51-
return (1)
104+
def activate_entry(samdb,entity,activate):
105+
uid = u.find_key(entity, 'uid')
106+
query = (f"(sAMAccountName={uid})")
107+
try:
108+
if activate == True:
109+
samdb.enable_account(query)
110+
return(u.returncode(0,'Entry activated'))
111+
else:
112+
samdb.disable_account(query)
113+
return(u.returncode(0,'Entry desactivated'))
114+
except ldb.LdbError as e:
115+
code, message = e.args
116+
print(u.returncode(1, f"Erreur {code} : {message}"))
117+
return (None)
52118

53-
def reset_entity_password(l,entity):
54-
return (1)
119+
def change_entity_password(samdb,entity):
120+
if 'oldPassword' in entity['payload'] and 'newPassword' in entity['payload']:
121+
oldPassword = entity['payload']['oldPassword']
122+
newPassword = entity['payload']['newPassword']
123+
if oldPassword != '' and newPassword != '':
124+
uid = u.find_key(entity, 'uid')
125+
# test ancien password
126+
if verify_password(uid,oldPassword) == 0:
127+
try:
128+
query = (f"(sAMAccountName={uid})")
129+
samdb.setpassword(query, newPassword, True)
130+
return u.returncode(0, "Password for " + uid + " changed")
131+
except ldb.LdbError as e:
132+
print(u.returncode(1, "Error entity_change_password"))
133+
return (None)
134+
return(u.returncode(1, "Internal Error Error entity_change_password"))
55135

136+
def reset_entity_password(samdb,entity):
137+
if 'newPassword' in entity['payload']:
138+
try:
139+
newPassword = entity['payload']['newPassword']
140+
if newPassword != '':
141+
uid = u.find_key(entity, 'uid')
142+
query = (f"(sAMAccountName={uid})")
143+
samdb.setpassword(query, newPassword, True)
144+
return u.returncode(0, "Password for " + uid + " changed")
145+
except ldb.LdbError as e:
146+
code, message = e.args
147+
print(u.returncode(1, f"Erreur {code} : {message}"))
148+
return (None)
149+
return u.returncode(1, "Unexpected error")
56150

151+
def generate_password():
152+
longueur = 16
153+
chars = string.ascii_letters + string.digits + string.punctuation
154+
return( ''.join(secrets.choice(chars) for _ in range(longueur)) )
57155

156+
def verify_password(user,password):
157+
lp = LoadParm()
158+
creds = Credentials()
159+
creds.guess(lp)
160+
creds.set_username(user)
161+
creds.set_password(password)
162+
try:
163+
test = SamDB(url=u.config('host'), session_info=system_session(), credentials=creds, lp=lp)
164+
return 0
165+
except ldb.LdbError as e:
166+
code, message = e.args
167+
return (1)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"concernedTo":"673caf105bb040153c074f2d","payload":{"uid":"omaton","oldPassword":"Abbert1xIEIIE88!","newPassword":"AbCx34IddWZE1!","_id":"673caf105bb040153c074f2d","inetOrgPerson":{"cn":"Maton Olivier","displayName":"Olivier Maton","facsimileTelephoneNumber":"","givenName":"Olivier","labeledURI":"","mail":"xx@xx.fr","mobile":"","postalAddress":"","preferredLanguage":"","sn":"Maton","telephoneNumber":"","title":"","uid":"omaton","employeeNumber":["184944"],"employeeType":"TAIGA","departmentNumber":["esn"],"jpegPhoto":"","userCertificate":""},"additionalFields":{"objectClasses":["supannPerson"],"attributes":{"supannPerson":{"supannAutreMail":"contact@latx.com","supannEmpId":184944,"supannEntiteAffectationPrincipale":"esn","supannEtablissement":"{UAI}A123456","supannNomdeNaissance":"","supannOIDCDatedeNaissance":"01/01/1970","supannOIDCGenre":"M.","supannPrenomsEtatCivil":"Olivier","supannRefId":["{TAIGA}184944"],"supannTypeEntiteAffectation":["esn"],"supanncivilite":"M.","supannCodeINSEEPaysDeNaissance":"","supannCodeINSEEVilleDeNaissance":"","supannListeRouge":"","mailForwardingAddress":"","supannMailPerso":"","supannRoleGenerique":"","supannParrainDN":"","supannActivite":"","supannEmpDateFin":"","supannEtuAnneeInscription":"","supannEntiteAffectation":[],"supannEtUid":"","supannEtuCursusAnnee":"","supannEtuDiplome":"","supannCodeIne":""}}},"dataStatus":1,"deletedFlag":false,"initState":0,"lastBackendSync":"2025-01-21T12:17:55.427Z","lastSync":"2024-11-19T15:34:14.599Z","lifecycle":-1,"metadata":{"createdBy":"taiga","createdAt":"2024-11-19T15:30:24.431Z","lastUpdatedBy":"admin","lastUpdatedAt":"2025-01-21T12:17:52.740Z"},"primaryEmployeeNumber":"","srcFusionId":"","state":99,"fingerprint":"30e1fb7f3ce51202908e6c2b065786ed6d904038e40f302b8c31cc97b1b081eb"},"options":{"async":false,"timeoutDiscard":true,"disableLogs":true,"switchToProcessing":false,"updateStatus":false}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"concernedTo":"673df967f8edfbb98437994f","payload":{"identity":{"action":"IDENTITY_UPDATE","identity":{"_id":"673df967f8edfbb98437994f","inetOrgPerson":{"cn":"Maton Olivier","displayName":"Olivier Maton","facsimileTelephoneNumber":"","givenName":"Olivier","labeledURI":"","mail":"olivier.maton@exemple.fr","mobile":"06 05 04 03 02","postalAddress":"15 rue des pingouins, 54000, Nancy","preferredLanguage":"","sn":"Maton","telephoneNumber":"","title":"","uid":"omaton","employeeNumber":"179892","employeeType":"TAIGA","departmentNumber":["adm"],"jpegPhoto":"","userCertificate":""},"additionalFields":{"objectClasses":["supannPerson","eduPerson","sogxuser","ealPerson"],"attributes":{"eduPerson":{"edupersonaffiliation":["staff","member"],"edupersonprimaryaffiliation":"staff","edupersonprincipalname":"omaton@exemple.com"},"sogxuser":{"proxyaddress":["administrator@exemple.conf"],"sogxquota":0,"sogxdisableflag":0},"supannPerson":{"supannAutreMail":"olivier.maton@gmoil.com","supannEmpId":"175","supannEtablissement":"{UAI}0690184A","supannOIDCDatedeNaissance":"01/01/1970","supannOIDCGenre":"M.","supannPrenomsEtatCivil":"Olivier","supannRefId":["179892","175"],"supannTypeEntiteAffectation":["adm"],"supanncivilite":"M.","supannEntiteAffectationPrincipale":"adm","supannNomdeNaissance":"","supannCodeINSEEPaysDeNaissance":"","supannCodeINSEEVilleDeNaissance":"","supannListeRouge":"","mailForwardingAddress":"","supannMailPerso":"","supannRoleGenerique":"","supannEtuId":"","supannParrainDN":"","supannActivite":"","supannEmpDateFin":"","supannEtuDiplome":"","supannEtuAnneeInscription":""},"ealPerson":{"ealnumcarte":"043d6232346f80","ealmail2":"","ealmobile2":"","ealformation":"","ealsituation":"","ealcycle":"","ealan":"","ealdepartement":"","ealwifi":"","ealnumetd":"","ealenseignement":[],"ealue":[]}}},"customFields":{"photo":"adm-175.jpg"},"dataStatus":1,"deletedFlag":false,"initInfo":{"sentDate":"","initDate":"2025-01-29T10:47:15.870Z"},"initState":1,"lastBackendSync":"","lastSync":"2025-01-29T08:27:38.932Z","lifecycle":-1,"metadata":{"createdAt":"2024-11-20T14:59:51.924Z","createdBy":"Taiga","lastUpdatedAt":"2025-01-30T16:59:24.708Z","lastUpdatedBy":"admin"},"primaryEmployeeNumber":"","srcFusionId":"","state":2,"fingerprint":"b46334b0f30216223ac51cb2e87bea7e5d843bba2a529142d6b72ff731e52623"}}},"options":{"async":false,"updateStatus":true,"task":"679bafef3b8386f9c7f360a3"}}

0 commit comments

Comments
 (0)