Enterprise Authentication Integration
Generating an Account Audit Report Automatically
Goal
You reconcile the HR roster and the LDAP directory to extract ghost accounts, accounts not created, privileged ghost accounts, and long-inactive accounts with scripts, and after quarantine handling, write an audit report.
Why it matters
"Are departed employees' accounts disabled immediately?" is the first question of every security audit. And most organizations do this reconciliation once a quarter by hand in Excel. Incidents happen in between. Ghost accounts arise not from laziness but from structure — incremental synchronization cannot detect deletions, and without provisioning (SCIM), accounts remain as they are in individual systems. If you can run this reconciliation automatically every week, it becomes operations and not audit response.
Steps
- Preparation: start slapd on 1389 and load
00-base,10-people, and20-groups. - Extract every
inetOrgPersonin the directory and create/root/audit/ldap_users.csv. The first line isuid,cn,ou,title, sorted by uid in ascending order. - Copy
/opt/lab/fixtures/auth/audit/hr_roster.csvto/root/audit/hr.csv. (The contents must be identical) - Save the uids that are in the directory but not in the HR roster to
/root/audit/ghost.txt, one per line in ascending order. - Save the uids that are in the HR roster but not in the directory to
/root/audit/missing.txtin the same format. - Among the ghost accounts, pick those that are members of the group
cn=admins,ou=Groups,dc=labhub,dc=co,dc=krand save them to/root/audit/critical.txt. - Based on
/opt/lab/fixtures/auth/audit/lastlogin.csv, save the uids with no login for 90 days or more as of 2026-08-01 to/root/audit/stale.txtin ascending order. (A uid that is not in the file is treated as "no login history" and included in the targets.) - Move all the ghost accounts under
ou=Disabled,dc=labhub,dc=co,dc=kr. (You must create theou=Disabledentry first.) After the move, they must not be found inou=People, and the number of entries inou=Disabledmust equal the number of ghost accounts. - Write
/root/audit/report.md. It must have six h2 headings,## 총계,## 유령 계정,## 미생성 계정,## 특권 계정,## 휴면 후보, and## 조치 계획(in order: totals, ghost accounts, accounts not created, privileged accounts, dormancy candidates, action plan), and the following five lines must be included exactly.total=<디렉터리 전체 사용자 수(격리 포함)> ghost=<유령 계정 수> missing=<미생성 계정 수> critical=<특권 유령 계정 수> stale=<90일 미접속 계정 수>
Notes
- Set difference:
comm -23 <(sort a.txt) <(sort b.txt) - Date to seconds:
date -d 2026-05-01 +%s - DN move:
ldapmodrdn -r -s "ou=Disabled,dc=labhub,dc=co,dc=kr" "<기존DN>" "uid=<uid>"(the placeholder is the existing DN) - Common mistake 1: giving unsorted input to
comm. The result is silently wrong. - Common mistake 2: including the CSV header line in the uid list.
- Common mistake 3: deleting ghost accounts. Quarantine is the principle because of audit trails and referential integrity.
Extract directory accounts
Extract every inetOrgPerson in the directory and create /root/audit/ldap_users.csv.
The first line is uid,cn,ou,title, sorted by uid in ascending order.
Extract only the attributes you need. To match the output format to CSV you have to process the ldapsearch result, so start by cutting the clutter with -LLL.
Obtain the HR roster
Copy /opt/lab/fixtures/auth/audit/hr_roster.csv to
/root/audit/hr.csv. (The contents must be identical)
Do not touch the original; work on a copy. If you count the rows first, you can check the results of the later set operations.
Extract ghost accounts
Save the uids that are in the directory but not in the HR roster to
/root/audit/ghost.txt, one per line in ascending order.
Sort both uid lists and take the set difference. comm is accurate only when its inputs are sorted.
Extract accounts not created
Save the uids that are in the HR roster but not in the directory to
/root/audit/missing.txt in the same format.
It is the same set difference in the opposite direction. Remember that this list is not a security issue but a work delay indicator.
Privileged ghost accounts
Among the ghost accounts, pick those that are members of the group cn=admins,ou=Groups,dc=labhub,dc=co,dc=kr
and save them to /root/audit/critical.txt.
It is the intersection of the ghost account list and the administrator group member list. This is the part that becomes the top-priority action target in an audit.
Long-inactive accounts
Based on /opt/lab/fixtures/auth/audit/lastlogin.csv,
save the uids with no login for 90 days or more as of 2026-08-01 to
/root/audit/stale.txt in ascending order.
(A uid that is not in the file is treated as "no login history" and included in the targets.)
The reference date must be fixed for the result to be reproducible. For date calculations, it is simple to convert to seconds with the date command and compare.
Quarantine handling
Move all the ghost accounts under ou=Disabled,dc=labhub,dc=co,dc=kr.
(You must create the ou=Disabled entry first.)
After the move, they must not be found in ou=People,
and the number of entries in ou=Disabled must equal the number of ghost accounts.
Think about why you quarantine accounts instead of deleting them. The data must remain after the move, and they must drop out of the "active users" search.
Write the audit report
Write /root/audit/report.md.
It must have six h2 headings, ## 총계, ## 유령 계정, ## 미생성 계정, ## 특권 계정, ## 휴면 후보,
and ## 조치 계획 (in order: totals, ghost accounts, accounts not created, privileged accounts, dormancy candidates, action plan), and the following five lines must be included exactly.
total=<디렉터리 전체 사용자 수(격리 포함)>
ghost=<유령 계정 수>
missing=<미생성 계정 수>
critical=<특권 유령 계정 수>
stale=<90일 미접속 계정 수>
The value of a report is in the numbers and the trend. Quote the figures you obtained in the previous steps as they are, and attach an action plan to each item.