This article will cover a simple access policy that when completed will lock out a user using BIG-IP Access Policy Manager.  Start by making an access policy with the Device Wizard. Since I just want to make a quick and easy example, I’ll be using the fourth radio option, Web Application Access Management for Local Traffic Virtual Servers.

apm_ul1

Create a virtual server via the wizard or use an existing virtual server if you already have a HTTPS virtual server. I called my Policy “Lockout” and I disabled the Antivirus Check just because I don’t want to crowd my access policy.

apm_ul2

I chose Active Directory as my authentication factor but feel free to use what you like. Next, create a virtual server if you don’t already have one. I have one already but if didn’t, I would do the following.

apm_ul3

Review the configuration and before finishing the wizard, click on Edit Access Policy in Visual Policy Editor.

apm_ul4

Your access policy should look like the following. First change the Max Logon Attempts Allowed to one.

apm_ul5

Next, I just added a Lockout macro (I need to be more creative with the naming scheme). Our macro will only consist of one block but for the sake of encapsulation, I made it into a macro in case in the future we want to add something else to it.

apm_ul6

In the macro, create a new iRule Event with ID “lookup user” and with the following branch rules.

Name Expression
Lockout user expr { [mcget {session.custom.badpwdcount}] >= [mcget {session.custom.lockout}] }
Can allow through expr { [mcget {session.custom.badpwdcount}] < [mcget {session.custom.lockout}] }

Now add some more appropriate terminals to our macro since the default “Out” is not very descriptive.

apm_ul7

Great, now just add the macro between the Logon Page and the AD Auth. The AD Auth is most likely on the Lockout branch but we can easily move it to the correct, Allow Through, branch by clicking on the little down arrow on the AD Auth block.

apm_ul8

Now that everything is in place, we should edit the endings of the access policy so that it would make more sense. Right now we only have Allow and Deny but we should add something like a Lockout with more information for the user. Don’t forget to attach the lockout ending to the lockout branch (use a different name if you want).

apm_ul9

Error Title Error Message
You’ve been locked out, %{session.logon.last.username} Please try again in %{session.custom.timeout} minutes.

In the Error title, I added a session variable that personalizes the lockout. Also, I added a custom session variable I added in iRules that lets the users know how much more they have to wait to try again. Apply the access policy and finish the device wizard. The final step is to attach the iRule below.

when ACCESS_POLICY_AGENT_EVENT {
  set user [ACCESS::session data get session.logon.last.username]
  if {[ACCESS::policy agent_id] eq "lookup user"} {
    # The lockout and timeout variables are customizable here. 
    # The lockout variable determines how many times a user may try
    # before getting locked out. The timeout variable determines how
    # long a user has to wait until they can come out of their lockout.
    set lockout 5
    set timeout 900
    # We do not want to touch (reset the timer) the user unless we know
    # for sure that this user’s bad password count has not exceeded the
    # lockout number.
    set badpwd [table lookup -notouch $user]
    if {$badpwd == {}} {
      table add $user 0 $timeout
    } elseif {$badpwd < $lockout} {
      table lookup $user
    }
    ACCESS::session data set session.custom.badpwdcount $badpwd
    ACCESS::session data set session.custom.lockout $lockout
    ACCESS::session data set session.custom.timeout [expr {[table timeout -remaining $user] / 60}]
  }
}
# When the policy completed we want to check the authentication results.
# If the user failed, we want to increment their bad password count. If 
# they have succeeded logon, we want to remove them from the session table. 
when ACCESS_POLICY_COMPLETED {
  set user [ACCESS::session data get session.logon.last.username]
  set result [ACCESS::session data get session.ad.last.authresult]
  # If we never went to authentication, the auth result would be null 
  # and we don’t want to do anything in that case.
  if {$result == ""} {
    return
  } elseif {$result} {
    table delete $user
  } else {
    table incr $user
  }
}

A failed login should result in this screen:

apm_ul10

Thanks again to ystephie for another great solution!

About the Author

image

 

Stephanie is a summer intern at F5, heading back to school soon to continue her EECS degree at UC Berkeley, and has been having a blast creating interesting solutions for BIG-IP. Stephanie’s passion for engineering, and smile, is contagious.

Related Articles

Comments on this Article
Comment made 27-Mar-2014 by MarkD 01 9
Great article! I wound up using this while using APM to proxy ActiveSync. I used your article to emulate the lockout functionality of TMG (http://blogs.technet.com/b/isablog/archive/2012/11/01/using-the-account-lockout-feature-in-tmg-2010.aspx).
0
Comment made 28-Mar-2014 by Jason Rahm
sweet, nice work, Mark!
0
Comment made 29-May-2016 by abdul rahman 1
HI , I have tried the same as mentioned but its not working for me. I have been through the document multiple times, where should we assign these variables. where should we declare session.custom.badpwdcount session.custom.lockout
0