RailsConf 2014

Authorization in a Service-Oriented Environment

Authorization in a Service-Oriented Environment

by Alan Cohen

In this video titled 'Authorization in a Service-Oriented Environment', Alan Cohen from Climate Corporation addresses the complex challenges of implementing authorization in a Service-Oriented Architecture (SOA). He differentiates between authentication and authorization, emphasizing that while authentication verifies identity, authorization determines access rights.

Cohen provides an overview of SOA, describing it as a loosely coupled architecture aimed at fulfilling business needs through the reusability of components and scalability. He discusses various authorization methods such as role-based, attribute-based, and rule-based control, but focuses on the necessity for a more flexible and scalable approach suited for heterogeneous environments where services may be built in different languages.

Key points discussed in the talk include:

- Importance of SOA: SOA allows for modular development, resource allocation, and a codebase capable of scaling across teams.

- Challenges of Service-Oriented Authorization: Authorization must be reusable and decoupled from application code to ensure scalability and maintainability, especially when services evolve.

- Current Authorization Libraries: While tools like CanCan are effective, Cohen argues they embed rules in application code, making future updates and scaling difficult.

- XACML: Cohen touches on the Extensible Access Control Markup Language (XACML), which separates access decisions from application code but notes its complexity is excessive for simpler applications.

- Developing a New Framework: He discusses the creation of a new language to define authorization policies that are agnostic to specific frameworks and languages, along with a Ruby gem named 'IronHide' that serves as a bridge to allow applications to implement these rules.

Cohen concludes that the proposed framework aims to simplify authorization processes, increase reusability, and maintain scalability across various services. The approach is still a work in progress, but it seeks to provide a foundation for a more reliable and manageable authorization system across diverse environments.

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.