open-balena-admin: an admin interface for openbalena

I would like to share a project that I have been working on called open-balena-admin, which is a compilation of three separate but related projects: open-balena-ui, open-balena-remote and open-balena-postgrest. The open-balena-admin platform consists of a web interface and back-end supporting services which integrate with open-balena and provide the following functionality:

  • Support for multiple organizations and users in open-balena
  • Remote access to devices (ssh, vnc and http into host or containers)
  • Fleet / device management (create fleets, add devices, manage variables / tags / labels)
  • Support for creating and managing custom device types
  • Device management dashboard
  • Remote device diagnostics

The open-balena-admin project includes docker-compose build scripts, which mirror the open-balena build process, and build instructions can be found on the github page. The project also includes helm scripts for kubernetes deployment environments which follow the same format as bartversluijs’ helm project for open-balena.

Currently this project only scratches the surface of what is possible with this type of interface. It also has a number of gaps / issues which I could use help from the open-balena community in addressing, specifically permissions and enhanced security. While I will continue to build it out and post updates, please do let me know if you are interested in contributing to this project as it would greatly accelerate the effort. Otherwise, I am happy to offer this back to the community which we have derived so much value from over the last few years.

18 Likes

This looks awesome!

Great work, I like the multi-tenant solution. How did you implement this, is it an extra layer on top of openbalena?
I can also see each user can be given different permissions?

1 Like

@GoogleIt thanks! open-balena-admin actually uses the native open-balena-db database via a PostgreSQL REST interface. So any org or user that is created in open-balena-admin can log in and execute commands via balena-cli, make API calls via open-balena-api, etc. Same thing goes for fleets / devices you add in open-balena-admin, API keys you create, env vars, etc. - they are all just part of native open-balena despite being managed by open-balena-admin. For the users you create, you’ll need to make sure that they have sufficient permissions to perform the actions you are doing using the other interfaces, since balena-cli, open-balena-api, etc. honor those permissions.

1 Like

Damn David, this so impressive!
@dtischler @mpous @maggie0002 You gonna need to see this!

4 Likes

WOW!! This projects VERY impressive @drcnyc!

I will take a closer look at it today, and we’ll also make sure we let the community know as well! :slight_smile:

2 Likes

And thanks for the ping @nmaas87 :handshake:

2 Likes

I’ve also dumped the database once to take a look at the structure. What a monumental task and it enables pretty useful features in openbalena. It’s also an amazing project from a security standpoint, now I don’t have to fiddle around with some scripts/the API to revoke an API key and can just use this nice web interface.

Do you know how to create a user that only has access to fleets and devices of a certain organization? If that is possible, it means multi-tenancy can be achieved which would be awesome.

This is incredible work, @drcnyc !

@nmaas87 @dtischler @pranavpeshwe I appreciate your kind words, but at the end of the day this is just icing on the cake, and none of this would be possible without open-balena - the amazing product your team has built. And obviously your decision to make it available to the open source community. Thank you!

@GoogleIt what I found to be really helpful was the sbvr file in open-balena-api, which once you get your head around it becomes a great roadmap. Regarding multi-tenancy, it’s really only partially implemented at the moment. You can create users that have all of the standard balena permissions - but these permissions are only relevant when utilizing the web interface of open-balena-api or balena-cli, which apply those permissions. I suspect what you are looking for is the ability to log in to the web interface and only see your own devices, etc. That will require interpreting those same permissions in open-balena-ui, which currently the groundwork is there to do, but it needs some heavy lifting. For example, following a successful login, open-balena-ui currently stores the permissions of the logged in user in the browser’s localStorage, along with the client side JWT secret to validate them. The react-admin framework that open-balena-ui utilizes has some nice permissioning features that could be utilized to interpret these permissions and hide/show areas of the ui appropriately. But we would also need to build this logic into the open-balena-postgrest proxy (which currently just confirms the user is authenticated, and provides full access if they are), to ensure that back end calls are filtered based on those permissions as well. If you’ve got the interest and some spare time, I’d love some help with this! If not, it’s definitely high up on my to-do list…

4 Likes

Impressive work in that dashboard. I do really like how nicely the SSH terminal and the https “terminal” renders the device’s https application. Well done and nice to see you jumping into the SBVR file.

Just a little background on the SBVR file. It’s the data model description that is used by the open source project GitHub - balena-io/pinejs: Generate rest APIs from natural language models to automatically generate a full OData API from the data model and understand valid OData request to the database. Pinejs comes with a database level permission system, I can highly recommend to check the pinejs documentation for CustomServerCode.

Well done @drcnyc !

1 Like

@fisehara I appreciate the additional guidance here. The SBVR format is great - and I saw how you guys are able to convert it directly into SQL code to generate the PostgreSQL database when API first starts up.

