Recently by Jeff Kunkle

Near Infinity recently announced the release of Grant, a Ruby on Rails plugin for securing and auditing access to your Rails model objects, and I'm here to tell you a little bit about it. There are two primary pieces of Grant, model security and model audit. I'll be focusing on model security for this post and will address model audit in a later entry.

Grant's model security is deliberately designed to force the developer to make conscious security decisions about what CRUD operations a user should be allowed to perform on your model objects. It doesn't care how you choose to authenticate and authorize your users to perform a CRUD operation, it only cares that you actually do it.

Rather than specify which operations are restricted, Grant restricts all CRUD operations unless they're explicitly granted to the user. It also restricts adding or removing items from has_many and has_and_belongs_to_many associations. Only allowing operations explicitly granted forces you to make conscious security decisions. While it obviously can't ensure you make the correct decisions, it should help ease the latent fear that you've inadvertently forgotten to secure something.

Enough talk, let me show you an example of how you might use it. To enable model security you simply include the Grant::ModelSecurity module in your model class. In this example you see three grant statements. The first grants find (aka read) permission to everyone. The second example grants create, update, and destroy permission when the passed block evaluates to true, which in this case happens when the model is editable by the current user. You can put any code you want in that block as long as it returns a boolean value. Similarly, the third grant statement permits additions and removals from the tags association when it's block evaluates to true. A Grant::ModelSecurityError is raised if any grant block evaluates to false or nil.

class EditablePage < ActiveRecord::Base
  include Grant::ModelSecurity
  has_many :tags

  grant(:find) { true }
  grant(:create, :update, :destroy) do |user, model| 
    model.editable_by_user? user 
  end
  grant(:add => :tags, :remove => :tags) do |user, model, associated_model| 
    model.editable_by_user? user 
  end

  def editable_by_user? user
    user.administrator?
  end
end

There's a lot more to the grant statement than shown in the above example. For instance, you can have multiple grant statements for the same action. Ultimate permission to perform the action will not be granted unless all grant blocks evaluate to true.

As you can see, Grant is pretty simple to use, but it's not going to do the dirty work for you. It's up to you to make the proper security decisions. Grant's just there to make sure you don't forget.

The safe navigation operator is almost certainly my favorite operator in Groovy. It allows you to guard against NullPointerException(s) much more cleanly than defining a nasty if/else mess. Consider the following example.

class Book {
    String title
    Author author
}

class Author {
    String firstName
    String lastName
}

def author = new Author(firstName:'Jason')
def book = new Book(title:'Say no to NPEs', author:author)

println book.author?.lastName

