WCF Security: WCF Performance & ProtectionLevel - Part 2
<p>
In the <a href="http://adilakhter.wordpress.com/2009/08/06/wcf-security-wcf-performance-protectionlevel-part-1/">previous post</a>, we have stated the several problems not being able to configure <code>ProtectionLevel</code> for different endpoint declaratively using configuration files. In this post, we address this issue and thereby, describe how to specify <code>ProtectionLevel</code> for multiple endpoints of a service using <code>.config</code> file.
</p>
<p>
<strong>Outline</strong>. In this post, we start by stating motivation of specifing <code>ProtectionLevel</code> for multiple endpoints of a service <span id="dottedDiv">declaritvely</span> instead of programmatically. Then, we discuss the steps to achieve it.
</p>
<h1 align="center">Motivation: ProtectionLevel for Multiple Endpoints </h1>
<p>
Basically, <code>ProtectionLevel</code> enforces a security requirement on request and response messages in the channel, and all the consumer of the message must conform to that requirement; anything otherwise results in runtime exception. In the last post, we have described how to configure <code>ProtectionLevel</code> at different level of WCF messaging stack and observed that it can only be set programmatically in the contract of a WCF service, which unfortunately has impacts on <span id="dottedDiv">all the preconfigured bindings</span>.
</p>
<p>
For instance, consider that we would like to have two different endpoints to use different <code>ProtectionLevel</code>. In addition, we want to make it configurable so that we can the security behavior of the endpoint conveniently after it has been deployed.
</p>
<p><span id="dottedDiv">Are these requirements practical?</span> To answer that, consider following case: we have only one endpoint and we are using message level security with <code>wsHttpBinding</code> (or <code>ws2007httpbinding</code> preferable one for internet based WCF Service). For internet users consuming this service, we are using <code>ProtectionLevel.EncryptAndSign</code> because of the security requirement imposed for our application. However, in case of local intranet, we don't want to take the overhead of
ProtectionLevel.EncryptAndSign rather would like to use ProtectionLevel.Sign to make the service a bit more responsive and efficient by getting rid of the overhead of encryption of requests and responses. Most importantly, we don't need ProtectionLevel.EncryptAndSign for the messages in this context as per security policy. Out of the box, there is no features available that can enable the use of different ProtectionLevel in these cases.
<p> Obviously, there is one naive approach to host to service twice by compiling the code in 2 different <code>ProtectionLevel</code>. At 1 to 10 scale, how would you rate this solution ? Ok , then let's move on…</p>
<p>
<img alt src="http://blog.adilakhter.com/wp-content/uploads/2009/08/080609_1814_wcfsecurity12.png"></p>
<p>
Thus, what we need is to make two different endpoints to work with different <code>ProtectionLevel</code>, and using <span id="dottedDiv">custom endpoint behavior</span>, it can be achieved. Thus, the internet users will be able to use the <code>wsHttpBinding</code> with default <code>ProtectionLevel</code>, while the intranet users use the less secure-- <code>ProtectionLevel.Sign</code>. The next section shows how to achieve this.
</p>
<p>
<img alt src="http://blog.adilakhter.com/wp-content/uploads/2009/08/080609_1814_wcfsecurity22.png"><span style="font-family:Arial;font-size:10pt;">
</span></p>
<h1 align="center">ProtectionLevel Configuration via Custom Endpoint Behavior</h1>
<p>
To do this, we have following these steps.First we have to create a Custom EndpointBehavior by implementing <code>IEndpointBehavior</code> as below –
</p>
[gist]5057151[/gist]
<p>
Then, we create a <code>BehaviorElement</code> by extending <code>BehaviorExtensionElement</code> to make the behavior configurable through config file.
</p>
[gist]5057168[/gist]
<p> Thus the coding part this done. Let's start configuring. To do so, first thing that needs to be done is to add a <code>behaviorExtensions</code> inside <code>system.serviceModel>behaviorExtensions</code> specifying the newly created custom Endpoint behavior :
</p>
[gist]5057176[/gist]
<p>Then, we create a endpoint behavior like below: </p>
[gist]5057185[/gist]
<p>Now, if we need to use a similar <code>ProtectionLevel</code> that we configured at the previous step in any endpoint , we simply need to add it as <code>behaviorConfiguration</code>, and we are done. </p>
[gist]5057201[/gist]
<h2 align="center">More on MessageSecurityBehavior</h2>
<p>
So far, we have described how to configure <code>ProtectionLevel</code> at runtime. Next we explain <code>MessageSecurityBehavior</code>. By changing the <code>ChannelProtectionRequirement</code> of an Endpoint, the new custom behavior impacts requests and responses of the channel. Moreover, the contract also binds to the configured <code>ProtectionLevel</code>. Then, the two different <code>MessagePartSpecification</code> was created, where 1<sup>st</sup> one is an empty <code>MessagePartSpecification</code>, and 2<sup>nd</sup> one refers to the <code>MessagePartSpecification</code> which contains body.
</p>
<p><img alt src="http://blog.adilakhter.com/wp-content/uploads/2009/08/080609_1814_wcfsecurity3.png"></p>
<p>
Depending of different value <code>ProtectionLevel</code>, the <code>MessagePartSpecification</code> are set to <code>ChannelProtectionRequirements</code>.
</p>
<p><img alt src="http://blog.adilakhter.com/wp-content/uploads/2009/08/080609_1814_wcfsecurity4.png"></p>
<p>
For instance, in case <code>ProtectionLevel.Sign</code>, in <code>OutgoingSignatureParts</code> and <code>IncomingSignatureParts</code> of <code>ChannelProtectionRequirements</code> <code>MessagePartSpecification</code> that included Body is being added to be signed from client to the server and again back to client from server. However, in this case , encryption is not needed, so in <code>OutgoingEncryptionParts</code> and <code>IncomingEncryptionParts </code>, empty <code>MessagePartSpecification</code> is added, and that results in unencrypted messages.
</p>
<h1 align="center">Conclusion</h1>
In this post, we show how to declaritively specify the <code>ProtectionLevel</code> for multiple endpoints exposed by a WCF service. Though it's not difficult to update the <code>ProtectionLevel</code> at runtime, we must note that client and server always conform to the <code>ProtectionLevel</code> requirement, and as a consequence, updating the <code>ProtectionLevel</code> at runtime might results in updating the clients configuration/code.
<h1 align="center">Additional Links</h1>
<ol>
<li> WCF Security: WCF Performance & ProtectionLevel – Part 1 : <a href="http://adilakhter.wordpress.com/2009/08/06/wcf-security-wcf-performance-protectionlevel-part-1/">http://adilakhter.wordpress.com/2009/08/06/wcf-security-wcf-performance-protectionlevel-part-1/</a>
</li>
<li> Custom WCF Behaviors through App.Config :<a href="http://winterdom.com/2006/10/customwcfbehaviorsthroughappconfig">http://winterdom.com/2006/10/customwcfbehaviorsthroughappconfig</a>
</li>
<li>Configuring ProtectionLevel : <a href="http://blogs.msdn.com/drnick/archive/2008/03/10/configuring-protection-level.aspx">http://blogs.msdn.com/drnick/archive/2008/03/10/configuring-protection-level.aspx</a>
</li>
<li>Fundamentals of WCF Security : <a href="http://www.code-magazine.com/article.aspx?quickid=0611051">http://www.code-magazine.com/article.aspx?quickid=0611051</a></li>
</ol>
Comments ()