Mumba API Platform

The Mumba API platform is an advanced but flexible architecture built on a scalable microservice philosophy. It is built on the WAMP protocol which provides for more security over the more common REST architectures.

Overview

The components in and around the Mumba API Platform are:

  • Devices only connect to the Mumba API Platform. They never connect directly with your enterprise network.

  • Mumba uses middleware comprised of JSON Graph and Role Based Access Control to control access to data available to the user. Features can be adapted to use existing enterprise access control systems if applicable.

  • Mumba uses local data to improve performance of the application when it refers to "common" data (such as names and position titles).

  • Enterprise data can be accessed on-the-fly via data API's installed within the enterprise network.

Request lifecycle

Device connection

Devices connect to the Mumba API Platform by establishing an anonymous websocket connection using the WAMP protocol. This provides very limited access to platform internals, exposing API's that are only related to:

  • login,

  • automated password reset (if applicable),

  • global system notifications (such as for scheduled outages), and

  • download links for native mobile applications.

When a user logs in, the anonymous websocket connection is dropped and a new connection is requested. During this process either the username and password is sent to an authentication API within the Mumba API Platform, or a return-url is used by an external identity management system (such as Azure AD, oAuth, or OpenID).

If authentication is successful, the new websocket connection is opened. The user's unique identifier is baked into the connection and cannot be easily falsified. In other words, when a user authenticates, we can be absolutely sure about the identity of the user. While unencrypted connection can be easily manipulated, our connections are protected by an A+ rated TLS connection.

The websocket connection remains open until the user logs out of the application, closes the browser (or tab), or closes the native mobile application.

Data DMZ

In order to read and write data securely, either between local or enterprise data sources, the Mumba API Platform uses a gatekeeper middleware in the form of a JSON Graph Router.

JSON Graph is a convention for modeling graph information as a JSON object. More information about the format of the data can be found at http://netflix.github.io/falcor/documentation/jsongraph.html.

In partnership with the JSON Graph router is a Role Based Access Control (RBAC) API that is used to control user permissions between the device. These two components form what we refer to as a Data DMZ (demilitarised zone).

Configuring routes for the JSON Graph is deliberately very specific in order to avoid data bleed. Reads and writes can also be defined separately and meticulously. For example, an Article object can be configured such that the date it was created can be read, but it will exclude that property from ever being updated even though underlying data API's in the trusted network may have this ability.

The following example would be a typical payload for a JSON Graph route to read data:

[GET, ["articleById", 1, STRINGS(["title", "createdAt"])]]

Here we are requesting an Article by its ID, but only the title and createdAt data properties will be returned. In addition, a malicious user cannot go fishing for hidden fields because the router will completely fail to recognise the request as valid.

The following example would be a typical payload for a route to write data:

[SET, ["articleById", 1, STRINGS(["title"])], { title: "New Title" }]

Here we are just updating a single property. Once again, a malicious user cannot go poking around because the writable properties are restricted to a white list.

Cordoning personal information in the DMZ

In the previous example we see a very typical instance of accessing the JSON Graph by using the ID of objects. Most of the time this works well, even for reading things like a user's public profile. However, when it comes to accessing or updating highly personal data, we use a different technique to lock data to the user that is logged in. The following example highlights how we do this.

We might read a user's profile with a request like this:

[GET, ["profileById", 1, STRINGS(["firstName", "lastName"])]]

We could use a similar request to update user data like this:

[SET, ["profileById", 1, STRINGS(["phone"])], { phone: "0400000000" }]

We can and do use this type of route, but only for administrative purposes and only in conjunction with very strict RBAC settings.

However, a better solution for a normal user to update their own profile looks something like this:

[SET, ["my", "profile", STRINGS(["phone"])], { phone: "0400000000" }]

This is far safer to use because you will recall that when the websocket connection is established, it is locked to the user ID. When the router receives this request, we add the user's ID from the connection so that only that user's data is touched. This technique is especially suitable when accessing highly personal information like payslips or banking details.

Enterprise Access Control

While we provide our own access control layer within the Mumba API Platform, we can of course customise any function to use an existing Access Control System as long as that system publishes a web API. Take an example where a user is a manager and needs to approve leave submitted by their subordinates.

First of all, we need to establish whether a user is a manager with permission to deal with leave. Mumba will make a request like this:

[GET, ["my", "leave", "permissions"]]

This will normally be configured to query our RBAC API, but we could also configure the router to query an enterprise access control system. Regardless of which system is actually being used, the response is standardised as follows:

{ "approve": true, "reject": true }

Now Mumba knows, yes, this user can manage leave so Mumba can enable a link in a menu or a tile on a dashboard. Clicking that will typically result in a request that looks like:

[GET, ["my", "actionable_leave", RANGE(0, 9), STRINGS(...)]]

