BIG-IP APM–Customized Logon Page

The default logon page for the Access Policy Manager module is pretty basic, particularly so if only the minimal username and password is configured.  However, APM is wildly flexible.  In this tech tip, I’ll cover customizing the logon page by adding a dropdown box of services to the standard username and password fields.

Introduction

Background Information

The goal here is to provide access to multiple web applications behind APM through the use of an admin-defined dropdown menu and different LTM pools for each web application. We will be generating the list dynamically through the use of data groups so there will be no need to manually edit the iRule code each time an admin decides to add another option.

Solution Overview

Combining advanced customization, data groups, and iRules, we can dynamically generate html code for each key value pair in the data group. We simply add a session variable in the logon page through advanced customization and insert our html code, generated with iRules, through the session variable. The data group serves as a user friendly way of adding more applications as a layer of indirection.

Create the Access Policy

Before I can create the custom logon page, I need to have an access policy defined.  I’ll do this by utilizing the Device Wizards option under the Templates and Wizards main tab.  Select Web Application Access Management for Local Traffic Virtual Servers as show below in Figure 1.

After following the steps in the wizard (AAA server, virtual IP, pool info, etc), I get to the summary page shown below in Figure 2.  Before clicking finished, I need to enter the Visual Policy Editor to make a couple edits.

Immediately after the start box in the VPE, I add an iRule Event as show in Figure 3.  This will trigger the iRule event ACCESS_POLICY_AGENT_EVENT  in the iRule featured later in this article.

I make sure to assign an ID to the event before saving it.  Next, I click into the Logon Page event in the VPE and add a text field immediately after the password field.  I then set the Post Variable Name and the Session Variable Name to ‘appname’. (The name is not significant but will need to match a statement in some HTML I’ll replace later in the article.)  In the Logon Page Input Field #3 box, I enter ‘Application’ (this ensures the logon page agent will know to expect it as one of the POST parameters) and then click save.  See Figure 4 below for details.

Note: The logon page agent will only parse and store POST parameters it knows about.

Finally, I update the access policy by clicking Apply Access Policy and then finish the Device Wizard.

Customize the Logon Page

Now that the policy is created, I need to login to the CLI to complete several steps.

1. Change Directory into the specific policy’s logon directory:

cd/config/customization/advanced/logon/<policy_name>_act_logon_page_ag (where <policy_name> is your policy name.  devCenEx_act_logon_page_ag in my case.

2. Make a copy of the tmp_logon_en.inc file (the name logon_en.inc is significant.)

cp tmp_logon_en.inc logon_en.inc

3. Add group and world read permissions to the logon_en.inc file

chmod a+r logon_en.inc

4. Edit and save the logon_en.inc file, replacing this auto-generated PHP code with the HTML code below it.   Notice the label and select tags reference Applications and appname (respectively) from our Logon Page in Figure 4.

Auto-generated PHP (remove)

<?
//------------------------------------------------------------
foreach( $fields_settings as $field_settings )
{
    if( $field_settings["type"] != "none" )
    {
        if( $GLOBALS["label_position"] == "above" ){
?>
    <tr>
        <td colspan=2 class="credentials_table_unified_cell" ><label for="<? print( $field_settings["type"] );

?>"
><? print( $field_settings["caption"] ); ?></label><input type=<? print( $field_settings["type"] ); ?> name=<? print( $field_settings["name"] ); ?> class="credentials_input_<? print( $field_settings["type"] );

?>"
<? print( ( $field_settings["rw"] == 0 ? "disabled" : "" ) ); ?> value="<? print( $field_settings["value"] );

?>"
autocomplete="off"></td> </tr> <? }else{ ?> <tr> <td class="credentials_table_label_cell" ><? print( $field_settings["caption"] ); ?></td> <td class="credentials_table_field_cell"><input type="<? print( $field_settings["type"] );

?>"
name="<? print( $field_settings["name"] );

?>"
class="credentials_input_<? print( $field_settings["type"] );

?>"
<? print( ( $field_settings["rw"] == 0 ? "disabled" : "" ) ); ?> value="<? print( $field_settings["value"] );

?>"
autocomplete="off"></td> </tr> <? } } } //------------------------------------------------------------ ?>
Custom HTML (add)
<tr>
        <td colspan=2 class="credentials_table_unified_cell" ><label for="text">Username</label>
        <input type=text name=username class="credentials_input_text"  value="" autocomplete="off" autocapitalize="off"></td>
    </tr>
    <tr>
        <td colspan=2 class="credentials_table_unified_cell" ><label for="password">Password</label>
        <input type=password name=password class="credentials_input_password"  value="" autocomplete="off" autocapitalize="off"></td>
    </tr>
    <tr>
        <td colspan=2 class="credentials_table_unified_cell" ><label for="text">Applications</label>
          <select name="appname">
            %{session.custom.logon_opt} 
          </select>
       </td>
    </tr>
Note: The HTML above can be further customized if desired.  The important section of code is:

     <select name>=”appname”>

         %{session.custom.logon_opt}

     </select>

The POST variable was created in the Logon page and then the dummy session variable that will be utilized in the iRule.

5. Apply the customizations to the policy

advCustHelp <your policy name>

b customization group <your policy_name>_general_ui action update

b profile access <your policy name> generation action increment

6. Create a string class for the applications.  The string should be the name of the application to be displayed in the Logon Page and the value should be the pool that hosts the applicable service.  See Figure 5 below for the GUI entry for the class.

class ExampleDataGroup {
   {
      "OWA" { "intranet-pool" }
      "Share Point" { "sharepoint-pool" }
   }
}

7. Create the iRule (via iRule editor, GUI, or tmsh)

when ACCESS_POLICY_AGENT_EVENT {
  set htmlstr ""
  # Pull data from the data group
  set keys [class names ExampleDataGroup]
  # log local0. "DATA GROUP:: $keys"
  foreach key $keys {
  # log local0. "KEY:: $key"
  # Add a new option in the drop down box for each key
    set htmlstr [concat $htmlstr "<option value=\"$key\">$key</option>"]
  }
  # log local0. "HTML STRING:: $htmlstr"
  # Using the session variable we inserted through advanced customization, we can insert the html code we generated above
  ACCESS::session data set "session.custom.logon_opt" $htmlstr
}

when ACCESS_ACL_ALLOWED {
  set appname [ACCESS::session data get "session.logon.last.appname"]
  # log local0. "appname: $appname"
  set keys [class names ExampleDataGroup]
  set index [lsearch $keys $appname]
  # log local0. "index: $index"
  if {$index >= 0} {
    set keyValue [class element $index ExampleDataGroup]
    pool [lindex $keyValue 1]
    # log local0. "POOL:: [lindex $keyValue 1]"
  }
}

Note that the class name referenced in the iRule should match the actual class name (instead of ExampleDataGroup as shown above)

8. Apply the iRule to the APM virtual server and I’m done!

tmsh modify /ltm virtual custom_dropdown_vs rules { custom_dropdown_iRule }

Figure 6 below shows the resulting logon page from the customizations performed.  This is just the surface of what can be done to customize the logon page.  Many thanks to F5er ystephie for writing up the documentation steps for this solution.

 

Related Articles

 

 

 
© 2008 SYS-CON Media