Did you see that ?. operator on the last line of the code sample? That's the safe navigation operator, and it's the equivalent of writing the following if statement (although it's much more readable).

if (book.author != null) {
    println book.author.lastName
}

The safe navigation operator essentially checks to see if the object you're about to invoke a method on is null. If it is null, it simply skips the method invocation and returns null. If it isn't null, it proceeds as usual. It works for method chaining too, so if you're worried about book being null, you could write

println book?.author?.lastName

This way, if either book or author are null, you simply print out null instead of causing a NullPointerException.

Since learning about the safe navigation operator, I've used it successfully in dozens of classes without any problem. Until last week. Consider the following line of code .

println book?.author?.firstName?.trim().concat(" is great.")

Thanks to the safe navigation operator we can write this concatenation of firstName and a sentence fragment without worrying about NullPointerException(s) and ugly if blocks. Or so I thought.

Looking at this line of code, I thought for sure I was safe from any sneaky NullPointerException. If book, author or firstName are null I'll simply end up printing null and not have to worry about the concat() method. After all, if the trim() method succeeds, there's no sense in guarding it's result for null. And that's where I was wrong.

I naively assumed the method chain would stop once the safe navigation operator encountered a null when in fact it does not. While the trim() method is safe from being called on a null firstName object, it will return null, upon which the concat() method is called. Oops!

While I was reading through some Apple documentation on Bonjour I stumbled across a discussion on link-local addressing and DNS search domains. While the details of link-local addressing aren't that important here, the discussion on DNS search domains triggered a little light bulb in my brain.

You see, DNS search domains are used as a guide to help your computer lookup an IP address when something simple like "blogs" is typed into your browser's URL. If you setup a DNS search domain of "nearinfinity.com", typing "blogs" will force your computer to first check if there's an address for "blogs.nearinfinity.com". If not it falls back to its default behavior.

If you're a person that spends a lot of time on a small number of websites, you could use DNS search domains to your advantage to make navigating to those sites a snap. For instance, I just setup "nearinfinity.com" as an entry in my DNS search domains on my Mac. Simply go to the network preferences pane, click the advanced button at the bottom left, and then the DNS tab on the resulting popup.

dns_search_domains_osx.jpg

So now, whenever I type "blogs" in my URL I get "blogs.nearinfinity.com". Whenever I type "support" I get "support.nearinfinity.com". I think you probably get the idea. I know I'm no genius for discovering this since it's precisely the reason for having search domains. I just never thought to use them before.

Quick quiz, what is the output from the following JUnit test?

package com.nearinfinity.sandbox;
import junit.framework.TestCase;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class ModelTest extends TestCase {

    @Before
    public void setUp() {
        System.out.println("Setup called.");
    }

    @After
    public void teardown() {
        System.out.println("Teardown called.");
    }
 
    @Test
    public void testSomething() {
        assertTrue(true);
    }
 
}

If you said

Setup has been called.
Teardown has been called.

you'd be wrong. Don't feel bad though, I spent about two hours staring at a similar test until I finally figured out what was going on. So, what's the problem?

The problem lies in the mixed use of JUnit 3 and 4 concepts. The astute reader will notice that this test extends the JUnit 3 junit.framework.TestCase while also using JUnit 4 annotations. So which wins, the base class methods, the annotations, or both? Well, it turns out that the JUnit 3 base class conventions win out and the annotations are ignored. With that said, can you now guess what the test output is? Did you guess

Setup has been called.

If not, don't feel bad. It's not immediately obvious. It turns out that the testSomething test method runs because it starts with the word test, not because it's decorated with the org.junit.Test annotation. The setUp method runs because it overrides junit.framework.TestCase's setUp method, not because it has a org.junit.Before annotation. Lastly, the teardown method doesn't run at all because it does not override the base class tearDown method due to the lowercase "d" and as we've seen, the org.junit.After annotation has no effect.

That lower case "d" cost me two hours of my life, which I now consider time well spent. It made me realize that my test's inheritance chain ultimately led to junit.framework.TestCase. The fact that the test had worked in the past was a textbook case of dumb luck.

So, if your JUnit 4 test classes start acting strange, make sure that base class you're extending doesn't ultimately lead to a junit.framework.TestCase.

The merits of placing security in the application layer versus the database is a debate I seem to find myself in regularly. As an application developer, I've historically argued for application-level security. It was something I understood well and felt like I had some control over. Over time, I've come to understand the debate from many perspectives and have adjusted my convictions accordingly.

For the record, I don't believe there is any absolutely correct answer. There are valid arguments for each side of the debate. My perspective has mostly been shaped through experience developing custom software for clients. I have little experience developing commercial software and surmise that your thoughts on the subject may differ if that's your day job.

In my experience, most customers view their data as the most important aspect of any system, not the application. They want to be sure their data is safe at all times. What if someone accesses the database through a different application, a third-party data broker or directly via a SQL client? How do you protect the data in those situations if all the restrictions are resident in the application? I hear these questions all the time.

The rebuttal to this argument that I hear most often is that nobody will ever access the data outside of the application. This seems like an obviously shortsighted statement to me and I don't think anyone actually believes it. It's more of a synonym for saying that you'd rather not worry about security at the database layer because it's out of your control, too hard, etc. Pick your favorite excuse. I've probably used them all myself.

What it all boils down to is that the database is very likely to outlive your application. In fact, it'll probably outlive your application and several subsequent ones. Why would a customer want to pay someone to rebuild the security logic each time? It's tedious, expensive, and error prone. Additionally, you're application may not be the only one accessing the database. What are the odds that two development teams implement security constraints the same exact way in each application? Not good, I promise.

As I stated in the beginning, I've definitely changed my perspectives on application versus database-level security. I was certainly an application-level security bigot before, but I find it difficult to continue my unwavering ways when looking at the problem more critically. I just hope my fellow colleagues don't renounce me for siding with the DBAs on this one.