On Wed, Jun 17, 2015 at 11:55:54AM +0200, Giorgio Pioda wrote: > > No. But it might be possible to (adapt and) use Petter's script: > > /usr/share/debian-edu-config/tools/ldap-migrate-squeeze-wheezy > > Actually on my wheezy tjener this script is missing. Do I have to install > some additional packages? Sorry, only available in git. IIRC now it isn't shipped due to it's experimental status. Attached for your convenience. Wolfgang
#!/usr/bin/perl
#
# Migrate the relevant parts of the Debian Edu LDAP database from
# Squeeze to Wheezy.
#
# Extract users and groups from the slapcad output to insert with
# slapadd. It must be run just after installation of the main server.
sub usage {
my $exitcode = shift;
print <<'EOF';
Usage: $0
Migrate LDAP information from a Debian Edu Squeeze main server to a
Debian Edu Wheezy main server.
How to use it:
# Get a copy of the Squeeze LDAP database
ssh root@squeeze-tjener "service slapd stop"
ssh root@squeeze-tjener "slapcat" > tjener-squeeze.ldif
ssh root@squeeze-tjener "service slapd start"
# Fetch Kerberos master key used to encrypt user passwords
ssh root@squeeze-tjener "klist -K -k /etc/krb5kdc/stash"
# Get a copy of the current Wheezy LDAP database
service slapd stop
slapcat > tjener-wheezy.ldif
service slapd start # Restart local LDAP server
ldap-migrate-squeeze-wheezy # Create input file for ldapmodify to merge
ldapadmindn=$(ldapsearch -H ldap://localhost/ -x "(&(cn=admin)(objectClass=simpleSecurityObject))" 2>/dev/null | perl -p0e 's/\n //g' | awk '/^dn: / {print $2}')
ldapmodify -H ldap://localhost/ -ZZ -D "$ldapadmindn" -W -v -x < tjener-wheezy-ldapmodify.ldif # Load the new/changed entries into LDAP
# List current key with KNVO 1
klist -K -k /etc/krb5kdc/stash
# Add old Kerberos master key used to encrypt user passwords as KNVO 2
kdb5_util add_mkey
# Add new Kerberos master key to get a KNVO number higher than the old key
kdb5_util add_mkey
# Activate key with KNVO 3
kdb5_util use_mkey 3
# Migrate all users to KNVO 3
kdb5_util update_princ_encryption
# Store key with KNVO 3 in /etc/krb5kdc/stash
kdb5_util stash
# Remove now obsolete keys with KNVO 1 and 2
kdb5_util purge_mkeys -v
# Copy home directories from old to new main-server
rsync -av root@squeeze-tjener:/skole/tjener/home0/. /skole/tjener/home0/.
WARNING: This code is experimental!
EOF
exit($exitcore) if $exitcode;
}
use strict;
use warnings;
use Getopt::Std;
use Net::LDAP::LDIF;
use Data::Dumper;
my $debug = 0;
my %opts;
getopts("d", \%opts) || usage(1);
$debug = 1 if $opts{d};
my $oldldiffile = "tjener-squeeze.ldif";
my $curldiffile = "tjener-wheezy.ldif";
my $newldiffile = "tjener-wheezy-ldapmodify.ldif";
my $oldldif = Net::LDAP::LDIF->new( $oldldiffile, "r", onerror => 'undef' );
unless ($oldldif) { warn "unable to read $oldldiffile"; usage(1); }
my $curldif = Net::LDAP::LDIF->new( $curldiffile, "r", onerror => 'undef' );
unless ($curldif) { warn "unable to read $curldiffile"; usage(1); }
my $newldif = Net::LDAP::LDIF->new( $newldiffile, "w", onerror => 'undef',
change => 1 );
unless ($newldif) { warn "unable to write $newldiffile"; usage(1); }
my %curuser;
my %curgroup;
my %cursudorole;
my %curnisnetgroup;
my %curhost;
while (not $curldif->eof() ) {
my $entry = $curldif->read_entry();
if ( ! $curldif->error() ) {
my %cls;
map { $cls{$_} = 1 } $entry->get_value('objectClass');
print Data::Dumper->Dump([\%cls], [qw(*cls)]) if $debug;
if (exists $cls{'posixAccount'} && exists $cls{'person'}
&& ! exists $cls{'gosaUserTemplate'}
&& ! exists $cls{'gotoWorkstation'}) {
$curuser{$entry->get_value('uid')} = 1;
} elsif (exists $cls{'posixGroup'} ) {
$curgroup{$entry->get_value('cn')} = $entry;
} elsif (exists $cls{'sudoRole'} ) {
$cursudorole{$entry->get_value('cn')} = $entry;
} elsif (exists $cls{'nisNetgroup'} ) {
$curnisnetgroup{$entry->get_value('cn')} = $entry;
} elsif (exists $cls{'device'}
|| exists $cls{'goServer'}
|| exists $cls{'gotoWorkstation'}) {
$curhost{$entry->get_value('cn')} = $entry;
}
}
}
print Data::Dumper->Dump([\%curuser], [qw(*curuser)]) if $debug;
print Data::Dumper->Dump([\%curgroup], [qw(*curgroup)]) if $debug;
print Data::Dumper->Dump([\%curnisnetgroup], [qw(*curnisnetgroup)]) if $debug;
# Extract every user and group LDAP object not already in the LDAP
# database.
while (not $oldldif->eof() ) {
my $entry = $oldldif->read_entry();
if ( $oldldif->error() ) {
print "Error msg: ", $oldldif->error( ), "\n";
print "Error lines:\n", $oldldif->error_lines( ), "\n";
} else {
my %cls;
map { $cls{$_} = 1 } $entry->get_value('objectClass');
if (exists $cls{'posixAccount'} && exists $cls{'person'}
&& ! exists $cls{'gosaUserTemplate'}
&& ! exists $cls{'gotoWorkstation'}) {
my $uid = $entry->get_value('uid');
if (!exists ($curuser{$uid})) {
$entry = trim_internal_attributes_from_entry($entry);
$newldif->write_entry($entry);
}
} elsif (exists $cls{'sudoRole'}) {
my $cn = $entry->get_value('cn');
if (!exists ($cursudorole{$cn})) {
$entry = trim_internal_attributes_from_entry($entry);
$newldif->write_entry($entry);
}
} elsif (exists $cls{'posixGroup'} ) {
change_or_add($newldif, $entry, \%curgroup, ['memberUid']);
} elsif (exists $cls{'nisNetgroup'}) {
change_or_add($newldif, $entry, \%curnisnetgroup, ['memberNisNetgroup', 'nisNetgroupTriple']);
} elsif (exists $cls{'device'}
|| exists $cls{'goServer'}
|| exists $cls{'gotoWorkstation'}) {
my $cn = $entry->get_value('cn');
if (!exists ($curhost{$cn})) {
$entry = trim_internal_attributes_from_entry($entry);
$newldif->write_entry($entry);
}
}
print Data::Dumper->Dump([\$entry], [qw(*entry)]) if $debug;
}
}
$newldif->done();
$curldif->done();
$oldldif->done();
sub trim_internal_attributes_from_entry {
my ($entry) = @_;
# Drop these attributes from all new LDAP objects. They are not
# user settable in OpenLDAP.
my @dropattr = qw(creatorsName entryUUID structuralObjectClass
createTimestamp entryCSN modifiersName
modifyTimestamp);
for my $attr (@dropattr) {
$entry->delete( $attr => []);
}
return $entry;
}
sub change_or_add {
my ($newldif, $entry, $group, $attr_names_aref) = @_;
my $cn = $entry->get_value('cn');
if (exists ($group->{$cn})) {
# check membership of both groups and create change records
my $curentry = $group->{$cn};
for my $attr_name (@$attr_names_aref) {
my @oldmembers = sort $entry->get_value($attr_name);
my @curmembers = sort $curentry->get_value($attr_name);
print "Cur: ", Dumper(\@curmembers), "\n" if $debug;
print "Old: ", Dumper(\@oldmembers), "\n" if $debug;
my %curmemhash;
map { $curmemhash{$_} = 1 } @curmembers;
my $newentry;
my @newmembers;
for my $oldmember (@oldmembers) {
if (!exists $curmemhash{$oldmember}) {
print "Adding $oldmember to group $cn\n" if $debug;
if (! defined $newentry) {
$newentry = $entry->clone();
$newentry->changetype('modify');
}
push(@newmembers, $oldmember);
}
}
if (@newmembers) {
$newentry->replace($attr_name =>
[@curmembers, @newmembers]);
$newldif->write_entry($newentry);
}
}
} else {
# Missing entry, just add it
$entry = trim_internal_attributes_from_entry($entry);
$newldif->write_entry($entry);
}
}
Attachment:
signature.asc
Description: Digital signature