Identity Access Management (IAM) Integration With Tornjak

Maia Iyer
Universal Workload Identity
6 min readOct 25, 2022

What is Tornjak?

In a previous blog, we have discussed the need for a universal identity framework that can be consumed by any cloud service provider. Some major open-source projects that directly address this need include Secure Production Identity Framework for Everyone (SPIFFE) and the SPIFFE Runtime Environment (SPIRE). SPIFFE is a defined standard for a universal identity framework, and SPIRE is an implementation of the SPIFFE standard. Both of these projects are currently graduated Cloud Native Computing Foundation (CNCF) projects.

Tornjak is a project aimed at further developing the usability of SPIRE. Specifically, the goal of Tornjak is to become a control plane that provides an interface for the management of SPIRE and related entities. The hope is that this makes it easier to get started with SPIRE, and additionally provide global visibility and auditability capabilities of workload management.

Tornjak Architecture

A user can communicate with the Tornjak frontend, which communicates with potentially multiple Tornjak backends. The Tornjak backend is part of the SPIRE server deployment.
Typical Tornjak Architecture

Tornjak provides a UI for such a control plane with two main components:

  1. Tornjak Frontend: From a high level, this is a browser application that organizes and displays metadata and SPIRE information to a single user. Additionally, it translates user input into Tornjak API calls passed to the backend.
  2. Tornjak Backend: This component is tightly coupled with a single SPIRE server instance and is deployed directly within the same container. It receives Tornjak API calls received via a listening address, and handles and executes Tornjak-specific calls and forwards them to the SPIRE server. Accessing the backend merely requires access to the listening address, and one need not necessarily access the frontend to execute calls.

We have introduced the code structure in more depth in a previous post. For now, this is sufficient for discussing the latest implemented feature — Identity and Access Management!

Why the need for IAM?

Identity and Access Management (IAM) concerns itself with controlling who has permissions to access what resource. There are two main parts in implementing IAM: authentication (verifying “who”) and authorization (giving permissions to “what”).

Any user that knows the access point for Tornjak can have full control over Tornjak, and consequently, all SPIRE entities. That’s why we introduced IAM through the OAuth2.0 protocol so that we can restrict access depending on the user.

Tornjak Architecture + IAM Using OAuth2.0

From the above architecture diagram, anyone that can access the Tornjak backend access point can currently do anything to SPIRE. Therefore, to secure SPIRE, we must secure this backend access point. Our approach to do so is centered around some key concepts:

  • Role-based access control (RBAC): protocol that restricts access to a resource server based on the roles a user has been assigned.
  • Access token: proof to the secured API (in this case, the Tornjak backend) that the requester is trusted by the Auth server, as the Auth server has signed the token with its private key. This also contains authorization information such as which role a user has.

Our goal was to implement role-based access control using JSON web tokens (JWTs) as access tokens. We will demonstrate this with two roles:

  • Viewers that can only see resources
  • Admins that include elevated privileges such as identity creation and agent banning

To do this, we integrated Tornjak with a separate Auth server, which will handle all user management separately. A Chief Information Security Officer (CISO) will be able to delegate permissions and roles to specific users. The integration implements authentication in the frontend and authorization in the backend. Namely, in order for the backend to be secure, it must be configured to expect an access token with the correct permissions (authorization). On the other hand, in order for the frontend to successfully make calls to the backend, it must be able to obtain and pass a valid access token with Tornjak API calls to verify the user has permissions (authentication).

The typical Tornjak architecture, where the Auth server receives user credentials and gives access tokens to the frontend. The frontend sends the access tokens to the backend with each API call, and the backend can view public Auth server keys.
Tornjak Architecture incorporated with an Auth Server

Tornjak IAM Pipeline

We follow the standard Authorization Code Flow template to create a secure pipeline. Essentially, the frontend handles obtaining the access token, which will be sent to the backend server that can validate this access token.

Authorization Code Flow with annotations on Tornjak entities.

For authentication, when a user accesses the Tornjak frontend browser application, the frontend redirects the user to the Auth server, for the user to register or login with some user credentials. Eventually, the Auth server gives the frontend an access token for the session. Then, for the duration of the session, the frontend sends Tornjak API calls to the backend, always with an access token included in the Authorization header.

For authorization, the backend, after receiving a request, checks for the access token, validates this token against the public keys provided by the Auth server, validates the expiration, and then carries out the request based on whether or not the token includes the appropriate role for the call. For example, if the request is to create an entry, and the role included is “admin,” the backend will carry out the request. If the role included is “viewer” or no role is included, the backend will return an authorization error instead.

Keycloak logo

Sample Auth Server: Keycloak

For demonstration purposes, we implemented the feature using a popular, open-sourced product Keycloak as an Auth server. We have more details on this choice and how to configure Keycloak for Tornjak in the follow-up blog Step By Step Guide To Setup Keycloak Configuration For Tornjak blog post.

Setup for Tornjak to work with Keycloak is simple! At a high level, the steps to integrate are as follows:

  1. Set up the Keycloak server with Tornjak realm and several user accounts
  2. Configure Tornjak to point at the Keycloak instance
  3. Deploy Tornjak along with the Spire servers
  4. Access Tornjak and login! The frontend requires no setup, as it is able to automatically handle either a secured or unsecured calls based on Tornjak configuration.

We will also include in-depth tutorials for the setup and deployment in upcoming blog posts.

Recommendations for this feature

Based on the fact that the Tornjak frontend is a public client, there are a couple security considerations to be aware of when configuring this feature. If configured without this consideration, the system may be prone to Cross-Site Request Forgery, replay attacks, and man-in-the-middle attacks.

The recommended steps to mitigate the threat include configuring the auth server to supply access tokens with a short time-to-live, which will decrease the usability of stolen access tokens. Furthermore, the use of TLS/mTLS for the HTTP endpoint to prevent eavesdropping and stealing of the access token.

Upcoming Features — Contribute!

We have many exciting next steps planned for Tornjak! Related to developing this feature, we are looking into a couple increased functionalities:

  • Decoupling the authorization logic from the backend application: This might allow more flexibility for different organization structures, where instead of role-based access control, we may be able to implement attribute-based access control.
  • Implementing Upstream Authority Feature: This will allow customization of a certificate authority that can sign intermediate SPIRE certificates, as is implemented in SPIRE, directly from Tornjak portal.
  • Implementing IAM for the Tornjak manager: The Tornjak manager is another feature that allows users to connect to multiple Tornjak backends at once, giving management ability across trust domains. Implementing IAM with the Tornjak manager will allow secure management across multiple SPIRE instances and trust domains.
  • Auditability capabilities: In hopes of achieving global visibility of workload communication and persisting the access control details in a centralized place.

If you are interested in any of the above features or in becoming a contributor to help us further this work, we would love to have you! Our code is located here and we have several open issues. Additionally, if you have any questions or simply want to chat with us, we have a channel #tornjak within the CNCF SPIFFE community where you are free to reach out to us!

Maia Iyer — Tornjak Contributor (Medium: Maia Iyer, SPIFFE Slack: @Maia Iyer)
Mohammed Abdi — Tornjak Contributor (Medium: Mohammed M. Abdi, SPIFFE Slack: @Mohammed Abdi)
Mariusz Sabath — Tornjak Maintainer (Medium: Mariusz Sabath, SPIFFE Slack: @Mariusz Sabath)

--

--