Forum Discussion
Active Directory Logon Hours and APM session timeout
Hi,
Not really a question but documenting here incase anyone else wants to reuse this code.
I was asked to create a VPN connection on our F5 that would only allow access during a users normal working hours. As this information is already store in Active Directory under "User Logon Hours" I decided to use this to calculate when to terminate the APM session. Obviously a user can't authenticate against AD outside of their logon hours, so all I needed to do was to calculate how long left the user has until their logon hours expire. I used the following code in a Variable Assign to update the "Maximum Session Timeout" value for APM.
if {[ expr { [mcget {session.ad.last.attr.logonHours}] != "" }] } {
Get the value from AD
set logonHours [mcget {session.ad.last.attr.logonHours}]
set default maximum session time
set maximumSessionSeconds 604800
set start of session times
set startHour [clock format [mcget {session.user.starttime}] -format %H]
set startTime [clock format [mcget {session.user.starttime}] -format %H%M]
set startDay [clock format [mcget {session.user.starttime}] -format %w]
set default session timeout
set secondsRemaining 1
set finishDay $startDay
set rolledOver 0
create array to store the binary list of permitted logon hours
array set daysofweek {}
for { set a 0} {$a < 7} {incr a} {
set hexHours "0x[string range $logonHours [expr 2+$a*6] [expr 7+$a*6] ]"
set hexHours "[string range $logonHours [expr 2+$a*6] [expr 7+$a*6] ]"
set daysofweek($a) [string cat [string reverse [binary format %08b "0x[string range $hexHours 2 3]"]] [string reverse [binary format %08b "0x[string range $hexHours 4 5]"]] [string reverse [binary format %08b "0x[string range $hexHours 6 7]"]]]
binary scan [binary format H* $hexHours] b* tmp1
set daysofweek($a) $tmp1
}
set value so that it forces entry into the loop
set finishHour 2359
while { $finishHour == 2359 && $secondsRemaining < $maximumSessionSeconds } {
set finishHour [string first 0 $daysofweek($finishDay) $startHour]
if { [ expr $finishHour == "-1"] } {
set finishHour 2359
incr rolledOver
}
incr secondsRemaining [expr [clock scan $finishHour] - [clock scan $startTime] ]
if { [expr $finishHour ==2359 ] } {
if { [expr $finishDay < 6 ]} {
roll over to following day
incr finishDay
} else {
except Sat needs reseting to Sun
set finishDay 0
}
we have rolled over days
so reset the time to midnight
set startTime 0000
set startHour 0
and give back the extra minute that we "borrowed" to make the time calculation work
incr secondsRemaining 60
}
If we have finally looped around a full week then we need to break out of the loop
if { $startDay == $finishDay && $rolledOver > 1 } {
set finishHour [string first 0 $daysofweek($finishDay) $startHour]
incr secondsRemaining [expr [clock scan $finishHour] - [clock scan $startTime] ]
break
}
}
return $secondsRemaining
} else {
return $maximumSessionSeconds
}This takes the blob from the the AD attribute logonHours and decodes it and then works out how many seconds it is from now until the next denied logon hour according to AD. We then set that number to the maximum session timeout, so that the APM will close the session when the user is denied access by AD.
Rob
1 Reply
- Stanislas_Piro2
Cumulonimbus
Hi,
Thanks for sharing. I did not know that AD attribute exists.
When I read your code, I thought it is complicated for a simple need.
I think this code is a quite simpler (not tested with AD)
set maximumSessionSeconds 604800 if {[set logonHours [mcget {session.ad.last.attr.logonHours}]] != ""} { convert string to binary string set logon_hours_binary_string ""; for { set a 0} {$a < 21} {incr a} { binary scan [binary format H2 [string range $logonHours [expr {$a*2}] [expr {($a+1)*2 -1}]]] B8 hex2bin; append logon_hours_binary_string [string reverse $hex2bin]; } unset hex2bin; evaluate the number of seconds from last sunday set time_from_sunday [expr {[clock seconds] - [clock scan "last sunday"]}]; search in string next hours with 0 value set current_index [expr {$time_from_sunday / 3600}]; convert the index to number of seconds from last sunday if { ([set next_denied_index [string first 0 $logon_hours_binary_string$logon_hours_binary_string $current_index]] == -1) || ($next_denied_index > [expr {168 + $current_index}]) } { set next_denied_index [expr {168 + $current_index}] }; evaluate number on seconds to disconnect time return [expr { $next_denied_index*3600 - $time_from_sunday}] } else { return $maximumSessionSeconds }
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
