Suppressing Personal Identifiable Information (PII) in WCF log files

Given the vast amount of information transported between systems in today's enterprise environments, a lot of which is considered either private (addresses, social security numbers, credit card information, mortgage and pension plans, etc) or of high business value, information security is key.

From the release of WCF, it has brought us tremendous flexibility and allowed development teams to be almost completely agnostic of the way information is transported between point A to point B, focusing on adding business value instead.

Another great feature WCF brings us is runtime troubleshooting. In WCF, an administrator can simply enable logging to troubleshoot an environment which is in production.

Although a great feature for troubleshooting, Personal Identifiable Information (PII) you care about deeply while on the wire (using transport and message-level security to protect it) is available in plain text if logging is turned on at the server side.

WCF's logging features currently filter out specific PII by default (only if the message is not malformed). However, this functionality is not exposed to the developer.

Consider the following scenario:

  • You want the administrator to be able to monitor messages for auditing, logging or troubleshooting purposes;
  • certain information is considered PII and should not show up in the log files.

You could write your own logging subsystem and hook it in to your services. This takes a lot of work, is error prone, needs custom maintenance, documentation, etc.

My proposal for the scenario:

  • Use a behavior which
    • introspects the published ServiceEndPoints for published OperationDescriptions and the used DataContracts,
    • finds public properties on the DataContract marked as PII;
    • instructs the WCF logging runtime to ignore the contents of the specified message elements.
  • configure the behavior through code (this is not generally considered a best practice, but the security needs of the service outweighs the flexibility needs of configuration);

Let's have a look at how the solution works:

Take a DataContract, e.g. PurchaseOrder and apply an attribute (PII) on each property which represents PII.

wcf_pii_datacontract

Next, add a PIIProtectionBehavior attribute to your service implementation class

wcf_pii_protectionbehavior_attribute

You're done. The PIIProtectionBehavior attribute is also an IServiceBehavior implementation which performs the introspection on the EndPoints.

The result when logging is turned on:

wcf_pii_messagelogging

As you can see, 'CreditCardnumber' is no longer logged, it just displays '<-- Removed -->' .

I've attached the sample code, hope it's useful!

Ofcourse, the normal disclaimers apply, the accompanied sample is for educational purposes only, it has not gone through rigorous testing, might contain bugs due to limited testing (me ;-)), etc. Please see the sourcecode for further remarks.

PurchaseManagement.zip