10.14. Security AuditingI will end this chapter with presenting a useful feature WCF supports called security audits. As the name implies, a security audit is a logbook of the security-related events in your services. WCF can log authentication and authorization attempts, their time and location, and the client's identity. The class ServiceSecurityAuditBehavior governs auditing and is listed in Example 10-30 along with its supporting enumerations. Example 10-30. The ServiceSecurityAuditBehavior class
ServiceSecurityAuditBehavior is a service behavior. The AuditLogLocation property specifies where to store the log entries, in the application logfile or in the security log, both in the event log on the host computer. The MessageAuthenticationAuditLevel property governs the authentication audit verbosity. For performance's sake, you may want to audit only failures, or both success and failures. For diagnostic purposes you can also audit successful authentication. The default value of MessageAuthenticationAuditLevel is AuditLevel.None. Similarly, you use the ServiceAuthorizationAuditLevel property to control authorization audit verbosity, and it is also disabled by default. 10.14.1. Configuring Security AuditsThe typical way of enabling a security audit is in the host config file, by adding a custom behavior section and referencing it at the service declaration, as shown in Example 10-31. Example 10-31. Configuring a security audit
You can also configure security auditing programmatically by adding the behavior at runtime to the host before opening it. Similar to adding other behaviors programmatically, you can check that the host does not already have an audit behavior, to avoid overriding the config file, as shown in Example 10-32. Example 10-32. Enabling a security audit programmatically
You can streamline the code in Example 10-32 by adding the SecurityAuditEnabled Boolean property to ServiceHost<T>: public class ServiceHost<T> : ServiceHost { public bool SecurityAuditEnabled {get;set;} //More members } Using ServiceHost<T>, Example 10-32 is reduced to: ServiceHost<MyService> host = new ServiceHost<MyService>( ); host.SecurityAuditEnabled = true; host.Open( ); Example 10-33 shows the implementation of the SecurityAuditEnabled property. Example 10-33. Implementing the SecurityAuditEnabled property
In the get, the SecurityAuditEnabled property accesses the description of the service and looks for an instance of ServiceSecurityAuditBehavior. If one is found, and if both the authentication and the authorization audits are set to AuditLevel.SuccessOrFailure, then SecurityAuditEnabled returns TRue, and false otherwise. In the set, the property enables the security audit only if the description does not contain a previous value as a result of a config file. If no prior behavior is found, SecurityAuditEnabled sets both the authentication and authorization audits to AuditLevel.SuccessOrFailure. 10.14.2. Declarative Security AuditYou can also write an attribute that surfaces the security audit options at the service level. I chose to add that support in the form of a single Boolean property on the SecurityBehavior attribute called SecurityAuditEnabled: [AttributeUsage(AttributeTargets.Class)] public class SecurityBehaviorAttribute : Attribute,IServiceBehavior { public bool SecurityAuditEnabled {get;set;} //More members } The default of SecurityAuditEnabled is falseno security audit. Using the property complements the rest of the declarative security model; for example: [SecurityBehavior(ServiceSecurity.Internet,UseAspNetProviders = true, SecurityAuditEnabled = true)] class MyService : IMyContract {...} Example 10-34 shows how that support was added to the SecurityBehavior attribute. Example 10-34. Implementing a declarative security audit
The Validate( ) method of IServiceBehavior enables auditing using the same verbosity level as ServiceHost<T>, while avoiding overriding the config file. |