From 2041f440140db4935734084f25d2fae4110092a2 Mon Sep 17 00:00:00 2001 From: jbjohnso Date: Fri, 25 Jan 2013 21:04:12 +0000 Subject: [PATCH] Fix issues around prejoin=0, allow for multi domain support git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@15000 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- perl-xCAT/xCAT/Schema.pm | 3 +- xCAT-server/lib/perl/xCAT/Template.pm | 81 +++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 13 deletions(-) diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index b90157d1c..aff404e07 100644 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -705,7 +705,7 @@ linuximage => { }, }, passwd => { - cols => [qw(key username password cryptmethod comments disable)], + cols => [qw(key username password cryptmethod authdomain comments disable)], keys => [qw(key username)], table_desc => 'Contains default userids and passwords for xCAT to access cluster components. In most cases, xCAT will also actually set the userid/password in the relevant component when it is being configured or installed. Userids/passwords for specific cluster components can be overidden in other tables, e.g. mpa, ipmi, ppchcp, etc.', descriptions => { @@ -713,6 +713,7 @@ passwd => { username => 'The default userid for this type of component', password => 'The default password for this type of component', cryptmethod => 'Indicates the method that was used to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod is not supported however the code attempts to auto-discover MD5 encrypted passwords.', + authdomain => 'The domain in which this entry has meaning, e.g. specifying different domain administrators per active directory domain', comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", }, diff --git a/xCAT-server/lib/perl/xCAT/Template.pm b/xCAT-server/lib/perl/xCAT/Template.pm index 1cfd1afb4..a38a5dcf5 100644 --- a/xCAT-server/lib/perl/xCAT/Template.pm +++ b/xCAT-server/lib/perl/xCAT/Template.pm @@ -290,7 +290,18 @@ sub windows_account_data { unless ($::XCATSITEVALS{directoryprovider} eq "activedirectory" and $::XCATSITEVALS{domain}) { return $useraccountxml; } - $useraccountxml.="\n\nAdministrators\nDomain Admins\n\n".$::XCATSITEVALS{domain}."\n\n\n"; + my $domain; + my $doment; + my $domaintab = xCAT::Table->new('domain',-create=>0); + if ($domaintab) { + $doment = $domaintab->getNodeAttribs($node,['authdomain'],prefetchcache=>1); + } + if ($doment and $doment->{authdomain}) { + $domain = $doment->{authdomain}; + } else { + $domain = $::XCATSITEVALS{domain}; + } + $useraccountxml.="\n\nAdministrators\nDomain Admins\n\n".$domain."\n\n\n"; return $useraccountxml; } #this will examine table data, decide *if* a Microsoft-Windows-UnattendedJoin is warranted @@ -304,16 +315,31 @@ sub windows_join_data { } #we are still here, meaning configuration has a domain and activedirectory set, probably want to join.. #TODO: provide a per-node 'disable' so that non-AD could be mixed into a nominally AD environment - my $adinfo = machinepassword(wantref=>1); #TODO: needs rearranging in non prejoin case my $prejoin =1; if (defined $::XCATSITEVALS{prejoinactivedirectory} and not $::XCATSITEVALS{prejoinactivedirectory} ) { $prejoin = 0; } - my $componentxml = ''."\n\n".$adinfo->{domain}."\n"; - if ($adinfo->{ou}) { - $componentxml .= "".$adinfo->{ou}."\n"; + my $domain; + my $doment; + my $domaintab = xCAT::Table->new('domain',-create=>0); + if ($domaintab) { + $doment = $domaintab->getNodeAttribs($node,['ou','authdomain'],prefetchcache=>1); + } + my $ou; + if ($doment and $doment->{ou}) { + $ou = $doment->{ou}; + } + if ($doment and $doment->{authdomain}) { + $domain = $doment->{authdomain}; + } else { + $domain = $::XCATSITEVALS{domain}; + } + my $componentxml = ''."\n\n".$domain."\n"; + if ($ou) { + $componentxml .= "".$ou."\n"; } if ($prejoin) { + my $adinfo = machinepassword(wantref=>1); #TODO: needs rearranging in non prejoin case #a note, MS is incorrect when they document unsecure join as " UnsecureJoin is performed, by using a null session with a pre-existing account. This means there is no authentication to the domain controller when configuring the machine account; it is done anonymously". #the more informative bit is http://technet.microsoft.com/en-us/library/cc730845%28v=ws.10%29.aspx which says of 'securejoin': this method is actually less secure because the credentials reside in the ImageUnattend.xml file in plain text. #xCAT is generating a one-time password that is kept as limited as is feasible for the deployment strategy @@ -322,7 +348,22 @@ sub windows_join_data { $componentxml .= "".$adinfo->{password}."\ntrue\n"; } else { #this is the pass-through credentials case, currrently inaccessible until TODO, this must be used #with care as used incorrectly, an LDAP manager account is at high risk of compromise - $componentxml .= "".$adinfo->{domain}."\n".$adinfo->{adminuser}."\n".$adinfo->{adminpass}."\n\n"; + my $passtab = xCAT::Table->new('passwd',-create=>0); + unless ($passtab) { sendmsg([1,"Error authenticating to Active Directory"],$node); return; } + my @adpents = $passtab->getAttribs({key=>'activedirectory'},['username','password','authdomain']); + my $adpent; + my $username; + my $password; + foreach $adpent (@adpents) { + if ($adpent and $adpent->{authdomain} and $adpent->{authdomain} ne $domain) { next; } + if ($adpent and $adpent->{username} and $adpent->{password}) { + $username = $adpent->{username}; + $password = $adpent->{password}; + last; + } + } + unless ($username and $password) { die "Missing active directory admin auth data from passwd table" } + $componentxml .= "".$domain."\n".$username."\n".$password."\n\n"; } $componentxml .= "\n\n"; @@ -407,25 +448,30 @@ sub machinepassword { $ENV{HOME}='/etc/xcat'; $ENV{LDAPRC}='ad.ldaprc'; my $ou; + my $domain; if ($domaintab) { - my $ouent = $domaintab->getNodeAttribs('node','ou'); + my $ouent = $domaintab->getNodeAttribs($node,['ou','authdomain'],prefetchcache=>1); if ($ouent and $ouent->{ou}) { $ou = $ouent->{ou}; } + if ($ouent and $ouent->{authdomain}) { + $domain = $ouent->{authdomain}; + } } $passdata->{ou}=$ou; #my $sitetab = xCAT::Table->new('site'); #unless ($sitetab) { # return "ERROR: unable to open site table"; #} - my $domain; #(my $et) = $sitetab->getAttribs({key=>"domain"},'value'); + unless ($domain) { my @domains = xCAT::TableUtils->get_site_attribute("domain"); my $tmp = $domains[0]; if (defined($tmp)) { $domain = $tmp; } else { - return "ERROR: no domain set in site table"; + return "ERROR: no domain set in site table or in domain.authdomain for $node"; + } } $passdata->{domain}=$domain; my $realm = uc($domain); @@ -435,8 +481,19 @@ sub machinepassword { unless ($loggedrealms{$realm}) { my $passtab = xCAT::Table->new('passwd',-create=>0); unless ($passtab) { sendmsg([1,"Error authenticating to Active Directory"],$node); return; } - (my $adpent) = $passtab->getAttribs({key=>'activedirectory'},['username','password']); - unless ($adpent and $adpent->{username} and $adpent->{password}) { + my @adpents = $passtab->getAttribs({key=>'activedirectory'},['username','password','authdomain']); + my $adpent; + my $username; + my $password; + foreach $adpent (@adpents) { + if ($adpent and $adpent->{authdomain} and $adpent->{authdomain} ne $domain) { next; } + if ($adpent and $adpent->{username} and $adpent->{password}) { + $username = $adpent->{username}; + $password = $adpent->{password}; + last; + } + } + unless ($username and $password) { return "ERROR: activedirectory entry missing from passwd table"; } my $err = xCAT::ADUtils::krb_login(username=>$adpent->{username},password=>$adpent->{password},realm=>$realm); @@ -448,7 +505,7 @@ sub machinepassword { #my $server = $sitetab->getAttribs({key=>'directoryserver'},['value']); my $server; my @servers = xCAT::TableUtils->get_site_attribute("directoryserver"); - $tmp = $servers[0]; + my $tmp = $servers[0]; if (defined($tmp)) { $server = $tmp; } else {