The challenge I had with using database-level authentication / authorization is that there is only one database user used by open-balena-api (the docker user) regardless of which open-balena user is making the call. Similarly, all of the database calls made by open-balena-ui (via a custom dataProvider that interfaces with PostgREST) use the same docker user - so authorization needs to be implemented above the database level. Interestingly, PostgREST would actually prefer to utilize database-level permissions, as it works this way out of the box - but I had to build a proxy around PostgREST to handle authentication / authorization because of the above issue - and right now everything is authorized once a user is authenticated, because authorization is not yet implemented at the open-balena-ui or at the open-balena-postgrest level.

Users in open-balena are stored in the user table within the resin database, which I believe are separate and distinct from database-level users - so I’m stuck on how we could use database-level permissions when all database calls are using a single database user (regardless of which open-balena user is making the database call).

1 Like

@drcnyc amazing work and thank you for sharing with the community.

I have been using openBalena for three or four years and have made a very terrible looking interface for seeing a device’s state and starting/stopping services and often thought how great it would be to have a fully featured community driven UI.

I will now be deleting my UI effort and subscribing to you repos. Will try to contribute to your project where I can.

Cheers
Chris

@dash I’m glad you like it! There are many areas that could use improvement / building out so I would definitely appreciate any contributions you are willing to make.

This provides much greater insight into the key contents of the database than manual querying. The device creation interface also automates much of the process for entering an already-provisioned device, and saved me at least a day. Thank you!

You are a star! I’ll definitely have a go at it in the coming days!

We noticed that the Admin project appears to talk directly to the Postgres database using Postgrest. I understand the PineJS library is very much in control of the data model in the database and it has hooks which should fire when certain resources are updated. I am not sure what the Admin interface is doing exactly, but if it needs to talk to the DB directly wouldn’t this be dangerous?

Hi @brownster, thanks for your interest in open-balena-admin. We have been using it in our production environment and haven’t seen any issues where hooks are not running when expected / needed, for example when you add a service variable via open-balena-admin, the service on the affected devices automatically restarts, etc. Are there specific hooks you are thinking of which should be firing but are not?

Unless you are referring to the data dependencies themselves, which are also implemented as constraints at the database level (when the tables are created and the sbvr is decoded) and open-balena-admin conforms to those when creating new resources, updating resources etc. For example, when creating a device, it ensures required fields are provided, and automatically creates an actor which is needed - but the goes a step further and also creates a provisioning key for that device.

So for the most part we have replicated what is happening in PineJS, to allow use of a flexible web interface like open-balena-admin. Other examples are where we generate UUIDs, SSH keys, etc. PineJS is handling this for the various balena tools (balena-cli, open-baena-api, balena cloud etc.) but we were not able to utilize this in the context of our web interface - although we would be interested in any ideas / contributions you may have to improve this.

Firstly, I just wanted to say congratulations on making a much-needed tool for the openBalena ecosystem.

I would feel uncomfortable directly touching the data in the Postgres side; as you’ve mentioned you’re replicating the functionality that PineJS is offering, so why not deal with the data model natively? Is there something you’re doing which isn’t supported via the API and if so, could you elaborate on this somewhere? For a toy-app this, for sure, doesn’t matter but I think some folks are looking to use this in production / serious environments and it would be great to have this info to hand.

Please don’t take this as anything other than positive, constructive criticism - I have been away from the openBalena scene for some time, and it’s great to come back and see folks engaging with it :slight_smile:

Hi @richbayliss, no worries at all - I am very much interested in all types of feedback including criticisms. This is the part of open source that I enjoy the most, because it drives deeper understanding and progress.

The whole reason this project came about was because of limitations in what open-balena can do out of the box - specifically no ability to manage multiple organizations or users (all activity was single user and single organization) and no ability to manage custom device types. This functionality exists within balena-cloud, but it appears that it is maintained in separate private repositories, which is understandable. And for this same reason, I wouldn’t expect these features to be built in to open-balena-api, at least not by the balena team, as they already exist in private repos, likely with different functionality around user lifecycles etc.

But these features, along with many others that open-balena-admin was built to address (such as remote device access, cloud management, diagnostics, remote control, etc.) are important to anyone looking to actually use open-balena in a production environment. Without it you are stuck using command line tools, API calls or building a custom management interface. And that’s for the features that are available via balena-cli or open-balena-api; for others such as managing multiple users / orgs / custom device types, you are just out of luck because the functionality does not exist in any of those tools.

For many, these feature limitations and lack of management interface are a deal breaker to using open-balena, and while there is obviously balena cloud available to address them, many parts of that system are not open source (such as the device dashboard and management interface) so for the audience who is looking for an all open-source solution, there really is no option without compromising on both functionality and ease of use - which is what led to the development of open-balena-admin.

