PlugIn dynamisch laden und Berechtigungen festlegen(Sandbox)

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Ich habe eine komplexe Serveranwendung, in der dynamisch PlugIns ge- und
entladen werden können. Leider scheitert das ganze am festlegend er
Sicherheitsrichtlinie.

Die Vorgehensweise ist bekannt - Je PlugIn eine AppDomain, Policy festlegen
und das Objekt remote laden. So weit so gut.

Das Problem ist jedoch, dass wenn ich die Policy von FullTrustet auf
"irgendwas" anderes setzte, sei es High, es es nur eine minnimale
Restriktion, so erhalte ich, wenn ich eine Plugin-Funktion aufrufe, die
Meldung "Die Sicherheitsberechtigungen der Assembly
microsoft.visualbasic.dll sind zwischen den Anwendungsdomänen nicht
kompatibel". Ich habe mich erkundigt und gelesen, ich solle die Assemly
einen Strong Name geben und signieren. Das habe ich getan, seber fehler, nur
nicht mit microsoft.visualbasic.dll sondern mit der Signierten Assembly.

Nächster Versuch: Die PlugIns und die SharedPlugInLib in den Gac
installieren, außerdem noch Berechtigungen über die .NET-Kofiguration
festlegen. Funktionierte so weit ganz gut, sofern "FullTrustet" eingestellt
war. Wenn nicht, dann erschien immer eine "Sicherheitsausnahme", selbst
dann, wenn das Permissionset zwar nicht "FullTrustet" war, jedoch dennoch
alle Rechte hatte.

Ich bin nun ein wenig ratlos.

Das ganze ist in etwa so aufgebaut:

ASP.NET-Appdomain:
ASP.NET Anwendungs.dll (FullTrustet)

PlugIn1-Appdomain:
-->SharedPlugInLib.dll (Execution, Reflektions, .NET Remoting, laden von
Assemblies)
---->Plugin1.dll (Nur Execution, auf keinen Fall Reflektions!!!)

PlugIn2-Appdomain:
-->SharedPlugInLib.dll (...)
---->Plugin1.dll (...)

Das PlugIn soll mit der ASP.NET Anwendung kommunizieren. Die
Kommunikationsfunktionen und für die PlugIns notwendigen Klassen sind in der
PlugIn-Loader.dll drin. Kommuniziert wird über .NET Remoting.

Jetzt soll es so sein, dass die PlugIns nur das Ausfürhungsrecht haben, in
keinem Fall jedoch .NET Remoting oder Reflektionsverwenden dürfen(Grund: Im
"PlugIn" sind mehrere UserScritps, welche nicht auf einander zugreifen
dürfen. Nur für jeden User ein eigenes PlugIn zu machen, dies hätte zur
Folge, dass ca. 1500 AppDomains erstellt werden müsten....daher müssen die
Reflektions deaktiviert werden).
Die SharedPlugInLib jedoch muss Reflektions und .NET Remoting können. Doch
sind beide Assemblies ja ind er selben App-Domain.


AppDomain1 AppDomain2
---------- ----------------------------
ASP.NET <---> SharedPlugInLib <---> PlugIn
(FullTrustet) (Wenig Rechte) (Kaum Rechte)

Ich habe auch schon versucht, die Berechtigungen erst festzulegen, wenn das
PlugIn von der SharedPlugInLib gestartet wird - Jedoch muss, wenn das PlugIn
eine Funktion in der SharedPlugInLib aufruft, die Berechtigung zurück
erhalten, da diese auf den Server zugreifen müssen.

Hier ein wenig Quelltext, sofern notwendig:

Serverseitig:
-------

Dim adSetup As AppDomainSetup = New AppDomainSetup
adSetup.ApplicationBase = "C:\stne.de\game\bin"
adSetup.PrivateBinPath = "C:\stne.de\game\bin"
adSetup.PrivateBinPathProbe = "C:\stne.de\game\bin"

PluginDomain = AppDomain.CreateDomain("plugin_1", Nothing, adSetup)

'Create a new AppDomain PolicyLevel.
Dim domainPolicy As PolicyLevel = PolicyLevel.CreateAppDomainLevel()

'Create a 'Membership Condition' to be assigned to a new code group
Dim allCodeMC As AllMembershipCondition = New AllMembershipCondition

'Create a new permission set with the same permissions as the
'"LocalIntranet" permission set.
Dim CustomPS As PermissionSet = New PermissionSet(PermissionState.None)

'Add the permission needed to read from the registry.
CustomPS.AddPermission(New SecurityPermission(PermissionState.Unrestricted))
'...
'Um den für die Newsgroup Quelltext abzukürzen, weitere Zeilen ausgelassen


