Modern React + Vite frontend for the SOARCA platform, providing a lightweight UI to interact with SOARCA services. The app uses TypeScript, styled-components for theming, React Router for navigation, and React Query for data fetching.
Warning
SOARCA-GUI is still in development and features and look may change with time.
- Node.js 20+ (if runned locally)
- npm 10+ (if runned locally)
- Docker and Docker Compose (for building/running from docker image)
Development mode provides hot-reload capabilities and a proxy server for API requests to the SOARCA backend. In order to provide an enjoyable development experience, we provide both a local environment and a Docker setup. In order to accomodate both scenarios and provided minimal user configuration needed, we opted for the architecture shown below.
Development can happen in two ways: locally running Vite on your machine or in a Docker container.
flowchart TB
subgraph User[" "]
direction TB
UserLabel["User Machine"]
Browser["Browser<br/>localhost:HOST_PORT"]
end
subgraph LocalDev["Local Development Mode"]
direction TB
LocalLabel["Local Development"]
LocalVite["Vite Dev Server<br/>Port: VITE_SERVER_PORT"]
LocalProxy["Vite Proxy<br/>/api → VITE_BACKEND_URL"]
LocalHMR["Hot Module<br/>Replacement"]
end
subgraph DockerDev["Docker Container Mode"]
direction TB
ContainerLabel["Development Container"]
ContainerVite["Vite Dev Server<br/>Port: VITE_SERVER_PORT"]
ContainerProxy["Vite Proxy<br/>/api → VITE_BACKEND_URL"]
ContainerHMR["Hot Module<br/>Replacement"]
end
subgraph Backend[" "]
direction TB
BackendLabel["SOARCA Backend"]
API["API Endpoints"]
end
UserLabel ~~~ Browser
LocalLabel ~~~ LocalVite
ContainerLabel ~~~ ContainerVite
BackendLabel ~~~ API
%% Local development flow
Browser -->|Local Mode| LocalVite
LocalVite -->|Source Files| LocalHMR
LocalHMR -->|Live Updates| Browser
Browser -->|"/api/*"| LocalProxy
LocalProxy -->|"Rewrite & Forward"| API
%% Docker development flow
Browser -->|Container Mode| ContainerVite
ContainerVite -->|Source Files| ContainerHMR
ContainerHMR -->|Live Updates| Browser
Browser -->|"/api/*"| ContainerProxy
ContainerProxy -->|"Rewrite & Forward"| API
%% Backend responses
API -->|Response| LocalProxy
LocalProxy -->|Response| Browser
API -->|Response| ContainerProxy
ContainerProxy -->|Response| Browser
style LocalVite fill:#C5E1FF,stroke:#4A90E2,color:#000
style ContainerVite fill:#C5E1FF,stroke:#4A90E2,color:#000
style Browser fill:#B8F5D3,stroke:#2ECC71,color:#000
style API fill:#FFE5CC,stroke:#E67E22,color:#000
style LocalHMR fill:#FFD1DC,stroke:#E74C3C,color:#000
style ContainerHMR fill:#FFD1DC,stroke:#E74C3C,color:#000
style LocalProxy fill:#C2F0F0,stroke:#16A085,color:#000
style ContainerProxy fill:#C2F0F0,stroke:#16A085,color:#000
style UserLabel fill:#F0F0F0,stroke:#999,color:#333
style LocalLabel fill:#F0F0F0,stroke:#999,color:#333
style ContainerLabel fill:#F0F0F0,stroke:#999,color:#333
style BackendLabel fill:#F0F0F0,stroke:#999,color:#333
classDef envVar fill:#D4F1D4,stroke:#27AE60,stroke-width:2px,color:#000
class VITE_SERVER_PORT envVar
class HOST_PORT envVar
class VITE_BACKEND_URL envVar
Environment variables involved:
VITE_BACKEND_URL- Backend API URL (proxied by Vite dev server)VITE_SERVER_PORT- Port where Vite dev server listensVITE_ENABLE_HTTPS- Set totrueto serve the development or preview build over HTTPSVITE_HTTPS_CERT_FILE- Path to the TLS certificate used by ViteVITE_HTTPS_KEY_FILE- Path to the TLS certificate key used by ViteVITE_VERIFY_SSL- Set totrueto verify the backend certificate when Vite proxies API requestsDOCKER_HOST_PORT- The port of the host machine that is mapped to theVITE_SERVER_PORTof the Vite dev server running in the container. This is only relevant when running the Development Container.HOST_PORT- is the same of theVITE_SERVER_PORTif run locally orDOCKER_HOST_PORTif running the Development Container.
-
Install (dev)dependencies:
npm install -D
-
Configure environment variables: Optionally create a
.envfile (explanation and defaults can be found in.env.example). Vite will load*.envfiles for the active mode and only expose variables that begin withVITE_to the browser (see https://vite.dev/guide/env-and-mode).If no enviroment variables are provided, the defaults are:
VITE_BACKEND_URL:http://localhost:8080- (SOARCA default)VITE_SERVER_PORT:5173- (Vite default)VITE_ENABLE_HTTPS:false
To enable HTTPS, set
VITE_ENABLE_HTTPS=trueand provideVITE_HTTPS_CERT_FILEandVITE_HTTPS_KEY_FILE. SetVITE_BACKEND_URL=https://localhost:8080when SOARCA also uses HTTPS. -
Start the dev server:
npm run dev
The app will be available at
http://localhost:HOST_PORTwith hot-reload enabled. You will see in the terminal where exactly the app is being served.
-
Configure environment variables: Optionally provide values via the shell, a project
.env, or--env-filewhen starting Compose (explanation and defaults can be found in.env.example).If no enviroment variables are provided, the defaults are:
VITE_BACKEND_URL:http://host.docker.internal:8080- (Thelocalhost:8080equivalent of the Container internal network)VITE_SERVER_PORT:5173DOCKER_HOST_PORT— port on the host mapped to theVITE_SERVER_PORT(default:5173)
For HTTPS, place
server.crtandserver.keyin./certs, then setVITE_ENABLE_HTTPS=true. The development Compose file mounts that directory read-only at/app/certs. -
Start the container:
docker compose -f docker-compose.dev.yml up
The app will be available at
http://localhost:HOST_PORTwith hot-reload enabled.
The GUI reads its login providers from /auth-config.json, a file you deploy
next to the GUI. It signs the user in with the authorization code flow and
PKCE, and sends the access token to SOARCA as a bearer token. No client secret
is involved. The GUI then asks SOARCA for the user's permissions through
/api/principal/permissions.
-
Serve the GUI over HTTPS (see
VITE_ENABLE_HTTPSabove, or the Nginx image). The GUI already forwards/api/*to SOARCA throughVITE_BACKEND_URLorNGINX_BACKEND_URL. -
Register a public client for the GUI at your identity provider with the redirect URI
https://<GUI host>/login/callback:- Microsoft Entra ID: add a Single-page application platform, and grant
the delegated SOARCA API permission
access_as_userwith admin consent. If SOARCA setsAUTH_ENTRA_ALLOWED_CLIENT_IDS, add the GUI client ID to it. - Other OIDC providers: create a public client without a secret. SOARCA
checks the token audience against
OIDC_CLIENT_ID, so the provider must issue the GUI's tokens for that audience.
- Microsoft Entra ID: add a Single-page application platform, and grant
the delegated SOARCA API permission
-
Copy
config/auth-config.example.jsontoconfig/auth-config.jsonand fill in one entry per provider.issuermust be the same issuer SOARCA is configured with, trailing slash included.scopesis optional. For Entra,scopesmust contain the SOARCA API scope, for exampleapi://<SOARCA API client ID>/access_as_user.iconis optional and sets the icon on the provider's login button. Without it the button showslock. Any other value makes the login page show an error that lists the allowed names.iconIcon on the button microsoftWindows logo ( IconBrandWindows)authentikOAuth logo ( IconBrandOauth); Tabler has no Authentik logolockOpen padlock ( IconLockOpen2)Earlier versions picked the Windows logo for a provider with
"id": "entra". That no longer happens, so add"icon": "microsoft"to keep it. -
Register
https://<GUI host>/loginat the provider as the address to return to after sign-out (post_logout_redirect_uri). For Entra, add it as an extra redirect URI of the Single-page application platform. Without it the provider may refuse the sign-out or stay on its own page afterwards. For Entra, also add the optional ID token claimlogin_hint(Token configuration in the app registration). The GUI passes it back on sign-out, so Entra skips its "pick an account to sign out" screen. -
Make the file available to the GUI:
npm run dev,npm run previewand the development container serveconfig/auth-config.jsonfrom the project directory.- The production container reads
/app/config/auth-config.json. Compose mountsSOARCA_GUI_CONFIG_DIR(default./config) there.
The file is read when the login page opens, so changes need no rebuild or restart. If the file is missing or invalid, the login page shows the reason instead of the provider buttons.
SOARCA's own auth settings (AUTH_ENABLED, OIDC_ISSUER, OIDC_CLIENT_ID,
the AUTH_ENTRA_* variables and role mapping) are described in the
SOARCA authentication documentation.
When SOARCA runs with AUTH_ENABLED=false, the GUI skips sign-in. In that
mode the GUI also works over plain HTTP. Sign-in itself needs HTTPS, because
the browser only offers the PKCE crypto and cross-tab locks on secure pages.
Menus and actions follow the permissions SOARCA reports for the user; SOARCA
enforces them. The tokens are stored in the browser's local storage, so every
tab shares the sign-in. Signing out clears them and then sends the browser to
the provider's end-session endpoint, which ends the session there and returns
to the login page. If the provider's discovery document has no
end_session_endpoint, the GUI only clears its own tokens and the provider
session stays open. If the provider cannot be reached, the GUI still clears
its tokens and the login page says the provider session may still be open. If
the GUI cannot clear its tokens, it shows an error and the user stays signed in.
Authentik's default provider invalidation flow ends only the session for the
GUI. The user's Authentik login stays active, so the next sign-in skips the
password. Configure a different invalidation flow on the Authentik provider
if users must be signed out of Authentik too. Authentik also ignores
prompt=select_account, so it never shows an account picker.
If a reverse proxy in front of SOARCA authenticates users and adds the bearer token, the GUI picks up the signed-in user without any extra settings.
Production mode builds optimized static assets and serves them via Nginx. We use this mode to publish Docker images and make releases, but it can be useful to run a production build locally through Vite as well by building the project locally and previewing it. Also this mode is supported for both local and Docker Container environment. As before, a diagram of the architecture is shown down below.
Production deployment can happen in two ways: locally using Vite's preview server or in a Docker container using Nginx.
flowchart TB
subgraph User[" "]
direction TB
UserLabel["User Machine"]
Browser["Browser<br/>localhost:HOST_PORT"]
end
subgraph LocalProd["Local Production Mode"]
direction TB
LocalLabel["Local Build & Preview"]
LocalBuild["npm run build"]
LocalDist["dist/<br/>Static Assets"]
VitePreview["Vite Preview Server<br/>Port: 3000<br/>Proxy: VITE_BACKEND_URL"]
end
subgraph DockerProd["Docker Container Mode"]
direction TB
ContainerLabel["Multi-stage Docker Build"]
subgraph BuildStage[" "]
direction TB
BuildLabel["Build Stage"]
NPM["npm install"]
Build["npm run build"]
Dist["dist/"]
end
subgraph ProdStage[" "]
direction TB
ProdLabel["Production Stage"]
StaticFiles["Static Files<br/>/usr/share/nginx/html"]
NginxConf["Nginx Config<br/>Port: NGINX_SERVER_PORT<br/>Proxy: NGINX_BACKEND_URL"]
Nginx["Nginx Server"]
end
end
subgraph Backend[" "]
direction TB
BackendLabel["SOARCA Backend"]
API["API Endpoints"]
end
UserLabel ~~~ Browser
LocalLabel ~~~ LocalBuild
ContainerLabel ~~~ BuildStage
BuildLabel ~~~ NPM
ProdLabel ~~~ StaticFiles
BackendLabel ~~~ API
%% Local production flow
LocalBuild --> LocalDist
LocalDist --> VitePreview
Browser -->|Local Mode| VitePreview
VitePreview -->|"/api/*"| API
%% Docker production flow
NPM --> Build
Build --> Dist
Dist -->|Copy| StaticFiles
StaticFiles --> Nginx
Nginx --> NginxConf
Browser -->|Container Mode| Nginx
NginxConf -->|"/api/*"| API
API -->|Response| NginxConf
NginxConf -->|Response| Browser
API -->|Response| VitePreview
VitePreview -->|Response| Browser
style LocalBuild fill:#C5E1FF,stroke:#4A90E2,color:#000
style Build fill:#C5E1FF,stroke:#4A90E2,color:#000
style Browser fill:#B8F5D3,stroke:#2ECC71,color:#000
style API fill:#FFE5CC,stroke:#E67E22,color:#000
style VitePreview fill:#C2F0F0,stroke:#16A085,color:#000
style Nginx fill:#C2F0F0,stroke:#16A085,color:#000
style NginxConf fill:#C2F0F0,stroke:#16A085,color:#000
style LocalDist fill:#FFF4CC,stroke:#F39C12,color:#000
style Dist fill:#FFF4CC,stroke:#F39C12,color:#000
style StaticFiles fill:#FFF4CC,stroke:#F39C12,color:#000
style NPM fill:#E8D4FF,stroke:#9B59B6,color:#000
style UserLabel fill:#F0F0F0,stroke:#999,color:#333
style LocalLabel fill:#F0F0F0,stroke:#999,color:#333
style ContainerLabel fill:#F0F0F0,stroke:#999,color:#333
style BuildLabel fill:#F0F0F0,stroke:#999,color:#333
style ProdLabel fill:#F0F0F0,stroke:#999,color:#333
style BackendLabel fill:#F0F0F0,stroke:#999,color:#333
classDef envVar fill:#D4F1D4,stroke:#27AE60,stroke-width:2px,color:#000
class VITE_BACKEND_URL envVar
class NGINX_BACKEND_URL envVar
class NGINX_SERVER_PORT envVar
class HOST_PORT envVar
Environment variables involved:
VITE_APP_VERSION- Application version embedded into the client bundle at build time (optional, falls back to git describe or "development")NGINX_BACKEND_URL- Backend API URL used by Nginx at runtime to proxy/api/*requests. This is only relevant when running in Docker Container Mode.NGINX_SERVER_PORT- Port where Nginx listens inside the container. This is only relevant when running in Docker Container Mode.NGINX_CERT_FILE- TLS certificate path inside the containerNGINX_CERT_KEY_FILE- TLS certificate key path inside the containerNGINX_PROXY_SSL_VERIFY- Controls verification of the backend TLS certificateSOARCA_CERTS_VOLUME- External Docker volume containing the SOARCA TLS certificate and keySOARCA_GUI_VERSION- Docker Hub image tag to run, defaulting tolatestDOCKER_HOST_PORT- The port of the host machine that is mapped to theNGINX_SERVER_PORTof the Nginx server running in the container. This is only relevant when running in Docker Container Mode.HOST_PORT- Port 4173 (Vite default) for local preview mode (npm run preview) orDOCKER_HOST_PORTwhen running in Docker Container Mode.
-
Install dependencies:
npm install
-
Configure environment variables: Optionally create a
.envfile (explanation and defaults can be found in.env.example). Note thatVITE_variables must be set at build time to be embedded into the static bundle.If no environment variables are provided, the defaults are:
VITE_ENABLE_HTTPS:false
-
Build and preview:
npm run build npm run preview
The app will be available at
http://localhost:4173(Vite preview server default).[!WARNING] For actual production deployment, use a proper web server like Nginx (see Docker section below).
-
Configure environment variables: Optionally provide values via the shell, a project
.env, or--env-filewhen starting Compose (explanation and defaults can be found in.env.example). The production container serves HTTPS and expects the certificate volume created by the SOARCA deployment.If no environment variables are provided, the defaults are:
SOARCA_GUI_VERSION:latestSOARCA_CERTS_VOLUME:soarca_certs_data_containerNGINX_BACKEND_URL:https://host.docker.internal:8080/NGINX_SERVER_PORT:8081NGINX_PROXY_SSL_VERIFY:off, to support SOARCA's generated self-signed certificateSOARCA_GUI_CONFIG_DIR:./config- host directory withauth-config.json, mounted read-only at/app/configDOCKER_HOST_PORT:8081- port on the host mapped to theNGINX_SERVER_PORT
-
Pull and start the container:
docker compose pull docker compose up -d
The app will be available at
https://localhost:DOCKER_HOST_PORT.
npm run dev- Start Vite dev server with hot-reloadnpm run build- Type-check and create production bundlenpm run preview- Serve the production build locally (Vite preview server)npm run lint- Run oxlint, then Stylelint (CSS property order)npm run lint:css- Run only Stylelint; add-- --fixto reorder properties automaticallynpm run format- Format the code with oxfmtnpm run format:check- Check formatting without writing changes (run in CI)npm test- Run unit tests (Vitest)
- Project docs: https://cossas.github.io/SOARCA/docs/
- Contribution guidelines: https://cossas.github.io/SOARCA/docs/contribution-guidelines/
Usage of SOARCA-GUI is described here: https://cossas.github.io/SOARCA/docs/
- Collapse either side panel with its chevron button. A primary-coloured canvas-facing border marks a collapsed panel.
- Right-click the canvas, a step, a connection or a connection badge for its actions. Hover a submenu or use the arrow keys to open its choices.
- Hold Shift and drag to select several steps, then drag the selection to move them together.
- Ctrl-click (Cmd-click on macOS) adds a step to the selection or removes it. The "Controls" section under the step list has the full list of controls.
- The properties panel groups fields in tabs. A step has Details, Execution, Variables and Advanced. The playbook has Metadata, Resources and Advanced. Fields without a form input, such as extensions, are edited as JSON in the Advanced tab.
- The editor sets
id,created_by,createdandmodifieditself, so the panel does not show them. - Lists such as playbook types and labels use searchable selects. Type a new value and press Enter to add one that is not in the list.
- Variables, agents, targets and authentication info are rows that expand one at a time. The input for a variable's value follows its type.
- Valid from and valid until are shown and typed in your local time zone. The playbook stores them in UTC.
- Fields with a red asterisk are required by CACAO 2.0. Save is blocked while a required field is empty or a JSON box has invalid JSON. It then opens the step and tab with the problem. Missing connections are warnings and do not block saving.
- The read-only diagram supports panning and step details. Use its zoom buttons to change the zoom.
- Leaving the visual editor with unsaved changes asks for confirmation, including in-app navigation, reloads and closing the tab.
The visual playbook editor was written from scratch for SOARCA-GUI, using these projects as a reference for CACAO concepts:
- CACAO Roaster by the Open Cybersecurity Alliance (Apache-2.0), a browser-based editor for CACAO v2.0 playbooks.
- CACAO Layout Extension by Cyentific AS, now maintained by the OASIS CACAO TC (MIT, Copyright (c) 2023 Cyentific). The editor stores step positions under this extension's id (
extension-definition--418ee24c-9cb1-46d9-afa5-309e01aabc7f).
Want to contribute to this project? Please keep in mind the following rules:
- This repository uses git rebase strategy
- For each PR, there should be at least one issue
- Make sure all tests pass (including lint errors)