Ayende @ Rahien

Hi!
My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 5,968 | Comments: 44,488

filter by tags archive

Future Query Of implemented


It took very little time to actually make this work. I knew there was a reason liked my stack, it is flexible and easy to work with.

You can check the implementation here, it is about 100 lines of code.

And the test for it:

FutureQueryOf<Parent> futureQueryOfParents = new FutureQueryOf<Parent>(DetachedCriteria.For<Parent>());
FutureQueryOf<Child> futureQueryOfChildren = new FutureQueryOf<Child>(DetachedCriteria.For<Child>());
Assert.AreEqual(0, futureQueryOfParents.Results.Count);

//This also kills the database, because we use an in
// memory one ,so we ensure that the code is not 
// executing a second query
CurrentContext.DisposeUnitOfWork();

Assert.AreEqual(0,  futureQueryOfChildren.Results.Count);

Interception as an extensibility mechanism


I got a request to allow system-mode for Rhino Security, something like this:

using(Security.ActAsSystem())
{
	// in here the security behaves as if you have permission 
	// to do everything
	// queries are not enhanced, etc.
}

It is not something that I really want to allow, so I started to think how we can implement this, I came up with the following solution:

public class AuthorizationServiceWithActAsSystemSupport : IAuhorizationService
{
	IAuhorizationService inner;

	public AuthorizationServiceWithActAsSystemSupport(IAuhorizationService inner)
	{
		this.inner = innner;
	}

	private bool IsActAsSystem
	{
		get { return true.Equals(Local.Data["act.as.system"]); }
	}

	public bool IsAllowed(IUser user, string operationName)
	{
		if(IsActAsSystem)
			return true;
		return inner.IsAllowed(user, operationName);
	}

	public void AddPermissionsToQuery(IUser user, string operationName, ICriteria query)
	{
		if(IsActAsSystem)
			return;
		inner.AddPermissionsToQuery(user, operationName, query);
	}

	// .. the rest
}

Now, all we need to do is register it first:

component IAuthorizationService, AuthorizationServiceWithActAsSystemSupport

faciliy RhinoSecurityFacility

And that is it. This both answer the requirement and doesn't add the functionality that I don't like to the system.

Again, neat.

Is plagiarism the best compliment?


They say that plagiarism is the best compliment, although I have no idea who they are.

It was brought to my attention that this book seems to have lifted more than a few answers directly from my post, not to mention that nearly all the questions are lifted from Scott Hanselman's post.

I don't know if Scott was asked about it, but I certainly wasn't. I skimmed a bit in Google books and I couldn't find any credit section.

I really don't like it.

Future<TNHibernateQuery>


A while ago I added query batching support to NHibernate, so you can execute multiply queries to the database in a single roundtrip. That was well and good, except that you need to know, in advance, what you want to batch. This is often the case, but not nearly enough. Fairly often, I want disparate actions that would be batched together. It just occurred to me that this is entirely possible to do.

In my Rhino Igloo project, I have a lot of places where I have code very similar to this (except it can go for quite a while):

Users.DataSource = Controller.GetUsers();
Issues.DataSource = Controller.GetIssues();
Products.DataSource = Controller.GetProducts();
DataBind();

I solved the problem of batching those by figuring out in advance what I need and then doing a single batch query for all of them, then handing out the result through each of those methods.

This is complicated and sometimes fragile.

What would happen if I could ignore that and instead built API that looked like this?

public FutureOf<User> GetUsers();
public FutureOf<Issue> GetIssues();
public FutureOf<Product> GetProducts();

Where FutureOf<T> would be defined as:

public class FutureOf<T> : IEnumerable<T>
{
	//...
}

Now, what is special here, I hear you way. Well, when you start enumerating over a future, it gather all the future queries that has been created so far, executing them in a single batch against the database, and return the results.

Where before I needed to take special care to get this result, now it is just a naturally occurring phenomenon :-)

Neat, if I say so myself.

Rhino SecurityPart II - Discussing the Implementation


I just finished testing an annoying but important feature, NHibernate's second level cache integration with Rhino Security. The security rules are a natural candidate for caching, since they change to change on an infrequent basis but are queried often. As such, it is obvious why I spent time ensuring that the whole thing works successfully.

