Python and ISE Monitor Mode

There are several ways to run ISE (wired) in monitor mode and AuthZ results: dACL, another VLAN, etc. It is always a good idea ๐Ÿ™‚ to run ISE in monitor mode first to verify everything is working and then pull the trigger and change it to the production and actually enforce the policy.

What We Need and What We Want

Cisco ISE deployment for wired. Default ACL on the ports and dACL after successful authentication.

The Goal – put everything in monitor mode, check that all devices are authenticated and verified. (like MAB-only devices are added to the ISE).

Once done – switch to production mode.

How? Just change network device type from monitor to production in ISE.

Brief summary

Switch setup

All ports are configured the same way (something like this):

interface gig 0/X 
 ip access-group ACL-ISE-DEFAULT in
 authentication periodic
 authentication timer reauthenticate server
 access-session port-control auto
 dot1x pae authenticator
 dot1x timeout tx-period 7
 dot1x max-reauth-req 3
 spanning-tree portfast edge
 service-policy type control subscriber DOT1X-DEFAULT

And ACL-ISE-DEFAULT access-list:

ip access-list extended ACL-ISE-DEFAULT
 remark Used for initial ACL on the interface prior to authentication
 permit udp any eq bootpc any eq bootps
 permit udp any any eq domain
 permit icmp any any
 permit udp any any eq tftp
 deny   ip any any

Once the device is authenticated, ISE pushes dACL which is just “permit ip any any“.

ISE Setup

ISE will have everything for two cases: monitor mode and production mode:

  • Network device types
  • dACLs
  • Authorization results
  • Policy sets

Network device types for Monitor and Production:

dACLs for Monitor and Production: (both are just “permit ip any any“). Note: the name is important, it will be used for verification:

Authorization profiles for Monitor and Production:




Policy sets for Monitor and Production. Both sets are identical with only difference in the Authorization rules:

deny access in production = fail in monitor mode

Authorization in Monitor mode:

Authorization in Production mode:

The intermediate result

We have with global and port configuration on the switches as it should be. The switch has monitor device type in ISE and ISE has the configuration for both monitor and production modes.

When unknown MAB-only device is trying to connect, it hits Default AuthZ rule in the Monitor Policy Sets and “PERMIT_ALL_TRAFFIC_FAIL” dACL is pushed:

switch#show authentication sessions mac 001f.9e25.1f8c
            Interface:  GigabitEthernet0/29
          MAC Address:  001f.9e25.1f8c
           IP Address:
            User-Name:  00-1F-9e-25-1F-8C
               Status:  Authz Success
               Domain:  DATA
      Security Policy:  Should Secure
      Security Status:  Unsecure
       Oper host mode:  multi-auth
     Oper control dir:  in
        Authorized By:  Authentication Server
          Vlan Policy:  N/A
              ACS ACL:  xACSACLx-IP-PERMIT_ALL_TRAFFIC_FAIL-5e389e86
      Session timeout:  N/A
         Idle timeout:  N/A
    Common Session ID:  07070707000003B2E1AF3CE6
      Acct Session ID:  0x0000046D
               Handle:  0xB60003B3

Runnable methods list:
       Method   State
       mab      Authc Success

What’s next?

We need to verify all authentication sessions, check why devices hit the policy which would deny access in production.

In the case of MAB-Only devices – add them to the specific group.

Python, it’s your turn.

Iโ€™ve created a script to check all authentication sessions on the switch and collect all sessions with FAIL in it. That’s why we need something different in ACL name. The script could be used also to check all authentication sessions and collect VLANs (if the result of the AuthZ rule is a VLAN change).

The process of how it works:

The link to GitHubย repo is here.

The breakdown – credentials, as usual:)

credentials = {
    'username': ['admin'],
    'password': ['admin'],
    'secret': ['admin'],
} โ€“ main script. Created class Device with different methods to init and close connection, collect_active_sessions – get all access-sessions and store mac addresses in the list, collect_active_sessions_details – collect details for each session. If there is FAIL in the output – collect:

  • interface
  • mac-address
  • method
  • status
  • user_name
  • vendor

Note: check which command should be used

  • show access-session mac<MAC-ADDRESS> detail
  • show authentication session mac <MAC-ADDRESS>

result.jsonโ€“ store results

{'001f.9e25.1f8c': {'interface': ' GigabitEthernet0/29',
                    'ip_address': '',
                    'mac_address': '001f.9e25.1f8c',
                    'method': 'mab',
                    'status': 'Authz Success',
                    'user_name': '00-1F-9E-25-1F-8C',
                    'vendor': 'Cisco Systems, Inc'},
 'b000.b4ba.24a0': {'interface': ' GigabitEthernet0/27',
                    'ip_address': '',
                    'mac_address': 'b000.b4ba.24a0',
                    'method': 'mab',
                    'status': 'Authz Success',
                    'user_name': 'B0-00-B4-BA-24-A0',
                    'vendor': 'Cisco Systems, Inc'}}

Of course, the script could be used for different cases if you need just to collect and store all active sessions or all sessions in a particular method/VLAN/interface.


You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *