User Access Audit - c#

I am working with a c# MVC website that has been developed over the course of several months by different people. The site is quite big and uses the .NET membership facilities regulate user access to various features.
I have now been tasked with a security audit, to list what users or roles have access to which features. I can do this by hand, but given the large number of controllers and their actions, it would be easier if I could do this with code. I am at a loss on how to even begin.
So, in short, how do I get a list of all the controllers on a site, their actions, and determine which, if any, users/roles have access to them?

You can use a little reflection to get controller methods. You can get your controllers:
var controllers = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(Controller));
where Controller is the standard base class; if you've got your own custom base controller you can use that instead. This assumes you're running this code within the app; if that's not the case then replace Assembly.GetExecutingAssembly() with the appropriate logic to find your app's assembly. Assembly.GetExecutingAssembly() is easier, so I'd say to just add a function to do this somewhere in your admin-only area, if there is such a thing.
That line above will give you an array of System.Type objects for your controllers. From there, foreach (var TController in controllers) through them and get their methods:
var actions = new ReflectedControllerDescriptor(typeof(TController)).GetCanonicalActions();
This gets you an array of ActionDescriptor objects, from which you can use GetFilterAttributes() and GetCustomAttributes() to see what attributes are on that method - you're mostly looking for AuthorizeAttribute, AllowAnonymousAttribute, and your custom auth stuff. The ReflectedControllerDescriptor has these methods as well, for attributes applied to the entire controller instead of per-method.
Once you know which auth-related attributes are set, you can inspect the properties of those methods to see what they're set to. For example, AuthorizeAttribute exposes a Roles property, so for a method marked [Authorise("admin", "superuser")] you'll get a string containing those terms, so with a little logic you can split it up into the individual role names and use those for grouping/sorting/whatever. For any custom attributes... well, that depends on how you've implemented them, but if they don't expose what you need you can always edit them so they do.
If your methods use something like User.IsInRole internally... well, I'm not sure there's a way to find that programmatically. You might be stuck using Call Hierarchy view or Find All References to see where that sort of method is being accessed, so you can sift through manually.
Meanwhile, as part of this audit it's probably worth logging what's actually being accessed, if you don't already. In my projects, I tend to implement an action filter inheriting from ActionFilterAttribute, using some logic that inspects the attributes as described above, and using the ActionDescriptor and HttpContext.User that get passed in as part of the filter context to record what action is being accessed and who's accessing it.

Related

Should filter share code with webapi controller?

