A Practical Guide to Deploying SAML for AnyConnect

With the shift of employees working from home and increased mobility, the demand on companies’ remote-access (RA) VPN capabilities has grown at an alarming rate. At the onset of the COVID-19 pandemic, companies needed to rapidly adapt their RA VPN deployments to account for a sharp increase in users. Purchasing additional licensing, deploying additional firewalls to handle the increased load, configuring VPN policies for new user groups, and onboarding new user accounts all had to happen very quickly.

With this increased reliance on RA VPNs also came increased risk as hackers target these critical systems. New VPN vulnerabilities were identified and had to be remediated. In addition to the technical risks of these vulnerabilities, individual users could also be targeted, which could lead to compromised credentials. Companies that had not already configured multifactor authentication (MFA) thus began exploring the options available to them.

This guide looks at one solution: deploying Security Assertion Markup Language (SAML) with Cisco AnyConnect on a Cisco Adaptive Security Appliance (ASA) firewall. The benefits of SAML and other MFA options supporting Single Sign-On (SSO) include:

  • A centralized location for a user to manage their credentials across multiple applications
  • A similar user login experience across multiple applications
  • Increased security and compliance
  • Lower administrative burden to the IT organization

Authentication vs. Authorization

There are various guides for configuring SAML for AnyConnect with an Identity Provider (IdP) like Azure, Okta, Duo and others. What we have found with these guides is that they highlight the necessary components for authentication, but not authorization. If you have multiple group-policies configured with AnyConnect, it is not clearly defined in these guides how to direct users to their appropriate group-policy. Instead, the guides default to all authenticated users receiving the same group-policy.

Why is additional authorization important? Your remote-access group-policies are what restrict users to specific resources behind the VPN, identify various timeout values, how many logins are permitted per user, the VPN networks they receive, and other security mechanisms. Certain user groups like vendors or partners may require more restricted access than your employees. Within this guide you will be shown one method of providing additional authorization using an internal LDAP server and the use of groups to identify their corresponding group-policy.

Guide Prerequisites

This guide has the following prerequisites:

  • You are running Cisco ASA version 9.8 or later (all commands and output in this guide are from 9.12(2))
  • You are running a Cisco AnyConnect client version that supports SAML
  • You have a working Cisco AnyConnect configuration using an authentication mechanism other than SAML
  • You have access to an IdP that uses SAML like Azure, Okta, Duo or some other service
  • The IdP should be configured to send a login name that will be recognized by your LDAP servers (most authentication servers send the username users log in to the service with (commonly their email address), whereas many LDAP servers may require the userPrincipleName or sAMAccountName)

Note: This guide is not intended to serve as a security best practices guide for configuring Cisco AnyConnect. You are responsible for identifying your security requirements and ensuring that your configuration meets those requirements.

Implementation Guide

You will need to review the documentation for your IdP and adjust these steps appropriately. These steps are based on an example scenario of needing separate policies for two groups (employees and vendors). This helps illustrate how to implement authorization to provide different security policies for each user group.

  1. To begin, log in to your Cisco ASA firewall using SSH and access the configuration mode.
HQ-Firewall# configure terminal

HQ-Firewall(config)#
  1. Import your IdP signing certificate into a new trustpoint. This should be available within the dashboard of your IdP.
      1. Configure the trustpoint enrollment.
HQ-Firewall(config)# crypto ca trustpoint SAML-IdP-TP

HQ-Firewall(config-ca-trustpoint)# enrollment terminal

HQ-Firewall(config-ca-trustpoint)# no ca-check

HQ-Firewall(config-ca-trustpoint)# exit
      1. Obtain the Base64 encoded certificate from your IdP dashboard and authenticate it on the Cisco ASA. Note that when using Azure as an IdP you may need to first create the tunnel-group (shown later in this guide) as Azure will require the case-sensitive tunnel-group name before providing the Base64 encoded CA certificate.
HQ-Firewall(config)# crypto ca authenticate SAML-IdP-TP

Enter the base 64 encoded CA certificate.

End with the word "quit" on a line by itself

<<Base64 Encoded CA Certificate>>

quit


INFO: Certificate has the following attributes:

