Does anyone have experience with F# code in partial trust scenarios? As in, creating assemblies with [<AllowPartiallyTrustedCallers>]
?
I am working on a couple of projects that we need to be able to run in partial trust, and we have been trying to use Level 2 Security Rules (http://msdn.microsoft.com/en-us/library/dd233102.aspx). In practice for our self-contained assemblies this is easy - just put an attribute; but sometimes our assemblies reference third-party DLLs that are not annotated and assumed "SecurityCritical." This is where it gets "interesting."
Having worked with it for past couple of days there appears to be a serious issue with F#. .NET security policy expects you to annotate types/methods with [<SecuritySafeCritical>]
if they reference or call "SecurityCritical" code, which happens to be most of the code out there on NuGet because this is what it defaults to. Now, in F# this works ok until you start using closures. You cannot do:
namespace Foo
open System.Security
[<assembly: AllowPartiallyTrustedCallers>]
[<assembly: SecurityRules(SecurityRuleSet.Level2)>]
do()
[<SecurityCritical>]
module C =
let get () = [ 1 .. 10 ]
[<SecuritySafeCritical>]
module M =
let foo () =
seq {
for i in 1 .. 10 do
yield!
C.get ()
|> Seq.filter (fun x -> x % 2 = 0)
}
This assembly fails to pass SecAnnotate.exe
checks because F# compiler lifts the closure to a separate type, which is now NOT annotated with [<SecuritySafeCritical>]
, defaults to Transparent, but references some critical code, which is an error.
It sounds like a minor restriction but it cost me many hours altering code to avoid closures and satisfy SecAnnotate constraints. Maybe F# could propagate security attributes to closure types it creates? Is there another simple way around this that I am missing?
One thing that every single successful author has in common is a deep interest in people and the workings of other people's minds. Even if you want to write hardcore science fiction, you need to create characters that will catch your readers' attention and hearts to go alongside the robots and rocket ships.
You can apply SecurityCritical
as an assembly-level attribute:
[<assembly: SecurityCritical>]
A better approach though, assuming you're just writing a "plain" F# assembly -- i.e., one that isn't doing anything which requires special security (e.g., P/Invoke) -- would be to replace:
[<assembly: AllowPartiallyTrustedCallers>]
with
[<assembly: SecurityTransparent>]
The MSDN page for SecurityTransparentAttribute says:
Specifies that an assembly cannot cause an elevation of privilege.
Transparent assemblies can be accessed from partially trusted code and cannot expose access to any protected resources or functionality. Code in the assembly is not allowed to suppress code access security checks and cannot cause an elevation of privilege.
The F# 3.0 version of FSharp.Core also uses this attribute for the same reason.
Links to additional information:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With