I got a webapi Authorize filter which does some security checks on the queryString for "Get" calls.
For post methods, since I need to peek at the payload to retrieve the object (moreover, that would make my filter dependent upon my dtos, which I'm not a huge fan either...), and since I didn't find an easy way to open the post payload in the filter, I ended the subject by making the check in a controller method.
Obviously, the logic is the same in both cases.
So I put the validation logic in an abstract controller and make it "public static" so they can be called from the filter and from all inheriting controllers. I've read the google results from the follwoing query (avoiding calling static methods), and truth be told, I also find this ugly and untestable.
But what would be an elegant alternative ?
I've considered creating a (static ?) helper class but I only find it's syntactic sugar around the same concept.
I also think that helpers should not be IOc'ed maybe I'm wrong here ?
Thanks for your input !
You should include the details of validations that you wanna do on the query string to help us understand the problem in more details. However based on the information provided I have following to say.
Creating a static method in Controllers and accessing it in Filters is more ugly than exposing DTOs to Authorize Filter. The controllers acts as service layer and Filters are (to some extent) part of it(service layer) too. So there is nothing wrong if you have to expose DTOs to Filters. It can simply be seen as "DTOs being exposed to service layer".
However, if you really wish to avoid it, put an abstraction as part of your service layers which can be exposed to the Filters. Like you can create a interface (and its implementations) that exposes a validation method for your purpose that can be consumed from within the Authorize Filter.

Dynamically Ignore WebAPI method on controller for api explorer documentation

we have implemented a webAPI and we have a number of API controllers.
We provide an API documentation for our API and what we want to do is to exclude certain web methods from the documentation but we want this to be done dynamically depending on the environment we are running.
just to give you an understanding of what I mean, let's say I have the following web method
[ApiExplorerSettings(IgnoreApi = true)]
public Product getProduct()
{
...
}
By setting the IgnoreAPI property on the ApiExplorerSettingAttribute to true, it excludes the web method from the documentation which is what we want but we need a way of setting the "true" value dynamically.
Ideally we would like to have a database table with bool values for each webMethod and based on these set the value for IgnoreAPi property.
Is there a way to achieve this? Your help will be much appreciated.
You can implement a custom IApiExplorer and register it in Web API's services to have full control over which APIs are listed or not.
Here's a blog post from the dev who implemented most of this: https://learn.microsoft.com/en-us/archive/blogs/yaohuang1/asp-net-web-api-introducing-iapiexplorerapiexplorer
And here's the IApiExplorer interface definition: http://msdn.microsoft.com/en-us/library/system.web.http.description.iapiexplorer(v=vs.118).aspx
One thing you could do is derive from (or re-use the existing source of) the existing ApiExplorer implementation and call base to get the default list, and then further filter it however you want.
And per s_hewitt's comment, the recommendation is:
Deriving from ApiExplorer, implementing the two methods ShouldExploreAction and ShouldExploreController is the way to go. Make your DB calls in those two methods, looking up based on route, controller and action.
I don't know much about the documentation generation of WebAPI, but I do know about attributes. Attributes are compiled into the code and result in hard coded values being held in directly in the data in the EXE or DLL. They cannot be changed.
Having said that, you might be able to apply attributes as a second set after normal compilation. Perhaps PostSharp could help here? Perhaps changing the solution configuration could be a way of indicating the environment you want to build for and this which methods get the IgnoreApi treatment. You could create your own attribute to apply to the methods that describes which environments the method should be ignored within. (I think it's more likely you'll be able to do what you want in PostSharp if you don't try and call a database to get hold of this data.)

custom attribute object lifetime and isolation

I have a Web API project where I intend on using an attribute that inherits from ActionFilterAttribute to do logging in a standardized fashion. As part of that logging, I want to extract some values from HttpActionContext in the OnActionExecuting method. I would then want to refer to these as part of OnActionExecuted. I have specified [AttributeUsage(AttributeTargets.Class)] for this attribute. My assumption is that my custom attribute would be instantiated in concert with the class it is applied to, and have the same lifetime as the class to which the attribute is applied. I can't find anything to concretely back this up. I've done some testing and that seems to be how it works but I worry that my test is too limited. I'm assuming that multiple calls to the same controller will generate new instances of that controller and thus new instances of the attribute. I'm basically worried about the thread safety of the data I retrieve as part of OnActionExcecuting.
Anyone know any resources or links that can confirm or deny my assumptions?
It depends on what you are going to use.
Attributes (filters) in Web API are cached (filter pipeline is private readonly Lazy<Collection<FilterInfo>> _filterPipeline; and initialized only once). see here
Therefore if you initialize something in the attribute's constructor, it will remain the same on subsequent executions.
However, the HttpActionContext is created created for every request from HttpControllerContext and HttpActionDescriptor and then passed on to each of the cached filters in the pipeline. see here
As a result, even though the instances of the filters are reused, the value of the context in the methods is specific to the specific request.

Change the Location of the Controller inside the Project structure

I found this Post (How to extend where MVC looks for views) about changing the location of the View.
I was wondering if there's something similar for changing the location of the controller.
I just want to change the location of the class inside project and don't want to affect the url.
For example Instead of placing the Controller into
MyMvcProject\Controllers\
MyController1.cs
MyController2.cs
MyController3.cs
I want to achieve something like
MyMvcProject\MyGroup1\
MyController1.cs
MyController2.cs
MyMvcProject\MyGroup2\
MyController3.cs
and also support Areas:
MyMvcProject\Areas\MyGroup3\
MyController4.cs
Is it possible to achieve this? And if yes, where can I find documentation about it?
You can do what you want, and it doesn't require any special configuration, because ASP.NET MVC does not care about where you put your controllers. First, controllers are located using reflection, so the name of the folder where you put your controllers is irrelevant. Controllers are searched by type name and optionally by namespace (for disambiguation). You can even have controllers in separate projects/assemblies. As long as the controller ends up in an assembly in the bin folder then it's searchable by the framework.
As mentioned above, you'll need to create a controller factory to support your custom resolution. Here's an example:
http://develoq.net/2010/custom-controller-factory-in-asp-net-mvc/
As others have already stated you need to do one of the following:
Derive from IControllerFactory interface and provide an implementation of the CreateController and ReleaseController methods.
Derive from DefaultControllerFactory and override the default behaviours.
Here are some links to get you started:
Custom controller factory in ASP.Net
Inside the ASP.NET MVC Controller factory
Dive deep into MVC - IControllerFactory
Also, if you're willing to spend a bit of money I would also recommend the book Pro ASP.NET MVC 3 Framework as this explains almost every aspect of how the MVC framework can be customised (including an example on how to create a custom controller factory - the source code for which can be freely downloaded from the publishers website).
I think it is impossible to do this. ASP.NET MVC have defined the convention that we have to follow.
Controllers are in Controllers folder, views are in Views{ControllerName}\
I believe you cannot change the convention unless you create your own ControllerFactory.
If you really want to do that, just implement IControllerFactory interface (or try to derive from DefaultControllerFactory).
Then your Application_Start register your controller factory using ControllerBuilder.Current.SetControllerFactory method.
Look at the ControllerFactory documentation and to the MVC source code for details.
What you're asking and what your example shows are two different things; depending on which one you want to achieve, you may or may not need to do any work.
There are two requirements for a class to be a controller in the MVC Framework:
It has to have a class name of Name + "Controller"
It has to have a parameterless public constructor.
Your sample "normal" MVC layout is actually not valid:
MyMvcProject\Controllers\
MyController1.cs
MyController2.cs
MyController3.cs
Those classes wouldn't be found by MVC because they don't have the correct name, regardless of which folder they are in.
If all you want to do is change the namespace/folder names, that "just works", assuming you name them the same as the appropriate route segment(s):
MyMvcProject\MyGroup1\
Page1Controller.cs
Page2Controller.cs
MyMvcProject\MyGroup2\
Page3Controller.cs
MyMvcProject\Areas\Area1\
Area1Page1Controller.cs
This walkthrough (written for MVC 2 but works just as well in MVC3) shows you how to support Areas with the default controller behavior.
If you actually want to name them SomethingController1 or SomethingElseController5, or otherwise change the route -> classname mappings, then you do need to implement a custom ControllerFactory, and inject it into the MVC pipeline.
There are plenty of examples on the web on how to do this, including the one posted earlier.

What to use instead of OnActionExecuting? ASP.NET MVC

I've got some things I do in the OnActionExecuting method in a BaseController, that all my other controllers are based off of.
I'm doing some simple things like putting a variable into ViewData that "nearly" all of my views will need, and populating a couple properties that my controllers use.
Thing that bugs me is, this work is being done even on actions that don't need it. Is there a better place to hook into to more efficiently perform this work? In case I ever need to something a little "heavier" than what I do now (i.e. DB access, etc...).
UPDATE: I'm more specifically referring to a typical controller scenario. Where there are several actions that simply show a view. And a few that take a form submission, do some work, and redirect to another action.
In this case, I want the actions that show views to use the work that is done in the OnActionExecuting method. But the actions that accept form submissions, the work being done in OnActionExecuting is not being used and therefor just adds unnecessary processing time.
Maybe I'm not explaining it very well... hope it's clearer now.
TIA!
If it's easier to blacklist actions (by attributing actions for which this logic shouldn't be performed) than whitelisting actions, you could create a [SuppressWhateverLogic] attribute and apply it to the methods you want to be blacklisted. Then modify your OnActionExecuting() method to look for this attribute (via ActionExecutingContext.ActionDescriptor.IsDefined()), and if the attribute exists then bail out of the logic.
If it's easier to whitelist actions, move the logic out of Controller.OnActionExecuting() and create a custom [MyLogic] filter by subclassing ActionFilterAttribute. Add the logic to MyLogicAttribute.OnActionExecuting(), then attribute the methods you want with [MyLogic] to associate the logic with those methods.
Create a second "AdvancedBaseController" which derives from BaseController?

Categories

Resources