Guest

Cisco ASA 5500-X Series Next-Generation Firewalls

DAP Advanced Functions Configuration Example

DAP Advanced Functions Configuration Example

Document ID: 115947

Updated: Sep 27, 2013

Contributed by Cisco TAC Engineers.

   Print

Introduction

This document describes the advanced functions of Dynamic Access Policies (DAP) for remote access VPNs. You can use these advanced functions when you need additional flexibility to match by criteria.

Note: Refer to Important Information on Debug Commands before you use debug commands.

Prerequisites

Requirements

Cisco recommends that you have knowledge of these topics:

Components Used

This document is not restricted to specific software and hardware versions, but the Adaptive Security Device Manager (ASDM) is required in order to complete the configuration.

The information in this document was created from the devices in a specific lab environment. All of the devices used in this document started with a cleared (default) configuration. If your network is live, make sure that you understand the potential impact of any command.

Background Information

Caution: Use DAP advanced custom Lua functions only if the ASDM GUI configuration or the EVAL function does not provide the matching behavior you need. In production deployments, use advanced Lua functions with extreme care and with guidance from Cisco Engineering/Technical Assistance Center (TAC) in order to avoid any unintended behavior with DAP.

If you use DAP for remote access VPNs, you may need the additional flexibility to match by criteria. For example, you can apply a different DAP based on these scenarios:

  • An organizational unit (OU) or other level of the hierarchy contains the user object.
  • A group name (memberOf) adheres to naming convention but has many possible matches, so you want to use a wildcard on group names.
  • You want to check for anti-virus, anti-spyware, or firewall packages on the endpoint PC.
  1. Use the ASDM in order to create a logical expression for your match criteria.

    dap-adv-functions-01.png

  2. Use the advanced mode in order to create custom functions with a logical expression and Lua code.

    dap-adv-functions-02.png

OU-Based Match Example

The Lightweight Directory Access Protocol (LDAP) server can return many attributes that DAP can use in a logical expression.

For an example of these attributes, use the debug dap trace command on the Adaptive Security Appliance (ASA) console.

