Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions AI_CONTRIBUTING_RULES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Global AI Agent Instructions (Jules)

**1. The "Living Wiki" Mandate:**
This repository maintains its documentation as a living wiki. The primary sources of truth are the `SYSTEM_ARCHITECTURE.md` and `SECURITY_ARCHITECTURE.md` files.

**2. Mandatory PR Checklist:**
For *every single Pull Request* you generate, regardless of the specific issue assigned to you, you MUST perform the following checks before committing:
* **Diff Review:** Analyze your proposed code changes.
* **Wiki Sync:** If your code alters the network flow, port configurations, authentication methods, database schemas, or deployment commands, you MUST open `SYSTEM_ARCHITECTURE.md`, `SECURITY_ARCHITECTURE.md` and all other markdown files in the root directory and `/docs/` directory to update the relevant sections to reflect your exact code changes. Also update the `docs/system_data_flow.svg` as appropriate.
* **Commit Inclusion:** The documentation updates must be included in the same commit/PR as the code changes. Do not submit a PR where the code and the architecture wiki are out of sync.

**3. Global Build Constraint:**
Whenever generating or modifying Dockerfiles for this project, you MUST ensure the font package is explicitly set to `fonts-freefont-ttf` to prevent downstream rendering failures.
61 changes: 53 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This repository combines all the OSH modules and dependencies to deploy the OSH
- [Java 21](https://www.oracle.com/java/technologies/downloads/#java21)
- [Oakridge Build Node Repository](https://github.com/Botts-Innovative-Research/osh-oakridge-buildnode)
- Node v22
- [Docker](https://docs.docker.com/get-docker/) (Required to run the PostGIS database system)

## Installation
Clone the repository and update all submodules recursively
Expand Down Expand Up @@ -44,25 +45,63 @@ After the build completes, it can be located in `build/distributions/`

Option 1: Command Line
```bash
unzip build/distributions/osh-node-oscar-1.0.zip
cd osh-node-oscar-1.0/osh-node-oscar-1.0
# Note: Replace <version> with the current version, e.g. 3.0.0
unzip build/distributions/osh-node-oscar-<version>.zip
cd osh-node-oscar-<version>/osh-node-oscar-<version>
```
```bash
tar -xf build/distributions/osh-node-oscar-1.0.zip
cd osh-node-oscar-1.0/osh-node-oscar-1.0
# Note: Replace <version> with the current version, e.g. 3.0.0
tar -xf build/distributions/osh-node-oscar-<version>.zip
cd osh-node-oscar-<version>/osh-node-oscar-<version>
```
Option 2: Use File Explorer
1. Navigate to `path/to/osh-oakridge-buildnode/build/distributions/`
2. Right-click `osh-node-oscar-1.0.zip`.
2. Right-click `osh-node-oscar-<version>.zip` (where `<version>` is the current release version, e.g. `3.0.0`).
3. Select **Extract All..**
4. Choose your destination, (or leave the default) and extract.
1. Launch the OSH node:
Run the launch script, "launch.sh" for linux/mac and "launch.bat" for windows.
1. Launch the OSH node and PostGIS Database:
The database management system is handled through Docker. The default launch scripts automatically build and run a PostGIS container using the `Dockerfile` located in `dist/release/postgis`, and then start the OSH node.
Run the launch script, `launch-all.sh` (or `launch.sh` within the `osh-node-oscar` folder directly if the database is already running) for linux, `launch-all-arm.sh` (or `launch-arm.sh` if it exists) for mac, and `launch-all.bat` (or `launch.bat`) for windows.
2. Access the OSH Node
- Remote: **[ip-address]:8282/sensorhub/admin**
- Locally: **http://localhost:8282/sensorhub/admin**

The default credentials to access the OSH Node are admin:admin. This can be changed in the Security section of the admin page.
### First-Time Setup
On first boot, OSCAR enters an **Uninitialized State** and requires configuration via a Setup Wizard.
1. Navigate to `http://localhost:8282/` or `http://localhost:8282/sensorhub/admin`.
2. You will be automatically redirected to the **Setup Wizard**.
3. **Create an Admin Password**: Set a strong password for the `admin` account.
4. **Configure TOTP**:
- Scan the displayed QR code with an authenticator app (Google Authenticator, Authy, etc.).
- **Important**: Save the secret key shown in the wizard!
- Use the **Test Code** form to verify your setup before proceeding.
5. Once complete, you will be redirected to the Admin UI login.

### Logging In
After initialization, use the following credentials:
- **Username**: `admin`
- **Password**: The password you set during the Setup Wizard.
- **Two-Factor Authentication**:
- If your browser or client supports it, enter your password as usual and provide the 6-digit TOTP code when prompted.
- If you are prompted for a single login by the browser and can't provide a TOTP code separately, enter your password followed by a colon and the code (e.g., `mypassword:123456`).

**Language Selection**
The user can select different languages for the Admin UI by using the language drop-down menu located in the top right corner of the Admin UI toolbar. Selecting a new language will instantly switch the UI localization.

**Two-Factor Authentication (2FA)**
2FA is mandatory for the administrator account and can be configured for other users to add an extra layer of security. To set this up for additional users:
1. Log in to the Admin UI as `admin`.
2. Navigate to the **Security** section.
3. Edit a user profile and set up Two-Factor Authentication. A popup window will appear with a QR code generated locally on the server.
4. Scan the QR code with an authenticator app (like Google Authenticator or Authy) to complete the setup.

**Importing/Exporting Lane Configurations via CSV**
Configurations for Lane Systems can be bulk managed via spreadsheet (CSV).
1. Log in to the Admin UI.
2. Navigate to **Services -> OSCAR Service**.
3. Within the configuration form for the OSCAR service, locate the property for spreadsheet configuration (`spreadsheetConfigPath`).
4. To export, click the download button to retrieve the current configurations as a CSV file.
5. To import, upload your modified CSV file through the provided upload mechanism in the service configuration to apply new or updated lane setups.

For documentation on configuring a Lane System on the OSH Admin panel, please refer to the OSCAR Documentation provided in the Google Drive documentation folder.

Expand All @@ -73,6 +112,12 @@ After configuring the Lanes on the OSH Admin Panel, you can navigate to the Clie

For documentation on configuring a server on the OSCAR Client refer to the OSCAR Documentation provided in the Google Drive documentation folder.

## Security and Federation
- [Security Architecture](SECURITY_ARCHITECTURE.md)
- [System Architecture](SYSTEM_ARCHITECTURE.md)
- [Federation Provisioning (API Keys)](docs/FEDERATION_PROVISIONING.md)
- [Tailscale Security and Configuration](docs/TAILSCALE_CONFIGURATION.md)

# Release Checklist
- Version in `build.gradle`
- Version in `dist/config/standard/config.json`
Expand Down
52 changes: 52 additions & 0 deletions SECURITY_ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# OSCAR Security Hardening Architecture

**Critical Domain Context:**
This project is an Open Source Central Alarm Station (OSCAR) monitoring radiation portal monitors. The application runs cross-platform on Windows, macOS, and Linux. The primary critical threat is the unauthorized suppression, modification, or spoofing of alarms. Note this specific nomenclature:
* **G Alarm:** Gamma Alarm.
* **N Alarm:** Neutron Alarm.
* **G-N:** Gamma Neutron Alarm.

**OpenSensorHub (OSH) Ecosystem Constraint:**
OSCAR is built on the OpenSensorHub framework. **Under no circumstances may any code modifications break compatibility with the larger OSH ecosystem.** * Standard OGC SWE, SOS, and SPS API endpoints must remain fully compliant.
* Sensor drivers (e.g., video processing, hardware interfaces mapped in `config.csv`) must not be prevented from initializing or communicating.
* Machine-to-machine API routes cannot rely on human-interactive authentication (like 302 redirects to a TOTP login).

**Global Build Constraint:**
Whenever generating or modifying Dockerfiles for this project, you MUST ensure the font package is explicitly set to `fonts-freefont-ttf`. This is strictly required to prevent downstream rendering failures in the application's graphical reporting components.

## Database Security Implementation

### SCRAM-SHA-256 Authentication
PostgreSQL is configured to enforce `scram-sha-256` authentication for all database users. This is initialized during the PostGIS container setup via `POSTGRES_INITDB_ARGS`.

### Docker Secrets for Database Credentials
The system uses Docker Secrets (via bind mounts) to manage database passwords.
- **Injected Secret Path**: `/run/secrets/db_password` within the container.
- **Environment Variable**: `POSTGRES_PASSWORD_FILE` points to this secret path.
- **Backend Priority**: The OSH Java backend is architected to prioritize the `POSTGRES_PASSWORD_FILE` environment variable during initialization, overriding any plaintext credentials in `config.json`.

### Configurable Networking and TLS
- **DB Host**: The database host is configurable via the `DB_HOST` environment variable (default: `localhost`), enabling secure deployment on separate LAN machines.
- **TLS Enforcement**: All connections from the OSH backend to PostGIS are secured over TLS. This is enforced by using `sslmode=require` in the JDBC connection string in the `ConnectionManager`.

## Application-Level Security Hardening

### Persistent Local CA and TLS Certificates
On first boot, the system generates a persistent Root CA and a leaf TLS certificate.
- **Root CA Private Key**: Securely stored within the PKCS12 keystore (`osh-keystore.p12`) under the alias `root-ca`. This allows for automated, silent renewal of leaf certificates.
- **Lifespan**: The Root CA is generated with a 20-year lifespan, while the Leaf certificate has a 1-year lifespan.
- **Automated Renewal**: Upon each startup, the system checks the expiration of the active Leaf certificate. If it expires within 30 days, a new Leaf certificate is automatically generated and signed by the persistent Root CA.
- **Leaf Certificate**: Stored in the same PKCS12 keystore (`osh-keystore.p12`) under the alias `jetty`.
- **Key Storage Security**: The keystore password is automatically generated and stored in a hidden `.app_secrets` file. Access to this file and the keystore is restricted to the executing user using POSIX permissions (Linux/macOS) or ACLs (Windows). The system implements a "fail-secure" startup policy: if `.app_secrets` is missing, the application will halt with a critical error rather than falling back to default passwords.
- **Public CA Download**: The public Root CA certificate is available for download at `/sensorhub/admin/ca-cert` to allow clients to establish trust.

### Setup Wizard and Credential Management
The system does not ship with default administrative credentials.
- **Uninitialized State**: If the system detects that it has not been configured (no admin password set), it enters an uninitialized state.
- **Mandatory Redirection**: In the uninitialized state, all requests to the root URL or Admin UI are redirected to a Setup Wizard.
- **Initialization**: The Setup Wizard forces the creation of a strong admin password (hashed using PBKDF2) and initializes the TOTP 2FA seed.
- **Bifurcated Authentication (TOTP + API Keys)**: OSCAR implements two distinct authentication flows to ensure secure human access and robust machine-to-machine (M2M) communication.
- **Human UI Routes (/, /admin, /VAADIN, /setup)**: Require a valid session. If unauthenticated, the user is redirected (302) to `/sensorhub/login`. Login requires username, password, and TOTP. Validated 2FA sessions are bridged across contexts using `BridgedAuthenticator`.
- **Machine/API Routes (SOS, SPS, WebSockets)**: Secured via long-lived API Keys. Keys are provided via `Authorization: Bearer <key>` or `X-API-Key` headers. These routes return standard `401/403` status codes instead of redirects if authentication fails.
- **API Key Management**: Administrators can generate, view (once), and revoke API keys via the Admin UI. Keys are hashed (PBKDF2) before storage.
- **Secure Provisioning**: Automated utilities (`provision-node.sh` and `provision-node.bat`) are provided for secure key distribution via Tailscale. See [Federation Provisioning](docs/FEDERATION_PROVISIONING.md) and [Tailscale Configuration](docs/TAILSCALE_CONFIGURATION.md) for detailed instructions and security requirements.
53 changes: 53 additions & 0 deletions SYSTEM_ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# OSCAR System Architecture

## Overview
OSCAR (Open Source Central Alarm Station) is a monitoring system for radiation portal monitors based on the OpenSensorHub (OSH) framework.

## Data Flow Diagram
![OSCAR System Data Flow](docs/system_data_flow.svg)

## Component Network Flow and Ports

### Components:
- **OSH Backend**: Java-based core application.
- **PostGIS Database**: PostgreSQL with PostGIS extensions for persistent storage.
- **Client Web UI**: React/Frontend viewer.

### Default Port Configuration:
- **OSH Backend API (HTTP)**: `8282`
- **OSH Backend Admin UI**: `8282`
- **PostGIS Database**: `5432`
- **MQTT Server (HiveMQ)**: WebSockets on `/mqtt` (via proxy on port `8282`)

### Network Flows:
- **Client to OSH**: Clients interact with OSH through its REST API and Web UI on port `8282`.
- **OSH to PostGIS**: The OSH backend connects to the PostGIS database over the network (local or LAN) on port `5432`. This connection is secured via TLS and authenticated with SCRAM-SHA-256.
- **Certificate Management**: OSH manages its own internal PKI. On first boot, a 20-year Root CA and a 1-year Leaf certificate are generated and stored in `osh-keystore.p12`. The system automatically renews the Leaf certificate if it is within 30 days of expiration during the boot sequence.

## Deployment and Lifecycle Commands

### Main Launch Scripts:
Located in `dist/release/`:
- `launch-all.sh`: Starts the PostGIS container and the OSH backend (Linux/macOS).
- `launch-all-arm.sh`: Starts the PostGIS container and the OSH backend (ARM64, e.g., Mac M1/M2/M3).
- `launch-all.bat`: Starts the PostGIS container and the OSH backend (Windows).

### Automated Provisioning Utilities:
Located in the repository root:
- `provision-node.sh`: Securely pushes an API key to a remote node via Tailscale (Unix/Linux/macOS).
- `provision-node.bat`: Securely pushes an API key to a remote node via Tailscale (Windows).

See [Federation Provisioning](docs/FEDERATION_PROVISIONING.md) and [Tailscale Configuration](docs/TAILSCALE_CONFIGURATION.md) for detailed setup and usage instructions.

### Standalone Database Scripts:
Located in `dist/release/postgis/`:
- `run-postgis.sh`: Starts the PostGIS container independently (Linux/macOS).
- `run-postgis-arm.sh`: Starts the PostGIS container independently (ARM64).
- `run-postgis.bat`: Starts the PostGIS container independently (Windows).

## Database Utilities
Cross-platform scripts are provided in the repository root for maintenance:
- `backup.sh/bat`: Safely creates a database dump.
- `restore.sh/bat`: Restores the database from a dump.

These utilities respect the `DB_HOST` and `POSTGRES_PASSWORD_FILE` environment variables.
32 changes: 32 additions & 0 deletions backup.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@echo off
setlocal enabledelayedexpansion

if "%DB_HOST%"=="" (set DB_HOST=localhost)
set DB_NAME=gis
set DB_USER=postgres

if "%POSTGRES_PASSWORD_FILE%"=="" (
echo Error: POSTGRES_PASSWORD_FILE environment variable is not set.
exit /b 1
)

if not exist "%POSTGRES_PASSWORD_FILE%" (
echo Error: Password file %POSTGRES_PASSWORD_FILE% does not exist.
exit /b 1
)

set /p PGPASSWORD=<"%POSTGRES_PASSWORD_FILE%"

set TIMESTAMP=%date:~10,4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%
set TIMESTAMP=%TIMESTAMP: =0%
set BACKUP_FILE=backup_%TIMESTAMP%.dump

echo Backing up database %DB_NAME% from %DB_HOST%...
pg_dump -h %DB_HOST% -U %DB_USER% -d %DB_NAME% -F c -f "%BACKUP_FILE%"

if %errorlevel% equ 0 (
echo Backup completed successfully: %BACKUP_FILE%
) else (
echo Backup failed.
exit /b 1
)
27 changes: 27 additions & 0 deletions backup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash

DB_HOST="${DB_HOST:-localhost}"
DB_NAME="gis"
DB_USER="postgres"

if [ -z "$POSTGRES_PASSWORD_FILE" ]; then
echo "Error: POSTGRES_PASSWORD_FILE environment variable is not set."
exit 1
fi

if [ ! -f "$POSTGRES_PASSWORD_FILE" ]; then
echo "Error: Password file $POSTGRES_PASSWORD_FILE does not exist."
exit 1
fi

export PGPASSWORD=$(cat "$POSTGRES_PASSWORD_FILE")

echo "Backing up database $DB_NAME from $DB_HOST..."
pg_dump -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" -F c -f "backup_$(date +%Y%m%d_%H%M%S).dump"

if [ $? -eq 0 ]; then
echo "Backup completed successfully."
else
echo "Backup failed."
exit 1
fi
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apply from: gradle.oshCoreDir + '/common.gradle'
description = ''

allprojects {
version = "3.0.0-rc.5"
version = "3.0.0"
}

subprojects {
Expand Down
9 changes: 9 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# OSCAR Build Node Change Log
All notable changes to this project will be documented in this file.
## 3.0.0 2026-02-04
This is the official first release of 3.0.0
### Changes
- Data from database is purged regularly with "daily files" exported at midnight
- Added internationalization (i18n) to the frontend
- Sorted lanes by alphanumeric order in the frontend dashboard
- Use server-side filters in frontend tables
### Fixed
- Fixed issue where database is queried everytime Admin UI is loaded

## 3.0.0-rc.5 2025-12-11
### Changes
Expand Down
11 changes: 5 additions & 6 deletions dist/config/standard/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@
"roles": [
"admin"
],
"allow": [
"fileserver[af72442c-1ce6-4baa-a126-ed41dda26910]"
],
"allow": [],
"deny": []
},
{
Expand Down Expand Up @@ -94,7 +92,7 @@
"uiClass": "com.botts.ui.oscar.forms.OSCARServiceForm"
}
],
"deploymentName": "OSCAR 3.0.0-rc.5",
"deploymentName": "OSCAR 3.0.0",
"enableLandingPage": false,
"id": "5cb05c9c-9123-4fa1-8731-ffaa51489678",
"autoStart": true,
Expand Down Expand Up @@ -158,7 +156,8 @@
"initialBuckets": [
"sitemap",
"reports",
"videos"
"videos",
"adjudication"
],
"fileStoreRootDir": "files",
"endPoint": "/buckets",
Expand All @@ -174,7 +173,7 @@
"url": "localhost:5432",
"dbName": "gis",
"login": "postgres",
"password": "postgres",
"password": "",
"idProviderType": "SEQUENTIAL",
"autoCommitPeriod": 10,
"useBatch": false,
Expand Down
Loading
Loading