Fingerprint:     0e3f2808 afcc9758 049dca03 7e07a059

Do you accept this certificate? [yes/no]: yes


Trustpoint CA certificate accepted.


% Certificate successfully imported

HQ-Firewall(config)#
  1. Add your SAML IdP to your webvpn configuration.
      1. Enter webvpn configuration mode.
HQ-Firewall(config)# webvpn
      1. Configure a new SAML IdP using the URL provided by your IdP.
HQ-Firewall(config-webvpn)# saml idp http://www.example.com/your/saml/app/url
      1. Configure the Sign-in and Sign-out URL of your IdP. These URLs will be provided by your IdP.
HQ-Firewall(config-webvpn-saml-idp)# url sign-in https://www.example.com/your/sign-in-url

HQ-Firewall(config-webvpn-saml-idp)# url sign-out https://www.example.com/your/sign-out-url
      1. Set the base-URL of your Cisco ASA. This would be the URL that users enter in the AnyConnect client application.
HQ-Firewall(config-webvpn-saml-idp)# base-url https://vpn.yourcompany.com
      1. Associate the IdP trustpoint created in earlier steps and your existing AnyConnect trustpoint (SP trustpoint) that you should already have configured as part of the prerequisites.

HQ-Firewall(config-webvpn-saml-idp)# trustpoint idp SAML-IdP-TP

HQ-Firewall(config-webvpn-saml-idp)# trustpoint sp YOUR-ANYCONNECT-TP

      1. Enable signing of SAML requests. This defaults to sha256, so you may need to validate with your IdP which of the available methods should be used.
HQ-Firewall(config-webvpn-saml-idp)# signature
      1. Optional: Set the timeout of the assertion in the SAML request. This overrides the NotOnOrAfter value in the assertion if the sum of NotBefore and the timeout (in seconds) is less than NotOnOrAfter. This helps further restrict how long a user’s assertion is valid for, but you must ensure that NTP is properly set up on your Cisco ASA and in sync to avoid time drift issues. If you do not configure this, the NotOnOrAfter value configured in your IdP will control this function.
HQ-Firewall(config-webvpn-saml-idp)# timeout assertion 300
      1. Optional: Enable reauthentication. This forces the IdP to reauthenticate a user, even if they were already signed in to the IdP prior to using the AnyConnect application.
HQ-Firewall(config-webvpn-saml-idp)# force re-authentication
  1. Configure a default group-policy that provides no access.
HQ-Firewall(config)# group-policy NO-ACCESS-GP internal

HQ-Firewall(config)# group-policy NO-ACCESS-GP attributes

HQ-Firewall(config-group-policy)# vpn-simultaneous-logins 0

HQ-Firewall(config-group-policy)# vpn-tunnel-protocol ssl-client
  1. Configure a tunnel-group for your SAML IdP.
      1. Enable the tunnel group-list to be visible in the AnyConnect client. This will allow various user groups to select a group-alias relating to their group. See Additional Notes for further details.
HQ-Firewall(config)# webvpn

HQ-Firewall(config-webvpn)# tunnel-group-list enable
      1. Configure a new tunnel-group for remote-access.
HQ-Firewall(config)# tunnel-group SAML-IdP-TG type remote-access

HQ-Firewall(config)# tunnel-group SAML-IdP-TG webvpn-attributes
      1. Set the authentication method to SAML and associate your IdP (using the URL of the SAML IdP configured earlier).
HQ-Firewall(config-tunnel-webvpn)# authentication saml

HQ-Firewall(config-tunnel-webvpn)# saml identity-provider http://www.example.com/your/saml/app/url
      1. Configure the two group-aliases relating to the example user groups.
HQ-Firewall(config-tunnel-webvpn)# group-alias Employee enable

HQ-Firewall(config-tunnel-webvpn)# group-alias Vendor enable
      1. Associate the previously created no access group-policy with the tunnel-group. This ensures that even though a user may be associated with a particular IdP application/service, they will only obtain access to the VPN if authorized (which will be configured in subsequent steps).
HQ-Firewall(config)# tunnel-group SAML-IdP-TG general-attributes

