ispman/bin ispman.ldifupdate,NONE,1.1
Joerg Delker <[email protected]>
| Newsgroups | gmane.comp.isp.ispman.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ispman/ispman/bin
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19651/bin
Added Files:
ispman.ldifupdate
Log Message:
moved ldifupdate to bin
--- NEW FILE: ispman.ldifupdate ---
#!/usr/bin/perl -w
# Script to update LDIF data
# Reads from one ldif file and writes to another ldif
# Messages are dumped on STDERR
# please adjust defines below to suit your environment
# All entries are parsed (unless filtered with option "-b") and changed
# according to current schema
# For details see comments below
use strict;
use Getopt::Std;
use Net::LDAP::LDIF;
use Net::LDAP::Entry;
use HTML::Entities;
use MIME::Base64;
# defines
my @oc_normalDomain = qw(ispmanDomain PureFTPdUser posixAccount);
my @oc_replicaDomain = qw(ispmanDomain ispmanBranch);
my @oc_virtualHost = qw(ispmanVirtualHost posixAccount PureFTPdUser);
my @oc_domainUser = qw(ispmanDomainUser posixAccount);
my $default_domainHomedir = "/ispman/domains";
my @default_fileserver = qw( );
my @default_webhost = qw( );
my $default_loginShell = "/bin/false";
my $default_vhostShell = "/bin/false";
my $dummyUid = "999999";
my $dummyGid = "999999";
my $dummyPassword = "123456";
# private variables
my ( $ldif_in, $ldif_out, $basedn );
my ( %opts, $mode );
sub usage {
print qq[
ISPMan ldifupdate
A utility to update your ispman LDAP data according to current ISPMan schema.
It will convert the given input LDIF and output it to an output LDIF
either in add or modify format.
Syntax: ldifupdate <options>
Options:
-i <file> input LDIF filename
-o <file> output LDIF filename
-b <basedn> base DN (optional), which limits changes to this subtree
-m <add/modify> type of LDIF to create (default=add)
];
}
sub update_oc {
my ( $entry, $src, $dst, %opt ) = @_;
my $msg = "";
my %in_src;
my %in_dst;
for (@$src) { $in_src{$_} = 1; }
for (@$dst) {
if ( !$in_src{$_} ) {
$msg .= "adding objectclass: \"$_\"\n";
$entry->add( "objectclass", $_ );
}
$in_dst{$_} = 1;
}
if (!$opt{addonly}){
for (@$src) {
if ( !$in_dst{$_} ) {
$msg .= "deleting objectclass: \"$_\"\n";
$entry->delete( "objectclass" => [$_] );
}
}
}
return $msg;
}
## main
# get parameters
getopt( 'iobm', \%opts );
unless ( $opts{'i'} or $opts{'o'} ) {
usage();
exit 1;
}
# set mode
$mode = $opts{'m'} || "add";
if ( $mode ne "add" and $mode ne "modify" ) {
print STDERR "unknown mode: $mode\n";
usage();
exit 1;
}
# input file
$ldif_in = Net::LDAP::LDIF->new( $opts{'i'} );
# basedn
$basedn = $opts{'b'};
#### Phase 1: Preparation ####
print "Phase 1: Preparing...\n\n";
my %clients = ();
my %groups = ();
# read and parse ldap data
while ( not $ldif_in->eof() ) {
my $entry = $ldif_in->read_entry();
# skip entry if we find an error
if ( $ldif_in->error() ) {
print STDERR "Error msg: ", $ldif_in->error(), "\n";
print STDERR "Error lines:\n", $ldif_in->error_lines(), "\n";
}
my $dn = $entry->dn();
next unless !defined($basedn) or $dn =~ m/$basedn$/;
my @oc = $entry->get_value("objectclass");
my %oc;
for (@oc) { $oc{$_} = 1 }
if ( $oc{"ispmanClient"} ) {
$clients{ $entry->get_value("ispmanClientId") } = $entry->{'attrs'};
}
if ( $oc{"posixGroup"} ) {
if ( $dn =~ /^cn=(.*?),/ ) {
$groups{$1} = 1;
}
}
}
$ldif_in->done();
print "Phase 2: Checking...\n\n";
# input file
$ldif_in = Net::LDAP::LDIF->new( $opts{'i'} );
# output file
$ldif_out =
Net::LDAP::LDIF->new( $opts{'o'}, "w", 'change' => ( $mode eq "modify" ) );
# read and parse ldap data
while ( not $ldif_in->eof() ) {
my $entry = $ldif_in->read_entry();
# define slot for new entry
my $added_entry;
# skip entry if we find an error
if ( $ldif_in->error() ) {
print STDERR "Error msg: ", $ldif_in->error(), "\n";
print STDERR "Error lines:\n", $ldif_in->error_lines(), "\n";
}
$entry->changetype($mode);
my $dn = $entry->dn();
next unless !defined($basedn) or $dn =~ m/$basedn$/;
my $msg = "";
my $chng = "";
my @oc = $entry->get_value("objectclass");
my %oc;
for (@oc) { $oc{$_} = 1 }
## work on entry
if ( $#oc == 0 && $oc[0] eq "top" ) {
# if there is only one objectclass: top
# replace with ispmanBranch
$msg .= "replacing objectclass: \"top\" -> \"ispmanBranch\"\n";
$entry->replace( "objectclass", "ispmanBranch" );
}
elsif ( $dn =~ m/^ou=/ && $oc[0] ne "ispmanBranch" ) {
# if entry starts with "ou=" replace
# objectclasses top, organizationalunit with ispmanBranch
$msg .= "replacing objectclass: -> \"ispmanBranch\"\n";
$entry->replace( "objectclass", "ispmanBranch" );
}
elsif ( $oc{"ispmanDomain"} ) {
my $ispmanDomain = $entry->get_value("ispmanDomain");
# update ispmanDomain objectclasses
if ( $entry->get_value("ispmanDomainType") eq "replica" ) {
$msg .= update_oc( $entry, \@oc, \@oc_replicaDomain );
}
else {
## normal domain
$msg .= update_oc( $entry, \@oc, \@oc_normalDomain );
# check ispmanDomainDefaultFileServer attribute
if ( !defined $entry->get_value("ispmanDomainDefaultFileServer") ) {
$msg .= "WARNING! no \"Default Fileserver\" defined!\n";
if (@default_fileserver) {
foreach (@default_fileserver) {
$msg .=
"adding ispmanDomainDefaultFileServer: \"$_\"\n";
$entry->add( "ispmanDomainDefaultFileServer", $_ );
}
}
else {
$msg .=
"Please adjust \@default_fileserver array to set them automatically\n";
}
}
# check ispmanDomainDefaultWebServer attribute
if ( !defined $entry->get_value("ispmanDomainDefaultWebHost") ) {
$msg .= "WARNING! no \"Default Webhost\" defined!\n";
if (@default_webhost) {
foreach (@default_webhost) {
$msg .= "adding ispmanDomainWebHost: \"$_\"\n";
$entry->add( "ispmanDomainDefaultWebHost", $_ );
}
}
else {
$msg .=
"Please adjust \@default_webhost array to set them automatically\n";
}
}
# checking FTPStatus
if ( !$entry->get_value("FTPStatus") ) {
$msg .= "adding FTPStatus: active\n";
$entry->add( "FTPStatus", "active" );
}
# check related group entry
if ( !$groups{$ispmanDomain} ) {
# add new group entry
$added_entry = Net::LDAP::Entry->new;
$added_entry->dn( "cn=" . $ispmanDomain . "," . $dn );
$added_entry->add(
objectclass => 'posixGroup',
cn => $ispmanDomain,
gidnumber => $entry->get_value("gidnumber")
);
$msg .=
"creating new posixGroup entry for domain "
. $ispmanDomain . "\n";
}
# check ResellerId
my $clientId = $entry->get_value("ispmanClientId");
my $resellerId = $entry->get_value("ispmanResellerId");
if ( $clientId && !$resellerId ) {
$resellerId = $clients{$clientId}{"ispmanresellerid"}[0];
if ($resellerId) {
$msg .= "adding ispmanResellerId: $resellerId\n";
$entry->add( "ispmanResellerId", $resellerId );
}
else {
$msg .=
"ERROR: unable to determine ispmanResellerId"
. " for domain $ispmanDomain\n";
}
my $resellerName = $clients{$clientId}{"ispmanresellername"}[0];
if ($resellerName) {
$msg .= "adding ispmanResellerName: $resellerName\n";
$entry->add( "ispmanResellerName", $resellerName );
}
else {
$msg .=
"ERROR: unable to determine ispmanResellerName"
. " for domain $ispmanDomain\n";
}
}
}
}
elsif ( $oc{'ispmanVirtualHost'} ) {
# update ispmanVhost
my $ispmanDomain = $entry->get_value("ispmanDomain")
|| die("ispmanDomain undefined!");
my $ispmanVhostName = $entry->get_value("ispmanVhostName")
|| die("ispmanVhostName undefined!");
# checking/replacing vhost objectclasses
$msg .= update_oc( $entry, \@oc, \@oc_virtualHost );
# checking vhost cn attribute
my $lcn = $entry->get_value("cn");
my $cn = join ".", ( $ispmanVhostName, $ispmanDomain );
if ( !defined $lcn ) {
$msg .= "adding cn with \"$cn\"\n";
$entry->add( "cn", $cn );
}
elsif ( $lcn ne $cn ) {
$msg .= "changing cn: \"$lcn\" -> \"$cn\"\n";
$entry->replace( "cn", $cn );
}
# checking vhost uid attribute
my $luid = $entry->get_value("uid");
my $uid = join ".", ( $ispmanVhostName, $ispmanDomain );
if ( !defined $luid ) {
$msg .= "adding uid with \"$uid\"\n";
$entry->add( "uid", $uid );
}
elsif ( $luid ne $uid ) {
$msg .= "changing uid: \"$luid\" -> \"$uid\"\n";
$entry->replace( "uid", $uid );
}
# checking vhost uidNumber attribute
unless ( $entry->get_value("uidNumber") ) {
$msg .=
"adding dummy uidNumber: $dummyUid (This should be replaced later!\n)";
$entry->add( "uidNumber", $dummyUid );
}
# checking vhost gidNumber attribute
unless ( $entry->get_value("gidNumber") ) {
$msg .=
"adding dummy gidNumber: $dummyGid (This should be replaced later!)\n";
$entry->add( "gidNumber", $dummyGid );
}
# checking vhost homeDirectory attribute
my $homedir = join '/',
( $default_domainHomedir, $ispmanDomain, 'vhosts', $ispmanVhostName );
unless ( $entry->get_value("homeDirectory") ) {
$msg .= "adding homeDirectory: \"$homedir\"\n";
$entry->add( "homeDirectory", $homedir );
}
# checking vhost userPassword attribute
unless ( $entry->get_value("userPassword") ) {
$msg .=
"adding userPassword: \"$dummyPassword\" (This should be replaced later!)\n";
$entry->add( "userPassword", $dummyPassword );
}
# checking vhost ispmanVhostDocumentRoot
my $docroot = $entry->get_value("ispmanVhostDocumentRoot");
if ($docroot) {
if ( $docroot =~ /^$ispmanVhostName\// ) {
$msg .=
"NOTICE: ispmanVhostDocumentRoot looks like old entry\n";
my ($fixeddocroot) = $docroot =~ m/^$ispmanVhostName\/(.*)/;
$msg .=
"changing ispmanVhostDocumentRoot: \"$docroot\" -> \"$fixeddocroot\"\n";
$entry->replace( "ispmanVhostDocumentRoot", $fixeddocroot );
}
}
else {
$msg .= "ERROR: ispmanVhostDocumentRoot is missing!\n";
}
# checking vhost ispmanVhostScriptDir
my $scdir = $entry->get_value("ispmanVhostScriptDir");
if ($scdir) {
if ( $scdir =~ /^$ispmanVhostName\// ) {
$msg .=
"NOTICE: ispmanVhostDocumentRoot looks like old entry\n";
my ($fixedscdir) = $scdir =~ m/^$ispmanVhostName\/(.*)/;
$msg .=
"changing ispmanVhostScriptDir: \"$scdir\" -> \"$fixedscdir\"\n";
$entry->replace( "ispmanVhostScriptDir", $fixedscdir );
}
}
else {
$msg .= "ERROR: ispmanVhostScriptDir is missing!\n";
}
# checking vhost ispmanVhostLogdir attribute
my $logdir = $entry->get_value("ispmanVhostLogdir");
if ($logdir) {
if ( $logdir =~ /^$ispmanVhostName\// ) {
$msg .= "NOTICE: ispmanVhostLogdir looks like old entry\n";
my ($fixedlogdir) = $logdir =~ m/^$ispmanVhostName\/(.*)/;
$msg .=
"changing ispmanVhostLogdir: \"$logdir\" -> \"$fixedlogdir\"\n";
$entry->replace( "ispmanVhostLogdir", $fixedlogdir );
}
}
else {
$msg .= "WARNING: ispmanVhostLogdir is missing!\n";
$msg .= "adding ispmanVhostLogdir: \"logs\"\n";
$entry->add( "ispmanVhostLogdir", "logs" );
}
# checking vhost ispmanVhostStatdir attribute
my $statdir = $entry->get_value("ispmanVhostStatdir");
if ($statdir) {
if ( $statdir =~ /^$ispmanVhostName\// ) {
$msg .= "NOTICE: ispmanVhostStatdir looks like old entry\n";
my ($fixedstatdir) = $statdir =~ m/^$ispmanVhostName\/(.*)/;
$msg .=
"changing ispmanVhostStatdir: \"$statdir\" -> \"$fixedstatdir\"\n";
$entry->replace( "ispmanVhostStatdir", $fixedstatdir );
}
}
else {
$msg .= "WARNING: ispmanVhostStatdir is missing!\n";
$msg .= "adding ispmanVhostStatdir: \"stats\"\n";
$entry->add( "ispmanVhostStatdir", "stats" );
}
# checking vhost loginShell
unless ( $entry->get_value("loginshell") ) {
$msg .= "adding loginShell: $default_vhostShell\n";
$entry->add( "loginshell", $default_vhostShell );
}
# checking ispmanVhostExtraConf
my $extraconf = $entry->get_value("ispmanVhostExtraConf");
if ( $extraconf && $extraconf =~ /<.*>/ ) {
my $codedconf = HTML::Entities::encode($extraconf);
$msg .= "NOTICE: ispmanVhostExtraConf is not HTML encoded!\n";
$msg .= "changing: ispmanVhostExtraConf\n";
$entry->replace( "ispmanVhostExtraConf", $codedconf );
}
# checking ispmanStatus
if ( !$entry->get_value("ispmanStatus") ) {
$msg .= "adding ispmanStatus: active\n";
$entry->add( "ispmanStatus", "active" );
}
# checking FTPStatus
if ( !$entry->get_value("FTPStatus") ) {
$msg .= "adding FTPStatus: active\n";
$entry->add( "FTPStatus", "active" );
}
# checking ispmanVhostServerAlias
my @aliases = $entry->get_value("ispmanVhostServerAlias");
if (@aliases) {
# create new alias container
my $ou = Net::LDAP::Entry->new;
$ou->add(
'objectclass' => 'ispmanBranch',
'ou' => 'vhostAliases'
);
$ou->dn( "ou=vhostAliases," . $entry->dn() );
$ou->changetype("add");
$ldif_out->write_entry($ou);
$msg .= "creating vhostAlias container...\n";
# move all aliases to new entries
for (@aliases) {
my $alias = Net::LDAP::Entry->new;
$alias->add(
'objectclass' => 'ispmanVirtualHostAlias',
'ispmanDomain' => $ispmanDomain,
'ispmanVhostName' => $ispmanVhostName,
'ispmanVhostServerAlias' => $_
);
$alias->dn( "ispmanVhostServerAlias=$_," . $ou->dn() );
$alias->changetype("add");
$ldif_out->write_entry($alias);
$entry->delete("ispmanVhostServerAlias");
$msg .= "moving vhostAlias \"$_\" to container\n";
}
}
}
elsif ( $oc{'ispmanDomainUser'} ) {
# checking minimum objectclasses
$msg .= update_oc( $entry, \@oc, \@oc_domainUser,
addonly => 1);
# checking for alternate uid
my @uids = $entry->get_value("uid");
my $uid = join "@", $entry->get_value("ispmanUserId"),
$entry->get_value("ispmanDomain");
my $hasAlternateUid = 0;
for (@uids) {
if ( $_ eq $uid ) { $hasAlternateUid = 1; }
}
if ( !$hasAlternateUid ) {
$msg .= "adding uid: \"$uid\"\n";
$entry->add( "uid", $uid );
}
# checking for bogus mailHost
if ( $entry->get_value("mailHost")
&& $entry->get_value("mailHost") eq "undefined" )
{
$msg .= "deleting mailhost: undefined\n";
$entry->delete( "mailhost" => ["undefined"] );
}
# checking for bogus fileHost
if ( $entry->get_value("fileHost")
&& $entry->get_value("fileHost") eq "undefined" )
{
$msg .= "deleting filehost: undefined\n";
$entry->delete( "filehost" => ["undefined"] );
}
# checking loginShell
unless ( $entry->get_value("loginshell") ) {
$msg .= "adding default loginShell: $default_loginShell\n";
$entry->add( "loginshell", $default_loginShell );
}
}
else {
# check other entries here
}
## check that RDN is also attribute/value pair
# get the RDN as attr/value
my ( $attrib, $attribval ) = $dn =~ m/^(\w+)?\=([^,]*)/;
my @values = $entry->get_value($attrib);
my $found = 0;
for (@values) {
if ( $_ eq $attribval ) { $found = 1 }
}
if ( !$found ) {
$msg .= "adding RDN to attributes ($attrib: $attribval)\n";
$entry->add( $attrib, $attribval );
}
# output msg
if ($msg) {
print STDERR "DN: $dn\n";
print STDERR $msg, "\n";
}
# write ldif data
$ldif_out->write_entry($entry);
# write added ldif data when present
$ldif_out->write_entry($added_entry) if ($added_entry);
}
$ldif_in->done();
$ldif_out->done();
__END__
-------------------------------------------------------
This SF.Net email is sponsored by OSTG. Have you noticed the changes on
Linux.com, ITManagersJournal and NewsForge in the past few weeks? Now,
one more big change to announce. We are now OSTG- Open Source Technology
Group. Come see the changes on the new OSTG site. www.ostg.com