11-14-2024 02:22 AM - edited 12-11-2024 02:05 AM
Hi community,
I was challenged to find out, which 802.1X supplications use legacy TLS versions (and ciphers) for TLS based EAP methods (like EAP-TLS or PEAP). Main motivation is to harden the ISE configuration by disabling legacy TLS versions and ciphers on the ISE side.
The main problem is, that there is no ISE builting report for this. The only known way (at least to my knowledge) using the GUI is the "Authentication detail report" as illustrated in the example below:
However, especially in large environments with lots of clients, it does not scale to check each Authentication detail report and write down the results.
As of ISE 3.4 there is no way to extract this information by ERS/OpenAPI, MNT-API, DataConnect, pxGrid or ISE Log Analytics. The only way to get this information besides the Authentication detail report are:
I want to show you, how I solved this task using Syslog:
Product | Version | Purpose |
ISE | 3.4 | Authentication server |
syslog-ng | 3.38.1 | Syslog receiver for data from ISE |
Python | 3.12 | Perform data analysis and report creation |
⚠ I guess there are other ways as well. For example using some kind of "clever" logging solution like an ELK stack or Splunk. But I don't have any of them at the moment.
The target syslog server, must be added to the ISE "Remote Logging Targets" configuration (Administration > System > Logging). However, there are some things to consider. Using the default values (Type UDP Syslog and the maximum length of 1024 Bytes), the analysis of the data may be pretty hard, because the desired Syslog messages are split into multiple syslog messages. This is because, one 802.1X "Passed Authentication" entry is bigger than 1024 Bytes.
Example:
Message 1 (truncated)
Nov 14 10:52:01 192.0.2.100 CISE_Passed_Authentications 0000000188 6 0 2024-11-14 10:52:01.536 +01:00 0000966111 5200 NOTICE Passed-Authentication: Authentication succeeded, ConfigVersionId=254, Device IP Address=172.16.50.17, DestinationIPAddress=192.0.2.100, DestinationPort=1812, UserName=myclient01.example.org, Protocol=Radius, NetworkDeviceName=mySwitch01, User-Name=myclient01, NAS-IP-Address=172.16.50.17, NAS-Port=50101, Service-Type=Framed, Framed-MTU=1468, Called-Station-ID=CC-7F-76-70-5D-81, Calling-Station-ID=00-50-56-A2-60-5E, NAS-Port-Type=Ethernet, NAS-Port-Id=Ethernet1/0/1, EAP-Key-Name=, cisco-av-pair=service-type=Framed,
Message 2 (truncated)
Nov 14 10:52:01 192.0.2.100 CISE_Passed_Authentications 0000000188 6 1 NetworkDeviceProfileName=Cisco, NetworkDeviceProfileId=cfa07202-702a-4f12-81f4-7471f217a627, IsThirdPartyDeviceFlow=false, RadiusFlowType=Wired802_1x, AuthenticationMethod=x509_PKI, SelectedAccessService=AUTH_DOT1X, SelectedAuthorizationProfiles=myProfile, RequestLatency=119, IdentityGroup=Endpoint Identity Groups:Generic, Step=11001, Step=11017, Step=15049, Step=15008, Step=15048, Step=11507, Step=12500, Step=12625, Step=11006, Step=11001, Step=11018, Step=12502, Step=12800, Step=12805, Step=12806, Step=12807, Step=12808, Step=12809, Step=12810, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12505, Step=11006, Step=11001,
Message 3 (truncated)
Nov 14 10:52:01 192.0.2.100 CISE_Passed_Authentications 0000000188 6 3 EapAuthentication=EAP-TLS, Serial Number=17 02 89 66 81 00 00 1E, Subject - Common Name=myclient01.example.org, Subject Alternative Name=myclient01.example.org EndPointMACAddress=00-50-56-A2-60-5E, PostureAssessmentStatus=NotApplicable, EndPointMatchedProfile=VMWare-Device, ISEPolicySetName=Dot1X Wired, IdentitySelectionMatchedRule=Default, StepData=4= DEVICE.Device Type, StepData=55=certificate for myclient01.example.org, StepData=56=certificate for myclient01.example.org, StepData=57=certificate for myclient01.example.org, StepData=58=External OCSP Server,
Message 4 (truncated)
Nov 14 10:52:01 192.0.2.100 CISE_Passed_Authentications 0000000188 6 4 StepData=59=certificate for myclient01.example.org, StepData=60=certificate for myclient01.example.org, StepData=61=certificate for myclient01.example.org, TotalAuthenLatency=163, ClientLatency=44, allowEasyWiredSession=false, TLSCipher=ECDHE-RSA-AES256-GCM-SHA384, TLSVersion=TLSv1.2, DTLSSupport=Unknown, Subject=CN=myclient01.example.org,
So, very crucial fields for some report creation are split into multiple syslog messages, which makes it hard to analyze the data. I don't say it's impossible, but you need to consider this.
The important fields for our report are:
My workaround for this is, to configure my ISE remote logging target as:
UDP would be possible as well, but this will result in IP fragmented Syslog packets. This is typically no problem (except for some firewalls and virtual reassembly). If using TCP, one syslog is transported in one TCP "stream".
Considering a typical "Passed authentication" syslog message with the size of ~7.000 Bytes. If you have a large deployment with lots of authentications per day, this could result in multiple GB of data per day.
If using a default syslog server configuration, the syslog message will be logged to the file system like:
Nov 14 10:54:01 192.0.2.100 CISE_Passed_Authentications 0000000188 6 0 2024-11-14 10:52:01.536 +01:00 0000966111 5200 NOTICE Passed-Authentication: Authentication succeeded, ConfigVersionId=254, Device IP Address=172.16.50.17, DestinationIPAddress=192.0.2.100, DestinationPort=1812, UserName=myclient01.example.org, Protocol=Radius, NetworkDeviceName=mySwitch01, User-Name=myclient01, NAS-IP-Address=172.16.50.17, NAS-Port=50101, Service-Type=Framed, Framed-MTU=1468, Called-Station-ID=CC-7F-76-70-5D-81, Calling-Station-ID=00-50-56-A2-60-5E, NAS-Port-Type=Ethernet, NAS-Port-Id=Ethernet1/0/1, EAP-Key-Name=, cisco-av-pair=service-type=Framed, NetworkDeviceProfileName=Cisco, NetworkDeviceProfileId=cfa07202-702a-4f12-81f4-7471f217a627, IsThirdPartyDeviceFlow=false, RadiusFlowType=Wired802_1x, AuthenticationMethod=x509_PKI, SelectedAccessService=AUTH_DOT1X, SelectedAuthorizationProfiles=myProfile, RequestLatency=119, IdentityGroup=Endpoint Identity Groups:Generic, Step=11001, Step=11017, Step=15049, Step=15008, Step=15048, Step=11507, Step=12500, Step=12625, Step=11006, Step=11001, Step=11018, Step=12502, Step=12800, Step=12805, Step=12806, Step=12807, Step=12808, Step=12809, Step=12810, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=12810, Step=12568, Step=12569, Step=12987, Step=12989, Step=12553, Step=12572, Step=12554, Step=12571, Step=12811, Step=12812, Step=12813, Step=12803, Step=12804, Step=12801, Step=12802, Step=12816, Step=12509, Step=12505, Step=11006, Step=11001, Step=11018, Step=12504, Step=61025, Step=15041, Step=22072, Step=22070, Step=22037, Step=12506, Step=24715, Step=15036, Step=24209, Step=24211, Step=15048, Step=15048, Step=15016, Step=22081, Step=22080, Step=11503, Step=11002, SelectedAuthenticationIdentityStores=Preloaded_Certificate_Profile, AuthenticationStatus=AuthenticationPassed, NetworkDeviceGroups=Location#All Locations#myLab, NetworkDeviceGroups=Device Type#All Device Types#Wired#Cisco#Switches#IOS-Gen, IdentityPolicyMatchedRule=Default, EapAuthentication=EAP-TLS, Serial Number=17 02 89 66 81 00 00 1E, Subject - Common Name=myclient01.example.org, Subject Alternative Name=myclient01.example.org EndPointMACAddress=00-50-56-A2-60-5E, PostureAssessmentStatus=NotApplicable, EndPointMatchedProfile=VMWare-Device, ISEPolicySetName=Dot1X Wired, IdentitySelectionMatchedRule=Default, StepData=4= DEVICE.Device Type, StepData=55=certificate for myclient01.example.org, StepData=56=certificate for myclient01.example.org, StepData=57=certificate for myclient01.example.org, StepData=58=External OCSP Server, StepData=59=certificate for myclient01.example.org, StepData=60=certificate for myclient01.example.org, StepData=61=certificate for myclient01.example.org, TotalAuthenLatency=163, ClientLatency=44, allowEasyWiredSession=false, TLSCipher=ECDHE-RSA-AES256-GCM-SHA384, TLSVersion=TLSv1.2, DTLSSupport=Unknown, Subject=CN=myclient01.example.org,.... },
So we need some kind of tool or script to extract the needed information and write a report. However, for our use case, the log message has some irrelevant information and consumes some amount of disk space. When parsing a file, containing logs of a week, your tool needs to process multiple GB of data, which will take some time.
I want to optimize this, by only storing data, which is relevant for my report and store it in a well-structured format for further processing. So this would be my desired target output data for the log message above:
{"_kv":{"UserName":"myclient01.example.org","NAS-Port-Type":"Ethernet","Called-Station-ID":"CC-7F-76-70-5D-81", "Calling-Station-ID":"02:11:22:33:44:55", "TLSVersion":"TLSv1.2","TLSCipher":"ECDHE-RSA-AES256-GCM-SHA384","NAS-Port-Type":"Wireless - IEEE 802.11","EapAuthentication":"EAP-TLS"}}
In the example above, the log entry is encoded as JSON, with only the relevant fields. This makes analysis more lightweight later on.
The required syslog-ng configuration file for this would be:
########################
# Sources
########################
source s_net_tcp {
network();
};
########################
# Destinations
########################
destination d_ise_passed_auth_json {
file("/var/log/ise/passed_auth.json"
template("$(format-json \
--key .kv.UserName \
--key .kv.TLSVersion \
--key .kv.TLSCipher \
--key .kv.Called-Station-ID \
--key .kv.Calling-Station-ID \
--key .kv.NAS-Port-Type \
--key .kv.EapTunnel \
--key .kv.EapAuthentication \
--key .kv.AD-User-SamAccount-Name \
)\n"));
};
########################
# Filters
########################
filter f_ise_passed_auth {
match("CISE_Passed_Authentications" template("${MSGHDR}"))
};
########################
# Parsers
########################
parser p_ise_kv {
kv-parser(prefix(".kv."));
};
########################
# Log paths
########################
log { sourc