redbird
(Fresh Scripter)
2003-07-10 09:13 PM
Connecting to AD using different user credentials

We are using RIS and kixtart scripts to load machines. When the machine is loaded it performs a GUIRUNONCE section in which we call a script that installs the MSI packages. The issue is the script is running as the local administrator and we would like to query AD to find the machine account and its description. The description contains the user profile name that is used to load all software for that user. The issue is that the local administrator account does not have access to query AD. It needs a valid AD user account credentials to even query it. Of course we do not have access to the administrator account and would not use the AD administrator account for this.

We have a script that will work when logged on to AD on the machine, but during the machine build process it is using the local administrator account.


Howard Bullock
(KiX Supporter)
2003-07-10 09:17 PM
Re: Connecting to AD using different user credentials

Use a standard AD account and Explore OpenDsObject.

quote:
The IADsOpenDSObject::OpenDSObject method binds to an ADSI object using the given credentials, retrieving an IDispatch pointer on the specified object.


http://www.kixtart.org/board/ultimatebb.php?ubb=get_topic;f=13;t=000616#000001

http://www.kixtart.org/board/ultimatebb.php?ubb=get_topic;f=13;t=000578#000005

[ 10. July 2003, 21:19: Message edited by: Howard Bullock ]


redbird
(Fresh Scripter)
2003-07-11 06:20 PM
Re: Connecting to AD using different user credentials

Howard, Thank you very much for your reply. I have tried several things in that direction and still no luck. You posted a LDAP query which is similar to what we are doing. I did not know if you may be able to use this as an example...

Break ON

; Create the connection and command object.
$oConnection1 = CreateObject("ADODB.Connection")
? "@error @serror"
$oCommand1 = CreateObject("ADODB.Command")
? "@error @serror"

; Open the connection.
$oConnection1.Provider = "ADsDSOObject" ; This is the ADSI OLE-DB provider name
? "@error @serror"
$oConnection1.Open ("Active Directory Provider")
? "@error @serror"

; Create a command object for this connection.
$oCommand1.ActiveConnection = $oConnection1
? "@error @serror"

; Compose a search string.
$oCommand1.CommandText = "select name, objectClass from 'LDAP://us-tyco-e/DC=us, DC=tycoelectronics, DC=com' " +
"WHERE objectClass='user'" ; and objectClass<>'computer'"

; Execute the query.
$rs = $oCommand1.Execute
? "ex: @error @serror"

;--------------------------------------
; Navigate the record set
;--------------------------------------

While (Not $rs.EOF)
?
for each $item in $rs.Fields
? $item.Name + " = "
$Value = $item.Value
if VarTypeName($Value) = "String"
" " + $Value
else
for each $v in $Value
" " + $v
next
endif
next
;? $rs.Fields("Name")
$rs.MoveNext
Loop

That was your code, but we want to specify credentials for the objects when we query. I was able to modify the connection.open specifying credentials there,

$oConnection1.Open ("Active Directory Provider", $username, $password)

but the .execute of the query fails.

; Execute the query.
$rs = $oCommand1.Execute

Any suggestions?


Howard Bullock
(KiX Supporter)
2003-07-11 06:35 PM
Re: Connecting to AD using different user credentials

I am presently away for the weekend and will not have much time to be online. Please post your code so that we can see what your trying to do.

redbird
(Fresh Scripter)
2003-07-11 06:49 PM
Re: Connecting to AD using different user credentials

Howard, again thank you for your prompt reply. I have been reading the bulletin board and looking through much of it and really respect your information. Here is my code:

Dim $mach[1000]
Dim $Filter[0] ;Declare filter for Object
$Filter[0]="Computer" ;Or replace "Group" with "User" or "Computer"
$MyProvider = "LDAP://" ;AD Provider used to search
$IniFile = "c:\winnt\myfile.inf"
; Set the login credential
$sUser = "Domail\user"
$sPassword = "***********"
; Set the domain controler and the proper context
$sDomain = "DC=myad,DC=mydomain,DC=edu"

? @WKSTA ;Print Machine Name
$mach=ADSearch(@WKSTA) ;Search AD for Machine Name

If $ItemFound
$MyPath = $mach[0]

$MyAdsPath = $MyProvider + $MyPath ;Concat for FULL Path to Object

; Connect to ADS with the provided login credential
$oProvider = GetObject("LDAP:")
$rootDSE = $oProvider.OpenDSObject("LDAP://" + $sDomain + "/RootDSE", $sUser, $sPassword, 1)


