Skip to content

Architecture

Prajwol P edited this page Jul 6, 2024 · 5 revisions

Project Tree

The expected project tree looks like this:

.
|- backend
  |- osquery-be  <- backend for osquery, and our extension; language: Python/FastAPI
  |- pb  <- backend service based on Pocketbase; language: Go/Pocketbase
|- cli  <- codebase for the CLI tool; language: Go
|- docs
  |- diagrams  <- primarily D2 diagrams; language: D2
  |- ...  <- other docs components, including presentation
|- extension <- our extension, uses MV3; language: TypeScript/Vue/Plasmo
|- frontend
  |- app  <- initially planned Nuxt frontend app; not in use now; language: Vue/Nuxt
  |- streamlit-app  <- current frontend app using Streamlit; language: Python/Streamlit
    |- dragonfly <- to cache user auth token, which needed to be introduced due to a limitation in streamlit

DB Schemas

The DB schemas are drawn using d2 language (https://d2lang.com/).

While writing diagrams in d2 in VS Code, it is recommended to install the extension: Terrastruct.d2. It allows you to work on diagrams with preview in side-by-side layout.

Current status of the schema

The schema diagrams are being tracked in issue#6. Current form of schema looks like this:

DB Schema

Frontend

The current frontend app lives on frontend/streamlit-app directory. It is a Python-based Streamlit (st) app. The directory structure follows Streamlit's multi-page feature to allow users to navigate between multiple pages.

Due to limitations in st, I have made use of auth guard as middleware. It's just a simple workaround to make it mandatory for users to be logged in to access any page. First, dashboard.py is the entrypoint of the st app. If you look at code of any st page, including this entrypoint, you'll see the logic to check whether the user is logged in. If the user is logged in, then they get access to any page, else they need to log in or sign up. This is the workaround. Another workaround that I have used to persist user session for longer is the use of dragonfly (we used to use redis) to cache auth token. It is unsafe, but it works for now.

Reason(s) for the workaround(s): st doesn't persist its storage after page reload, and accessing DOM and browser APIs for cookies/localstorage is not straightforward.

Future Improvements

  • Move redis (dragonfly) to frontend/streamlit-app directory. For that we can make a common docker compose file for both redis and streamlit-app. ✔️
  • Remove redis (dragonfly) entirely. But we need to implement cookie storage to store auth token for persistence.

BEM-CLI

The CLI tool is an essential part of the project. We use BEM-CLI to launch osqueryd with its flags, and later to manage extensions (e.g. for installing/uninstalling). But for the first time use, the organization admin has to setup the tool. Setting up the tool means providing org API key and owner email (the user who owns the device), which creates a config file (json) at a directory. osqueryd uses this config file to enroll the user/node and for any subsequent requests.

Expected file name for config: $HOME/bem.json. Expected config file structure:

{
  "api_key": "API_KEY_FOR_ORG",
  "owner_email": "EMAIL_OF_DEVICE_OWNER"
}

Future Improvements

  • Create the config file in a directory, and the directory has to be placed somewhere like /etc or /opt, etc.
  • Allow admins to pass api_key and owner_email via flags. For e.g. bem-cli setup --api_key="..." --owner_email="...".
  • Add root.crt for osqueryd. See backend/osquery-be below.

Backend

backend/osquery-be

PoC for API server for osquery. Although it is ready to be configured for use with osquery, I am still evaluating using this server vs using pocketbase backend. osquery requires connecting to server over HTTPS, so I have configured Caddy with needed configurations. This means writing Caddyfile, setting up git to track root.* cert pair, etc.

With osqueryd, you need to also pass it root cert for TLS encryption, so you use the root.crt (which is auto-generated by Caddy). Hence, the root.* certs commited in the backend/osquery-be project can used with osqueryd, without regenerating the certs. The plan is to add root.crt with BEM-CLI, which supplies the cert to osqueryd as one of its flags.

backend/pb

The backend is entirely Pocketbase. However, I am expanding Pocketbase with Go for working with migrations, and other potential usecases. The migrations create and update tables in SQLite database. Any changes to tables made via GUI will reflect via migrations, which can be committed to code and shared.

I have added endpoints for osqueryd, akin to what has been done in osquery-be backend, but in Go. However, we need to add Caddy config as well to make it function with osqueryd. Check the corresponding branch/PR for the work in progress.