-flesh out ADutils to add users
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@5310 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
parent
4dfda3a6d8
commit
0c7745d8ea
@ -5,43 +5,192 @@
|
||||
|
||||
#there exists direct perl ldap module, but too rare to bank on, going to use ldapmodify from
|
||||
#system calls
|
||||
|
||||
package xCAT::ADUtils;
|
||||
use strict;
|
||||
use MIME::Base64;
|
||||
use Encode;
|
||||
use xCAT::Utils qw/genpassword/;
|
||||
use IPC::Open3;
|
||||
use IO::Select;
|
||||
use Symbol qw/gensym/;
|
||||
|
||||
|
||||
my $machineldiftemplate = 'dn: CN=##UPCASENODENAME##,##OU##
|
||||
my $machineldiftemplate = 'dn: CN=##NODENAME##,##OU##
|
||||
changetype: add
|
||||
objectClass: top
|
||||
objectClass: person
|
||||
objectClass: organizationalPerson
|
||||
objectClass: user
|
||||
objectClass: computer
|
||||
cn: ##UPCASENODENAME##
|
||||
distinguishedName: CN=##UPCASENODENAME##,##OU##
|
||||
cn: ##NODENAME##
|
||||
distinguishedName: CN=##NODENAME##,##OU##
|
||||
objectCategory: CN=Computer,CN=Schema,CN=Configuration##REALMDCS##
|
||||
instanceType: 4
|
||||
displayName: ##UPCASENODENAME##$
|
||||
name: ##UPCASENODENAME##
|
||||
displayName: ##NODENAME##$
|
||||
name: ##NODENAME##
|
||||
userAccountControl: 4096
|
||||
codePage: 0
|
||||
countryCode: 0
|
||||
accountExpires: 0
|
||||
sAMAccountName: ##UPCASENODENAME##$
|
||||
dNSHostName: ##UPCASENODENAME####DNSDOMAIN##
|
||||
servicePrincipalName: HOST/##UPCASENODENAME##
|
||||
servicePrincipalName: HOST/##UPCASENODENAME####DNSDOMAIN##
|
||||
sAMAccountName: ##NODENAME##$
|
||||
dNSHostName: ##NODENAME####DNSDOMAIN##
|
||||
servicePrincipalName: HOST/##NODENAME##
|
||||
servicePrincipalName: HOST/##NODENAME####DNSDOMAIN##
|
||||
|
||||
dn: CN=##UPCASENODENAME##,##OU##
|
||||
dn: CN=##NODENAME##,##OU##
|
||||
changetype: modify
|
||||
replace: unicodePwd
|
||||
unicodePwd::##B64PASSWORD##';
|
||||
my $useraccounttemplate = 'dn: CN=##FULLNAME##,##OU##
|
||||
changetype: add
|
||||
objectClass: top
|
||||
objectClass: person
|
||||
objectClass: organizationalPerson
|
||||
objectClass: user
|
||||
objectCategory: CN=Person,CN=Schema,CN=Configuration##REALMDCS##
|
||||
codePage: 0
|
||||
countryCode: 0
|
||||
distinguishedName: CN=##FULLNAME##,##OU##
|
||||
cn: ##FULLNAME##
|
||||
sn: ##LASTNAME##
|
||||
givenName: ##FIRSTNAME##
|
||||
displayName: ##FULLNAME##
|
||||
name: ##FULLNAME##
|
||||
instanceType: 4
|
||||
userAccountControl: 514
|
||||
accountExpires: 0
|
||||
uidNumber: ##UID##
|
||||
gidNumber: ##GID##
|
||||
sAMAccountName: ##USERNAME##
|
||||
userPrincipalName: ##USERNAME##@##DNSDOMAIN##
|
||||
mail: ##USERNAME##@##DNSDOMAIN##
|
||||
homeDirectory: ##USERSMBHOME##
|
||||
homeDrive: ##USERSMBDRIVELETTER##
|
||||
unixHomeDirectory: ##USERHOME##
|
||||
loginShell: ##USERSHELL##
|
||||
|
||||
dn: CN=##FULLNAME##,##OU##
|
||||
changetype: modify
|
||||
replace: unicodePwd
|
||||
unicodePwd::##B64PASSWORD##
|
||||
|
||||
dn: CN=##FULLNAME##,##OU##
|
||||
changetype: modify
|
||||
replace: userAccountControl
|
||||
userAccountControl: 512';
|
||||
|
||||
|
||||
=cut
|
||||
example: add_user_account(username=>'fred',fullname=>'fred the great');
|
||||
=cut
|
||||
sub add_user_account {
|
||||
my %args = @_;
|
||||
my $dnsdomain = $args{dnsdomain};
|
||||
unless ($dnsdomain =~ /^\./) {
|
||||
$dnsdomain = '.'.$dnsdomain;
|
||||
}
|
||||
my $directoryserver = $args{directoryserver};
|
||||
my $domain_components = $dnsdomain;
|
||||
$domain_components =~ s/\./,dc=/g;
|
||||
unless ($domain_components =~ /^,dc=/) {
|
||||
$domain_components = ",dc=".$domain_components;
|
||||
}
|
||||
my $ou = $args{ou};
|
||||
if ($ou) {
|
||||
unless ($ou =~ /$domain_components\z/) {
|
||||
$ou .= $domain_components;
|
||||
}
|
||||
} else {
|
||||
$ou = "CN=Users".$domain_components;
|
||||
}
|
||||
unless ($domain_components and $dnsdomain and $ou and $directoryserver) {
|
||||
return {error=>"Unable to determine all required parameters"};
|
||||
}
|
||||
my $newpassword = $args{password};
|
||||
unless ($newpassword) {
|
||||
$newpassword = '"'.genpassword(8).'"';
|
||||
}
|
||||
Encode::from_to($newpassword,"utf8","utf16le"); #ms uses utf16le, we use utf8
|
||||
my $b64password = encode_base64($newpassword);
|
||||
my $username = $args{username};
|
||||
my $fullname;
|
||||
if ($args{fullname}) {
|
||||
$fullname = $args{fullname};
|
||||
} else {
|
||||
$fullname = $username;
|
||||
}
|
||||
my $firstname;
|
||||
if ($args{firstname}) {
|
||||
$firstname = $args{firstname};
|
||||
} else {
|
||||
$firstname = $fullname;
|
||||
$firstname =~ s/ .*//; #remove anything after any space
|
||||
}
|
||||
my $lastname;
|
||||
if ($args{lastname}) {
|
||||
$firstname = $args{lastname};
|
||||
} else {
|
||||
$lastname = $fullname;
|
||||
$lastname =~ s/.* //; #remove anything before any space
|
||||
}
|
||||
my $gid;
|
||||
my $uid;
|
||||
if ($args{gid}) {
|
||||
$gid = $args{gid};
|
||||
} else {
|
||||
$gid = 100; #TODO, something more generic?
|
||||
}
|
||||
if ($args{uid}) {
|
||||
$uid = $args{uid};
|
||||
} else {
|
||||
my $base = $domain_components;
|
||||
$base =~ s/^,//;
|
||||
my $parms = find_free_params(directoryserver=>$directoryserver,ou=>$base);
|
||||
unless ($parms) {
|
||||
return { error => "Unable to auto-detect a valid uid" };
|
||||
}
|
||||
$uid = $parms->{uidNumber};
|
||||
}
|
||||
my $shell = $args{shell};
|
||||
unless ($shell) { $shell = "/bin/bash"; }
|
||||
my $uhome = $args{homedir};
|
||||
unless ($uhome) { $uhome = "/home/".$username; }
|
||||
my $ldif = $useraccounttemplate;
|
||||
if ($args{smbhome} and $args{smbhomeletter}) {
|
||||
my $smbhome = $args{smbhome};
|
||||
my $smbhomeletter = $args{smbhomeletter};
|
||||
$ldif =~ s/##USERSMBHOME##/$smbhome/g;
|
||||
$ldif =~ s/##USERSMBDRIVELETTER##/$smbhome/g;
|
||||
} else {
|
||||
$ldif =~ s/homeDirectory: ##USERSMBHOME##
|
||||
//g;
|
||||
$ldif =~ s/homeDrive: ##USERSMBDRIVELETTER##
|
||||
//g;
|
||||
}
|
||||
$ldif =~ s/##FULLNAME##/$fullname/g;
|
||||
$ldif =~ s/##USERNAME##/$username/g;
|
||||
$ldif =~ s/##FIRSTNAME##/$firstname/g;
|
||||
$ldif =~ s/##LASTNAME##/$lastname/g;
|
||||
$ldif =~ s/##OU##/$ou/g;
|
||||
$ldif =~ s/##DNSDOMAIN##/$dnsdomain/g;
|
||||
$ldif =~ s/##REALMDCS##/$domain_components/g;
|
||||
$ldif =~ s/##UID##/$uid/g;
|
||||
$ldif =~ s/##GID##/$gid/g;
|
||||
$ldif =~ s/##USERHOME##/$uhome/g;
|
||||
$ldif =~ s/##USERSHELL##/$shell/g;
|
||||
$ldif =~ s/##B64PASSWORD##/$b64password/g;
|
||||
my $dn = "CN=$fullname,$ou";
|
||||
my $rc = system("ldapsearch -H ldaps://$directoryserver -b \"$dn\"");
|
||||
if ($rc == 0) {
|
||||
return {error=>"User already exists"};
|
||||
} elsif (not $rc==8192) {
|
||||
return {error=>"Unknown error $rc"};
|
||||
}
|
||||
open(HUH,">","/tmp/huhh");
|
||||
print HUH $ldif;
|
||||
$rc = system("echo '$ldif'|ldapmodify -H ldaps://$directoryserver");
|
||||
return {password=>$newpassword};
|
||||
}
|
||||
=cut
|
||||
add_machine_account
|
||||
Arguments are in a hash:
|
||||
@ -50,7 +199,6 @@ Arguments are in a hash:
|
||||
sub add_machine_account {
|
||||
my %args = @_;
|
||||
my $nodename = $args{node};
|
||||
my $ou = $args{ou};
|
||||
my $dnsdomain = $args{dnsdomain};
|
||||
if (not $dnsdomain and $nodename =~ /\./) { #if no domain provided, guess from nodename
|
||||
$dnsdomain = $nodename;
|
||||
@ -60,12 +208,12 @@ sub add_machine_account {
|
||||
$dnsdomain = '.'.$dnsdomain;
|
||||
}
|
||||
$nodename =~ s/\..*//; #strip dns domain if part of nodename
|
||||
my $upnodename = uc($nodename);
|
||||
my $domain_components = $dnsdomain;
|
||||
$domain_components =~ s/\./,dc=/g;
|
||||
unless ($domain_components =~ /^,dc=/) {
|
||||
$domain_components = ",dc=".$domain_components;
|
||||
}
|
||||
my $ou = $args{ou};
|
||||
if ($ou) {
|
||||
unless ($ou =~ /$domain_components\z/) {
|
||||
$ou .= $domain_components;
|
||||
@ -74,7 +222,7 @@ sub add_machine_account {
|
||||
$ou = "CN=Computers".$domain_components;
|
||||
}
|
||||
my $directoryserver = $args{directoryserver};
|
||||
unless ($domain_components and $dnsdomain and $ou and $upnodename and $directoryserver) {
|
||||
unless ($domain_components and $dnsdomain and $ou and $nodename and $directoryserver) {
|
||||
return {error=>"Unable to determine all required parameters"};
|
||||
}
|
||||
my $newpassword = $args{password};
|
||||
@ -88,17 +236,53 @@ sub add_machine_account {
|
||||
$ldif =~ s/##OU##/$ou/g;
|
||||
$ldif =~ s/##REALMDCS##/$domain_components/g;
|
||||
$ldif =~ s/##DNSDOMAIN##/$dnsdomain/g;
|
||||
$ldif =~ s/##UPCASENODENAME##/$upnodename/g;
|
||||
my $dn = "CN=$upnodename,$ou";
|
||||
$ldif =~ s/##NODENAME##/$nodename/g;
|
||||
my $dn = "CN=$nodename,$ou";
|
||||
my $rc = system("ldapsearch -H ldaps://$directoryserver -b $dn");
|
||||
if ($rc == 0) {
|
||||
return {error=>"System already exists"};
|
||||
} elsif (not $rc==8192) {
|
||||
return {error=>"Unknown error $rc"};
|
||||
}
|
||||
open(HUH,">","/tmp/huhh");
|
||||
print HUH $ldif;
|
||||
$rc = system("echo '$ldif'|ldapmodify -H ldaps://$directoryserver");
|
||||
return {password=>$newpassword};
|
||||
}
|
||||
|
||||
sub krb_login {
|
||||
#TODO: klist -s to see if credentials are good
|
||||
my %args = @_;
|
||||
my $password = $args{password};
|
||||
my $username = $args{username};
|
||||
my $realm = $args{realm};
|
||||
my $krbin;
|
||||
my $krbout;
|
||||
my $krberr = gensym;
|
||||
my $kinit = open3($krbin,$krbout,$krberr,qw/kinit/,$username."@".$realm);
|
||||
my $ksel = IO::Select->new($krbout,$krberr);
|
||||
my @handles;
|
||||
while (@handles = $ksel->can_read()) {
|
||||
foreach (@handles) {
|
||||
my $line;
|
||||
my $done = sysread $_,$line,180;
|
||||
unless ($done) {
|
||||
$ksel->remove($_);
|
||||
}
|
||||
if ($line =~ /Password for /) {
|
||||
print $krbin $password."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (waitpid($kinit,0)) {
|
||||
return $?;
|
||||
} else {
|
||||
die "Bug, $kinit got reaped before we could get to it\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub find_free_params { #search for things like next available uidNumber
|
||||
my %args = @_;
|
||||
my @needed_parms = split /,/,$args{needed_params};
|
||||
@ -112,11 +296,12 @@ sub find_free_params { #search for things like next available uidNumber
|
||||
my $dc = $args{ou};
|
||||
my $ldapout;
|
||||
my $ldapin;
|
||||
my $ldaperr;
|
||||
my $ldaperr=gensym;
|
||||
my $ldappid = open3($ldapin,$ldapout,$ldaperr,qw!ldapsearch -H !,"ldaps://$directoryserver","-b","$dc",qw!(uidNumber=*) uidNumber!);
|
||||
my $select = IO::Select->new($ldapout,$ldaperr);
|
||||
my @handles;
|
||||
my %useduids=();
|
||||
my $failure;
|
||||
while (@handles = $select->can_read()) {
|
||||
foreach (@handles) {
|
||||
my $line = <$_>;
|
||||
@ -124,12 +309,18 @@ sub find_free_params { #search for things like next available uidNumber
|
||||
$select->remove($_);
|
||||
next;
|
||||
}
|
||||
if ($line =~ /^uidNumber: (\d+)$/) {
|
||||
if ($_ == $ldaperr) {
|
||||
if ($line =~ /error/i or $line =~ /problem/i) {
|
||||
print $line;
|
||||
$failure=1;
|
||||
}
|
||||
} elsif ($line =~ /^uidNumber: (\d+)$/) {
|
||||
$useduids{$1}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($failure) { return undef; }
|
||||
while (1) { #loop through until 'return'
|
||||
unless ($useduids{$uidnumber}) {
|
||||
return {uidNumber=>$uidnumber};
|
||||
@ -140,4 +331,8 @@ sub find_free_params { #search for things like next available uidNumber
|
||||
|
||||
|
||||
use Data::Dumper;
|
||||
print Dumper(find_free_params(directoryserver=>"v4.xcat.e1350",ou=>"dc=xcat,dc=e1350"));
|
||||
#print krb_login(username=>"Administrator",password=>"cluster",realm=>"XCAT.E1350");
|
||||
#print Dumper(find_free_params(directoryserver=>"v4.xcat.e1350",ou=>"dc=xcat,dc=e1350"));
|
||||
#print Dumper add_user_account(dnsdomain=>'xcat.e1350',username=>'ffuu',directoryserver=>'v4.xcat.e1350');
|
||||
#print Dumper add_machine_account(node=>'ufred.xcat.e1350',directoryserver=>'v4.xcat.e1350');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user