00:00:16.960
Okay.
00:00:18.000
Can everyone hear me? Please raise your hand.
00:00:21.520
Yeah, cool! Uh, this is my first talk, so I’m a little bit nervous.
00:00:24.560
I’m going to actually take a picture for my mom.
00:00:26.880
So, if everyone can just wave, awesome!
00:00:29.039
Yes, right!
00:00:38.000
Alright, cool. So, my talk is about authorization.
00:00:41.200
Um, service-oriented authorization.
00:00:44.480
My name is Alan, by the way. You can find me on Twitter and GitHub.
00:00:51.920
I work at a company called Climate Corporation. I'm a Ruby developer there, and I’ve been with them for about a year and a half working on our insurance product. I work on the back end as well as other parts of our web infrastructure.
00:01:06.320
We have products that help protect farmers from weather disasters and improve their farming operations during the planting season and before and after.
00:01:29.759
Um, it’s sort of like—I'm going to make it buzzword compliant—it's big data farming.
00:01:38.320
So, a little bit of background before I get into my talk. What is authorization?
00:01:51.919
So, if you were in this room before, you probably learned about authentication in a service-oriented environment. Today, I’m talking about authorization.
00:02:07.439
Authentication is concerned with identity, while authorization is concerned with access.
00:02:19.760
There are different types of authorization. If you’ve ever implemented it, you could think about role-based access control, attribute-based access control, access control lists, rule-based action control—it can go on and on.
00:02:30.239
I’m not talking about a specific implementation of authorization, but just in general.
00:02:32.560
So, what is service-oriented architecture? There have been many talks on service-oriented architecture at this conference. This entire track is about it.
00:02:51.840
You know, there have been talks yesterday, and I’ve attended a few of them. Service-oriented architecture comprises many different solutions to various problems, but it revolves around the same theme.
00:03:02.560
I guess what I want to find is a basic definition of it. I found this: it’s a loosely coupled architecture designed to meet the business needs of an organization.
00:03:16.319
I found this on the Microsoft Developer Network site, and it also had this really interesting quote.
00:03:18.800
SOAs are like snowflakes; no two are alike.
00:03:21.120
I wanted to find a better definition, and actually, when I was watching Brian Martin’s talk from "Big Rails, Big Ruby" last year, he said components scale individually.
00:03:28.239
That’s how he defines service-oriented architecture. I recommend that talk if you want to learn about implementing service-oriented architecture from someone who's had battle scars moving over to something like that.
00:03:54.319
But today, I’m not focusing on what it is. So, why talk about it? Why use service-oriented architecture?
00:04:14.000
Before we get into authorization, I want to discuss why we would use SOA. SOA offers many advantages.
00:04:31.360
Reusability: we can allocate resources as we need them. Loose coupling: we can change out libraries. It provides a code base that scales across teams.
00:04:37.360
So, we gain benefits that are good for both our software and our software development process.
00:04:56.520
However, there are challenges as well when you have service-oriented architecture. Services speaking to one another means that many things can become difficult.
00:05:16.400
But hopefully, you’re here because the benefits of SOA outweigh the problems that you might encounter.
00:05:22.080
And you’ve likely already made that decision; I’m not here to sell you on it.
00:05:24.640
So, what is service-oriented authorization?
00:05:27.680
If we think about the benefits of service-oriented architecture, it should parallel with authorization.
00:05:52.880
Reusability: I want to be able to use the same authorization tools, libraries, and code across multiple services.
00:06:08.160
Loose coupling: my application code is not tightly coupled to my authorization implementation.
00:06:22.080
And then lastly, scalability: this is a requirement when you have multiple services. This will be a general requirement when we discuss the framework I want to use.
00:06:40.160
Let’s imagine a typical Rails application, ignoring things like the database and other third-party services.
00:06:58.320
You have Rails, you have your business logic, and then you have some third-party gems you might use.
00:07:07.360
The important part is your business logic. If you have an online product like Basecamp, that’s the interesting stuff. That’s the part that’s going to generate revenue.
00:07:21.760
That’s why your customers pay you money—everything else is just there to help deliver that product.
00:07:39.760
I think authorization can be viewed as part of your business logic, whether it’s part of the security of your application or part of a feature in your application.
00:07:55.360
For example, only your employees should administer customer data for customer support, or in a product like Basecamp, you have admin users in different groups.
00:08:10.639
So, what does authorization look like today? I believe the most popular authorization library is CanCan.
00:08:25.600
I don’t know if you can see this, but here’s a snapshot of CanCan’s GitHub page. I think it’s probably the most popular authorization gem.
00:08:42.160
We use it in production, and it works. Historically, it has been well supported, and I think it’s still pretty good.
00:08:59.520
It provides a really nice declarative DSL for specifying rules for authorization.
00:09:13.200
With CanCan, you specify your rules within your application using a nice Ruby DSL. You can then ask questions like, 'Can a user manage this other user's data?' or 'Can a user purchase a policy if you’re selling insurance?'.
00:09:40.560
The question is, does this approach align with what we define as service-oriented authorization?
00:09:54.560
CanCan is reusable because it’s a library, and its authorization implementation is decoupled from our application.
00:10:15.360
However, it’s not really loosely coupled if you think about it: your authorization rules are embedded in your application code.
00:10:41.440
So, the rules are in your application, and there are limitations to this approach that aren’t immediately apparent.
00:11:01.920
If we want to keep the core of our application small and understandable, we need to focus on our business logic, which is what generates revenue.
00:11:13.680
Our business logic should only concern itself with authorization to the extent that we need to enforce it. We shouldn't care how it's implemented, just that it works.
00:11:33.760
This is your business logic enforcing authorization in your code, while the rest should be thought of as implementation details.
00:11:43.760
In a service-oriented architecture, you typically begin with a monolithic application. If we couple our rules to our application, it becomes difficult to break things into services.
00:12:03.760
This is especially challenging if these services concern a user—if you have user rules in your monolithic app, they need to be split out.
00:12:16.560
This could work if you’re going to continue using CanCan across these different Ruby or Rails applications, but a service-oriented architecture typically indicates you'll have a heterogeneous environment.
00:12:36.799
In production today, we don’t just have the Rails stack; we have other technologies like Java or Clojure, or whatever it may be in the future.
00:12:54.560
There isn’t an easy way to transition from CanCan to Clojure.
00:13:06.720
Therefore, we need to consider a different framework for this.
00:13:09.760
The goals of our approach include reusability, scalability, and loose coupling.
00:13:26.560
Let’s return to our app: we have a simplified Rails app that we can transition into different services.
00:13:41.040
Imagine your app when you move it onto different services: you might have different JavaScript front ends communicating to several different back ends.
00:13:57.360
The business logic that once resided in a single application may now reside across multiple applications.
00:14:14.720
The key takeaway is that this is a heterogeneous environment, and we shouldn't constrain ourselves by language or runtime.
00:14:39.520
Instead, we want to use the best tools available to grow and build our services.
00:14:56.320
Reusability means we want code that doesn’t require us to predict the future.
00:15:03.760
If I want to extract my authorization into another service, or part of my authorization into a separate service, I need to do that without having to rewrite everything.
00:15:19.760
Loose coupling indicates that we’re going to decouple the access decision from the access policy.
00:15:38.560
Therefore, we can’t use this approach outside our Rails application.
00:15:49.440
We also need the framework to be scalable.
00:16:04.160
While researching tools for this, I did not find much that satisfied our needs.
00:16:07.920
However, I did come across XACML. Raise your hand if you’ve heard of XACML?
00:16:25.840
It’s XML and stands for Extensible Access Control Markup Language. It’s a declarative policy language implemented in XML.
00:16:43.680
It defines a processing model that describes how to evaluate access requests according to rules defined in policies.
00:17:04.080
The specification is quite extensive, detailing an entire architecture using XML to define authorization rules.
00:17:14.880
The XACML model supports and encourages the separation of the access decision from the point of use.
00:17:52.560
When access decisions are baked into client applications, it’s very difficult to update the decision criteria as policies change.
00:18:07.280
However, if the client is decoupled from the access decision, then authorization policies can be updated on the fly and affect all clients immediately.
00:18:22.760
Here’s an example of what an XACML policy could look like. It’s complex, but it offers the ability to update and modify rules without altering the application code.
00:18:52.320
This approach allows us to use it in a heterogeneous environment, provided we have some authorization library that we can integrate into our application.
00:19:10.560
However, I feel this is overly complex for our needs. Our application is fairly simple compared to what I've seen.
00:19:29.840
So, when discussing this authorization framework, we thought about creating a very simple language that we could use.
00:19:43.680
As we build it out and test it, we can experiment with it, and if needed, we can incorporate additional features.
00:19:56.640
Initially, we aimed to implement as few features as possible.
00:20:09.680
Recapping, we talked about why we would choose service-oriented architecture and what service-oriented architecture might be.
00:20:20.000
We set our goals to include scalability, flexibility, and loose coupling.
00:20:31.680
In terms of our framework, we developed a language where we could define authorization policies.
00:20:44.160
This language is designed to be agnostic to Rails and allows us to create a reference implementation.
00:20:57.760
From there, we can determine if it is robust enough to replace our current implementation.
00:21:05.440
This is like version 0.1 alpha of the language; we don’t have an official specification, but we have a rough initial spec.
00:21:19.040
Let’s explore each object in this JSON structure.
00:21:37.040
First, we have a resource that can be defined within a namespace, such as the name of a class. If it's in a Rails application, it could be an Active Record model.
00:21:52.800
Then, we have an action or a set of actions. A rule will apply to a specific set of actions, similar to how CanCan operates.
00:22:07.760
Each rule will have conditions that define the evaluation context, determining if a rule is applicable.
00:22:27.200
For instance, the role of a user must equal 'admin' for access to be granted.
00:22:46.400
Every rule will also have an effect—either 'allow' or 'deny'.
00:23:00.000
We now have this language, but we need to link it to the application—what connects these two elements?
00:23:16.960
I've developed a small gem called Ironhide, following the convention of naming our gems after Transformer characters.
00:23:34.560
Ironhide serves as this bridge, allowing us to define a set of rules and include Ironhide in our application.
00:23:54.080
Ironhide exposes the same API that CanCan would, serving as a drop-in replacement.
00:24:03.040
It's important to note that Ironhide is not a service; it doesn't provide an authorization service.
00:24:12.000
It is simply a library that can link our application to various rules stored externally.
00:24:23.920
These rules can be stored anywhere, allowing flexibility in how and where they are stored.
00:24:34.160
Having this plugability gives us scalability. Now, do these goals align with our needs?
00:24:48.560
Reusability, scalability, and loose coupling are central to our approach.
00:25:05.920
The authorization rules are not part of the application code, nor are they confined within a single language.
00:25:19.040
They should be reusable across various environments, and by decoupling the backing store from the implementation, we ensure scalability.
00:25:37.360
Today, this project is still a work in progress. We’re continuing to experiment with it.
00:25:44.320
While XACML is a well-defined enterprise-level spec, we're in the process of designing and refining our implementation.
00:25:54.720
We're exploring whether this will be able to scale to many rules across many services.
00:26:04.560
I haven't figured out all the answers yet; it’s not yet in production.
00:26:14.320
Additionally, we need to standardize and name this policy language, as it currently has no name.
00:26:27.680
I'd like to finish my talk with a demo, so let’s see if this works.
00:26:41.520
Can everyone see that?
00:26:53.840
If I make the background light and the foreground dark, would that help?
00:27:03.840
Alright, so this is a rule that I’ve written directly into a flat file on my disk.
00:27:09.600
We define a resource within this app namespace, along with a set of actions, an effect, and a set of conditions.
00:27:27.520
Each user can be authorized to read or manage another user, with the condition that the user's ID equals that other user's manager ID.
00:27:43.760
Let's run this and jump directly into the console to start writing some code.
00:28:00.000
I can access user information.
00:28:11.120
This user has a manager ID, and that equals the manager's ID.
00:28:30.360
I didn't go into detail with the Ironhide library, but I’ll post a link to the source code.
00:28:46.160
I've tried to write a well-documented README, so it should be straightforward.
00:29:03.760
I’ve also created a configuration section.
00:29:11.600
So it works!
00:29:23.760
It’s amusing because I tried recording this, and it was probably easier to do it live.
00:29:33.840
Let me jump back and summarize.