At any rate, what I wanted to talk about today was structure of the framework. You can see the table layout below.

A few things to note:

  • The tables are all in the "security" schema, I find that it makes more sense this way, but you can set it to work with "security_Operation" if you really like (or the DB doesn't support schemas).
  • User is referenced a few times, but is not shown here. As I mentioned earlier, the user entity is an external concept. We are using the mapping rewriting technique that we discussed earlier.

(more below)

image

Here is the main interface for Rhino Security:

image

The tasks it performs are:

  • Enhance a query with security information.
  • Get an explanation about why permission was given / denied.
  • Perform an explicit permission check on entity or feature.

The last two are fairly easy to understand, but what does the last one means? It means that if I want to perform a "select * from accounts" and I enhance the query, I will give this baby:

SELECT THIS_.ID          AS ID4_0_,

       THIS_.SECURITYKEY AS SECURITY2_4_0_,

       THIS_.NAME        AS NAME4_0_

FROM   ACCOUNTS THIS_

WHERE  @p0 = (SELECT   THIS_0_.ALLOW AS Y0_

              FROM     SECURITY_PERMISSIONS THIS_0_

                       INNER JOIN SECURITY_OPERATIONS OP1_

                         ON THIS_0_.OPERATION = OP1_.ID

                       LEFT OUTER JOIN SECURITY_ENTITIESGROUPS ENTITYGROU2_

                         ON THIS_0_.ENTITIESGROUP = ENTITYGROU2_.ID

                       LEFT OUTER JOIN SECURITY_ENTITYREFERENCESTOENTITIESGROUPS ENTITIES7_

                         ON ENTITYGROU2_.ID = ENTITIES7_.GROUPID

                       LEFT OUTER JOIN SECURITY_ENTITYREFERENCES ENTITYKEY3_

                         ON ENTITIES7_.ENTITYREFERENCEID = ENTITYKEY3_.ID

              WHERE    OP1_.NAME IN (@p1,@p2)

                       AND (THIS_0_."User" = @p3

                             OR THIS_0_.USERSGROUP IN (@p4))

                       AND ((THIS_.SECURITYKEY = THIS_0_.ENTITYSECURITYKEY

                              OR THIS_.SECURITYKEY = ENTITYKEY3_.ENTITYSECURITYKEY)

                             OR (THIS_0_.ENTITYSECURITYKEY IS NULL

                                 AND THIS_0_.ENTITIESGROUP IS NULL))

              ORDER BY THIS_0_.LEVEL DESC,

                       THIS_0_.ALLOW ASC);

Isn't it cute?  This is much better than some home grown security system that I have seen (some of which I have built, actually), since it is stable with regards to the cost of the query that it will use. I mention before that it is possible to de-normalize the information into a single table, but since this requires more invasive approach from the application side, and since I have not seen performance issues with this yet, I'll leave it at this point for the moment.

Advance: Working with non DB backed users

In most applications, the user is a fully fledged entity, even if your authentication is elsewhere. Just keeping things like preferences will necessitate that, but let us assume that we really have that as a non DB entity.

In this case, we would need to make modifications to the tables (which we generally do, anyway, although automatically), and re-map the user references as an IUserType that can get the user from an id instead of a foreign key to entity. I think I'll wait until someone really needs it to make a demo of it.

Anyway, this is the main magic. It was fairly hard to get it right, as a matter of fact. But the query enhancement was one of the things that made security a breeze in my last project. We had a custom security module, but many of the concepts are the same.

The next part we will talk a bit about the IsAllowed and how that works. There is some nice magic there as well.

NHibernate and the second level cache tips


I have been tearing my hair our today, because I couldn't figure out why something that should have worked didn't ( second level caching , obviously ).

Along the way, I found out several things that you should be aware of. First of all, let us talk about what the feature is, shall we?

NHibernate is design as an enterprise OR/M product, and as such, it has very good support for running in web farms scenarios. This support include running along side with distributed caches, including immediate farm wide updates.  NHibernate goes to great lengths to ensure cache consistency in these scenarios (it is not perfect, but it is very good). A lot of the things that tripped me today were related to just that, NHibernate was working to ensure cache consistency and I wasn't aware of that.

The way it works, NHibernate keeps three caches.

  • The entities cache - the entity data is disassembled and then put in the cache, ready to be assembled to entities again.
  • The queries cache - the identifiers of entities returned from queries, but no the data itself (since this is in the entities cache).
  • The update timestamp cache - the last time a table was written to.

The last cache is very important, since it ensures that the cache will not serve stale results.

Now, when we come to actually using the cache, we have the following semantics.

  • Each session is associated with a timestamp on creation.
  • Every time we put query results in the cache, the timestamp of the executing session is recorded.
  • The timestamp cache is updated whenever a table is written to, but in a tricky sort of way:
    • When we perform the actual writing, we write a value that is somewhere in the future to the cache. So all queries that hit the cache now will not find it, and then hit the DB to get the new data. Since we are in the middle of transaction, they would wait until we finish the transaction. If we are using low isolation level, and another thread / machine attempts to put the old results back in the cache, it wouldn't hold, because the update timestamp is into the future.
    • When we perform the commit on the transaction, we update the timestamp cache with the current value.

Now, let us think about the meaning of this, shall we?

If a session has perform an update to a table, committed the transaction and then executed a cache query, it is not valid for the cache. That is because the timestamp written to the update cache is the transaction commit timestamp, while the query timestamp is the session's timestamp, which obviously comes earlier.

The update timestamp cache is not updated until you commit the transaction! This is to ensure that you will not read "uncommited values" from the cache.

Another gotcha is that if you open a session with your own connection, it will not be able to put anything in the cache (all its cached queries will have invalid timestamps!)

In general, those are not things that you need to concern yourself with, but I spent some time today just trying to get tests for the second level caching working, and it took me time to realize that in the tests I didn't used transactions and I used the same session for querying as for performing the updates.

Convention based security: A MonoRail Sample


I was asked how I would got about building a real world security with the concept of securing operations instead of data.

This is a quick & dirty implementation of the concept by marrying Rhino Security to MonoRail. This is so quick and dirty that I haven't even run it, so take this as a concept, not the real implementation, please.

The idea is that we can map each request to an operation, and use the convention of "id" as a special meaning to perform operation security that pertain to specific data.

Here is the code:

public class RhinoSecurityFilter : IFilter
{
    private readonly IAuthorizationService authorizationService;

    public RhinoSecurityFilter(IAuthorizationService authorizationService)
    {
        this.authorizationService = authorizationService;
    }

    public bool Perform(ExecuteWhen exec, IEngineContext context, IController controller,
                        IControllerContext controllerContext)
    {
        string operation = "/" + controllerContext.Name + "/" + controllerContext.Action;
        string id = context.Request["id"];
        object entity = null;
        if (string.IsNullOrEmpty(id) == false)
        {
            Type entityType = GetEntityType(controller);
            entity = TryGetEntity(entityType, id);
        }

        if(entity==null)
        {
            if (authorizationService.IsAllowed(context.CurrentUser, operation) == false)
            {
                DenyAccessToAction();
            }
        }
        else
        {
            if (authorizationService.IsAllowed(context.CurrentUser, entity, operation) == false)
            {
                DenyAccessToAction();
            }
        }
        return true;
    }
}

It just perform a security check using the /Controller/Action names, and it tries to get the entity from the "id" parameter if it can.

Then, we can write our base controller:

[Filter(ExecuteWhen.BeforeAction,typeof(RhinoSecurityFilter))]
public class AbstractController : SmartDispatcherController
{

}

Now you are left with configuring the security, but you already have a cross cutting security implementation.

As an example, hitting this url: /orders/list.castle?id=15

Will perform a security check that you have permission to list customer's 15 orders.

This is pretty extensive, probably overly so, however. A better alternative would be to define an attribute with the ability to override the default operation name, so you can group several action into the same operation.

You would still need a way to bypass that, however, since there are some thing where you would have to allow access and perform custom permissions, no matter how flexible Rhino Security is, or you may be required to do multiply checks to verify that, and this system doesn't allow for it.

Anyway, this is the overall idea, thoughts?

Designing the Security Model


Right now I want to talk more deeply than merely the security infrastructure, I want to talk about how you use this security infrastructure.

There are several approaches for those. One of them, which I have seen used heavily in CSLA, is to simply make the check in the properties. Something like this:

public class Comment
{
	public virtual IPAddress OriginIP 
	{ 
		get 
		{ 
			CanReadProperty(true); 
			return originIP; 
		} 
		set 
		{ 
			CanWriteProperty(true); 
			originIP = value; 
		} 
	}

	public virtual bool CanDelete() { ... }
}

We can move to a declarative model with attributes, like this:

[SecuredEntity]
public class Comment
{
	[SecuredProperty]
	public virtual IPAddress OriginIP
	{
		get { return originIP; }
		set { originIP = value; }
	}
}

We can take it a step further and decide that we don't want to explicitly state this, and just assume it by convention.

A while ago I decided to make a system work in this exact fashion. Of course, I am a big believer of convention over configuration, so we defined the following rules for the application:

  • Need to secure  Read / Write / Delete
  • Need to support custom operation as well, like "Assign work", "Authorize time sheet", etc
  • Developers will forget to make security calls, we need to develop a system that protects us from this.

We built a really nice implementation that hooked directly into the container and the data access later, you literally could not make a security breach, because you were always running under the context of a user, and the data was filtered for you by the data access in a generic fashion. For that matter, we didn't have to worry about authorization in the business code, we made in memory modification and then persisted that. If we had a security violation, we simply showed an error to the user.

We didn't have to define anything in the code either, it was all convention based and implicit. The only complexity was in configuring the security system itself, but that was the nature of the beast, after all. We though that we found the ultimate security pattern, and were quite pleased with ourselves. Until we started user testing. Then we run into... interesting issues.

We had the idea of a rule in the system, which could be used by the administrators to set policies. It worked just fine in our testing, until we started to get impossible errors from the users. I think that you can understand what it was by now, right? (Yes, the usual, developers always test as admin)

Normal users didn't have permissions to read those rules, but the system really needed them to perform core parts of its tasks. We are always running under the user context and we are always making the security check. The system was designed, up front, to be very explicit about it. Now we found that there really were reasons where the system needed access to the entities without performing those security checks.

Another "interesting issue" that came up was the issue of information aggregation. As it turn out, it was always the wrong idea to report that there is only a single entity in the system, just because the user has access to just that one. I'll let you draw the conclusion about the HR users that found out that they really couldn't see how many hours an employee worked in this month.

It was a big problem, and we had to scramble around and hack-a-lot the ultimate security solution that we so loved.

The security system had two major issues:

  • It was too granular.
  • It didn't have any operating context.

Since then, I have learned a lot about how to design and implement security modules, and my current design has the following requirements:

  • Security decisions are made on a use case level
  • Have a standard, enforced, approach of dealing with security
  • Make security decision easy to code.

How does this translate to code?

Well, first I need to define what a use case is in the code. For a web application, it is almost always at the page / request level, and that makes it very easy to deal with.

In my last project, we had the following base class defined:

public abstract class AbstractController
{
	public abstract AssertUserIsAllowed();
}

Since all the controllers in the application inherited from AbstractController, we had a single place that we put all the security checks. We still had to deal with security in other places, such as when we loaded data from the database, or wanted partial views, but this approach meant that we had remembered what was going on. If we needed to make security decisions elsewhere, we commented that in the assert.

But this was in a Rhino Igloo application, where by necessity we had to have a controller per page. Using MonoRail, we usually have a single controller that handles several actions, in which case I would tend to write something like this:

[AllowEveryone]
public void Login()
{
	...
}

[AllowAuthenticatedUsers]
public void Index()
{
	...
}
[ActionPerformsCustomSecurityCheck]
public void Save(...)
{
	...
}

And then I would mandate that all actions would have to have security attributes on them (Mandate as in, if it doesn't have security attribute, you can't access it).

Well, actually, right now I would probably route it through Rhino Security, which would give me more flexibility than this model, and would keep it out of the code.

Nevertheless, I would put security at the use case level. This is where I have the context to ask the correct questions. Anything else tend to lead to an increasingly complex set of special rules.

Rhino Security Overview: Part I


A few months ago I spoke about how I would build a security infrastructure for an enterprise application, I went over the design goals that I had and the failing of previous attempts.

Since then, I got a few requests to implement that, and since this is really neat piece of work, I decided to go ahead and build it.

The main goals, allow me to remind you, are:

  • Flexible
  • Performant
  • Does not constrain the domain model
  • Easy to work with
  • Understandable
  • No surprises

You can read the post about it to get a feeling about what I had in mind when I thought it up.

When it came the time to actually implement them, however, it turn out that as usual, the implementation is significantly different than the design in all the details. Here is the overall detail of the entities involved.

The main part that we have here is the security model, but notice that the application domain model is off to the side, and have very little to do with the security model. In fact, there is only a single requirement from the application domain model, the User entity needs to implement an interface with a single property, that is all. (more below)

image

 

From the point of view of interactions with the security system, we have two extensions points that we need to supply, a User entity implementing IUser, and a set of services implementing IEntityInformationExtractor<TEntity>:

image

The use of IEntityInformationExtractor<TEntity> is an interesting one. Rhino Security is using all my usual infrastructure, so it can take advantage of Windsor' generic specialization to do some nice tricks. Components of IEntityInformationExtractor<TEntity> are registered in the container, and resolved at runtime when there is a need for them.

This means that you can either implement a generic one for your model, or specialize as needed using generics. I like this approach very much, frankly.

From the point of view of the security model, we have the following:

  • User - the external User entity that is mapped into the security domain. Permissions are defined for users.
  • Users Group - a named grouping of users. Permissions are defined for users groups.
  • Entity - an external entity. Permissions are defined on entities.
  • Entities Groups - a named groups of entities. Permissions are defined on entities groups.
  • Operation - a named operation in the system, using the "/Account/Financial/View" pattern.
  • Permission - Allow or deny an operation for user / users group for an entity / entities group.

Here are a few examples of the kind of rules that we can defined with this method:

  • Allow "/Account/Financial/View" for "Ayende" on "All Accounts", level 1
  • Allow "/Account/Financial/View" for "Accounting Department" on "All Accounts", Level 1
  • Allow "/Case/Assign" for "HelpDesk" on "Standard cases", level 1
  • Allow "/Employee" for "Joe Smith" on "Direct Reports of Joe Smith", level 1

The major shift here is that we treat both entities and users groups as very cheap resources. Instead of having a just a few and structuring around them, we define what we want and then structure the groups around them. The burden them moves from complex code to maintaining the structure. I find this a very reasonable tradeoff for a simple security model and the flexibility that it gives me.

Next time, setting up the security model...

SQLite vs. SQL CE


Those two seems to be the most common embedded databases in the .NET world. This is important to me, since I want to do testing against embedded database.

SQL CE can be used with SQL Management Studio, which is nice, but it has three major issues for me so far:

  • It doesn't support memory only operations. SQLite does, and it means a difference of 12 seconds vs. 40 seconds in running ~100 tests that hit the DB. This is important, especially kicking up everything seems to take about 10 seconds anyway (using Test Driven.Net)
  • It doesn't support paging (WTF!)
  • It doesn't support comparing to a sub query, so this is not legal:
    select * from account where 1 = (select allow from permissions)

Right now I am experimenting with just how much I can twist around to get everything to break.

I am on the third NH bug this week, and counting :-)

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. Career planning (6):
    24 Jul 2015 - The immortal choices aren't
  2. Production postmortem (4):
    23 Jul 2015 - The case of the native memory leak
  3. API Design (7):
    20 Jul 2015 - We’ll let the users sort it out
  4. What is new in RavenDB 3.5 (3):
    15 Jul 2015 - Exploring data in the dark
  5. The RavenDB Comic Strip (3):
    28 May 2015 - Part III – High availability & sleeping soundly
View all series

RECENT COMMENTS

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats