Posts tagged “declarative_authorization”.

Garlic: Plugin Tests against Various Rails Versions

With Rails 2.2 around the corner, I decided to implement a scalable testing infrastructure for the declarative_authorization plugin. One great thing to notice at the RailsConf Europe was Ian’s garlic.  Though only given as a side note in Ian’s talk on resources_controller, it provides a nice way of keeping your plugin tested against all those Rails versions.

Very easy to set up.  Only add to your Rakefile a few lines that run garlic:

if File.directory?(File.join(File.dirname(__FILE__), 'garlic'))
  require File.join(File.dirname(__FILE__), 'garlic/lib/garlic_tasks')
  require File.join(File.dirname(__FILE__), 'garlic')
end
 
desc "clone the garlic repo (for running ci tasks)"
task :get_garlic do
  sh "git clone git://github.com/ianwhite/garlic.git garlic"
end

And define the tasks that garlic should perform for you.  In the declarative_authorization case, garlic should retrieve the plugin from the current path and take a few Rails versions as targets. For the test run, garlic just needs to run “rake”. This is the necessary recipe:

garlic do
  repo 'rails', :url => 'git://github.com/rails/rails'
  repo 'declarative_authorization', :path => '.'
 
  target 'edge'
  target '2.1-stable', :branch => 'origin/2-1-stable'
  target '2.2.0-RC1', :tag => 'v2.2.0'
 
  all_targets do
    prepare do
      plugin 'declarative_authorization', :clone => true
    end
 
    run do
      cd "vendor/plugins/declarative_authorization" do
        sh "rake"
      end
    end
  end
end

Thus, all that is needed to check my current declarative_authorization branch against all defined Rails versions is

rake get_garlic # just once
rake garlic:all

Great, all declarative_authorization tests pass on 2.2.0-RC1!

All specified targets passed: edge, 2.1-stable, 2.2.0-RC1

Authorization for 90 Controllers, 200 Models (and Counting…)

One of the interesting comments on our RailsConf Europe presentation on declarative_authorization was offered by Timo Hentschel. He stated that on the Rails CRM project with 90 Controllers and 200 Models that he is working on the declarative_authorization approach was simply not viable. Projects of this size are currently not the target of our plugin, though. Currently, we focus on bringing maintainable authorization into small to medium applications. Nevertheless, it is interesting to look into Timo’s points:

  • “Role definition is for admins not developers”: It certainly depends on the project size. With small to medium apps (our primary target) admins might just be the developers. Still, our future plans include a possible move of the authorization rules to database, enabling a policy editing UI.
  • “You’d need a UI for handling the policy development”: This might be true. But without further evaluation, I am not convinced of the superior performance of a UI when compared to a readable, concise policy syntax. Policy files still provide documentation and specification for free. We will look into UIs, especially to facilitate a test-driven policy development approach, though.
  • “I can’t redeploy on every role modification”: In practice, engineering an application’s policy is certainly error prone. Missing permissions will have to be added to roles once taken into production. Changing roles on a production system isn’t optimal either, though: role-permission assignments need to be carefully checked for side effects. Thus, a QA workflow would be desirable, just as provided by a deployment cycle. I would prefer to handle missing permission assignments just like other software bugs which need to be fixed asap. Nevertheless, with the planned features (TDD, UI, policy in DB) and an integrated authorization workflow, online role modifications may be feasible. In our self-service authorization approach we would even like end users to extend their permissions on their own, on a limited scope and in some environments.
  • “With 90 Controllers, the authorization policy will become unmanageably long”: This is certainly true with the current syntax. On the one hand, we will distribute rules to multiple files in order to group similar aspects. Also, currently one context is used per model. A hierarchy of contexts is planned to cut the number of specific rules and thus ease policy development and maintainability.

From Rails Security to Application Security

I’m in Berlin for RailsConf Europe currently where I’m talking together with Carsten Bormann about implementing application security in Agile development with Rails and announcing declarative_authorization.

Here is our presentation (will only really display nicely on Firefox 3, though, sorry; full window view):

Declarative Authorization

Having looked through quite a few existing Rails authorization plugins, we decided, we were in need of a different approach.  Mainly, it was the missing separation of authorization logic from business logic in the evaluated plugins that caused us to implement a new plugin, declarative_authorization.

In our declarative approach, authorization rules are grouped in a policy file, while only privileges are used inside program code to enforce restrictions. We developed for flexibility and simplicity, requiring only very simple statements in rules and program code. So instead of

class ConferenceController < ApplicationController
  access_control :DEFAULT => [:admin],
    [:index, :show]  => [...],
    [:edit, :update] => [:admin, :conference_organizer]
end

cond = permit?([:admin, :conference_organizer]) ?
           {} : {:published => true}
Conference.find(:all, :conditions => cond)

<% restrict_to [:admin, :conference_organizer] do %>
  <%= link_to 'Edit', edit_conference_path(conference) %>
<% end %>

with all the authorization logic interweaved with your code, you only need this

class ConferencesController < ApplicationController
  filter_access_to :all

  def index
    @conferences = Conference.with_permissions_to(:read)
  end
end

<%= link_to 'Edit', edit_conference_path(conference)
            if permitted_to? :edit, conference %>

And, separated in one place the authorization rules:

role :guest do
  has_permission_on :conferences, :to => :read
end

role :conference_organizer do
  has_permission_on :conferences, :to => :manage
end

So, the same rules are used in enforcing authorization in Model, View and Controller. Also, they are used for Query Rewriting to automatically constrain the retrieved records according to the authorization rules.  Thus, you just modify the rules on authorization requirement changes and you can also use the rules to talk to business owners of Agile projects.

For additional information and more examples, refer to the README and the rdoc documentation. Currently, we are using the plugin for an application with fairly complex authorization and it will be taking into production in the next iteration. So, look into it if you have authorization concerns in your application, it’s released under MIT license.