Authz: Authorization backend using ABAC and RBAC

Authz

The management of authorizations in applications must be simple and centralized.

So I have with Authz, a new open-source project simplified as follows.

A principal wishes to perform an action on an resource. This is possible according to policies and/or roles defined in the Authz backend.

To do this, there several posible ways, icluding the following two: by role assignment (RBAC) or by defined rules allowing to link a principal with a resource according to attributes (ABAC).

Let's start by looking at the different terms we will use.

Description of the different objects

  • Principal: This generic term is used to group together something that seeks to perform an action on a resource. It can be a user, a service account or a group of users,
  • Resource: This is an object on which an action can be performed: for example, an article on a CMS. This resource contains a type (called "kind" in Authz: article) and an identifier,
  • Action : An action is something that can be done on a resource, for example, on our articles, we can create, edit, delete them. These three elements are actions.
  • Policy: A policy is a rule that defines which actions can be applied to which resources,
  • Role : A role groups together a set of policies and therefore allows to define a set of actions that can be performed on several resources. It is assigned to a principal.

Authz allows to manage both ABAC and RBAC authorizations and even to use both at the same time. Let's see it in more detail.

Attribute-Based Access Control (ABAC) authorizations

ABAC

This model, more flexible than the role-based attribution, allows to describe authorization rules according to the attributes positioned on the principals and resources.

For example, let's imagine an attribute owner_id: 123 on an article in our CMS because it was written by the user with the id 123.

When declaring our principal (user), we will set an id: 123 attribute to it.

Now we can add a policy to perform edit and delete actions on article.* resources (all articles).

We also add the following rule: resource.owner_id == principal.id.

A policy can also have several rules.

Once this policy is in place, our user whose id is 123 will have the permission to edit and delete the articles he owns.

Role-Based Access Control (RBAC) authorizations

RBAC

On the role assignment side, it is simpler.

You just need to create a policy to perform edit and delete actions on article.* resources (all articles) without specifying attribute rules.

This policy can then be added to a role, which can contain multiple policies.

The role will then be assigned to principals, which will therefore allow them to edit and delete all articles.

Architecture

So how does Authz work?

RBAC

It is a centralized backend that can be used by your applications using HTTP or gRPC API calls.

To do this, you can create a service account that will give you a client_id and client_secret to use for authentication.

You can also use one of the SDKs available, for the moment in the following languages:

Your applications will be able to :

  • Declare and modify / delete principals,
  • Declare and modify / delete resources,
  • Check if a principal has an authorization.

The backend takes care of setting up the policies that give access to the principals.

Using the SDKs

Here, I will demonstrate only the Go SDK but the documentation is available on all repositories for the other SDKs.

First step, install the SDK in your application:

$ go get github.com/eko/authz/

Then you need to connect and identify your application to the backend:

authzClient, err := sdk.NewClient(&sdk.Config{
    ClientID: "your-client-id",
    ClientSecret: "your-client-secret",
    GrpcAddr: "localhost:8081",
})

You can now declare a principal:

response, err := authzClient.PrincipalCreate(ctx, &authz.PrincipalCreateRequest{
    Id: "user-123",
    Attributes: []*authz.Attribute{
        {Key: "email", Value: ""},
    },
})

Declare a resource:

response, err := authzClient.ResourceCreate(ctx, &authz.ResourceCreateRequest{
    Id: "post.456",
    Kind: "post",
    Value: "456",
    Attributes: []*authz.Attribute{
        {Key: "owner_email", Value: ""},
    },
})

You can see that here we have declared attributes on our resources. So we are using the ABAC model.

Let's now declare a policy with the rule to match these attributes:

import (
    "github.com/eko/authz/backend/sdk/rule"
)

response, err := authzClient.PolicyCreate(ctx, &authz.PolicyCreateRequest{
    Id: "post-owners",
    Resources: []string{"post.*"},
    Actions: []string{"edit", "delete"},
    AttributeRules: []string{
        rule.AttributeEqual(
            rule.PrincipalResourceAttribute{
                PrincipalAttribute: "email",
                ResourceAttribute:  "owner_email",
            },
        ),
    },
})

Finally, you can check if your principal has the necessary access to edit the article:

isAllowed, err := authzClient.IsAllowed(&authz.Check{
    Principal: "user-123",
    ResourceKind: "post",
    ResourceValue: "456",
    Action: "edit",
})
if err != nil {
    // Log error
}

if isAllowed {
    // Do something
}

Conclusion

You now know how Authz works and are ready to start!

The project is open-source under the MIT license, so you are welcome to contribute or exchange on features. I will be happy to exchange with you!

Go to https://github.com/eko/authz.