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