This is just Mumba's way of asking for the first 10 leave requests the user need to action. By configuring the JSON Graph Router with adapters, we can query the appropriate system within your enterprise network to get that list of information. Note that on the server side, the permission check is performed again prior to sending the response.

Now when the manager clicks "Approve" it will send a request like:

[SET, ["leaveById", 1234, "approved"], { "comment": "Enjoy!" }]

If the underlying system includes its own access checks, the router will simply forward the request onto the appropriate system and it will perform all the necessary access checks.

However, if we are not dealing with an integrated leave management system, Mumba will perform the following checks and balances before passing the approval onto the appropriate system:

  1. Check that the user approving the request has permission to do so.

  2. Check who owns the leave request that is being approved.

  3. Check that the user approving the request is the leave owner's manager.

  4. Check that the leave request hasn't already been actioned in some capacity.

Trusted Data API's

Behind the JSON Graph router is a hive of microservices that form a network of trusted data API's. These API's perform the heavy lifting for reading and writing data that is finessed into the JSON Graph that a user can access. The API's fall into two broad categories:

  1. Data API's - these are designed to allow for CRUD (Create, Read, Update, Delete) operations on raw data sources.

  2. Workers - these services that listen to events (for example, when a user's password is updated, a worker will send a confirmation email to the user).

Trusted data API's are restricted to a zone within the private network of the virtual machine so that they cannot be indiscriminately accessed.

Local Data

Mumba provides some features for which we are the point of truth (for example, our Channels module). We store this information in a database residing inside our trusted cloud network.

However, when we integrate with enterprise systems, it is sometimes beneficial for us to cache information that is regularly accessed, or information that is more-or-less publicly available within the corporate network. This will include information such as the user's real names, position title, physical locations or any other information that is deemed non-sensitive. Storing "common" data this way keeps our application performance snappy. Nobody likes lag.

This data is stored within an encrypted database so that in the event of physical theft of hardware, the raw data is extremely difficult to procure.

The more "common" data we can store the better, but beyond the basics of people's names and job titles, information that we cache is completely discretionary.

Enterprise Data

There are a number of ways that we can access your data, how and when we do this varies depending on many factors ranging from security considerations to server load.

As we've already mentioned, Mumba relies on caching at least a small amount of "common" data such as a user's name. There are two ways we can capture that information.

Caching Enterprise Data

The first way is to capture and update information in real-time when a user logs in. When a user is successfully authenticated we can contact an Identity Management System and request the properties that we have been authorised to collect and update them in our local caches.

The second way is to perform overnight batch updates during times when there is significantly less load on servers. This can usually be achieved by using a published web API. The connection is usually established by issuing Mumba with a system account with regular password rotation. Such credentials are stored in a secure, encrypted software vault that is only accessed during microservice startup. From there, microservices only ever hold the credentials in memory within our virtual machines, never writing them to disk. In addition, such connections will usually be funneled through a whitelisted IP trust between our servers and the enterprise network.

If system accounts are not possible for any reason, we can configure bespoke data API's on property within the enterprise network.

In cases where we are dealing with very old, legacy systems, we can resort to using data interchange files to transport data between systems, or, we can stand up services within your enterprise network to act as a bridge (see below).

Using Live Enterprise Data

There are many times where we don't want to cache information.

Sometimes information is in a state of flux and caches go out of date too quickly. For example, if your employees need to access work orders that can change at very short notice, pulling such data directly from an enterprise data source provides the most reliable experience for the employee.

Sometimes the data is sensitive and there is a desire to ensure such information is never inadvertently stored to disk outside of secured corporate networks. Good examples are payroll, banking and personal contact information.

Sometimes the data is controlled by systems with extremely complex rules. For example, when working with Kronos Time Management, it is completely impractical for us to reinvent all the rules surrounding rostering or leave management. In those cases, we will only ever connect using a recognised API with the appropriate enterprise system.

Connecting Directly from Mumba to Enterprise Data Sources

By far the best way to connect to enterprise data is through the use of vendor supplied web API's.

Connection is, once again, best established using tightly controlled system accounts where the permissions for those system accounts are rigorously configured in the enterprise network to provide no more than the absolutely minimum functionality required for Mumba to perform its job.

Using Bespoke API's to Access Enterprise Data Sources

If no web API exists for a given system, or a system cannot be customised to provide one, or security policies prevent direct connection to enterprise application layers, bespoke services can be built inside the enterprise network.

Connecting Enterprise Data API's to the Mumba API Platform

Application stacks often provide the ability to be customised. If so, such extensibility can be leveraged to connect to the Mumba API Platform using the WAMP protocol.

For example, a plugin could be added to a Payroll System to allow for notifications to be sent to the user's device:

A custom event handler could be added to the Payroll application stack. When an event is triggered inside the server, the handler registers a connection with the Mumba API Platform over WAMP, and submits a notification request to the JSON Graph Router. The Router forwards that request to the Notifier API which then performs its duties to send an email to the user, and send a notification to the user's device.