As to your question on the dangers of working directly in the database, just my personal opinion after building this tool, but I don’t think it’s all that risky. Which is a testament to the balena engineering team, because obviously what balena as a whole is doing is very complicated behind the scenes. But managing the database itself - users, organizations, API keys, SSH keys, devices, fleets, and the various levels of labels / variables are really pretty straightforward. Many of the areas in open-balena-admin are intentionally read only, because there’s no reason to modify them directly - images is one example, there are many others. We rely on balena-cli for pushing new releases, and there would be no reason to do otherwise. But for the “basic” areas that I mentioned earlier, I don’t see a lot of risk, and if we do come across some corner cases that create problems, we can always address them in the front end. But in general, the database itself does a good job of preventing bad data from being committed, I know this from the extensive development / debugging that went into creating open-balena-admin, where in many, many cases I unsuccessfully tried to commit bad data by accident.

So, while it would have been technically possible to create portions of open-balena-admin using open-balena-api for data management instead of directly managing it in postgres (via postgrest), it kind of defeats the purpose - because we will then be limited by what data / functionality is made available by open-balena-api, and as discussed earlier there are some key limitations there which to my knowledge have no timelines to be addressed. In addition, there are extensive synergies in being able to use tools like react-admin and postgrest which provide a framework to build a seamless web interface, vs developing a bespoke front end to open-balena-api as other dashboard tools have done in the past.

And lastly, regarding this not being suitable for a production environment, my understanding is that the entire open-balena suite is not geared for a production environment. And for good reasons, with only one user (superuser) and very basic security, among other reasons, it makes sense. So I kind of view open-balena-admin in a similar light. It is far from perfect (could do a lot better with security as well, needs more testing / development in key areas), but at the same time it makes open-balena more production ready in other ways, including addressing key vulnerabilities such as single superuser access. So I think that as long as people understand what it is (an open source and customizable tool to manage your open-balena instance) and what it isn’t (a front end for open-balena-api or PineJS) I think users can make their own informed decision as to whether it’s right for them. And it’s completely acceptable to me for anyone to decide it is not right for them.

So hopefully this explains my approach with open-balena-admin, obviously the intent was not to cause any issues or concern on the balena side (I am an ambassador after all!), rather this is meant to be a tool for use by the community to allow them to get the most out of their open-balena instance, and ideally get input and development participation along the way.

1 Like

@drcnyc @brownster @richbayliss this is a really helpful and interesting discussion; thanks so much for having it here in Forums so that others can benefit from it, and balena folks can gain insight on how to improve things as well.

I asked some of our engineers about this thread internally and they shared the following, which I want to make publicly visible as it seems to be core to our thinking about openBalena but is not obvious in our public-facing docs today:


Engineer 1:
Correct, direct querying is not advised. Pine assumes it has direct and exclusive control of the database so in theory it can change the layout of the database in completely arbitrary ways at any time.

In practice there’s no reason for that atm, so direct queries “work”, but that could change.

Writing to the database definitely should be done through Pine though. At the very least because Pine runs additional consistency checks you’d miss otherwise so you might get bad data into the database.

Engineer 2:
Reading data from the DB directly to present them should be fine, but it also means that they don’t get the computed terms (columns/tables) that we have already implemented in Pine (e.g. device.overall_status).

Writing data has bigger concerns, both about security and whether the resulting records can actually operate. That’s because it allows skipping of the following mechanisms:

  • DB stat validation rules, which Pine runs right before each Transaction commits

  • the Pine hooks that trigger on operations in order to:
    enforce data validation / rules right before the data reach the DB

  • fill-in default or generated values (which otherwise the user or the other system will have to fill), the highlights being:

  • the release.semver (which is also a computed term) + release.revision pair

  • the image location (which is the basis for our registry to work & devices to download updates)

In both cases, you would be skipping Pine’s permissions systems, which we would generally consider to be against best-practice.


What I gained from their responses are the following:

  • the implication for open-balena-admin is that it works today, but changes made by balena in the future could cause some functionality to break, so it might be worth reworking some bits of the solution in order to avoid these breaking points in the future

  • balena needs to find a way to make the above more clear to folks building on top of openBalena

  • openBalena in all its forms should still be considered in Beta status, especially until the codebase and automated testing for it can be properly implemented and feature-parity with balenaCloud

I’m open to suggestions on that second bullet point. My first thoughts are to make it more clear in the documentation somewhere, but in case that’s missed, I wonder if there’s actually some way to prevent such implementations or at least provide a warning. :thinking: If anyone has suggestions, I’m open to them and will be sharing feedback with the openBalena team.