? $MyAdsPath ;Print FULL Path
$ou = GetObject($MyAdsPath) ;Get Object with full path

$ou.Filter = $Filter

? $ou.Name ;Display Object Name cn
? $ou.description ;Display Object description

$UserID = $ou.description
$CN = SubStr($ou.Name,4)
$Tag = SubStr($CN,4)
If $UserID <> ""
;Write INI File
$result=WriteProfileString($IniFile,'ULID','id',$UserID)
$result=WriteProfileString($IniFile,'ULID','cn',$CN)
$result=WriteProfileString($IniFile,'ULID','Tag',$Tag)
$result=WriteProfileString($IniFile,'ULID','Valid',"True")
$result=WriteProfileString($IniFile,'ULID','AdsPath',$MyAdsPath)
Else

$result=WriteProfileString($IniFile,'ULID','id',"Basic")
$result=WriteProfileString($IniFile,'ULID','cn',$CN)
$result=WriteProfileString($IniFile,'ULID','Tag',$Tag)
$result=WriteProfileString($IniFile,'ULID','Valid',"False")
$result=WriteProfileString($IniFile,'ULID','AdsPath',$MyAdsPath)
EndIf

Else
;Object not found in AD
$result=WriteProfileString($IniFile,'ULID','id',@USERID)
$result=WriteProfileString($IniFile,'ULID','cn',@WKSTA)
$result=WriteProfileString($IniFile,'ULID','Tag',SubStr(@WKSTA,4))
$result=WriteProfileString($IniFile,'ULID','Valid',"False")
$result=WriteProfileString($IniFile,'ULID','AdsPath',"Error - Not Found")

EndIf

Exit

; Function ADSearch()
;
; v1.1
;
; Author: Heitz Alex (HeitzAlexandre@wanadoo.fr)
;
; Action: Search in Active Directory using LDAP
;
; Syntax: ADSearch("Account Name", "Full Name")
;
; Parameters: Full Name (Optional)
; The full name to search in the AD database
;
; Account Name (Optional)
; The account name (or ID name) to search in the AD database
;
; Dependancies: Active Directory client installed (Build-in in 2000 and XP systems)
;
; Remarks: Working on 9x (95, 98, Me) and NTx (4, 2000, XP) systems
; Account name of a computer has a trailing $
; Only * wildcard is supported.
; ADSearch can't be designed to only retreive user and computer (ADODB and LDAP limits)
;
;
; Returns: Array of elements containing the complete following string :
; "CN=full name,...rest of DSN...,DC=Domain,DC=Organization,DC=com or org or...,AccountName=account name,IsContainer=0|1, IsGroup=0|1
; Iscontainer is set to 1 when AccountName is empty
; IsGroup is set to 1 when the current element is a Group
;
; example: ADSearch("Computers") return 1 array with the following value : "CN=Computers,DC=Domain,DC=Organization,DC=com|AccountName=|IsContainer=1|IsGroup=0"
; ADSearch("P*") return X arrays with values like this one : "CN=Username,OU=OU container name,DC=Domain,DC=Organization,DC=com|AccountName=Useraccount|IsContainer=0|IsGroup=0"
; ADSearch(,"*$$") return X arrays with values like this one : "CN=Computer name,CN=Computers,DC=Domain,DC=Organization,DC=com|AccountName=Computer name$|IsContainer=0|IsGroup=0"
Function ADSearch(Optional $ADFullName,Optional $ADAccountName)
Dim $AdoCon
Dim $AdoCommand
Dim $Recordset
Dim $Filter
Dim $i
Select
Case Len($ADFullName)>0 AND Len($ADAccountName)>0
$filter=" where cn='"+$adfullname+"' and samAccountName='"+$ADAccountName+"' "
Case Len($ADFullName)>0
$filter=" where cn='"+$ADFullName+"' "
Case Len($ADAccountName)>0
$filter=" where samAccountName='"+$ADAccountName+"' "
Case 1
; I'm sure you don't want to retreive the complete Active Directory database
Return
EndSelect
$AdoCon = CreateObject("ADODB.Connection")
$AdoCon.Provider = "ADsDSOObject"

; WAS: Current credentials are used, as username and password aren't specified
;$AdoCon.Open("Active Directory Provider")
;Now I tried to specify credentials here since Local Adminstrator does not have
;access to AD
$AdoCon.Open("Active Directory Provider", $sUser, $sPassword)

; Create ADO command object for the connection.
$AdoCommand = CreateObject("ADODB.Command")
$AdoCommand.ActiveConnection = $AdoCon

