on 09-Mar-2015 15:37
Problem this snippet solves:
This example iCall will keep an APM Active Directory AAA object and pool in lockstep with a particular Site construct in an AD domain. It's a periodic script and should probably be run no more than every 30 seconds (although it's fairly lightweight in operation). It requires two configuration entries to be set:
If you change the AD sitename configured in the iCall script, it will repopulate the existing object with the new site's DCs -- making it very easy to retarget your domain controller traffic. It will also notice when DCs are added or removed from an existing site. If someone adds a non-site entry manually to the configuration, it'll remove it.
How to use this snippet:
This iCall script requires v11.4 or higher.
Code :
sys icall script /Common/f5.ad_aaa_maintainer { app-service none definition { ################################################# ## ad_aaa object maintainer ## version 1.0 -jm ## - works best with a periodic run of no ## greater than 30 seconds ## ## CONFIGURATION ## ## Active Directory Site Name # Set the name of the AD Site whose domain controllers # you want to track for the AAA object. This name is not # case sensitive. set ad_site "seattle" ## Active Directory AAA Object # Set the name of the AAA object whose pool members you # wish to maintain. set ad_aaa "olympus-f5" ## ## MAIN ## tmsh::log_level notice tmsh::stateless enabled # Get the domain and pool from the AAA object. set ad_domain [tmsh::get_field_value [lindex [tmsh::get_config /apm aaa active-directory $ad_aaa] 0] "domain"] if { $ad_domain == "" } { tmsh::log_level alert tmsh::log "ad_aaa_maintainer: ERROR! This AD AAA object is not configured correctly or does not exist. Please verify your iCall settings." exit 1 } set ad_pool [tmsh::get_field_value [lindex [tmsh::get_config /apm aaa active-directory $ad_aaa] 0] "pool"] if { $ad_pool == "" } { tmsh::log_level alert tmsh::log "ad_aaa_maintainer: ERROR! This AD AAA object is not configured as a pool-type object. Please verify your iCall settings." exit 1 } # Find the site's members from the Kerberos SRV records. set ad_ipaddrs [exec -keepnewline -- /usr/bin/dig +short -q _kerberos._tcp.${ad_site}._sites.${ad_domain}. SRV | /bin/cut -c9- | /bin/sort | /bin/sed "s/.\$//"] # Create an array of site DCs discovered from DNS. foreach name ${ad_ipaddrs} { set addr [exec -- /usr/bin/dig +short -q $name A] set dns_member($name) $addr } # If nothing was discovered from DNS, then error out -- someone has # removed our site. Otherwise, create an array of DCs from the # AAA object configuration. if { [array size dns_member] > 0 } { set ad_config_serverlist [tmsh::get_field_value [lindex [tmsh::get_config /apm aaa active-directory $ad_aaa] 0] "domain-controllers"] foreach member $ad_config_serverlist { set config_member([lindex $member 1]) [lindex [lindex $member 2] 1] } # Compare the two arrays and find differences. set ilist1 [array names dns_member] set ilist2 [array names config_member] foreach idx $ilist1 { # If we don't have a config entry for a DNS-discovered DC, # then it must have joined the site. Add it. if {![info exists config_member($idx)]} { lappend retn_list $idx tmsh::log "ad_aaa_maintainer: Domain Controller joined site $ad_site. Added $idx ip $dns_member($idx)." tmsh::modify /apm aaa active-directory $ad_aaa domain-controllers add "{ $idx { ip $dns_member($idx) } }" tmsh::modify /ltm pool $ad_pool members add "{ $dns_member($idx):any }" continue } # If an existing config entry has a different value for IP # address than the DNS entry tells us, change it to the new # value. if {$dns_member($idx) != $config_member($idx)} { tmsh::log "ad_aaa_maintainer: Domain Controller changed addresses in site $ad_site. Modified AAA object $ad_aaa : $idx ip $dns_member($idx) - was $config_member($idx)." tmsh::modify /apm aaa active-directory $ad_aaa domain-controllers modify "{ $idx { ip $dns_member($idx) } }" tmsh::modify /ltm pool $ad_pool members remove "{ $config_member($idx):any }" tmsh::modify /ltm pool $ad_pool members add "{ $dns_member($idx):any }" lappend retn_list $idx } } # If we have an entry in the config that doesn't appear in # DNS then the DC has either left the site or someone is adding # things to the configuration. Remove it from the AAA object # and pool. foreach idx $ilist2 { if {![info exists dns_member($idx)]} { tmsh::log "ad_aaa_maintainer: Domain Controller left site $ad_site. Deleted $idx from AAA object $ad_aaa." tmsh::modify /apm aaa active-directory $ad_aaa domain-controllers delete "{ $idx }" tmsh::modify /ltm pool $ad_pool members delete "{ $config_member($idx):any }" } } } else { tmsh::log_level alert tmsh::log "ad_aaa_maintainer: ERROR! No pool members detected. Please check your sitename for errors." exit 1 } ## ################################################# } description none events none } sys icall handler periodic f5.ad_aaa_task { interval 30 script f5.ad_aaa_maintainer }