mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 19:32:31 +00:00 
			
		
		
		
	-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:
		| @@ -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'); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user