Summary: OK – I got this working – but you may not like the solution.
So it still bugs me that WCF won’t directly support partial trust in V1. This means that it is much harder for partially trusted ASP.NET applications to host or use WCF services (same applies of course to all WCF clients like ClickOnce applications).
Today I decided to give it a go and find out how hard it really is. Here is what happened.
<sidebar>
If you want to call something from partial trust which does not allow partially trusted callers, you have to wrap it in/assert full trust (keep that in mind – we will need this later on) – or as my good friend Marcus would say: “the devil is in the detail” :)
</sidebar>
OK – so after you have a working client/service in full trust, these are the necessary steps:
- Move the WCF proxy to a separate assembly.
- Give that assembly a strong name.
- To be able to call the proxy from partial trust, you have to add a [assembly: AllowPartiallyTrustedCallers] attribute to the proxy assembly.
- Assert full trust in the proxy. The easiest way to do this is by adding an attribute on top of the proxy class.
[SecurityPermission(SecurityAction.Assert, Unrestricted=true)]
public class Proxy
{
…
}
-
Create a new policy file. It is recommended to use the medium trust policy as a starting point. You can find the policy files in the framework configuration directory. The medium trust policy is called ‘web_mediumtrust.config’
- You have to add a new code group for your proxy assembly to the policy file granting full trust. This code group should go directly under the ‘AllCode’ grop. Use a StrongNameMembershipCondition to identify the proxy (you get strong names in the right format from secutil.exe with the -hex and -s option).
<CodeGroup
class=“UnionCodeGroup“
version=“1“
PermissionSetName=“FullTrust“>
<IMembershipCondition
class=“StrongNameMembershipCondition“
version=“1“
PublicKeyBlob=“00..C9“ />
</CodeGroup>
-
Add a new trust level to global web.config that points to your policy file
<securityPolicy>
<trustLevel name=“WCF“ policyFile=“web_WCF.config“ />
</securityPolicy>
-
Apply this trust level to your application (either in your local web.config or via a location element in an upstream config)
<trust level=“WCF“ />
So far so good – the proxy is separated from the application and has full trust. But when you try running the application now, you will get an ugly ConfigurationErrorException saying the system.serviceModel/client configuration section cannot be accessed because the assembly does not allow partially trusted callers..WTF?!
After following an adventurous code path through the .NET configuration system and seeing variables named like isTrusted and isLocationTrusted – I suddenly knew what is going on.
I remember vaguely that ASP.NET has this concept of trusted configuration locations – e.g. a configuration handler that is registered in machine.config gets full trust even if the application using that section is running in partial trust. This on the other hand means that if a configuration handler is demanding full trust – and thats what System.ServiceModel.dll is essentially doing – the configuration section can’t be in a partially trusted location.
I then tried to move the <system.serviceModel> configuration section to a location element in global web.config – and (drum roll) – it worked…
<location path=“Default Web Site/PartialTrustWcfClient“>
<system.serviceModel>
…
</system.serviceModel>
</location>
By moving the config section we basically “wrapped” it in full trust. The only other option I see is wrapping the configuration section classes instead. This is quite some work and you would loose intellisense.
OK – so this just shows that partial trust is an un-supported and un-tested scenario in WCF V1. But it works and is – if you have to use WCF – better than running ASP.NET in full trust.
You can find the artifacts here.