Pretty printing Shibboleth logs
Figuring out problems with Shibboleth can be a daunting task, especially since logs contain many empty fields and it can be hard to tell them apart.
The Python script below reads a Shibboleth log file from standard input and prints every field on its own line.
#
# Set FORMAT to the value specified in shibboleth2.xml
#
# Usage:
# tail -f /var/log/shibboleth/transaction.log | python3 parselog.py
#
import fileinput
FORMAT="%u|%s|%IDP|%i|%ac|%t|%attr|%n|%b|%E|%S|%SS|%L|%UA|%a"
NAMES = {
"E": "Exception type",
"S": "Protocol status code",
"SS": "Protocol sub-status code",
"s": "Session id",
"a": "Client address",
"UA": "Client User-Agent",
"SP": "SP entityID",
"IDP": "IdP entityID",
"b": "Identity protocol binding",
"n": "Subject identifier of user",
"u": "REMOTE_USER",
"i": "Assertion id",
"t": "Authentication timestamp",
"ac": "SAML authentication context",
"L": "Logout result"
}
def lmap(f, l):
return list(map(f, l))
def lzip(a, b):
return list(zip(a, b))
def mapFn(x):
field = x[1:]
if field in NAMES:
return NAMES[field]
return field
fields = lmap(mapFn, FORMAT.split('|'))
fields.insert(0, 'Timestamp')
fields.insert(1, 'Transaction type')
for line in fileinput.input():
print("")
for name, value in lzip(fields, line.split('|')):
print(f"{name:30}: {value}")