Skip to content

Repository files navigation

SOARCA-GUI

https://cossas-project.org/portfolio/SOARCA/ Release Pipeline status License

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.

Requirements

Running the Project

Development Mode

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 Architecture

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
Loading

Environment variables involved:

  • VITE_BACKEND_URL - Backend API URL (proxied by Vite dev server)
  • VITE_SERVER_PORT - Port where Vite dev server listens
  • VITE_ENABLE_HTTPS - Set to true to serve the development or preview build over HTTPS
  • VITE_HTTPS_CERT_FILE - Path to the TLS certificate used by Vite
  • VITE_HTTPS_KEY_FILE - Path to the TLS certificate key used by Vite
  • VITE_VERIFY_SSL - Set to true to verify the backend certificate when Vite proxies API requests
  • DOCKER_HOST_PORT - The port of the host machine that is mapped to the VITE_SERVER_PORT of the Vite dev server running in the container. This is only relevant when running the Development Container.
  • HOST_PORT - is the same of the VITE_SERVER_PORT if run locally or DOCKER_HOST_PORT if running the Development Container.

Running Locally (recommended for development)

  1. Install (dev)dependencies:

    npm install -D
  2. Configure environment variables: Optionally create a .env file (explanation and defaults can be found in .env.example). Vite will load *.env files for the active mode and only expose variables that begin with VITE_ 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=true and provide VITE_HTTPS_CERT_FILE and VITE_HTTPS_KEY_FILE. Set VITE_BACKEND_URL=https://localhost:8080 when SOARCA also uses HTTPS.

  3. Start the dev server:

    npm run dev

    The app will be available at http://localhost:HOST_PORT with hot-reload enabled. You will see in the terminal where exactly the app is being served.

Running in Docker Container (reccomended for development without Node/npm setup)

  1. Configure environment variables: Optionally provide values via the shell, a project .env, or --env-file when 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 - (The localhost:8080 equivalent of the Container internal network)
    • VITE_SERVER_PORT: 5173
    • DOCKER_HOST_PORT — port on the host mapped to the VITE_SERVER_PORT (default: 5173)

    For HTTPS, place server.crt and server.key in ./certs, then set VITE_ENABLE_HTTPS=true. The development Compose file mounts that directory read-only at /app/certs.

  2. Start the container:

    docker compose -f docker-compose.dev.yml up

    The app will be available at http://localhost:HOST_PORT with hot-reload enabled.

Enable sign-in

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.

  1. Serve the GUI over HTTPS (see VITE_ENABLE_HTTPS above, or the Nginx image). The GUI already forwards /api/* to SOARCA through VITE_BACKEND_URL or NGINX_BACKEND_URL.

  2. 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_user with admin consent. If SOARCA sets AUTH_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.
  3. Copy config/auth-config.example.json to config/auth-config.json and fill in one entry per provider. issuer must be the same issuer SOARCA is configured with, trailing slash included. scopes is optional. For Entra, scopes must contain the SOARCA API scope, for example api://<SOARCA API client ID>/access_as_user.

    icon is optional and sets the icon on the provider's login button. Without it the button shows lock. Any other value makes the login page show an error that lists the allowed names.

    icon Icon on the button
    microsoft Windows logo (IconBrandWindows)
    authentik OAuth logo (IconBrandOauth); Tabler has no Authentik logo
    lock Open 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.

  4. Register https://<GUI host>/login at 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 claim login_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.

  5. Make the file available to the GUI:

    • npm run dev, npm run preview and the development container serve config/auth-config.json from the project directory.
    • The production container reads /app/config/auth-config.json. Compose mounts SOARCA_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

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 Architecture

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
Loading

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 container
  • NGINX_CERT_KEY_FILE - TLS certificate key path inside the container
  • NGINX_PROXY_SSL_VERIFY - Controls verification of the backend TLS certificate
  • SOARCA_CERTS_VOLUME - External Docker volume containing the SOARCA TLS certificate and key
  • SOARCA_GUI_VERSION - Docker Hub image tag to run, defaulting to latest
  • DOCKER_HOST_PORT - The port of the host machine that is mapped to the NGINX_SERVER_PORT of 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) or DOCKER_HOST_PORT when running in Docker Container Mode.

Running Locally (recommended for preview)

  1. Install dependencies:

    npm install
  2. Configure environment variables: Optionally create a .env file (explanation and defaults can be found in .env.example). Note that VITE_ 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
  3. 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).

Running in Docker Container (recommended for production)

  1. Configure environment variables: Optionally provide values via the shell, a project .env, or --env-file when 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: latest
    • SOARCA_CERTS_VOLUME: soarca_certs_data_container
    • NGINX_BACKEND_URL: https://host.docker.internal:8080/
    • NGINX_SERVER_PORT: 8081
    • NGINX_PROXY_SSL_VERIFY: off, to support SOARCA's generated self-signed certificate
    • SOARCA_GUI_CONFIG_DIR: ./config - host directory with auth-config.json, mounted read-only at /app/config
    • DOCKER_HOST_PORT: 8081 - port on the host mapped to the NGINX_SERVER_PORT
  2. Pull and start the container:

    docker compose pull
    docker compose up -d

    The app will be available at https://localhost:DOCKER_HOST_PORT.

NPM Scripts for local run

  • npm run dev - Start Vite dev server with hot-reload
  • npm run build - Type-check and create production bundle
  • npm 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 -- --fix to reorder properties automatically
  • npm run format - Format the code with oxfmt
  • npm run format:check - Check formatting without writing changes (run in CI)
  • npm test - Run unit tests (Vitest)

Documentation

Quick Use

Usage of SOARCA-GUI is described here: https://cossas.github.io/SOARCA/docs/

Visual playbook editor

  • 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, created and modified itself, 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.

Acknowledgements

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).

Contributing

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)

Releases

Used by

Contributors

Languages