aaieduhr / aosi-module-libldifsync
AOSI LibLdifSync Module
Package info
gitlab.opencode.hr/srce/aai-eduhr/aosi/aosi-module-libldifsync
Type:aosi-module
pkg:composer/aaieduhr/aosi-module-libldifsync
Requires
- php: >=8.2
- ext-ldap: *
- aaieduhr/aosi-module-libldifmanip: ^5
- psr/container: ^2.0
- psr/http-factory: ^1.0
- psr/http-message: ^2.0
- psr/log: ^3.0
Requires (Dev)
- aaieduhr/aosi: ^5
- phpstan/phpstan: ^2.1
- phpstan/phpstan-deprecation-rules: ^2.0
- phpunit/phpunit: ^10 || ^11
- rector/rector: ^2.0
- slevomat/coding-standard: ^8
- squizlabs/php_codesniffer: ^3
This package is not auto-updated.
Last update: 2026-04-15 09:16:26 UTC
README
Ovaj modul pruža SOAP metodu za LDIF sinkronizaciju (legacy AOSI v4 stil i novi v5 stil).
Funkcionalno replicira ponašanje starog Perl modula LDIFSync.pm.
SOAP endpointi
Modul ne izlaže vlastite SOAP endpoint-e. SOAP server i endpointi dolaze iz
aosi-module-soap-server:
- RPC/Encoded:
POST /AOSI - Document/Literal:
POST /AOSI-DOCUMENT - WSDL (RPC):
GET /wsdl - WSDL (Document):
GET /wsdl-document
Metode iz ovog modula registriraju se kroz getSoapServerMethods() i objavljuju u
glavnom AOSI WSDL-u zajedno s ostalim SOAP metodama.
Metoda ldapLDIFSync
Parametri:
user(uid ili DN)password(base64)base(base DN)type(1-8)offset(opcionalno, bajtovi; koristi se zatype=8)chunk_mb(opcionalno, MB; koristi se zatype=8)
Značenje type:
- info o originalnoj LDIF datoteci
- rotacija + čitanje rotirane datoteke
- info o rotiranoj datoteci
- čitanje rotirane datoteke
- info o dump datoteci
- dump svih zapisa u LDIF datoteku (default: asinkrono pokretanje)
- čitanje dump datoteke
- čitanje dump datoteke u chunkovima (
offset+chunk_mb)
Putanje LDIF datoteka uvijek se citaju iz aosi-module-libldifmanip/config/libldifmanip.php
(outputs['LDIFSync']). Ovaj modul vise nema vlastite sync/dump putanje.
Rotacija LDIF datoteka
Rotaciju (logrotate ili PHP fallback) obavlja servis LdifRotator
iz modula aosi-module-libldifmanip. Konfiguracija je u:
aosi-module-libldifmanip/config/libldifmanip.php→logrotate
Ako logrotate izvrsna datoteka nije dostupna (npr. macOS), koristi se PHP fallback
koji rotira u .1/.2/... i kreira novu praznu datoteku.
Dump LDAP-a
Dump svih zapisa (type=6) radi servis LdifDumper iz modula aosi-module-libldifmanip.
Konfiguracija izlaza je u:
aosi-module-libldifmanip/config/libldifmanip.php→outputs['LDIFSync']
Dump koristi isti profil kao i LDIFSync, samo dodaje sufiks _dumpAll na file_prefix.
Default datoteka dumpa je data/LDIFSync/LDIFSync_dumpAll_<realm>.ldif i ne prepisuje
standardne LDIFSync datoteke.
Za type=6 modul po defaultu pokrece dump asinkrono (CLI u pozadini) i odmah vraca
SOAP odgovor, da se izbjegnu HTTP timeouti na velikim imenicima.
Konfiguracija:
libldifsync.dump.async(true|false, defaulttrue)libldifsync.dump.php_binary(opcijski; putanja do izvršne datoteke PHP interpretera za asinkrono pokretanje)libldifsync.dump.async_log_file(naziv log datoteke uapp.logs.dir)libldifsync.read.type7_size_guard_enabled(true|false, defaulttrue)libldifsync.read.type7_limit_mb(default50)libldifsync.read.type7_limit_min_mb(default10)libldifsync.read.type7_limit_max_mb(default50)libldifsync.read.type8_chunk_mb(default5)libldifsync.read.type8_chunk_max_mb(default50)
Potpuni primjer konfiguracije (s komentarima) je u:
config/libldifsync.example.php
U asinkronom nacinu:
type=6vraca info o dump datoteci i warning da je dump pokrenuttype=5vraca metadata +dump_status(IN_PROGRESS,READY,NOT_FOUND)type=7cita cijeli dump tek kada je spreman; dok je dump aktivan vraca kod-25- ako je
type7_size_guard_enabled=truei dump je veci od limita,type=7vraca-26i preporuku zatype=8 type=8vraca chunk dumpa i metapodatke (chunk_next_offset,eof,total_size)app.logzapisldapLDIFSync called.ukljucuje iclient_ipapp.logzapisLibLdifSync: async dump startedukljucujebaseiclient_ip- async dump log je per-realm datoteka (
<ime>_<realm>.log) i na startu dumpa dobiva zaglavlje s:STARTED_AT,CLIENT_IP,REALM,BASE,DUMP_FILE
Preporuceni polling redoslijed:
- Pozovi
type=6(pokretanje dumpa). - Zatim pozivaj
type=5dokdump_statusne postaneREADY. - Ako je dump manji od limita, pozovi
type=7za puni sadrzaj. - Ako
type=7vrati-26, koristitype=8: prvi pozivoffset=0, zatim ponavljaj pozive soffset=chunk_next_offsetdokeofne postane1.
Napomena
SOAP endpointi rade kroz aosi-module-soap-server, a HTTP status (npr. 403) može
postaviti sam SOAP handler preko http_response_code(...). SOAP server taj status
preslikava u stvarni HTTP odgovor.
Modul ne registrira event listenere (before/after add/modify/delete). Ta funkcionalnost
za automatski LDIF zapis je u modulu aosi-module-libldifmanip.
LDAP autentikacija za LDIFSync
Za SOAP metodu ldapLDIFSync dopušten je isključivo korisnik cn=hreduadmin.
- Parametar
usermora biti točnocn=hreduadmin(ignoriraju se velika/mala slova i razmaci). - Parametar
passwordmora biti Base64 enkodirana lozinka. - Parametar
baseulazi u završni DN:cn=hreduadmin,<base>.
To znači:
- bilo koji drugi korisnik (
uid=...,cn=..., plain UID i sl.) je odbijen - neispravna lozinka je odbijena
- u oba slučaja SOAP vraća istu LDAP grešku autentikacije (
code=49, porukaWrong dn or password.), bez otkrivanja detalja.
Provjera je centralizirana u core modulu (aosi-module-core) kroz metodu
AaiEduHr\Aosi\Module\Core\Ldap::hrEduAdminBind(...), a libldifsync je samo koristi:
$result = $this->ldap->hrEduAdminBind($user, $password, $base);
if (!$result instanceof \LDAP\Connection) {
// Greška (npr. code=49) propagira se kroz $this->ldap->err_code()/err_message().
}
Provjera dozvoljene IP adrese
Primarni put provjere koristi metodu:
AaiEduHr\Aosi\Authn\ApiAuthnResolver::for($request, $validIps).
libldifsync SOAP handler:
- dohvaća allowlistu iz
libldifsync.valid_ips - poziva
ApiAuthnResolver::for(...) - koristi
ApiAuthn::isClientAuthenticated():trueako je klijent autenticiran certifikatom ili dozvoljenom IP adresomfalseako nije autentificiran
- za neautenticiranog klijenta vraća SOAP kod
-23, postavlja HTTP status403i zapisuje warning log s IP adresom klijenta
Konfiguracija se nalazi u:
vendor/aaieduhr/aosi-module-libldifsync/config/libldifsync.php
Pravila za valid_ips:
- prazna lista (
[]) znači zabrani sve - inače se radi točno podudaranje IP adrese (
===)
Primjer produkcijske konfiguracije:
'valid_ips' => [
'172.24.240.1', // primjer: Windows host prema WSL servisu
'10.10.65.107', // primjer: interni servisni host
],
Primjer testiranja:
curl -s -o /tmp/soap_response.xml -w "%{http_code}\n" \
-X POST "https://<host>/aosi/AOSI-DOCUMENT" \
-H "Content-Type: text/xml; charset=utf-8" \
-d @soap_payload.xml
Očekivani rezultat:
- dozvoljena IP: HTTP
200, SOAPcode=0 - nedozvoljena IP: HTTP
403, SOAPcode=-23
Ako je aplikacija iza reverznog proxyja, ClientIpResolver koristi forwarding zaglavlja
tek kada je proxy dodan u env.trusted_proxies (u config/env.php).
Podrška za više realm-ova
- Realm se derivira iz
baseparametra (dc=srce,dc=hr->srce). - Ako je
per_realm=trueu profiluoutputs['LDIFSync'], naziv datoteke dobiva sufiks_<realm>. - To omogućuje istovremeni rad s više base DN-ova (npr.
dc=srce,dc=hridc=intsrce,dc=hr) bez kolizija u nazivima datoteka.
SOAP poziv uvijek radi samo nad jednim realm-om (onim iz base parametra) i
vraća samo datoteku tog realma. Ako želite obraditi više realma, potrebno je
pozvati metodu više puta s različitim base vrijednostima.
Primjer poziva za više realma (RPC/Encoded):
# realm "srce"
curl -X POST "https://<host>/aosi/AOSI" \
-H "Content-Type: text/xml; charset=utf-8" \
-H "SOAPAction: \"urn:AOSI#ldapLDIFSync\"" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tns="urn:AOSI">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:ldapLDIFSync>
<user>cn=hreduadmin</user>
<password>BASE64</password>
<base>dc=srce,dc=hr</base>
<type>1</type>
</tns:ldapLDIFSync>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'
# realm "intsrce"
curl -X POST "https://<host>/aosi/AOSI" \
-H "Content-Type: text/xml; charset=utf-8" \
-H "SOAPAction: \"urn:AOSI#ldapLDIFSync\"" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tns="urn:AOSI">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:ldapLDIFSync>
<user>cn=hreduadmin</user>
<password>BASE64</password>
<base>dc=intsrce,dc=hr</base>
<type>1</type>
</tns:ldapLDIFSync>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'
Ako je env.environment postavljen na production, modul nema korisničko sučelje:
nema stavke u admin meniju i ne učitava se /libldifsync stranica. SOAP i WSDL
endpointi ostaju aktivni kroz aosi-module-soap-server.
Preduvjeti
Potrebne PHP ekstenzije:
ext-ldap
Testovi
Testovi su u tests/Soap/LibLdifSyncSoapHandlerTest.php i pokrivaju:
type=1(info o originalnoj LDIF datoteci)type=2(rotacija + citanje rotirane datoteke)type=3(info o rotiranoj datoteci)type=4(citanje rotirane datoteke)type=5(info o dump datoteci)type=6(dump svih zapisa u LDIF datoteku)type=7(citanje dump datoteke)type=8(chunk citanje dump datoteke)- normalizaciju
type=8parametara (offsetichunk_mb) prema konfiguraciji - ograničenje LDAP autentikacije na korisnika
cn=hreduadmin - uspjesan asinkroni start za
type=6(simulacija background procesa) - IP allowlist autentikaciju (allow/deny prema
libldifsync.valid_ips) - autentikaciju klijenta preko
ApiAuthnResolver::for(...)(allow/deny scenariji) - LDAP bind greske (propagacija
err_code/err_message)
Pokretanje testova:
vendor/bin/phpunit
Zadnje lokalno pokretanje:
24testa99assertiona0skipped
Licence
This work is published under European Union Public License (the ‘EUPL’) v1.2.
Autorstvo i alati
Autor: Krešimir Mihalj (kresimir.mihalj@srce.hr).
Kod je razvijen u PHPStormu uz asistenciju Codex‑a.