This script can map any CSV field or LDIF entries attributes to one or more LDIF entries attributes, with specific rules for DN generation and multi-values management.
This is written in Perl and uses:
You have to edit the script to modify the configuration:
$ vi file2ldif.pl
Parameters are:
You can define tasks to manage different CSV file structures. For example you can have one CSV file for users and another for groups. So the task name is the first level in the hash map, such as “person” and “group” in this example:
my $map => {
person => { ... }
group => { ... }
};
The task name is important because it will be used as a command line parameter to the script.
Then, in each task, you will define the mapping with the Net::LDAP::Entry syntax.
You will map fields with {i}, i being the field number for CSV, and the attribute name for LDIF (you can adjust begin and end delimiter in parameters $beginc and $endc).
If you have a CSV file with 3 columns, you can use {0}, {1} and {2} to map them. Here are two CSV file examples:
Login;"First Name";"Last Name" coudot;Clément;OUDOT jclarke;Jonathan;CLARKE
Group name;Default member group1;coudot group2;jclarke
Below is a sample configuration to parse those files:
my $map = {
person => {
dn => 'uid={0},ou=users,dc=example,dc=com',
objectClass => [ 'top', 'person', 'organizationalPerson', 'inetOrgPerson' ],
uid => '{0}',
givenName => '{1}',
sn => '{2}',
cn => '{1} {2}',
},
group => {
dn => 'cn={0},ou=groups,dc=example,dc=com',
objectClass => [ 'top', 'groupOfUniqueNames' ],
cn => '{0}',
uniqueMember => 'uid={1},ou=users,dc=example,dc=com',
},
};
Here is a sample entry from an LDIF extract of users:
dn: cn=clide,ou=users,dc=acme,dc=com objectClass: top objectClass: person cn: clide sn: barrow employeeType: gangster
You can create one task to reformat the user entry, and another to add the user in a group (whose name depends on employeeType attribute):
my $map = {
person => {
dn => 'uid={cn},ou=users,dc=example,dc=com',
objectClass => [ 'top', 'person', 'organizationalPerson', 'inetOrgPerson' ],
uid => '{cn}',,
sn => '{(uc)sn}',
cn => '{cn}',
},
group => {
change_op => 'add',
dn => 'cn={employeeType},ou=groups,dc=example,dc=com',
uniqueMember => 'uid={cn},ou=users,dc=example,dc=com',
},
};
By default, genertad LDIF uses a changetype 'add', this means you want to add complete entries.
You can set a third command line parameter to use other changetypes:
In 'modify' case, you can add the 'change_op' field inside a task to determine which change oepration will be performed:
You can use macros in mapping, for example to lower case values.
Available macros are:
Example:
$map => {
person => {
change_op => replace,
dn => 'uid={(lc)uid},ou=users,dc=example,dc=com,
mail => '{(fmail)givenname}.{(fmail}sn}@example.com',
}
};
You can run the script like this:
$ perl file2ldif.pl <taskname> <file> <changetype>
It will produce a taskname.ldif file.
For our CSV examples, this will be:
$ perl file2ldif.pl person example-users.csv $ perl file2ldif.pl group example-groups.csv
And resulting LDIF are:
dn: uid=coudot,ou=users,dc=example,dc=com uid: coudot cn:: Q2zDqW1lbnQgT1VET1Q= sn: OUDOT objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson givenName:: Q2zDqW1lbnQ= dn: uid=jclarke,ou=users,dc=example,dc=com uid: jclarke cn: Jonathan CLARKE sn: CLARKE objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson givenName: Jonathan
dn: cn=group1,ou=groups,dc=example,dc=com cn: group1 uniqueMember: uid=coudot,ou=users,dc=example,dc=com objectClass: top objectClass: groupOfUniqueNames dn: cn=group2,ou=groups,dc=example,dc=com cn: group2 uniqueMember: uid=jclarke,ou=users,dc=example,dc=com objectClass: top objectClass: groupOfUniqueNames
Imagine you want to create 1000 test entries with different login and password.
First, use a simple loop to generate a CSV file:
$ echo "login;password" > test-users.csv $ for i in `seq 1 1000`; do echo "user$i;password$i" >> test-users.csv; done
Then configure the mapping in file2ldif.pl script:
my $map = {
test => {
dn => 'uid={0},ou=users,dc=example,dc=com',
objectClass => [ 'top', 'person', 'organizationalPerson', 'inetOrgPerson' ],
uid => '{0}',
sn => '{0}',
cn => '{0}',
userPassword => '{1}',
},
};
And run:
$ perl file2ldif.pl test test-users.csv
Add the users in you directory:
$ ldapadd -D cn=manager,dc=example,dc=com -W -f test.ldif
Imagine you want to change to employeeType value of some users from 'gangster' to 'cop'.
First you will get an LDIF of concerned users:
$ ldapsearch -b ou=users,dc=example,dc=com '(employeeType=gangster)' -LLL > gangsters.ldif
Then configure the mapping in file2ldif.pl script:
my $map = {
justice => {
change_op => 'replace'
dn => '{dn}',
employeeType => 'cop',
},
};
And run:
$ perl file2ldif.pl justice gangsters.ldif modify
Apply changes in your directory:
$ ldapmodify -D cn=manager,dc=example,dc=com -W -f justice.ldif