Jump to content
DavidLago

Trying to dev a script to calculate Active Directory Authentication Time

Recommended Posts

DavidLago

Hello. 

I have 5 DCs, and I need to create a scheduled task to run a script that will test the authentication time for each one of them, once every minute. (Then I'll use it within a log analyser to create graphics).

I came up with a script using the great AD UDF (by water). First I tried using "for" and an array, but something was messing up the results, then I went for the dumb old fashioned way:

#Include <ad.au3>
#include <MsgBoxConstants.au3>

Global $AdTestTime = ""
Global $Timer1, $Timer2, $Timer3, $Timer4, $Timer5 = ""
Global $sAD1 = "MYSERVER109"
Global $sAD2 = "MYSERVER110"
Global $sAD3 = "MYSERVER111"
Global $sAD4 = "MYSERVER112"
Global $sAD5 = "MYSERVER113"

$Timer1 = Timerinit()
_AD_Open("", "", $sAD1)
_AD_Close()
Local $fDiff1 = TimerDiff($Timer1)

$Timer2 = Timerinit()
_AD_Open("", "", $sAD2)
_AD_Close()
Local $fDiff2 = TimerDiff($Timer2)

$Timer3 = Timerinit()
_AD_Open("", "", $sAD3)
_AD_Close()
Local $fDiff3 = TimerDiff($Timer3)

$Timer4 = Timerinit()
_AD_Open("", "", $sAD4)
_AD_Close()
Local $fDiff4 = TimerDiff($Timer4)

$Timer5 = Timerinit()
_AD_Open("", "", $sAD5)
_AD_Close()
Local $fDiff5 = TimerDiff($Timer5)

MsgBox(0,"", "MYSERVER109=" & $fDiff1)
MsgBox(0,"", "MYSERVER110=" & $fDiff2)
MsgBox(0,"", "MYSERVER111=" & $fDiff3)
MsgBox(0,"", "MYSERVER112=" & $fDiff4)
MsgBox(0,"", "MYSERVER113=" & $fDiff5)

Still, something is off here. 

The first AD to be tested is always the slowest one, by far, like 20 times slower. Then I started to suspect that the first one starts the "negotiation", and the following ones ride the gravy train.

If I repeat the first code twice, All servers seem to have a similar result.

$Timer1 = Timerinit()
_AD_Open("", "", $sAD1)
_AD_Close()
Local $fDiff1 = TimerDiff($Timer1)

$Timer1 = Timerinit()
_AD_Open("", "", $sAD1)
_AD_Close()
Local $fDiff1 = TimerDiff($Timer1)

$Timer2....

Am I right?

Also, is there a better way to test the authentication time?

Thanks for the help.

- Dave

Edited by DavidLago

Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites
Surf243

I'm not sure about a "better" way, but this is how I would do it. I do have a lot of DCs so listing them out would be hassle for me.

#include <AD.au3>

Global $iResult, $aDCs, $time, $timediff

$iResult = _AD_Open("", "", "", "", "", 1)
$aDCs = _AD_ListDomainControllers()
_AD_Close()
;_ArrayDisplay($aDCs, "", "|0:2") ; Display All DC's in Array
For $iIndex = 1 to $aDCs[0][0]
    $time = Timerinit()
    _AD_Open("", "", "", $aDCs[$iIndex][2])
    _AD_Close()
    $timediff = TimerDiff($time)
    ConsoleWrite($iIndex & " DC = " & $aDCs[$iIndex][2] & " | Time = " & $timediff & @CRLF)
Next

 

Share this post


Link to post
Share on other sites
DavidLago

Thanks, Surf. 

Actually I have more than 40 DCs, but I just want to test 5 of them, specifically. This "_AD_ListDomainControllers" function won't work with any parameters of filters, so, all of them will come to the array.

Also, The first one still comes with a higher latency. 

I think it's not because of the token thing, probably, calling up the include...


Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites
AutoBert
1 hour ago, DavidLago said:

Actually I have more than 40 DCs, but I just want to test 5 of them, specifically. This "_AD_ListDomainControllers" function won't work with any parameters of filters, so, all of them will come to the array.

And why not deleting the 35 from array, where you know their is no need to control?

Share this post


Link to post
Share on other sites
DavidLago
Just now, AutoBert said:

And why not deleting the 35 from array, where you know their is no need to control?

Thought about doing this:

Dim $aArray = ["DC1", "DC2", "DC3", "DC4", "DC5"]

 


Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites
AutoBert
1 minute ago, DavidLago said:

Thought about doing this:

Dim $aArray = ["DC1", "DC2", "DC3", "DC4", "DC5"]

 

seems this is the shorter way.

Share this post


Link to post
Share on other sites
jguinch

Each time you call _Ad_Open, the function creates a "ADODB.Connection" object.

Maybe it's slow the first time, then faster next

Can you check for this ?

Local $hTimer1 = TimerInit()
ObjCreate("ADODB.Connection")
ConsoleWrite(TimerDiff($hTimer1) & @CRLF)

Local $hTimer2 = TimerInit()
ObjCreate("ADODB.Connection")
ConsoleWrite(TimerDiff($hTimer2) & @CRLF)

I cannot check it for now...

Share this post


Link to post
Share on other sites
DavidLago
On 09/09/2016 at 5:09 PM, jguinch said:

Each time you call _Ad_Open, the function creates a "ADODB.Connection" object.

Maybe it's slow the first time, then faster next

Can you check for this ?

Local $hTimer1 = TimerInit()
ObjCreate("ADODB.Connection")
ConsoleWrite(TimerDiff($hTimer1) & @CRLF)

Local $hTimer2 = TimerInit()
ObjCreate("ADODB.Connection")
ConsoleWrite(TimerDiff($hTimer2) & @CRLF)

I cannot check it for now...

Thanks jguinch. It's exactly what happens here.

The first one always gets a lot of delay.

I increased the number of tests to 5, and ran a lot of them. It also seems to keep getting faster every execution. Look at the console outputs:

EXEC1:

--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
2.93141843646089
0.0276548909100084
0.0210975456426868
0.0196720358019648
0.00627224329917717

EXEC2:

--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
2.26912656446141
0.0159657102160873
0.00912326298062133
0.00912326298062133
0.00570203936288833

EXEC3:

--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
3.12699838660796
0.0290804007507305
0.0188167298975315
0.0153955062797985
0.0131146905346432

 

Maybe it's not a trustable test?

I'd like to see water's opinion on this too, since he was the one who came up with the UDF.


Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites
water

We discussed a similar "problem" on the German forum.
It seems that on the first run it takes some time for Windows to load the needed modules.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-01-27 - Version 1.3.3.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
DavidLago

I inserted the line "ObjCreate("ADODB.Connection")" before the script, and it didn't change the situation. The first one comes with a lot of delay.

So far, the only way I could come up with decent results was creating a _AD_OPEN line to "open the path" before the 'for' statement:

 

Global $time, $timediff
Dim $aArray = ["5", "MYSERVER109", "MYSERVER110", "MYSERVER111", "MYSERVER112", "MYSERVER113"]

; Function to "load up" the include
_AD_Open("", "", "MYSERVER109")
_AD_Close()

ObjCreate("ADODB.Connection")

For $i = 1 to 5 step 1
    Global $time = ""
    $time = Timerinit()
    _AD_Open("", "", $aArray[$i])
    _AD_Close()
    $timediff = TimerDiff($time)
    ConsoleWrite($aArray[$i] & "=" & $timediff & @CRLF)
Next

@water Do you think that _AD_OPEN could "simulate" some kind of authentication response?


Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites
water

Maybe if you directly measure in function _AD_Open before and after

; ADO Open Method: http://msdn.microsoft.com/en-us/library/ms676505.aspx
    $__oAD_Connection.Open() ; Open connection to AD

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-01-27 - Version 1.3.3.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
nikink

Suggestion/workaround - test 6 DCs, with the first being one you DON'T want to measure.

 

Ie: DC75, DC1, DC2,DC3,DC4,DC5

That way the delay only affects a DC you don't care about.

Another option is to run the script 5 times, with a different DC in the first position each time, thus they all get affected by the slow connection equally (which could be important if the latency is what you're trying to measure).

 

  • Like 1

Share this post


Link to post
Share on other sites
DavidLago
3 hours ago, nikink said:

Suggestion/workaround - test 6 DCs, with the first being one you DON'T want to measure.

 

Ie: DC75, DC1, DC2,DC3,DC4,DC5

That way the delay only affects a DC you don't care about.

Another option is to run the script 5 times, with a different DC in the first position each time, thus they all get affected by the slow connection equally (which could be important if the latency is what you're trying to measure).

 

That's exactly what I'm doing, @nikink, though, you outta agree this is a great jury-rig :P

I got the script running and getting me results already. I would like to find a solution, though. Or at least understand that behavior.

  • Like 1

Just a server analyst that has never been into programming that much. So, small fish here :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • Trinnon
      By Trinnon
      I have a question about the @error logging features in _AD_CreateUser.  Hopefully I am just missing something obvious.
      In my app I am creating a user if it does not exist then manipulating some attributes. 
      If the user does exist I would then call another function to remove groups from the user and modify some attributes.
      My question is...
      If the user already Exists, the _AD_CreateUser option gives $iValue = 0 and @error = 0.
      How can @error = 1 for the condition that the user already exists?
       
      I copied a small ship of the code in question along with my full .au3. 
      I am using AD UDF 1.4.9.0 (Water, thanks for the awesome work on this!!!).
      $iValue = _AD_CreateUser ($sOU, $sUser, $sCN)
      If $iValue = 1 Then
            _FileWriteLog ($Log, "Func UserCheck() - User '" & $sUser & "' successfully created ==> Calling UserAttribsNewUser Function.")
            Call ("NewUser")
      ElseIf @error = 1 Then
            _FileWriteLog ($Log, $sUser & " already exists ==> Calling UserAttribsExistingUser Function.")
            Call ("ExistingUser")
       
      AccountSettingConfigurations-Test1.au3
       
    • water
      By water
      Extensive library to control and manipulate Microsoft Active Directory.

      Threads: Development - General Help & Support - Example Scripts - Wiki
      Previous downloads: 30467
       
      Known Bugs: (last changed: 2018-06-01)
      None  
      Things to come: (last changed: 2018-06-01)
      None
      BTW: If you like this UDF please click the "I like this" button. This tells me where to next put my development effort
    • rudi
      By rudi
      Hello,
       
      from this posting of @Jos https://www.autoitscript.com/forum/topic/162005-getting-windows-users-account-type/?do=findComment&comment=1176831
      I can smoothly check, if a user is a *DIRECT* group member. Has anybody some code to check also, if a user is a *INDIRECT* member of a cascaded group construct?  Maybe with @Melba23 's AD UDF?
       
      The required rights are granted to group "Dept_B" User John is member of group "Dept_A" Group "Dept_A" is member of the group "Dept_B" So in the AD / NTFS FS environment John finally has the rights of both groups But when checking his "membership to group Dept_B" the result is "no member". The approach I can think of would be, to check all Group Members of group "Dept_B" whether they are of type group, then check again if "John" is member of than " 2nd level group"
      Func UserInGroup($InGroup,$ThisUser=@LogonDomain & "/" & @UserName) Local $objUser = ObjGet("WinNT://" & $ThisUser ) For $oGroup in $objUser.Groups If $oGroup.Name = $InGroup Then Return 1 EndIf Next Return 0 EndFunc Any suggestions appreciated, regards, Rudi.
    • water
      By water
      ADAT is a tool to simplify common AD administration tasks. Every administration task has its own tab. It is easy to add new functions (tabs) to the tool. Some often used functions are already available: list users, computers, OUs. File ADAT.ini can be customized to hold the AD logon information if necessary.
      Known Bugs:
      2018-03-07: If the Script started from SciTE works but the "Process" button in the compiled exe does not do anything then please add the following line at the top of your script:
      #Au3Stripper_Ignore_Funcs=Process_Tab*
        BTW: If you like this tool please click the "I like this" button. This tells me where to next put my development effort
    • bouzzi
      By bouzzi
      Hi guys,
      I'm trying to make a script that could tell me, from a username list file,  if the username is active, inactive or not existant  in a multi-domain Active Directory....
      I found a few scripts giving me hints but I found nothing to help me to accomplish this task...
      Do you have any ideas !
      Thanks
      Bouzzi!
       
×