Documenting security

Documenting security

Old forum URL: forums.lhotka.net/forums/t/234.aspx


Mark posted on Wednesday, May 31, 2006

Have any of you come up with a nice scheme to document the security in your objects?  For example, I'd like to be able to be able to detail the security rights for "Controller", "Accounting Clerk", etc - listing by object which properties they have read/write access to, as well as the general 'CanGet/Add/Edit/DeleteObject' routines.

On small projects, it's not that hard to keep up with, but on larger projects, it's fairly time-consuming to do it by hand (and keep it up-to-date).  The project I'm working on now has over 300 objects (and climbing) with 20+ roles.

hurcane replied on Thursday, June 01, 2006

This is just an off-the-cuff idea...

You could write a program to do a brute force analysis using reflection. The general flow could be like this:

Load list of security roles
For each security role
    Create principal object that has the single security role
    For each object in the assembly
        Test CanGet/Add/Edit/DeleteObject
        For each public property
           Test CanReadProperty/CanWriteProperty

As the application runs, it would generate output that you can then use to create your documentation. By using reflection, this application would not need to be changed unless multiple assemblies are involved.

This would not be a trivial program to write, but I think it would do the job.

RockfordLhotka replied on Friday, June 02, 2006

Another way to look at this is to consider that AddAuthorizationRules can be data driven. So you could put the auth rules in a table or config file of some sort, and then load the values when the object is created.

Then you could just run your report against that table, because it would be the same auth rules as used by the object.

Mark replied on Friday, June 02, 2006

I think I might explore the data-driven approach.  Haven't sat down and put much thought into it (yet), but I'm thinking I'd probably want a SecurityManager class that would cache all the security-related data from the database.  That would prevent repetitive data-access calls during object creation.  The individual objects would then talk to the SecurityManager instead of the DB directly.

RockfordLhotka replied on Friday, June 02, 2006

Yes, I think that's exactly what you'd want to do. I'd make SecurityManager NOT inherit from CSLA - but rather be an object with Shared/static methods like:
 
SecurityManager.GetSecurityInfo(obj)
 
Internally, SecurityManager would keep a dictionary of SecurityInfo objects, which would inherit from ReadOnlyBase - and would be keyed by the object's type name. SecurityInfo would have instance methods like:
 
CanGetObject()
CanAddObject()
CanEditObject()
CanDeleteObject()
LoadAuthorizationRules(authRules)
 
So then in your business object code you can easily implement the four Shared/static methods like this:
 
Public Shared Function CanGetObject() As Boolean
  Return SecurityManager.GetSecurityInfo(Me).CanGetObject()
  ' return SecurityManager.GetSecurityInfo(this).CanGetObject();
End Function
 
And your AddAuthorizationRules would look like something like this:
 
Protected Overrides Sub AddAuthorizationRules()
  SecurityManager.GetSecurityInfo(Me).LoadAuthorizationRules(AuthorizationRules)
End Sub
 
Obviously this means any complexity has been shifted into the SecurityInfo class - but that shouldn't be too hard to implement - its DataPortal_Fetch() will retrieve all auth data for a given object type and will store the allowed/denied lists for each property so those values can be easily used to set the AuthorizationRules.
 
SecurityManager basically then acts as an indexed cache of SecurityInfo objects - which are loaded on demand, but are only loaded once for an object type over the lifetime of the application.
 
Rocky
 


From: Mark [mailto:cslanet@lhotka.net]  
 
I think I might explore the data-driven approach.  Haven't sat down and put much thought into it (yet), but I'm thinking I'd probably want a SecurityManager class that would cache all the security-related data from the database.  That would prevent repetitive data-access calls during object creation.  The individual objects would then talk to the SecurityManager instead of the DB directly.

Mark replied on Friday, June 02, 2006

Your sample code looks almost identical to what I've quickly thrown together as a proof-of-concept.  :-)

The only gotcha with your sample - in the static CanGet/Add/Edit/DeleteObject methods, you can't reference 'this' (Me), so I'm passing in the object name instead.  Already had a const defined in each class with the object name, so it worked out well.

This looks very promising - I especially like the idea that I'll be able to adjust the security behavior of the application on-the-fly without having to recompile.

rasupit replied on Friday, June 02, 2006

Mark,

Search on Object Security on www.searchcsla.com.  I have created something like this for CSLA 1.x and have been using this method on all my projects.  Others have converted this to use database instead of xml.

This implementation works pretty good for company that I work here where security some times is an after tought and requesting global group could take weeks.

The design should be applicable to CSLA 2.0 version.

HTH,

Ricky

Patrick replied on Friday, June 09, 2006

After searching on the old forum for "Object Level Security" I found what seems to be the most recent version of the ObjectSecurity code which uses a database as the backend. Here is the link so you dont need to search for it Smile [:)].

http://groups.msn.com/CSLANET/general.msnw?action=get_message&mview=0&ID_Message=13839

All the best
Patrick

stefan replied on Saturday, June 03, 2006

In addition, you should check if the user changed in the meantime (think of the ProjectTracher example logout-login feature.) Then you'd have to refresh the whole SecurityManager's cache...

Edit:
Well, emptying the SecurityManager's cache on each logout would accomplish this issue,
so it really wasn't an issue ;-)

Stefan

david.wendelken replied on Wednesday, June 14, 2006

Regardless of how the list of rules is created, one thing to consider is to have your rules authorization method allow a rule to remain defined but be disabled at run-time (via a screen in your application).

This is very handy when doing demonstrations of your pre-alpha, alpha or beta code to your users and you discover that one of your custom validation rules has been coded incorrectly.

Pop up the screen, turn the rule off, and continue with your demo!

It's much better than having your users twiddle their thumbs waiting for you to recompile/re-install - particularly if you have to get a slow, lazy sysadmin to do the installation due to your company's security policies.

vbexpert replied on Sunday, June 25, 2006

I'm new to C#. Currently using C# for my new application. I was told I could not use "this" in static method when I implemented the following.

RockfordLhotka:

....
Public Shared Function CanGetObject() As Boolean
  Return SecurityManager.GetSecurityInfo(Me).CanGetObject()
  ' return SecurityManager.GetSecurityInfo(this).CanGetObject();
End Function
...
 


From: Mark [mailto:cslanet@lhotka.net]  

I think I might explore the data-driven approach.  Haven't sat down and put much thought into it (yet), but I'm thinking I'd probably want a SecurityManager class that would cache all the security-related data from the database.  That would prevent repetitive data-access calls during object creation.  The individual objects would then talk to the SecurityManager instead of the DB directly.

Mark replied on Sunday, June 25, 2006

That's correct - you can't (you'd typically pass in the object type instead).  Rocky's pretty much eliminated the need for this SecurityManager class by introducing class-level ValidationRules and AuthorizationRules in the forthcoming 2.1 release of CSLA.

SonOfPirate replied on Tuesday, June 27, 2006

However, remaining consistent with the concept of collaboration used within CSLA and throughout the .NET Framework, creating a SecurityManager class would allow additional features and functions not provided by the object-level methods presented in 2.1. 

We've used this approach previously and are in the process of implementing again in the new version because we use many configuration settings to drive security, such as a master enable/disable flag and the ability to use "integrated" security on our apps, etc.  Under this approach, as Rocky has shown, our objects delegate the security checks to the SecurityManager which encapsulates all of the logic for the requested operations.  Of course, this can always be overriden when desired in our business classes.

 I would only recommend this if there is some valued added by a separate SecurityManager class; otherwise, as you've said, the 'built-in' object-level features do the job well.

Copyright (c) Marimer LLC