I'm trying to implement a security mechanism to automatically test a particular plugins permissions and method security privileges and I've gotten a bit stuck on how to get this working.
I've writing a custom MEF Metadata attribute that takes a constructor property like:
params PluginPermission[] permission
This contains an array of all the permissions that the plugin is granted.
The PluginPermission class looks like:
PluginPermission.cs
public enum PluginPermission
{
CreateUsers,
DeleteUsers,
ReadPassword,
WritePassword,
AddUsersToGroups,
AddGroups,
DeleteGroups
}
I've also written a RequiredPermissionAttribute that targets individual methods and takes one or more PluginPermission objects to tell the system what permissions are required for an individual method to be execute. These are applied to the interface for the plugins like:
ILicensingManagement.cs
[RequiredPermission(PluginPermission.CreateUsers)]
bool AddUser(string userName);
Obviously if the plugin doesn't have the required permissions for a particular method the method is not executed.
What I'm stuck on is how to actually get the test method in the RequiredPermissionAttribute class to run before the method is executed and how to gracefully exit the execution if the permissions requirements for the method are not met by the plugin.
I looked at the xUnit BeforeAfterTestAttribute but the implementation seemed so specific I stuggled to pull the source code apart to arrive at the solution.
I can't comment on MEF specific things but one thing to keep in mind that custom attributes are nothing more than "tags", they do not do anything unless your code specifically checks for them, for example using reflection.
The BeforeAfterTestAttribute of xUnit probably works, because xUnit uses reflection to execute the methods. When it encounters this attribute it changes its behavious accordingly.
Attributes in the .NET framework namespace work because either the CLR checks for them or the compiler does.
I know this doesn't really answer your question completely but it was a bit too long to put into a comment.
Update: you can access the attributes using the Type if it's a class or the MethodInfo if it's a method, e.g.
MethodInfo mi = /* method info */;
Attribute[] attrs = mi.GetCustomAttributes(typeof(RequiredPermissionAttribute), false);
RequiredPermissionAttribute req = attrs.Cast<RequiredPermissionAttribute>().FirstOrDefault();
if ((req != null) && (/* current user does not have the required permission */)) throw new Exception();
But this is not a real security solution, a developer can easily avoid these checks. I've only briefly glanced at it but PostSharp could maybe help you.
Related
We have a setup where clients run stand-alone version of our system, but they all link to the same Identity Database with Entity Framework.
A user can be registered as a user on many versions of the application, thereby having multiple accounts with the same username, but the applicationId (stored in the web.config) is unique.
What I would like to do is use the UserManager.FindByName function, but have it automatically add the "&& applicationId = X" to the request sent to the context.
Well you can inherit from the UserManager class, but you have to rewrite the original code (.NET now is open source you can find the original code) and add your logic to it. However, this may be a lengthy action.
What i suggest is if you are using Entity Framework search for the user id by name and application id, then pass the id for the FindById method.
If follow down the implementation, you'll eventually find this method:
public virtual Task<TUser> FindByIdAsync(TKey userId)
{
this.ThrowIfDisposed();
return this.GetUserAggregateAsync((Expression<Func<TUser, bool>>) (u => u.Id.Equals(userId)));
}
In order to override this properly, it would have to be inside the UserStore class, since there are loads of internal methods (otherwise you'd have to rewrite every single internal method in the class), and add a new Type Parameter that would accept your ApplicationId, since UserStore is a generic class. Then you would be able to write another FindByIdAsync method, because it's a virtual method and it can't be overridden. You would also have to rewrite the GetUserAggregateAsync internal method, because it isn't prepared to handle your new Type Parameter.
Now, there are probably a few more hiccups that would show up, but you can, ultimately, rewrite this method to suit you, but I would advise against it because it's A LOT of work to achieve something that might be possible in another way.
Docs: http://docs.asp.net/projects/api/en/latest/autoapi/Microsoft/AspNet/Identity/EntityFramework/UserStore-TUser-TRole-TContext-TKey/index.html
Code: https://github.com/aspnet/identity/blob/master/src/Microsoft.AspNet.Identity.EntityFramework/UserStore.cs
I'm trying to emulate my custom project file as new PS Drive. I am trying to create my custom Powershell Provider that is derived from NavigationCmdletProvider. I have overridden PSDriveInfo to read and contain the project from the file and filepath is in the root of PSDriveInfo.
I can't override GetItem properly. What I want to do is use GetNamesFromPath(path, out tableName, out rowNumber) method. Since my custom project is basically dataset, I would like to use tableName to get the DataTable and rowNumber for ID of DataRow.
The problem is that I get the "path doesn't exist" kind of error. It doesn't event get into the overridden method. Am I missing something to override? The filepath doesn't exist really, but I simply need to handle the path and use WriteItemObject with what I want as object(s) returned, without checking is it valid path.
Edit 1:
One thing I noticed is that it never gets into GetItem and therefore into IsValidPath. When I debug and use breakpoints, first I load the drive and then Set-Location to the drive, IsItemContainer is called (it has to be overridden for Set-Location to work).
GetItem and IsValidPath are not called at all, as if it checks for valid path before calling overridden method. Can NavigationCmdletProvider work with non-existing paths (except for the file itself), just work with strings that will manually be handled as paths would?
Make sure you override the IsValidPath and ItemExists methods:
protected override bool IsValidPath(string path)
{
return true;
}
protected override bool ItemExists(string path)
{
return true;
}
If you are extending NavigationCmdletProvider then you should override IsValidPath, ItemExists, GetItem, GetChildItems and possibly other methods depending on what features you want to support for your PS drives.
The best way to find out which methods are missing implementation is to override all the virtual methods and put a breakpoint in each one. Then execute a cmdlet and see in the debugger what gets called and what are the parameter values.
Unfortunately, there isn't a lot of detailed documentation about implementing custom PowerShell providers. However, you can find a quite detailed tutorial on MSDN about this topic with a lot of source code examples. Additionally, you can take a look at the PowerShell VFS project - it's a wrapper around PowerShell provider API to make it easier to build complicated providers.
I have a private static readonly field in my class:
public class MyClass
{
// ISSUE #1 -- requires unproven: path != null
private static readonly DirectoryInfo MyDirectory =
new DirectoryInfo(Settings.Default.MyDirectoryPath);
protected virtual void SomeMethod()
{
if (MyDirectory.Exists)
{
// ISSUE #2 -- requires unproven: !string.IsNullOrEmpty(path)
var catalog = new DirectoryCatalog(MyDirectory.FullName);
}
}
}
For issue #1 I used a null coalescing operator to default to some magic string and that fixed it, but I don't really like that solution. I was hoping there was a better solution.
For issue #2 the only thing I can think of is using a Contract.Assumes because if I attempt to use Contract.Requires(MyDirectory.Exists || !String.IsNullOrEmpty(MyDirectory.FullName)); it complains about visibility (private field used in a requires on a protected method).
Issue #1 is a result of Settings.Default.MyDirectoryPath being code generated by Visual Studio without any contracts on the property. This issue is not limited to null strings. Many API's now have contracts that require say a TimeSpan to be non-negative but using a setting directly in the API will generate a Code Contracts warning.
A way to solve this issue is to wrap the setting in a method that has a contract. E.g.:
String GetMyDirectoryPath() {
Contract.Ensures(Contract.Result<String>() != null);
var myDirectoryPath = Settings.Default.MyDirectoryPath;
Contract.Assume(myDirectoryPath != null);
return myDirectoryPath;
}
Notice how the Contract.Assume really performs validation of your setting (which can't be verified by Code Contracts because it is controlled by an external configuration file). Had it been a TimeSpan that is expected to be non-negative you can either use Contract.Assume to do the validation resulting in a ContractException or some other method using your own exception instead.
Adding this extra layer is somewhat tedious but because the setting is defined outside the application it needs to be run-time validated at some point just as you have to validate interactive user input.
Issue #2 is probably because DirectoryInfo doesn't have any contracts defined. The easist way is to use Contract.Assume. This will make a statement about what you believe is the expected behavior of DirectoryInfo but a run-time check will still be in place to ensure that your belief is correct (provided that you keep the checks in your code).
var path = MyDirectory.FullName;
Contract.Assume(!string.IsNullOrEmpty(path));
var catalog = new DirectoryCatalog(path);
After having used Code Contracts in a current project for a while now I have found that it does force you to rewrite your code at times to correct for issues. You really have two options here.
You can add the setting to your project settings to output what the correct attributes to apply are to ignore certain warnings. This is done by adding the "-outputwarnmasks" flag to the "Extra Static Checker Options" under the Advanced section in the Code Contracts tab of the Project file settings. This will add information to the Build Output window giving you the correct attributes to add to ignore the individual cases. (very useful when dealing with Entity Framework).
You can rewrite your code to add the proper Requires and Ensures to your code so that the warnings don't appear.
If you want to rewrite the code:
To solve Issue #1 you would have to wrap the Settings class and expose a new MyDirectoryPath as a property that isn't code generated so that you can add a check in it and return an empty string and add the Contract.Ensures(Contract.Result<string>() != null) at the top of the Getter for the property.
To solve Issue #2 you would have to wrap you access to the class field inside a private static property that adds the proper Ensures and Requires.
I have usually gone with rewriting the code wherever possible except with Entity Framework/LINQ where you need to add the attributes, especially with complex queries.
** Disclaimer ** These are just the ways I have found to solve the issues as there isn't a great deal of information on other ways of working around these types of items.
Well, for Issue#2, I think you might want to use && not ||. But beyond that, perhaps for Issue#1 you can put those checks in the static constructor? Another option for Issue#2 is to have the method to take the directory as a parameter:
private static readonly DirectoryInfo MyDirectory;
static MyClass()
{
Contract.Requires(Settings.Default.MyDirectoryPath != null);
MyDirectory = new DirectoryInfo(Settings.Default.MyDirectoryPath);
}
protected void SomeMethod()
{
SomeOtherMethod(MyDirectory);
}
protected virtual void SomeOtherMethod(DirectoryInfo directory)
{
Contract.Requires(directory.Exists && !String.IsNullOrEmpty(directory.FullName));
var catalog = new DirectoryCatalog(directory.FullName);
}
I don't have much experience working with the Contract API, so I might be off my rocker with all this. :)
Contract.Requires(MyDirectory.Exists || !String.IsNullOrEmpty(MyDirectory.FullName));
Don't do this! MyDirectory.Exists can change at any time and the caller cannot guarantee it. Just throw an exception if the directory doesn't exist - this is what exceptions are for.
I need to organize some simple security in a class depends on value of the enum.
All that I can figure out is using attribute on a method and then run check then if it fails throw an exception.
Sample:
[ModulePermission(PermissonFlags.Create)]
public void CreateNew()
{
CheckPermission();
System.Windows.Forms.MessageBox.Show("Created!");
}
protected void CheckPermission()
{
var method = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod();
if (!flags.HasFlag(method.GetCustomAttributes(true).Cast<ModulePermissionAttribute>().First().Flags))
{
throw new ApplicationException("Access denied");
}
}
is there more elegant or simple way to do this, like just to trigger an event when method run?
Why not just use standard Code Access Security instead of reimplementing the attribute handling and stack walking?
I think that if you read through the linked documentation, you'll see that what you have is nowhere close to what is needed to achieve actual security. Thankfully, this hard problem has already been solved...
Not with an enum, but with strings - voila (enforced by the runtime, even in full-trust):
public static class PermissionFlags {
public const string Create = "Create";
}
[PrincipalPermission(SecurityAction.Demand, Role = PermissionFlags.Create)]
public void CreateNew() {
System.Windows.Forms.MessageBox.Show("Created!");
}
All you need to do now is to represent the user as a principal. This is done for you in ASP.NET, and there is a winform plugin (in VS2008 etc) to use ASP.NET for membership. It can be configured for vanilla winforms and WCF, too; at the most basic level, GenericPrincipal / GenericIdentity:
// during login...
string[] roles = { PermissionFlags.Create /* etc */ };
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Fred"), // user
roles);
But you can write your own principal / identity models easily enough (deferred / cached access checks, for example).
You might want to look at doing this with something like PostSharp, which will give you a framework for applying the attributes so that you don't have to run the check in your method. This may, however, increase the complexity depending on how the currently active flags are accessed. You'd probably need some class to cache the current permissions for the current user.
You could take a look at Aspect Oriented Programming.
Check out Postsharp for instance, which will enable you to 'weave' some additional logic at compile time in the methods that you've decorated with your ModulePermission attribute.
By doing so, you will not have to call the 'CheckPermission' method anymore inside that 'secured' method, since that logic can be weaved by Postsharp.
(A while ago, I've been playing around with Postsharp: http://fgheysels.blogspot.com/2008/08/locking-system-with-aspect-oriented.html )
Basically I'm trying to implement some sort of poor man's Aspect Oriented Programming in C#. I had thought about using a ContextAttribute but they seem only be be bound at the class level. Is there any way that I can put an attribute in such that it will receive the same parameters as the method which it annotates or some way to access the context in which it fired?
I have this code
public void AddUser(User user)
{
var errors = DataAnnotationsValidationRunner.GetErrors(user);
if (errors.Any())
throw new RulesException(errors);
users.Add(user);
}
from which I would like to extract the first 3 lines so I had something like
[Validated]
public void AddUser(User user)
{
users.Add(user);
}
I think you are missing a third component. Most AOP implementations (e.g. Aspect#) rely on a proxy or interceptor to actually execute the code. In your scenario, you lack whichever component needed to 1) know the attribute exists on the method, and 2) trigger the mechanism (or become it) needed to execute the code within the attribute.
Fortunately, there are already many (fairly) simple solutions available in open source. The simplest option I can think of would be to use a compile-time weaver like PostSharp. Grab a copy of that, and in the samples you'll find several examples of exactly what you are trying to do (you'd be interested in the OnMethodInvocationAspect).
The end result is that your code looks exactly like it does in the sample you provided, yet it's also running the code you wish.
Don't know exactly how your solution should look like, but in C# attributes do not execute code as long as you don't request them (as far as I know). And if you query for the attribute, you also have the context. So there is something wrong with your strategy in my opinion.