assert(function()
if ( (type(aaa.ldap.distinguishedName) == "string") and
(string.find(aaa.ldap.distinguishedName, "OU=Admins,dc=cisco,dc=com$")
~= nil) ) then
return true
end
return false
end

A distinguished name (DN) of the user is one attribute returned by the LDAP server. The DN implicitly identifies where the user object is located in the directory. For example, if the DN is CN=Joe User,OU=Admins,dc=cisco,dc=com, this user is located in OU=Admins,dc=cisco,dc=com. If all administrators are in this OU (or any container below this level), use this logical expression in order to match on the criteria:

assert(function()
if ( (type(aaa.ldap.distinguishedName) == "string") and
(string.find(aaa.ldap.distinguishedName, "OU=Admins,dc=cisco,dc=com$")
~= nil) ) then
return true
end
return false
end)()

In this example, the string.find function allows for a regular expression. The $ at the end of the string anchors this string to the end of the distinguishedName field.

Use the escape character % in your search string in order to escape special characters such as ( ) . % + - * ? [ ^ $. For example, you can escape the - character in this string (OU=Admins,dc=my-domain,dc=com$) as shown in this string (OU=Admins,dc=my%-domain,dc=com$).

Group Membership (memberOf) Example

You can create a similar, basic logical expression for pattern matching of Active Directory (AD) group membership. Because users can be members of multiple groups, DAP parses the response from the LDAP server into separate entries and holds them in a table. In this case, a more advanced function is required in order to:

  • Compare the memberOf field as a string if the user belongs to only one group.
  • Iterate through each returned memberOf field if the returned data is of type 'table.'

For example, if a user is a member of any group that ends with '-stu,' they match this DAP:

assert(function()
local pattern = "-stu$"
local attribute = aaa.ldap.memberOf
if ((type(attribute) == "string") and
(string.find(attribute, pattern) ~= nil)) then
return true
elseif (type(attribute) == "table") then
local k, v
for k, v in pairs(attribute) do
if (string.find(v, pattern) ~= nil) then
return true
end
end
end
return false
end)()

CheckAndMsg with Custom Function

This function uses DAP with action set to terminate:

(assert(function()
local block_connection = true
local update_threshold = "150000" --this is the value of lastupdate in
seconds
for k,v in pairs(endpoint.av) do
if (CheckAndMsg(EVAL(v.exists, "EQ", "true", "string") and EVAL
(v.lastupdate, "LT", update_threshhold, "integer"),
k.." exists; last update is "..string.sub((tonumber
(v.lastupdate)/86400), 1, 3).." days",
k.." does not exist; last update is "..string.sub((tonumber
(v.lastupdate)/86400), 1, 3).." days")) then
block_connection = false
end
end
return block_connection
end)())

Upon termination, it displays this message:

Login denied.<AV Name> does not exists; last update is <X> days

Anti-Virus, Anti-Spyware, and Firewall Examples

These Lua functions check for attributes related to anti-virus, anti-spyware, and firewall packages on the endpoint PC returned by Cisco Secure Desktop (CSD) host scan.

Check for Anti-Virus Installation

This custom function checks if CSD detects any anti-virus:

assert(function()
for k,v in pairs(endpoint.av) do
if (EVAL(v.exists, "EQ", "true", "string")) then
return true
end
end
return false
end)()

Check for Anti-Virus Installation and Last Update, and Provide Error Messages

This example demonstrates how DAP can check for an anti-virus installation, check for the last update, and notify the user for remediation. It uses a function similar to that in Check for Anti-Virus Installation.

Set the authentication, authorization, and accounting (AAA) attributes you wish to match. In the advanced field, ensure the AND operation is selected; in the action field, ensure the terminate option is selected. If the user matches the AAA attributes and if the Lua function returns a value of true, DAP is selected, a message appears that explains why the DAP record was displayed, and the user connection is terminated. If the Lua function does not return a value of true, DAP does not match and permits access. In the message box field, enter the message, "No anti-virus program found, please install anti-virus and try again." If the user has an anti-virus package and is below the update days threshold, they are not given a message as indicated by the double quotes in line 7 of this example:

(assert(function()
local block_connection = true
local update_days = "15" --days
local av_lastupdate = update_days*86400
for k,v in pairs(endpoint.av) do
if (CheckAndMsg(EVAL(v.exists, "EQ", "true", "string") and EVAL
(v.lastupdate, "LT", av_lastupdate, "integer"),
"",
k.." exists; but last update is greater than 15 days old.
Expecting under 15 days.")) then
block_connection = false
elseif (EVAL(v.exists, "NE", "true", "string")) then
block_connection = true
end
end
return block_connection
end)())

If the user has Norton anti-virus, but the last update is greater than 15 days, this sample message appears:

NortonAV exists; but last update is greater than 15 days old. Expecting 
under 15 days.

If the EVAL does not match, it goes to the next function, matches, and returns a value of true. Since there is no CheckAndMsg associated with the second function, it uses the DAP message text:

No anti-virus program found, please install anti-virus and try again.

In summary, DAP looks for a user AAA and endpoint attribute in order to match DAP. If DAP matches, the user is terminated with a message. The endpoint match is a result of a Lua EVAL that returns true or false to DAP. A true matches and denies the connection. A false does not match and does permit the connection.

  1. The first function in the loop checks if endpoint.av.xxxxx.exists is equal to true and if the last update is less than the configured days. Users without anti-virus software are permitted access, because the user AAA matches, but the Lua looks specifically for endpoint.av.xxxxx.exists = true and endpoint.av.xxxxx.lastupdate <= days.
  2. The second loop catches users without anti-virus software and blocks them, because the second function looks only for endpoint.av.xxxxx.exists NE true. If the user endpoint av exists is not equal to true, the function returns a value of true, which means they do not have anti-virus. DAP matches and denies the connection.

Check for Anti-Spyware Installation

This custom function checks if CSD detects anti-spyware:

assert(function()
for k,v in pairs(endpoint.as) do
if (EVAL(v.exists, "EQ", "true", "string")) then
return true
end
end
return false
end)()

Check for Firewall Installation

This custom function checks if CSD detects a firewall:

assert(function()
for k,v in pairs(endpoint.fw) do
if (EVAL(v.exists, "EQ", "true", "string")) then
return true
end
end
return false
end)()

Check for Anti-Virus, Anti-Spyware, or Firewall Installation

This function returns a true if an anti-virus, anti-spyware or a firewall package is found:

assert(function()
function check(antix)
if (type(antix) == "table") then
for k,v in pairs(antix) do
if (EVAL(v.exists, "EQ", "true", "string")) then
return true
end
end
end
return false
end
return (check(endpoint.av) or check(endpoint.fw) or check(endpoint.as))
end)()

Terminate If No Spyware Installation

The only difference between this function and the function in Check for Anti-Spyware Installation is that 'not' precedes the assert.

not assert(function()
for k,v in pairs(endpoint.as) do
if (EVAL(v.exists, "EQ", "true", "string")) then
return true
end
end
return false
end)()

Check for Anti-Virus and Firewall Installation, and Validate Last Anti-Virus Update Is Not Greater Than Thirty Days

This example returns true if an anti-virus and a firewall are found and if the last update of the anti-virus is not greater than 30 days:

assert(function()
function checkav(antix)
if (type(antix) == "table") then
for k,v in pairs(antix) do
if (EVAL(v.activescan, "EQ", "ok", "string") and EVAL
(v.lastupdate, "LT", "2592000", "integer")) then
return true
end
end
end
return false
end
function checkfw(antix)
if (type(antix) == "table") then
for k,v in pairs(antix) do
if (EVAL(v.enabled, "EQ", "ok", "string")) then
return true
end
end
end
return false
end
return (checkav(endpoint.av) and checkfw(endpoint.fw))
end)()

Because the firewall does not have a lastupdate value to return, it has a separate function.

Regular Expression Matching

This section describes functions that use regex expressions in order to match certain attributes and determine validity of the host machine. These regex capabilities have been tested and are valid:

  • Dollar sign ($) anchors the search string to the end of the returned value.
  • Caret (^) anchors the search string to the beginning of the returned value.
  • Bracketed characters, such as [Aa], match multiple characters in a specific position. For example, in order to match OU=Cisco (case insensitive ), use OU=[Cc][Ii][Ss][Cc][Oo].
  • Period (.) matches any single character in this position. For example, Group..Users matches Group01Users, Group33Users, and so on.

Connect If Endpoint PC Has Any Instance of Hotfix KB944

This function uses regular expression matching in order to see if the hotfix list contains a pattern. In this example, Cisco Secure Desktop returns all hotfixes on the endpoint PC; if there is an instance of KB944, the DAP policy matches and is enforced.

assert(function ()
local pattern = "KB944"
local true_on_match = true
local match = false
for k,v in pairs(endpoint.os.hotfix) do
print(k)
match = string.find(k, pattern)
if (match) then
if (true_on_match) then
return true
else return (false)
end
end
end
end)()

For example, if the host machine has hotfix KB944533 or hotfix KB944653, it matches the rule.

Use LUA Script to Check OUI of MAC Address

This function is similar to the one described in Connect If Endpoint PC Has Any Instance of Hotfix KB944. This function uses a regular expression in order to match the organizationally unique identifier (OUI) of the MAC address.

In this example, the MAC address starts with d067.e5XX.XX. Use a regular expression and Lua code in order to match machines that start with the same OUI MAC.

assert(function ()
local pattern = "^d067\.e5*"
local true_on_match = true

local match = false
for k,v in pairs(endpoint.device.MAC) do
print(k)
match = string.find(k, pattern)
if (match) then
if (true_on_match) then
return true
else return (false)
end
end
end
end)()

Note: A different version of this function is required for a multi-valued checking.

Connect Based on the First Three Letters of the Hostname (Not Case Sensitive)

This function uses regular expressions in order to determine if the first three letters of the hostname are msv (case insensitive):

assert(function()
local match_pattern = "^[Mm][Ss][Vv]"
local match_value = endpoint.device.hostname
if (type(match_value) == "string") then
if (string.find(match_value, match_pattern) ~= nil) then
return true
end
elseif (type(match_value) == "table") then
local k,v
for k,v in pairs(match_value) do
if (string.find(v, match_pattern) ~= nil) then
return true
end
end
end
return false
end)()

Connect If Device.id of Endpoint PC and Serial Number on the Certificate Are the Same

This Lua expression is meant to connect if the device.id of the endpoint PC and the serial number on the certificate are the same:

assert(function()
local match_pattern = endpoint.device.id
local match_value = endpoint.certificate.user["*"].subject_e
if (type(match_value) == "string") then
if (string.find(match_value, match_pattern) ~= nil) then
return true
end
elseif (type(match_value) == "table") then
local k,v
for k,v in pairs(match_value) do
if (string.find(v, match_pattern) ~= nil) then
return true
end
end
end
return false
end ) ()

Enforce DAP Based on CSD Host Scan for Domain Registry Key

This procedure provides an example of a configuration procedure with ASDM.

  1. Locate the registry key that holds the domain at \HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Domain.

    dap-adv-functions-03.jpg

  2. Define the host scan parameter for the registry setting.

    dap-adv-functions-04.jpg

  3. Apply the registry endpoint attribute to the DAP policy.

    dap-adv-functions-05.jpg

  4. Establish the Secure Sockets Layer (SSL) VPN session.

  5. Verify the DAP policy enforcement via DAP debugs.

    dap-adv-functions-06.jpg

DAP Support for Windows 7 and CSD 3.5

Windows 7 platforms are supported with CSD Release 3.5 or later. With the ASDM 6.2.x maintenance release and the 6.3.x releases, you can directly use the interface in order to check for Windows 7 OS. With earlier ASDM releases, an advanced DAP Lua script is required in order to check for Windows 7 machines. On an ASA with Release 8.x and pre-beta CSD Release 3.5, enter this Lua script string into the ASDM DAP advanced box in order to perform checks for Windows 7 machines:

(EVAL(endpoint.os.version,"EQ","Windows 7","string"))

Identification of iPhones, iPads, and Mobile Devices

This Lua expression lets you track specific mobile devices by their unique identifiers (UIDs). You can use DAP in order to achieve this basic functionality.

dap-adv-functions-07.jpg

When the value cannot be hard-coded and needs to be read from the AD, this becomes more difficult. Because there is no specific UID field in AD, you can store the value for a particular user under a different field. This example uses otherHomePhone to store the UID.

To help you identify the UID for an iPhone or iPad, search the web for an appropriate tool.

Once you identify the UID, add it to otherHomePhone in the AD entry for that user.

dap-adv-functions-08.jpg

From the debug ldap 255 command and from user test authentication, obtain the LDAP attribute being pushed, which is otherHomePhone.

Allow the phone to connect, then run a DAP trace during the attempted connection in order to identify the endpoint attribute that contains the UID (endpoint.anyconnect.deviceuniqueid).

This Lua expression can then compare the two parameters:

assert(function()
if (type(aaa.ldap.otherHomePhone) ==type(endpoint.anyconnect.deviceuniqueid)
then
return true
end
return false
end)()

Use of DAP to Prevent Connection by Specific Browser

This procedure describes how to use DAP to prevent connection by a Chrome browser:

  1. Enable CSD.

    dap-adv-functions-09.png

  2. Under host scan configuration, use the Process ID (PID) and the process name in order to add a process scan.

    You can determine the PID and process name on Windows with the Task Manager. In order to display the PID value, open Task Manager, go to the Processes tab, click the View menu, then click Select Columns. In the Select Columns or Select Process Page Columns dialog, tick and check the checkbox for PID (Process Identifier), and click OK.

    On Macs, you can determine the Process ID with the activity monitor. Or, in the bash shell (which you can can also use in Unix), use the ps -e command while the process is running, then match the PIDs to the process name with the cat /proc/<PID>/cmdline command.

    dap-adv-functions-10.png


    dap-adv-functions-11.png

  3. Create a DAP policy in order to test, among other things, if that process is running on the machine.

    dap-adv-functions-12.png

  4. Test your connection.

Caveats

  1. The problem with this solution is that the user cannot have Chrome open on his machine at all. DAP simply checks if that particular Chrome process is running, but does not check to see if the clientless session was initiated by that process or by some other process. So the user cannot run Chrome in the background when a WebVPN connection is attempted.
  2. Assume a scenario where the user uses Firefox to open a WebVPN session, and the login attempt fails. The user remembers that Chrome is still running, so the user terminates the Chrome connection and tries to login again. The login still fails because CSD has to re-run host scan. So, the user must also close the instance of Firefox that was used to access WebVPN, then restart Firefox. This process can be confusing to the user. Cisco recommends that you create a DAP failure message that tells the user to terminate Chrome and to close the browser they are currently using:

    dap-adv-functions-13.png
Updated: Sep 27, 2013
Document ID: 115947