Skip to content
Merged
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
17 changes: 17 additions & 0 deletions .github/workflows/development-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Development Compose example
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check generated development example
run: |
bash -n docker/setup-workbench.sh
bash docker/setup-workbench.sh --print-dev-compose > /tmp/compose.dev.yaml
diff -u docker/example-setup/compose.dev.yaml /tmp/compose.dev.yaml
22 changes: 9 additions & 13 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
# Docker Compose Setup

Use the interactive setup script `setup-workbench.sh` to quickly create and deploy a custom Workbench instance:
Use the interactive setup script to create a Workbench instance:

```bash
# Clone and run setup script
git clone https://github.com/mitre-attack/attack-workbench-deployment.git
cd attack-workbench-deployment/docker/
./setup-workbench.sh
```

After running the script, deploy with:
After setup, start the instance:

```bash
cd ../instances/your-instance-name

# deploy with docker compose
docker compose up -d

# or deploy in development mode
docker compose up -d --build
```

Access Workbench at <http://localhost>

Full variable descriptions and examples are available in [docs/configuration](docs/configuration.md).
Open <http://localhost>, or the HTTP port selected during setup.

For source builds or TAXII setup, see [docs/deployment](docs/deployment.md).
For live development, select developer mode during setup, then run
`docker compose up --watch --build`. See [local development](../docs/local-development.md)
for prerequisites, reload behavior, and switching branches.

For information on how to backup or restore the mongo database, see [docs/database-backups](docs/database-backups.md).
- [Configuration](../docs/configuration.md): ports, mounted files, and service settings.
- [Deployment](../docs/deployment.md): deployment choices and optional services.
- [Database backups](../docs/database-backups.md): backup and restore procedures.
117 changes: 90 additions & 27 deletions docker/example-setup/compose.dev.yaml
Original file line number Diff line number Diff line change
@@ -1,54 +1,117 @@
# This file was generated by setup-workbench.sh
# It will be automatically merged with compose.yaml when running docker compose commands

services:

frontend:
image: attack-workbench-frontend
build: ../../../attack-workbench-frontend
build:
context: ../../../attack-workbench-frontend
target: dev
environment:
- WORKBENCH_FRONTEND_API_PROXY_TARGET=http://rest-api:3000
ports: !override
- "${ATTACKWB_FRONTEND_HTTP_PORT:-80}:80"
volumes: !override
- "${ATTACKWB_FRONTEND_CONFIG_DIR:-./configs/frontend}:/etc/workbench:ro"
- type: bind
source: ../../../attack-workbench-frontend/src
target: /workspace/src
read_only: true
bind:
create_host_path: false
develop:
watch:
# Sync source files for hot-reload
- action: sync
path: ../../../attack-workbench-frontend/src
target: /app/src
# Angular polls source; restart it to discover newly added static assets.
- action: restart
path: ../../../attack-workbench-frontend/src/assets
- action: restart
# Watch the directory so adding/removing optional config.json is detected.
path: ${ATTACKWB_FRONTEND_CONFIG_DIR:-./configs/frontend}
ignore:
- node_modules/
- .env
- template.env
- '*.conf'
# Rebuild on Angular build configuration changes
- action: rebuild
path: ../../../attack-workbench-frontend/angular.json
- action: rebuild
path: ../../../attack-workbench-frontend/proxy.conf.cjs
- action: rebuild
path: ../../../attack-workbench-frontend/scripts
- action: rebuild
path: ../../../attack-workbench-frontend/tsconfig.json
- action: rebuild
path: ../../../attack-workbench-frontend/tsconfig.app.json
# Rebuild on package.json changes
- action: rebuild
path: ../../../attack-workbench-frontend/package.json
- action: rebuild
path: ../../../attack-workbench-frontend/package-lock.json

rest-api:
image: attack-workbench-rest-api
build: ../../../attack-workbench-rest-api
build:
context: ../../../attack-workbench-rest-api
target: dev
volumes:
- type: bind
source: ../../../attack-workbench-rest-api/app
target: /usr/src/app/app
read_only: true
bind:
create_host_path: false
- type: bind
source: ../../../attack-workbench-rest-api/bin
target: /usr/src/app/bin
read_only: true
bind:
create_host_path: false
develop:
watch:
# Sync app source files
- action: sync
# Restart the API to load edits from its source mounts
- action: restart
path: ../../../attack-workbench-rest-api/app
target: /usr/src/app/app
ignore:
- node_modules/
# Restart on config changes
- action: sync+restart
path: ../../../attack-workbench-rest-api/resources
target: /usr/src/app/resources
# Restart after server entrypoint and config changes
- action: restart
path: ../../../attack-workbench-rest-api/bin
# The base compose file mounts this config before the API starts.
- action: restart
path: ${ATTACKWB_RESTAPI_CONFIG_FILE:-./configs/rest-api/rest-api-service-config.json}
# Rebuild on package.json changes
- action: rebuild
path: ../../../attack-workbench-rest-api/package.json
- action: rebuild
path: ../../../attack-workbench-rest-api/package-lock.json