HQ-Firewall(config-tunnel-general)# default-group-policy NO-ACCESS-GP
  1. At this point in time, some IdPs will either require your case-sensitive tunnel-group name (SAML-IdP-TG in this example) or the entityID value from SAML metadata from your Cisco ASA. Refer to your IdP documentation to identify which value they require. You can obtain the entityID from the XML metadata given by the following command, otherwise you already know the tunnel-group name:
HQ-Firewall# show saml metadata SAML-IdP-TG
  1. Configure an LDAP attribute-map. You will need the specific paths for each LDAP group and there should be a one-to-one mapping between LDAP groups and Cisco ASA group-policies. Note that the EMPLOYEE-VPN-GP and VENDOR-VPN-GP with the AnyConnect group-policies you already have configured for these user groups as part of the prerequisites.
HQ-Firewall(config)# ldap attribute-map VPN-AUTHZ-AM

HQ-Firewall(config-ldap-attribute-map)# map-name  memberOf IETF-Radius-Class

HQ-Firewall(config-ldap-attribute-map)# map-value memberOf "CN=VPN_Access,OU=Employees,DC=mycompany,DC=com" EMPLOYEE-VPN-GP

HQ-Firewall(config-ldap-attribute-map)# map-value memberOf "CN=VPN_Access,OU=Vendors,DC=mycompany,DC=com" VENDOR-VPN-GP
  1. Configure AAA server settings to authorize users.
      1. Configure the AAA server. Adjust the interface, IP address and LDAP settings according to your implementation. It is recommended to configure two or more redundant LDAP servers.
HQ-Firewall(config)# aaa-server VPN-AUTHZ-AAA protocol ldap

HQ-Firewall(config)# aaa-server VPN-AUTHZ-AAA (inside) host 10.1.1.1

HQ-Firewall(config-aaa-server-host)# ldap-base-dn dc=mycompany,dc=com

HQ-Firewall(config-aaa-server-host)# ldap-group-base-dn dc=mycompany,dc=com

HQ-Firewall(config-aaa-server-host)# ldap-scope subtree

HQ-Firewall(config-aaa-server-host)# ldap-naming-attribute userPrincipleName

HQ-Firewall(config-aaa-server-host)# ldap-login-password YourSecurePassword

HQ-Firewall(config-aaa-server-host)# ldap-login-dn cn=YourServiceAccount,ou=ServiceAccounts,dc=mycompany,dc=com

HQ-Firewall(config-aaa-server-host)# ldap-over-ssl enable

HQ-Firewall(config-aaa-server-host)# server-type microsoft
      1. Associate the previously created LDAP attribute-map with each AAA-server configuration.
HQ-Firewall(config)# aaa-server VPN-AUTHZ-AAA (inside) host 10.1.1.1

HQ-Firewall(config-aaa-server-host)# ldap-attribute-map VPN-AUTHZ-AM
      1. Test that the remote LDAP server can be reached and that it can properly authorize a user from the firewall CLI. This confirms that your AAA server is reachable and configuration is correct if you see ‘Authorization Successful’.
HQ-Firewall# test aaa-server authorization VPN-AUTHZ-AAA username YourTestUser

Server IP Address or name: 10.1.1.1

INFO: Attempting Authorization test to IP address (10.1.1.1) (timeout: 12 seconds)

INFO: Authorization Successful
  1. You now have all the necessary components to associate the authorization server-group with the tunnel-group.
HQ-Firewall(config)# tunnel-group SAML-IdP-TG general-attributes

HQ-Firewall(config-tunnel-general)# authorization-server-group VPN-AUTHZ-AAA
  1. You are now set up to authorize users to groups related to their account, assigning them group-specific security policies!

Verification and Troubleshooting

To verify that a user is associated with the correct tunnel-group and group-policy, you can use the following command:

HQ-Firewall# show vpn-sessiondb anyconnect filter name YourTestUser


Session Type: AnyConnect

Username     : YourTestUser      Index        : 11789

Assigned IP  : 10.2.1.202           Public IP    : ##############

Protocol     : AnyConnect-Parent SSL-Tunnel DTLS-Tunnel

License      : AnyConnect Premium