$MyCommandText = "Select AdsPath from '" + $MyProvider + $sDomain + "'" + $filter

? $MyCommandText
$result=WriteProfileString($IniFile,'ULID','Command',$MyCommandText)
$AdoCommand.CommandText =$MyCommandText

; Execute the query.
$Recordset = $AdoCommand.Execute
If @ERROR=0
; $Recordset is 1 based
If $Recordset.RecordCount>0
? $recordset.recordcount
$ItemFound = $recordset.recordcount
ReDim $ADSearch[$recordset.RecordCount-1]
$Recordset.movefirst
For $i=0 to $recordset.RecordCount-1
; Here we'll parse the fields of the current record
$ADSearch[$i]=SubStr($Recordset.Fields("AdsPath").value,8) ; To get rid of " LDAP://"
; Moving to the next record we have in $Recordset
$Recordset.Movenext
Next
EndIf
Else
? @ERROR
EndIf
EndFunction


redbird
(Fresh Scripter)
2003-07-11 07:01 PM
Re: Connecting to AD using different user credentials

The point of contention seems to be 1. When logged on a computer with AD credentials it works fine. 2. When logged in as a local admininistrator it has an error...

; Execute the query.
$Recordset = $AdoCommand.Execute
If @ERROR=0
; $Recordset is 1 based
...
Else
? @ERROR
EndIf
EndFunction

And that is where it is failing. At the .Execute.

I know your are out of the office and it is a Friday, but I do appreciate your interest.


Sealeopard
(KiX Master)
2003-07-11 07:07 PM
Re: Connecting to AD using different user credentials

There's no problem at all. You're just encountering Windows security. You will need to authenticate against AD with a domain account.

redbird
(Fresh Scripter)
2003-07-11 07:13 PM
Re: Connecting to AD using different user credentials

You mean there is no way to execute this script with AD credentials instead of the local user credentials? So the objects with those credentials will still use the local credentials. Again I need this all to run asyncronously without user intervention. The machine could be network booted to the RIS and install everything. How is MS security causing this?

Sealeopard
(KiX Master)
2003-07-11 07:19 PM
Re: Connecting to AD using different user credentials

Please take a look at the FAQ Forum under Installing an Application as an Admin and the UDF Forum under fnWMIAuthentication() - Authenticates against a local or remote WMI provider . They might be of help.

Local users normally do not have any kind of domain rights.


ShawnAdministrator
(KiX Supporter)
2003-07-11 07:22 PM
Re: Connecting to AD using different user credentials

