Adding arbitrary attributes to the audit log
It can be useful to have a point-in-time record of specific attributes, particularly generated attributes, for audit purposes. The Shibboleth Identity Provider (IdP) audit log provides an appropriate location and is probably already being centrally monitored for other purposes.
This example shows how to add the eduPersonTargetedId
attribute as an extra field to the Shibboleth Identity Provider's audit log (idp-audit.xml
). This could also be used for other attributes such as pairwise-id
.
Assumptions
Your audit log configuration is unchanged from a v4.0 installation and your attribute resolver generates an attribute named eduPersonTargetedId
such as:
<AttributeDefinition id="eduPersonTargetedId" xsi:type="SAML2NameID"
nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
<InputDataConnector attributeNames="computedId" ref="computed"/>
<AttributeEncoder xsi:type="SAML1XMLObject"
name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
<AttributeEncoder xsi:type="SAML2XMLObject"
name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"
friendlyName="eduPersonTargetedId"/>
</AttributeDefinition>
Implementation
Create a new bean to make arbitrary attributes available
In conf/audit.xml
, add the following <beans>
(at the end, before the closing </beans>
). This script, based on the examples in AuditLoggingConfiguration, takes a single or multi-valued attribute generated by the resolver and returns it to a calling bean. If the attribute is multi-valued then it delimits the values with a comma (,
) in the same way as Perl's join(',', @list)
.
<bean id="AttributeValueExtraction"
parent="shibboleth.ContextFunctions.Scripted"
factory-method="inlineScript"
abstract="true">
<constructor-arg>
<value>
<![CDATA[
var getinfo = function() {
var rpContext = input.getSubcontext("net.shibboleth.idp.profile.context.RelyingPartyContext");
if (null === rpContext) {
return null;
}
var attrContext = rpContext.getSubcontext("net.shibboleth.idp.attribute.context.AttributeContext");
if (null === attrContext) {
return null;
}
var attributes = null
attributes = attrContext.getUnfilteredIdPAttributes();
if (null === attributes) {
return null;
}
attribute = attributes.get(custom);
if (null === attribute || attribute.getValues().isEmpty()) {
return null;
}
var iter = attribute.getValues().iterator();
var result = "";
while (iter.hasNext()) {
if(!result.equals("")) result = result + ",";
result = result + iter.next().getDisplayValue();
}
return result;
}
getinfo();
]]>
</value>
</constructor-arg>
</bean>
Create a sub-bean for the specific attribute required
After the AttributeValueExtraction
bean, add:
<bean id="audit-eduPersonTargetedId"
parent="AttributeValueExtraction"
p:customObject="eduPersonTargetedId" />
You can create multiple audit-...
beans if you require multiple attributes to be made available in the audit log.
Create the audit log value
After the audit-eduPersonTargetedID
bean, add:
This creates a new substitution value %eduPersonTargetedID
based on the value returned from audit-eduPersonTargetedID
.
Update the Audit log template to include the new value
In conf/audit.xml
, find <util:map id="shibboleth.AuditFormattingMap">
which may look like:
Add the new attribute (%eduPersonTargetedID
)to the end of the template:
and restart the IdP.