Dim polState As PolicyStatement = New PolicyStatement(CustomPS)

'Create a new code group which will serve as the root code group for the
'AppDomain policy level
Dim allCodeCG As CodeGroup = New UnionCodeGroup(allCodeMC, polState)
domainPolicy.RootCodeGroup = allCodeCG

'Create a new application domain.
PluginDomain.SetAppDomainPolicy(domainPolicy)



Dim PluginStarterHandle As ObjectHandle =
PluginDomain.CreateInstanceFrom(GetType(SharedPlugInLib.TScriptInit).Assembly.GetName.CodeBase,
GetType(SharedPlugInLib.TScriptInit).FullName)
Dim Starter As SharedPlugInLib.TScriptInit = PluginStarterHandle.Unwrap

Dim FileUri As New
Uri(System.Reflection.Assembly.GetExecutingAssembly.CodeBase)
Dim File As New
System.IO.FileInfo(HttpUtility.UrlDecode(FileUri.AbsolutePath))

Starter.Init(AppDomain.CurrentDomain, File.FullName,
"C:\stne.de\PlugIn\bin\PlugIn.dll")

Dim s As SharedPlugInLib.TScriptActivator =
PluginDomain.CreateInstanceFrom(GetType(SharedPlugInLib.TScriptActivator).Assembly.GetName.CodeBase,
GetType(SharedPlugInLib.TScriptActivator).FullName).Unwrap
Dim Code As String = s.Start("UserScripts.User64387", "TScript1", "Main")
Response.Write(Code)

AppDomain.Unload(PluginDomain)


SharedPlugInLib:
----------------

Public Class TScriptInit
Inherits MarshalByRefObject

Public Sub Init(ByVal ServerAppDomain As AppDomain, ByVal
ServerAssemblyFile As String, ByVal PlugInAssemblyFile As String)
TScriptGlobal.ServerAppDomain = ServerAppDomain
TScriptGlobal.ServerAssemblyFile = ServerAssemblyFile
TScriptGlobal.PlugInAssemblyFile = PlugInAssemblyFile
End Sub

End Class

Public Class TScriptActivator
Inherits MarshalByRefObject

Public Function Start(ByVal [Namespace] As String, ByVal Script As String,
ByVal EntryPoint As String) As String
Start2([Namespace], Script, EntryPoint)
End Function

Public Function Start2(ByVal [Namespace] As String, ByVal Script As String,
ByVal EntryPoint As String) As String
Dim us As TUserScript =
Activator.CreateInstanceFrom(TScriptGlobal.PlugInAssemblyFile, "PlugIn." &
[Namespace] & "." & Script).Unwrap
Dim mi As Reflection.MethodInfo = us.GetType.GetMethod(EntryPoint)

Return mi.Invoke(us, New Object() {}) 'Hier wird das PlugIn gestaretet!!!
End Function

End Class

PlugIn:
-------

Namespace UserScripts.User64387

Public Class TScript1
Inherits TUserScript

Public Function Main() As String
Return "Funktioniert"
End Function

End Class

End Namespace


-----------

Gruß
Sebastian Loncar


.



Relevant Pages

  • Re: CodeDom and GenerateInMemory memory leak
    ... So, what I need is a new appdomain, and at this point I am stuck. ... The call to CompileAssemblyFromSource() is ... Dim params As New CodeDom.Compiler.CompilerParameters ... Dim DynamicFunctionDelegate As DynamicDelegate = ...
    (microsoft.public.dotnet.languages.vb)
  • Re: Loading plugins in separate AppDomains
    ... In order for the plugin assemblies only to be loaded in the second AppDomain ... > MarshalByRefObject) in an assembly that implements the IPlugin interface. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Plugin difficulties
    ... if you set the ApplicationBase to the plugin directory ... > and then set the PrivateBinPath to the bin directory, ... Assemblies that are loaded in the secondary AppDomain, ...
    (microsoft.public.dotnet.framework.clr)
  • Re: Creating a Singleton that is a cross AppDomain Singleton
    ... public abstract class Plugin: MarshalByRefObject ... This would ensure that every plugin must be a MarshalByRefObject so you ... invoke methods on them without having them get loaded in that AppDomain. ... >> for the plugin assemblies only to be loaded in the second AppDomain you ...
    (microsoft.public.dotnet.csharp.general)
  • Re: Creating a Singleton that is a cross AppDomain Singleton
    ... public abstract class Plugin: MarshalByRefObject ... This would ensure that every plugin must be a MarshalByRefObject so you ... invoke methods on them without having them get loaded in that AppDomain. ... >> for the plugin assemblies only to be loaded in the second AppDomain you ...
    (microsoft.public.dotnet.framework.remoting)