taxii:
image: attack-workbench-taxii-server
build: ../../../attack-workbench-taxii-server
build:
context: ../../../attack-workbench-taxii-server
target: development
volumes:
- type: bind
source: ../../../attack-workbench-taxii-server/src
target: /app/src
read_only: true
bind:
create_host_path: false
develop:
watch:
# Sync source files
- action: sync
path: ../../../attack-workbench-taxii-server/taxii
target: /app/taxii
ignore:
- node_modules/
# Sync config files and restart
- action: sync+restart
path: ../../../attack-workbench-taxii-server/config
target: /app/config
# Rebuild TypeScript and restart both TAXII server and collector
- action: restart
path: ../../../attack-workbench-taxii-server/src
# Rebuild on package.json changes
- action: rebuild
path: ../../../attack-workbench-taxii-server/package.json
- action: rebuild
path: ../../../attack-workbench-taxii-server/package-lock.json
# Rebuild when Nest or TypeScript build configuration changes
- action: rebuild
path: ../../../attack-workbench-taxii-server/nest-cli.json
- action: rebuild
path: ../../../attack-workbench-taxii-server/ecosystem.config.js
- action: rebuild
path: ../../../attack-workbench-taxii-server/tsconfig.json
- action: rebuild
path: ../../../attack-workbench-taxii-server/tsconfig.build.json
3 changes: 3 additions & 0 deletions docker/example-setup/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ services:
volumes:
- "${ATTACKWB_FRONTEND_NGINX_CONFIG_FILE:-./configs/frontend/nginx.api.conf}:/etc/nginx/conf.d/default.conf:ro"
- "${ATTACKWB_FRONTEND_CERTS_PATH:-./certs}:/etc/nginx/certs:ro"
- "${ATTACKWB_FRONTEND_CONFIG_DIR:-./configs/frontend}:/etc/workbench:ro"
env_file:
- "${ATTACKWB_FRONTEND_ENV_FILE:-./configs/frontend/.env}"
restart: unless-stopped
logging:
driver: "json-file"
Expand Down
14 changes: 14 additions & 0 deletions docker/example-setup/configs/frontend/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"apiUrl": "api",
"attackWebsiteEnabled": false,
"attackWebsiteUrl": "https://attack.mitre.org",
"collectionManagerEnabled": true,
"recommendedIndexes": [
{
"name": "MITRE ATT&CK",
"url": "https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/index.json"
}
],
"logLevel": "ERROR",
"defaultLandingPage": ""
}
4 changes: 4 additions & 0 deletions docker/example-setup/configs/frontend/nginx.api.conf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ server {
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;

location = /assets/config.json {
add_header Cache-Control "no-store" always;
}

location / {
try_files $uri $uri/ /index.html;
}
Expand Down
4 changes: 4 additions & 0 deletions docker/example-setup/configs/frontend/nginx.api.ssl.conf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ server {
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;

location = /assets/config.json {
add_header Cache-Control "no-store" always;
}

location / {
try_files $uri $uri/ /index.html;
}
Expand Down
4 changes: 4 additions & 0 deletions docker/example-setup/configs/frontend/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ server {
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;

location = /assets/config.json {
add_header Cache-Control "no-store" always;
}

location / {
try_files $uri $uri/ /index.html;
}
Expand Down
4 changes: 4 additions & 0 deletions docker/example-setup/configs/frontend/nginx.ssl.conf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ server {
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;

location = /assets/config.json {
add_header Cache-Control "no-store" always;
}

location / {
try_files $uri $uri/ /index.html;
}
Expand Down
40 changes: 40 additions & 0 deletions docker/example-setup/configs/frontend/template.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Template-Version: 1.0
# Template-Updated: 2026-10-11
# Template-Source: attack-workbench-frontend/template.env
#
# Changelog
# ---------
# - 1.0 (2026-10-11): Introduce template metadata

# Optional frontend settings. Copy to .env and uncomment the values you need.
# Native commands load .env automatically; existing process variables take priority.
# See docs/admin/configuration.md. All public application settings reach the browser.

# Public application settings (production website/log defaults differ; see below).
# WORKBENCH_FRONTEND_API_URL=api
# WORKBENCH_FRONTEND_ATTACK_WEBSITE_ENABLED=false
# Development default: http://localhost:8000; production: https://attack.mitre.org
# WORKBENCH_FRONTEND_ATTACK_WEBSITE_URL=https://attack.mitre.org
# WORKBENCH_FRONTEND_COLLECTION_MANAGER_ENABLED=true
# WORKBENCH_FRONTEND_RECOMMENDED_INDEXES='[{"name":"MITRE ATT&CK","url":"https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/index.json"}]'
# Use [] to remove recommended indexes.
# Development default: INFO; production: ERROR
# WORKBENCH_FRONTEND_LOG_LEVEL=INFO
# WORKBENCH_FRONTEND_DEFAULT_LANDING_PAGE=

# Optional public JSON input. Native default: src/assets/config.json; container: /etc/workbench/config.json.
# WORKBENCH_FRONTEND_CONFIG_FILE=/path/to/config.json

# Development proxy upstream origin, without an /api suffix.
# WORKBENCH_FRONTEND_API_PROXY_TARGET=http://127.0.0.1:3000

# Build metadata: package version, Git HEAD, and current UTC time by default.
# Production runtime settings do not change this bundled build identity.
# WORKBENCH_FRONTEND_APP_VERSION=3.2.0
# WORKBENCH_FRONTEND_GIT_COMMIT=abc123
# WORKBENCH_FRONTEND_BUILD_DATE=2026-10-10T12:00:00Z
# Also export generated build metadata (path relative to the command's cwd).
# WORKBENCH_FRONTEND_BUILD_INFO_OUTPUT_PATH=dist/build-info.json

# Optional real-server test endpoint (Node tests have no Angular proxy).
# WORKBENCH_FRONTEND_TEST_API_URL=http://localhost:3000/api
54 changes: 46 additions & 8 deletions docker/example-setup/configs/rest-api/template.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Template-Version: 1.0
# Template-Updated: 2026-10-11
# Template-Source: attack-workbench-rest-api/template.env
#
# Changelog
# ---------
# - 1.0 (2026-10-11): Introduce template metadata

# Attack Workbench REST API - Environment Configuration Template
# Guidance:
# - Booleans: use true or false
Expand Down Expand Up @@ -62,22 +70,56 @@ DATABASE_URL=
# Default: empty (disabled)
#JSON_CONFIG_PATH=

# ALLOWED_VALUES_PATH (string) - Path to allowed values configuration file
# ALLOWED_VALUES_PATH (string) - Seed file read only when Allowed Values configuration is first initialized
# Default: ./app/config/allowed-values.json
#ALLOWED_VALUES_PATH=./app/config/allowed-values.json

# WB_REST_STATIC_MARKING_DEFS_PATH (string) - Directory of static marking definition JSON files
# Default: ./app/lib/default-static-marking-definitions/
#WB_REST_STATIC_MARKING_DEFS_PATH=./app/lib/default-static-marking-definitions/

# WB_REST_STATIC_BYPASS_RULES_PATH (string) - Default validation bypass rules loaded at startup
# Default: ./app/lib/default-bypass-rules.json
#WB_REST_STATIC_BYPASS_RULES_PATH=./app/lib/default-bypass-rules.json

# Scheduler
# ENABLE_SCHEDULER (bool) - Enable background scheduler
# Default: true
#ENABLE_SCHEDULER=true

# CHECK_WORKBENCH_INTERVAL (int, seconds) - Scheduler start interval
# Default: 10
#CHECK_WORKBENCH_INTERVAL=10
# SYNC_COLLECTION_INDEXES_CRON (string) - Cron schedule for polling collection indexes (process timezone)
# Default: * * * * * (every minute); disabled when ENABLE_SCHEDULER=false
#SYNC_COLLECTION_INDEXES_CRON=* * * * *

# CHECK_WIP_ATTACK_IDS_CRON (string) - Cron setting for WIP ATT&CK-ID checks (currently unused by scheduler)
# Default: 0 * * * * (hourly); no current task consumes this setting
#CHECK_WIP_ATTACK_IDS_CRON=0 * * * *

# VIRTUAL_TRACK_SCHEDULES_CRON (string) - Reconcile virtual-track schedules
# Discovers new cron schedules, recovers due dates, and retries failed runs.
# Standard 5-field cron syntax, interpreted in UTC.
# Default: * * * * * (every minute)
#VIRTUAL_TRACK_SCHEDULES_CRON=* * * * *

# Validation
# VALIDATE_WITH_ADM_SCHEMAS (bool) - Validate POST/PUT bodies against the ATT&CK Data Model
# When true, requests that fail ADM validation are rejected before persistence.
# Default: false
#VALIDATE_WITH_ADM_SCHEMAS=false

# VALIDATE_OBJECTS_CRON (string) - Cron pattern for the scheduled re-validation task
# Re-validates every SDO/SRO against the current ADM and refreshes workspace.validation.
# Standard 5-field cron syntax (minute hour day-of-month month day-of-week).
# Skipped entirely when ENABLE_SCHEDULER=false.
# Default: 0 3 * * * (daily at 3:00 AM)
#VALIDATE_OBJECTS_CRON=0 3 * * *

# ADM_LOG_LEVEL (enum) - Verbosity of the @mitre-attack/attack-data-model library's logger
# Read by the ADM library directly; independent of LOG_LEVEL and not configurable via JSON.
# Options: debug, info, warn, error, silent (inclusive — info enables info+warn+error)
# Set to error or silent to suppress per-relationship deprecation warnings during scheduler runs.
# Default: warn
#ADM_LOG_LEVEL=warn

# Session
# SESSION_SECRET (string) - Secret to sign session cookies.
Expand Down Expand Up @@ -141,7 +183,3 @@ DATABASE_URL=
# Useful when MongoDB or IdP uses a private CA
# Default: empty
#NODE_EXTRA_CA_CERTS=

# Validation
# VALIDATE_WITH_ADM_SCHEMAS - Toggle request body validation with ATT&CK Data Model schemas
#VALIDATE_WITH_ADM_SCHEMAS=false
Loading
Loading