Encryption   : AnyConnect-Parent: (1)none  SSL-Tunnel: (1)AES-GCM-256  DTLS-Tunnel: (1)AES-GCM-256

Hashing      : AnyConnect-Parent: (1)none  SSL-Tunnel: (1)SHA384  DTLS-Tunnel: (1)SHA384

Bytes Tx     : 51595857               Bytes Rx     : 59730082

Group Policy : EMPLOYEE-VPN-GP               Tunnel Group : SAML-IdP-TG

Login Time   : 10:11:12 EDT Tue Jun 15 2021

Duration     : 0d 3h:11m:20s

Inactivity   : 0h:00m:00s

VLAN Mapping : N/A                    VLAN         : none

Audt Sess ID : 0a459fe39234449d923444

Security Grp : none

If your user is successfully being authenticated by your IdP but immediately being disconnected from AnyConnect after authentication, it indicates that they are not being authorized properly. This could be the result of a few issues, including:

  • Your authorization servers are not reachable from the Cisco ASA. Confirm their reachability with the “test aaa” command:
test aaa-server authorization VPN-AUTHZ-AAA username YourTestUser
  • The IdP is not sending a login name that your LDAP servers accept. Depending on your logging level you can have the user test logging in to the RA VPN from their AnyConnect client and viewing the logs, or enable the necessary AAA authentication debugs (CAUTION: enabling debugs can adversely affect the performance of your firewall).
    • Use the following filter when viewing local logs:
show logging | inc ASA-6-1130
    • You should see various logs relating to AAA authorization and look for a username that relates to your test user along with authorization failed messages.
    • If necessary, enable AAA authorization debugs to troubleshoot further.
debug aaa authorization
  • The user is not associated with the correct LDAP group.
    • Use the following filter when viewing local logs:
show logging | inc ASA-7-734003
    • You should see various logs relating to aaa.ldap.memberOf. If you don’t see a memberOf relating to the LDAP group configured in your LDAP attribute-map, you will need to investigate further if your firewall is configured with the wrong group or the user was not correctly associated with the group on your LDAP server.
Jun 16 2021 13:34:27 HQ-Firewall : %ASA-7-734003: DAP: User YourTestUser, Addr 70.72.200.73: Session Attribute aaa.ldap.memberOf.1 = AppXAccess

Jun 16 2021 13:34:27 HQ-Firewall : %ASA-7-734003: DAP: User YourTestUser, Addr 70.72.200.73: Session Attribute aaa.ldap.memberOf.2 = VPN_Access

Jun 16 2021 13:34:27 HQ-Firewall : %ASA-7-734003: DAP: User YourTestUser, Addr 70.72.200.73: Session Attribute aaa.ldap.memberOf.3 = MarketingTeam
    • If necessary, enable AAA authorization debugs to troubleshoot further.
debug aaa authorization

Additional Notes

The tunnel-group configured in our example has multiple group-aliases associated with it. This allows for you to provide a better user experience by making a recognizable name for each of your user groups. However, this can create a perception problem, as it allows a user in group Y to select group X’s group-alias and successfully be authorized when both group-aliases are associated with the same tunnel-group. Although they will still only be authorized as a group Y user (and still get the appropriate security policies), it can cause some confusion. The benefit is that, in the future, if you need to change how a particular user group is authenticated or authorized, you can create a new tunnel-group for that group and move their existing group-alias to it. This requires no change in user behavior, as they still select the same alias from the drop-down in the AnyConnect client, allowing the administrator greater flexibility if changes are required in the future.

The username passed by the IdP needs to be the username that LDAP can look up and must also relate to the ldap-naming-attribute configured under the AAA server configuration. This is commonly the userPrincipleName or sAMAccountName. You will need to review your IdP documentation to see which value they can pass and which will be recognizable by your internal LDAP server.

When associating users with VPN related groups in LDAP, it is important to ensure that they are only associated with a single LDAP group in the LDAP attribute-map. If a user is associated with multiple groups, it can be unpredictable which group-policy the LDAP attribute-map will assign them to on the Cisco ASA.

Success stories

A LEADING PAYMENT SERVICE PROVIDER

“The Optanix single unified platform replaced multiple point tools, reducing the TCO.”