Fun with Boolean Expressions in Cisco NAC Appliance Rules

NetCraftsmen®

Let’s set the stage. Say you’re setting up NAC for remote access VPN users using L3 in-band virtual gateway. The VPN is handled by an ASA and authentication is handled by VPN SSO. There are three classes of users. The three classes of users each have a different VPN profile for connecting to the VPN. These profiles are provided with separate VPN pools on the ASA. This make separating the users into roles fairly straightforward as described below.

With VPN SSO, RADIUS accounting packets are sent from the ASA to the NAC Server (NAS). One RADIUS accounting attribute is called “Framed_IP”. This attribute contains the VPN pool IP address of the user. This information is used to map the user into a particular role. In this scenario, the computers used by the remote access users also have registry keys that define which user class they are in.

Now comes the fun part. Most of the users have the correct VPN profile for their user class, but there are some users that have an incorrect VPN profile. We’ll call the user classes CLASSA, CLASSB, and CLASSC. How do you block the users, using the incorrect profile, from the network and also provide them with the correct VPN profile?

From a 10,000 foot view, this is an easy task of completing the following steps:

  1. Define the unique registry keys for CLASSA, CLASSB, and CLASSC
  2. Create checks for each registry key and value name
  3. Create the rules based on the checks
  4. Create the requirements
  5. Tie the requirements to the rules to create requirement-rules
  6. Tie the requirement-rules to the roles for the different classes of users(ie CLASSA, CLASSB, and CLASSC)

The devil is truly in the details. Steps 1 and 2 are fairly straightforward. Use regedit to find the registry keys and value names. Then create the checks in the NAC Manager (NAM) by navigating to “Device Management > Clean Access > Clean Access Agent > Rules”.

Step 3 is where things get interesting. I’ll take the rules for CLASSA as an example. The rules will be tied to requirements that ensure that the VPN user is using the correct VPN profile. I’ll call the checks created for each class REGA, REGB, and REGC. I’ll be creating two rules. Below is a sentence description of what the rules will accomplish:

  1. For CLASSA, if the registry key on the VPN user’s computer matches REGA, then pass the rule. If the registry does not match REGA, but does match REGB, then fail the rule. On rule failure, the requirement tied to this rule will provide the user a download link to download the CLASSB VPN profile. If REGA does not exist and REGB does not exist, pass the rule. This will allow other users that do not match REGA and REGB to flow down to the next rule.
  2. For CLASSA, if the registry key on the VPN user’s computer matches REGA, then pass the rule. If the registry does not match REGA, but does match REGC, then fail the rule. On rule failure, the requirement tied to this rule will provide the user a download link to download the CLASSC VPN profile. If REGA does not exist and REGC does not exist, pass the rule. This will allow other users that do not match REGA and REGC to flow down to the next rule.
  3. This rule blocks access if none of the REGA, REGB, or REGC checks were seen. This would be a catchall rule looking for rogue users trying to access the network with an unapproved computer.

I’ll explain the boolean logic behind the first rule. The first thing to keep in mind is that the requirement-rule will only trigger on a failure of the rule. If the rule passes, the the requirement is deemed successful and no remediation is necessary. With that in mind, let’s take a look at boolean logic for the first rule. The rule will actually be:

     REGA | (!REGA & !REGB)

Let’s break this out into the individual parts.

         Part1: REGA
The first REGA designates that if REGA is not found, then fail the rule.

        Part2: (!REGA & !REGB)
The portion within the parentheses succeeds only if REGA is not found and REGB is not found. It is important to have the !REGA because we only want to Remember, what we are really looking for is failure scenarios. Failure occurs in three combinations:

  1. REGA is found and REGB not found
  2. REGA is found and REGB is found
  3. REGA is not found and REGB is found.

The first two combinations will never occur because they would already have passed the expression in Part1. The last combination is the one we want to fail. This means that the requirement remediation dialog box will only appear if REGA fails, but REGB is found.

       REGA | (!REGA & !REGB)
Putting it all together, if REGA is found, then the rule will succeed and remediation is not necessary. The immediate success is because of the “or” boolean expression right after the REGA. If REGA is not found, then the second part of the expression, within the parentheses, is evaluated. If this expression succeeds it means that REGB was not found. In this case we’re doing this because only want to provide remediation if REGB is found and REGA is not found.

Viewed in matrix form, it would look like

REGA REGB REGA or (!REGA and !REGB) Result
0 0 0 or (1 and 1) 1 (pass)
0 1 0 or (1 and 0) 0 (fail)
1 0 1 or (0 and 1) 1 (pass)
1 1 1 or (0 and 0) 1 (pass)

In summary, the most important thing to keep in mind is that you want the rule to fail in order to trigger the requirement remediation.

Leave a Reply