LDAP data in CSV format - Part II

User Aia had created this below script to help translate LDIF files to CSV format, and it works very well (thanks again Aia if you are reading this)

Here is the original thread.

However I've encountered a scenario where it may need to be changed slightly to be able to apply it. It was created for LDAP dir. user objects but I also have a need to translate an LDIF file containing group objects and their attributes (group members) into CSV files.

For the "group" objects in our LDAP directory, the group's members are expressed by a series of 'uniquemember' attributes, one per user. These attributes all have an identical name, and there are varying amounts of them depending on the group (we have ~20 groups). Some have 7-8 "uniquemember"s listed, some have hundreds.

For instance:

cn=Director,cn=groups,DC=MARCHON,DC=COM
cn=Director
uniquemember=uid=skressman,cn=users,DC=MARCHON,DC=COM
uniquemember=uid=rf1,cn=users,DC=MARCHON,DC=COM
uniquemember=uid=dingino,cn=users,dc=marchon,dc=com
uniquemember=uid=lgittler,cn=users,dc=marchon,dc=com
uniquemember=uid=junger,cn=users,dc=marchon,dc=com
uniquemember=uid=lbuchanan,cn=users,DC=MARCHON,DC=COM

The script lists statically the of attribute values separated by commas, so it's not capable of reading the varying amounts of 'uniquemember' attributes (the size of each group is different). I am trying to figure out how to express these groups and their members using the same CSV format or something very close.

Original script created by Aia below:

Save as ldap2csv.pl
Run as perl ldap2csv.pl ldapfile

#!/usr/bin/env perl
use strict;
use warnings;

# Bail out if no file is given as an argument.
my $ldap_file = shift || usage();

# To save output with extension .csv.
my $csv_file = "$ldap_file.csv";

# Preserve order of header labels.
my @header = qw(uid0 givenname salesorg sn telephonenumber l employeetype mail
                    uid c postalcode cn preferredlanguage employeenumber st);

# Boiler plate to open input and output files handles.
open my $in, '<', $ldap_file or die;
open my $out, '>', $csv_file or die;

# Write the header labels.
print  $out "uid,", join (',', @header[1..$#header]), "\n";

# Work engine.
{
    # Record separator is a paragraph representation.
    local $/="\n\n";

    # Process one record at a time.
    while(my $record = <$in>) {
        chomp $record; # Remove the record separator.
        my %data;
        @data{@header} = ();  # To label the data.
        my @entries = split '\n', $record; # Create data entries.

        # Save first entry uid or it will be over written by second instance.
        $data{'uid0'} = qq{"$entries[0]"};

        # Work with each entry.
        for my $entry (@entries){
            my ($key, $value) = split "=", $entry, 2; # split only by first equal.
            $value =~ s/\s+$//; # Clean trailing spaces.
            $value = qq{"$value"} if $value =~ /,/; # Surround with double quotes any entries with comas.
            $data{$key} = $value;
        }
        # Separate entries with comas.
        my $row = join ',', (map{ $data{$_}?$data{$_}:""} @header);

        # Write to output file.
        print $out "$row\n";
    }
}
# Dismiss file handles.
close $in;
close $out;

# Feed back to user.
print "$csv_file has been saved in the current directory\n";

sub usage {
    print "Usage: $0 ldapfilename\n";
    exit 1;
}
 

Here's a ksh script accomplishing the same end result with the exception of including all members in each group, instead of only the last member. The script also archives the csv file before clearing the contents. Is this what you are looking for?
:smiley:

#!/usr/bin/ksh93

if [[ $# -eq 0 ]];then
  print "Invalid Usage: Argument expected."
  exit 1
fi

LDAP_CSV_FILE="./SAM_GROUPS.ldif.csv"
LDIF_FILE="./"$@

if [[ ! -f ${LDIF_FILE} ]] ;
then
  print "SAM ldif file called" $@ "does not exist."
  exit 1
fi

if [[ -f ${LDAP_CSV_FILE} ]] ;
then
  cp ${LDAP_CSV_FILE} ${LDAP_CSV_FILE}"."`date +%Y%m%d`
 if [ $? == 0 ]; then
    cat /dev/null > ${LDAP_CSV_FILE}
 fi
fi

 while read LINE
do
if [[ ${LINE} == cn=* ]] && [[ ${LINE} != *","* ]] ;
then
  GROUP=${LINE:3}
fi

if [[ ${LINE} == uniquemember=* ]] ;
then
  MEMBER='"'${LINE:13}'"'
fi

if [[ ${LINE} == *uniquemember=* ]] ;
then
  echo ${GROUP}","${MEMBER} >> ${LDAP_CSV_FILE}
fi

done < ${LDIF_FILE}
1 Like

Three thumbs up for the Italian Tripod. Godspeed, kind stranger.