Can you provide us with the @ERROR number and @SERROR text from Execute ? (if you haven't done so already). Put this at the top of your script so that the entire message is displayed on your console:

$= SetOption("WrapAtEol","On")


**DONOTDELETE**
(Lurker)
2003-07-11 07:47 PM
Re: Connecting to AD using different user credentials

Another idea would be to get the script to work with an adminstrative account then use SU.EXE and KixCrypt to run it. That worked for me when I needed to use an account with Admin rights.

**DONOTDELETE**
(Lurker)
2003-07-11 07:58 PM
Re: Connecting to AD using different user credentials

By the way, what machine properties are you looking for? Would you maybe even be better off if you ran something on the server them dumped it all out to a text file then had your script reference a text file with all the parameters that you're looking for?

redbird
(Fresh Scripter)
2003-07-11 08:41 PM
Re: Connecting to AD using different user credentials

Thanks to all that responded. Shawn the @serror is: COM exception error "Execute" (Provider - Table does not exist.) [1/1]... Not sure what that means. the @error is 1

redbird
(Fresh Scripter)
2003-07-11 08:48 PM
Re: Connecting to AD using different user credentials

I also understand local users do not have DOMAIN rights, but is there a way to execute the script with elevated priveledges for instance a valid domain account that can access AD.

Howard Bullock
(KiX Supporter)
2003-07-11 11:43 PM
Re: Connecting to AD using different user credentials

RedBird, please describe in words what you want to accomplish and why you are trying to execute this from a client using an account that appears not to have sufficient permissions?

If you describe the business problem you are trying to solve then we can assist you in determining if your current approach is optimal or not. Maybe we can suggest alternative methods to achieve your goals.


redbird
(Fresh Scripter)
2003-07-12 12:10 AM
Re: Connecting to AD using different user credentials

We are trying to automate the process of building workstations (load os, software, etc). We have RIS and in the runonce section we call scripts to load the software. With AD we can pre-populate the computer account information with a description (assign it to a user). When RIS runs it loads the OS and then starts the scripts. The account it is running under is the local administrator account. When the scripts run (remember - no user interaction) they are using the local admin account and they then try to read AD to get the computer account description that we pre-populated earlier. The business logic is we can use AD as a one stop shop and create the accounts ONCE! and then re-assign them in the description. The machine names are static (Tag No) as well as the GUIDS. If we want to give joeuser and diffent machine, we simply change the description in AD. Do a PXE boot (f12) and load the RIS image and it will automatically find joeuser's in the description thus the next script will start loading all of joeuser's software. We simply re-boot a machine and load it and it is ready to be placed in service for joeuser. NICE. If joeuser has trouble on his machine he could perform the boot and re-load his machine and wait and come back and the machine would be ready to go. We have all the scripts to load the software using msi's. All we need to do is tie the machine to the user in one location instead of several different places. That is our goal. The one thing holding us back is this script. It doesn't work under the local admin credentials because it is in the runonce part of the load (from RIS). If that fails then we would intervene and can push the process along, but then it is not automated.

I was able to write a vb.net console ap to do this, but we have to load the .net framework on the machine, and the loads act flaky. We have had inconsistent results with that. We know the scripts are pretty solid and no overhead and were trying to convert the process to scripts particularly kix scripts. I would be willing to use any other script as well, but the ini file tools and other things make kix easier to use.

I am just so close to making this happen, except for the credential issue. I do not understand why the vb ap will allow me to pass the credentials to the ad object and I am not able to in kix.

I really do appreaciate all the help. We would consider running the script from the server to populate a file that would be read from the client, but it is another link in the puzzle, rather than a direct route and we would have to worry about keeping everything in sync.

It is all about consistency and simplicity.


Howard Bullock
(KiX Supporter)
2003-07-12 03:33 AM
Re: Connecting to AD using different user credentials

I am still looking into the alternate credential thing, but could you just execute the whole process as a domain user (service account with local admin) to avoid this issue?

Sealeopard
(KiX Master)
2003-07-12 03:56 PM
Re: Connecting to AD using different user credentials

The answer is in the FAQ I linked to. Have the script start a second script via SU or Task Scheduler under separate domain admin credentials.

Howard Bullock
(KiX Supporter)
2003-07-12 06:03 PM
Re: Connecting to AD using different user credentials

Jens, your solution requires WMI. Should not one be able to accomplish the same thing with the ADO OPEN method?

Sealeopard
(KiX Master)
2003-07-12 08:22 PM
Re: Connecting to AD using different user credentials

Howard, SU & Task Scheduler do not require WMI. The fnWMIAuthentication is WMI-based but I'm sure that the same can be accomplished with ADSI. However, it might even work by authenticating against a DC via the WMI-based UDF then continuing on with an ADSI call.

This might also be of help: INFO: User Authentication Issues with ADSI WinNT Provider


Howard Bullock
(KiX Supporter)
2003-07-12 09:14 PM
Re: Connecting to AD using different user credentials

I was not considering SU and task scheduler. I have previously suggested using OpenDsObject but redbird seems to want to use an ADO query. It would seem that we should be able to authenticate with the OPEN method. My first attempt failed but I am going to try again.

Sealeopard
(KiX Master)
2003-07-12 10:37 PM
Re: Connecting to AD using different user credentials

Something along these lines:
code:
$oConnect = CreateObject("ADODB.Connection")
$oConnect.Provider = "ADsDSOObject"
$oConnect.Properties("User ID") = $stUser
$oConnect.Properties("Password") = $stPass
$oConnect.Properties("Encrypt Password") = not 0
$oConnect.Open "DS Query", $stUser, $stPass

Adapted from Searching with ActiveX Data Objects (ADO)


Howard Bullock
(KiX Supporter)
2003-07-13 04:56 AM
Re: Connecting to AD using different user credentials

Jens, I am using 4.21 and have tried that syntax without success. Can you or someone else actually confirm some working code along these lines?


Break ON
$previousstate = SetOption( "WrapAtEOL", "ON" )

; Create the connection and command object.
$oConnection1 = CreateObject("ADODB.Connection")
? "@error @serror"
$oCommand1 = CreateObject("ADODB.Command")
? "@error @serror"

; Open the connection.
$oConnection1.Provider = "ADsDSOObject" ; This is the ADSI OLE-DB provider name
? "@error @serror"
$oConnection1.Properties("Password") = "ABC123xyz"
? "@error @serror"
$oConnection1.Properties("Encrypt Password") = not 0
? "@error @serror"
$oConnection1.Properties("User ID") = "domain\user1"
? "@error @serror"
$oConnection1.Open ("Active Directory Provider", "tycoelectronics\us035355", "ABC123xyz")
? "@error @serror"

; Create a command object for this connection.
$oCommand1.ActiveConnection = $oConnection1
? "@error @serror"

; Compose a search string.
$oCommand1.CommandText = "select name, objectClass from 'LDAP://us-tyco-e/DC=us,DC=tycoelectronics,DC=com' " +
"WHERE objectClass='user'" ; and objectClass<>'computer'"

; Execute the query.
$rs = $oCommand1.Execute
? "ex: @error @serror"


Result:

c:\data\scripts>C:\Data\Kix2001\KiX2001.421\kix32 test2.kix

0 The operation completed successfully.
0 The operation completed successfully.
0 The operation completed successfully.Password
ERROR : unexpected command!
Script: c:\data\scripts\test2.kix
Line : 13

[ 13. July 2003, 04:59: Message edited by: Howard Bullock ]


LonkeroAdministrator
(KiX Master Guru)
2003-07-13 05:10 AM
Re: Connecting to AD using different user credentials

obviously the error comes from:
$oConnection1.Properties("Password") = "ABC123xyz"

now, can kixtart even do what you want here?
"properties" is a collection of properties...
but can kixtart point to the pasword property and set the pass.
thinking here but can't think of succesfull example


Howard Bullock
(KiX Supporter)
2003-07-13 05:15 AM
Re: Connecting to AD using different user credentials

I think Shawn was pondering this type of syntax previously, but I can't remember what the topic was about.

[ 13. July 2003, 13:51: Message edited by: Howard Bullock ]


Howard Bullock
(KiX Supporter)
2003-07-13 05:17 AM
Re: Connecting to AD using different user credentials

The $x.Properties("PropName") seems like it should be redundant since the OPEN method permits the use of a user and password as well. I have tried the code without the $x.Preoperties("") lines without success.

LonkeroAdministrator
(KiX Master Guru)
2003-07-13 05:33 AM
Re: Connecting to AD using different user credentials

indeed, new kixforms has (at least planned [i haven't tested]) object collections...

anyway, some times kix can give error on wrong line.
even though previous line shows error as 0 the error can be there too.

do you have any place I can read about these ado things?
any linky for quick ref?


Howard Bullock
(KiX Supporter)
2003-07-13 01:55 PM
Re: Connecting to AD using different user credentials

The best place would http://msdn.microsoft.com. There is also a reference to it in the ADSI SDK documentation.

I know this isn't the quick link you requested but you may be able to find the correct page that eluded me by searching.


Sealeopard
(KiX Master)
2003-07-13 08:41 PM
Re: Connecting to AD using different user credentials

This might be of help:

Microsoft OLE DB Provider for Microsoft Active Directory Service in combinations with a SQL query through the DBCommand() UDF maybe?


NTDOCAdministrator
(KiX Master)
2003-07-14 09:21 AM
Re: Connecting to AD using different user credentials

Misc information.

You cannot specify credentials in a WMI Moniker. Monikers are used with VBScript GetObject function. To specify credentials, you must use VBScript's CreateObject function in combination with the WMI Scripting Library's "WbemScripting.SWbemLocator" object. SWbemLocator provides a single method named ConnectServer that accepts alternate credentials

There are two ways to connect to WMI - GetObject("winmgmts:") and CreateObject("WbemScripting.SWbemLocator"). You must use the latter if you want to supply alternate credentials

ALSO - Other method
'----Binding to a domain with alternate credentials
Set dso = GetObject("WinNT:")
Set dom = dso.OpenDSObject("WinNT://" & domainName, userName, password, ADS_SECURE_AUTHENTICATION)

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netdir/adsi/ads_authentication_enum.asp

[ 14. July 2003, 09:23: Message edited by: NTDOC ]


Sealeopard
(KiX Master)
2003-07-14 03:19 PM
Re: Connecting to AD using different user credentials

The SWbemLocator/ConnectServer method is illustrated in fnWMIAuthentication() - Authenticates against a local or remote WMI provider

redbird
(Fresh Scripter)
2003-07-18 05:17 PM
Re: Connecting to AD using different user credentials

Jens,

Could you give me an example of how I would apply your function to this application? I am a bit confused on where I would use this. I have a kix script that can call another script, but would kix32 be the application that would run under the other credentials?