From 7c6a932394f77502d321af2a0ee5258edfd50245 Mon Sep 17 00:00:00 2001 From: Philippe Parage <69145356+pparage@users.noreply.github.com> Date: Fri, 21 Aug 2026 16:05:25 +0200 Subject: [PATCH 1/2] feat(exercise-world): package Nacre and seed MISP --- .../docker/admin/misp-standalone/.env.example | 2 +- .../docker/admin/misp-standalone/Dockerfile | 14 +- .../docker/admin/misp-standalone/README.md | 13 +- .../admin/misp-standalone/docker-compose.yml | 7 +- .../misp-standalone/provisioning/provision.sh | 1 + .../sample-events/event-01-spearphishing.json | 5 +- .../sample-events/event-02-ransomware-c2.json | 5 +- .../provisioning/verify-exercise-world.py | 112 + 05_world_layer/.gitignore | 2 + 05_world_layer/NOTICE | 13 + 05_world_layer/README.md | 47 + 05_world_layer/manifest.json | 24 + 05_world_layer/sewf/nacre/VERSION | 13 + .../sewf/nacre/clusters/exercise-world.json | 1825 ++++++++++++++++ .../sewf/nacre/derived/by-sector.json | 206 ++ .../sewf/nacre/derived/entities.index.json | 1826 +++++++++++++++++ .../sewf/nacre/galaxies/exercise-world.json | 9 + 05_world_layer/tests/test_nacre_world.py | 167 ++ 05_world_layer/tools/generate_indexes.py | 179 ++ README.md | 16 +- manifest.json | 7 +- 21 files changed, 4480 insertions(+), 13 deletions(-) create mode 100644 03_container_layer/docker/admin/misp-standalone/provisioning/verify-exercise-world.py create mode 100644 05_world_layer/.gitignore create mode 100644 05_world_layer/NOTICE create mode 100644 05_world_layer/README.md create mode 100644 05_world_layer/manifest.json create mode 100644 05_world_layer/sewf/nacre/VERSION create mode 100644 05_world_layer/sewf/nacre/clusters/exercise-world.json create mode 100644 05_world_layer/sewf/nacre/derived/by-sector.json create mode 100644 05_world_layer/sewf/nacre/derived/entities.index.json create mode 100644 05_world_layer/sewf/nacre/galaxies/exercise-world.json create mode 100644 05_world_layer/tests/test_nacre_world.py create mode 100644 05_world_layer/tools/generate_indexes.py diff --git a/03_container_layer/docker/admin/misp-standalone/.env.example b/03_container_layer/docker/admin/misp-standalone/.env.example index abb97c3..468fb05 100644 --- a/03_container_layer/docker/admin/misp-standalone/.env.example +++ b/03_container_layer/docker/admin/misp-standalone/.env.example @@ -1,5 +1,5 @@ # ── MISP build / version ────────────────────────────────────────────────────── -MISP_VERSION=v2.5.37 +MISP_VERSION=v2.5.44 # ── Network ─────────────────────────────────────────────────────────────────── MISP_HTTP_PORT=80 diff --git a/03_container_layer/docker/admin/misp-standalone/Dockerfile b/03_container_layer/docker/admin/misp-standalone/Dockerfile index f3a3dd6..5f4ab09 100644 --- a/03_container_layer/docker/admin/misp-standalone/Dockerfile +++ b/03_container_layer/docker/admin/misp-standalone/Dockerfile @@ -6,7 +6,9 @@ # ────────────────────────────────────────────────────────────────────────────── FROM ubuntu:24.04 AS builder -ARG MISP_VERSION=v2.5.39 +ARG MISP_VERSION=v2.5.44 +ARG SEWF_CLUSTER_SHA256=55afe65a817c167a46dbd26850515aefb2bf72b9318f651d6adb172e498a44b4 +ARG SEWF_GALAXY_SHA256=f1fe9a26eae4148542e0d89126cdf4231c803b2c3fd255137b42e2c5f969807a ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -27,6 +29,16 @@ RUN git clone --depth 1 --branch "${MISP_VERSION}" --progress \ # --progress keeps git reporting per-submodule transfer stats during the wait. RUN git -C misp submodule update --init --recursive --depth 1 --jobs 8 --progress +# Keep the MISP-bundled Synthetic Exercise World byte-identical to the +# independently vendored Range42 snapshot in 05_world_layer. UUID/count smoke +# checks cannot detect metadata or entity substitutions that preserve counts. +RUN printf '%s %s\n' "${SEWF_CLUSTER_SHA256}" \ + /build/misp/app/files/misp-galaxy/clusters/exercise-world.json \ + | sha256sum -c - \ + && printf '%s %s\n' "${SEWF_GALAXY_SHA256}" \ + /build/misp/app/files/misp-galaxy/galaxies/exercise-world.json \ + | sha256sum -c - + # PHP vendor dependencies — skip platform checks that require runtime extensions WORKDIR /build/misp/app RUN composer install \ diff --git a/03_container_layer/docker/admin/misp-standalone/README.md b/03_container_layer/docker/admin/misp-standalone/README.md index 279e917..13144dc 100644 --- a/03_container_layer/docker/admin/misp-standalone/README.md +++ b/03_container_layer/docker/admin/misp-standalone/README.md @@ -69,7 +69,7 @@ Passwords are set via the corresponding `_PASSWORD` variables in `.env`. | Variable | Description | Default | |----------|-------------|---------| -| `MISP_VERSION` | MISP git tag to build from | `v2.5.37` | +| `MISP_VERSION` | MISP git tag to build from | `v2.5.44` | | `MISP_PORT` | Host port for the MISP web UI | `8080` | | `MISP_BASEURL` | URL advertised in events/feeds/e-mails | `http://localhost:8080` | | `MISP_ORG` | Default organisation name | `Default Organisation` | @@ -81,6 +81,11 @@ Passwords are set via the corresponding `_PASSWORD` variables in `.env`. | `MISP_DB_*` / `DB_*` | MariaDB connection settings | see `.env.example` | | `REDIS_HOST` / `REDIS_PORT` | Redis connection | `redis` / `6379` | +The Docker build verifies the SHA-256 values of the bundled `exercise-world` +galaxy and cluster against the pinned snapshots under +`05_world_layer/sewf/nacre/`. A MISP version bump that changes either file +fails the build until the world package is deliberately reviewed and updated. + --- ## Build and push @@ -89,13 +94,13 @@ Passwords are set via the corresponding `_PASSWORD` variables in `.env`. # Build and tag for a registry docker build \ --target runtime \ - --build-arg MISP_VERSION=v2.5.37 \ - -t registry.example.com/range42/misp-standalone:v2.5.37 \ + --build-arg MISP_VERSION=v2.5.44 \ + -t registry.example.com/range42/misp-standalone:v2.5.44 \ -t registry.example.com/range42/misp-standalone:latest \ . # Push -docker push registry.example.com/range42/misp-standalone:v2.5.37 +docker push registry.example.com/range42/misp-standalone:v2.5.44 docker push registry.example.com/range42/misp-standalone:latest ``` diff --git a/03_container_layer/docker/admin/misp-standalone/docker-compose.yml b/03_container_layer/docker/admin/misp-standalone/docker-compose.yml index 24f1047..14097c1 100644 --- a/03_container_layer/docker/admin/misp-standalone/docker-compose.yml +++ b/03_container_layer/docker/admin/misp-standalone/docker-compose.yml @@ -59,8 +59,8 @@ services: context: . target: runtime args: - MISP_VERSION: ${MISP_VERSION:-v2.5.37} - image: misp-standalone:${MISP_VERSION:-v2.5.37} + MISP_VERSION: ${MISP_VERSION:-v2.5.44} + image: misp-standalone:${MISP_VERSION:-v2.5.44} restart: unless-stopped env_file: - path: .env @@ -94,7 +94,7 @@ services: context: . target: runtime args: - MISP_VERSION: ${MISP_VERSION:-v2.5.37} + MISP_VERSION: ${MISP_VERSION:-v2.5.44} entrypoint: ["/provisioning/provision.sh"] env_file: - path: .env @@ -106,6 +106,7 @@ services: - ./provisioning/provision-users.sh:/provisioning/provision-users.sh:ro - ./provisioning/provision-warninglists.sh:/provisioning/provision-warninglists.sh:ro - ./provisioning/provision-content.sh:/provisioning/provision-content.sh:ro + - ./provisioning/verify-exercise-world.py:/provisioning/verify-exercise-world.py:ro - ./provisioning/provision-sample-events.sh:/provisioning/provision-sample-events.sh:ro - ./provisioning/sample-events:/provisioning/sample-events:ro depends_on: diff --git a/03_container_layer/docker/admin/misp-standalone/provisioning/provision.sh b/03_container_layer/docker/admin/misp-standalone/provisioning/provision.sh index 0a8a194..1a6d7ed 100755 --- a/03_container_layer/docker/admin/misp-standalone/provisioning/provision.sh +++ b/03_container_layer/docker/admin/misp-standalone/provisioning/provision.sh @@ -7,4 +7,5 @@ set -euo pipefail /provisioning/provision-users.sh /provisioning/provision-warninglists.sh /provisioning/provision-content.sh +python3 /provisioning/verify-exercise-world.py /provisioning/provision-sample-events.sh diff --git a/03_container_layer/docker/admin/misp-standalone/provisioning/sample-events/event-01-spearphishing.json b/03_container_layer/docker/admin/misp-standalone/provisioning/sample-events/event-01-spearphishing.json index 5dbe659..cc0e6ab 100644 --- a/03_container_layer/docker/admin/misp-standalone/provisioning/sample-events/event-01-spearphishing.json +++ b/03_container_layer/docker/admin/misp-standalone/provisioning/sample-events/event-01-spearphishing.json @@ -9,7 +9,10 @@ "Tag": [ {"name": "tlp:amber"}, {"name": "kill-chain:Delivery"}, - {"name": "kill-chain:Exploitation"} + {"name": "kill-chain:Exploitation"}, + {"name": "misp-galaxy:exercise-world=\"Asterin Union\""}, + {"name": "misp-galaxy:exercise-world=\"NovaCore Systems\""}, + {"name": "misp-galaxy:exercise-world=\"TA-700 Obsidian Jackal\""} ], "Attribute": [ { diff --git a/03_container_layer/docker/admin/misp-standalone/provisioning/sample-events/event-02-ransomware-c2.json b/03_container_layer/docker/admin/misp-standalone/provisioning/sample-events/event-02-ransomware-c2.json index d185668..d7b0a16 100644 --- a/03_container_layer/docker/admin/misp-standalone/provisioning/sample-events/event-02-ransomware-c2.json +++ b/03_container_layer/docker/admin/misp-standalone/provisioning/sample-events/event-02-ransomware-c2.json @@ -10,7 +10,10 @@ {"name": "tlp:amber"}, {"name": "kill-chain:Installation"}, {"name": "kill-chain:Command and Control"}, - {"name": "kill-chain:Actions on Objectives"} + {"name": "kill-chain:Actions on Objectives"}, + {"name": "misp-galaxy:exercise-world=\"Velkar Republic\""}, + {"name": "misp-galaxy:exercise-world=\"HelixCore Group\""}, + {"name": "misp-galaxy:exercise-world=\"TA-701 Silver Mantis\""} ], "Attribute": [ { diff --git a/03_container_layer/docker/admin/misp-standalone/provisioning/verify-exercise-world.py b/03_container_layer/docker/admin/misp-standalone/provisioning/verify-exercise-world.py new file mode 100644 index 0000000..0f5052c --- /dev/null +++ b/03_container_layer/docker/admin/misp-standalone/provisioning/verify-exercise-world.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +"""Fail provisioning unless the pinned Synthetic Exercise World is loaded.""" + +from __future__ import annotations + +import json +import os +import ssl +import sys +from pathlib import Path +from typing import Any +from urllib.request import Request, urlopen + + +EXPECTED_GALAXY_UUID = "3c3de5f0-5982-4c7f-88cf-8abf43b8d6c1" +EXPECTED_COLLECTION_UUID = "7d6d7f2f-b3d4-4bc5-9f27-43e12f7f4658" +EXPECTED_ENTITY_COUNT = 60 + + +class ExerciseWorldVerificationError(ValueError): + pass + + +def _list_items(payload: Any) -> list[Any]: + if isinstance(payload, list): + return payload + if not isinstance(payload, dict): + return [] + for key in ("response", "Galaxies", "galaxies"): + if isinstance(payload.get(key), list): + return payload[key] + if isinstance(payload.get("Galaxy"), list): + return payload["Galaxy"] + return [payload] + + +def find_exercise_world_galaxy(payload: Any) -> str: + for item in _list_items(payload): + galaxy = item.get("Galaxy", item) if isinstance(item, dict) else {} + if galaxy.get("type") != "exercise-world": + continue + if galaxy.get("uuid") != EXPECTED_GALAXY_UUID: + raise ExerciseWorldVerificationError( + f"exercise-world galaxy UUID mismatch: {galaxy.get('uuid')}" + ) + galaxy_id = galaxy.get("id") + if galaxy_id is None: + raise ExerciseWorldVerificationError("exercise-world galaxy is missing its database id") + return str(galaxy_id) + raise ExerciseWorldVerificationError("exercise-world galaxy is not loaded") + + +def verify_cluster_payload(payload: Any) -> None: + root = payload.get("Galaxy", payload) if isinstance(payload, dict) else {} + clusters = payload.get("GalaxyCluster") if isinstance(payload, dict) else None + if not isinstance(clusters, list) and isinstance(root, dict): + clusters = root.get("GalaxyCluster") + if not isinstance(clusters, list): + raise ExerciseWorldVerificationError("exercise-world response has no GalaxyCluster list") + + normalized = [ + item.get("GalaxyCluster", item) if isinstance(item, dict) else {} + for item in clusters + ] + if len(normalized) != EXPECTED_ENTITY_COUNT: + raise ExerciseWorldVerificationError( + f"exercise-world entity count mismatch: expected {EXPECTED_ENTITY_COUNT}, got {len(normalized)}" + ) + + entity_uuids = {item.get("uuid") for item in normalized} + if None in entity_uuids or len(entity_uuids) != EXPECTED_ENTITY_COUNT: + raise ExerciseWorldVerificationError("exercise-world entity UUIDs are missing or duplicated") + collection_uuids = {item.get("collection_uuid") for item in normalized} + if collection_uuids != {EXPECTED_COLLECTION_UUID}: + raise ExerciseWorldVerificationError( + f"exercise-world collection UUID mismatch: {sorted(str(value) for value in collection_uuids)}" + ) + + +def misp_get(base_url: str, auth_key: str, path: str) -> Any: + request = Request( + f"{base_url.rstrip('/')}{path}", + headers={"Authorization": auth_key, "Accept": "application/json"}, + ) + context = ssl._create_unverified_context() + with urlopen(request, context=context, timeout=30) as response: + return json.load(response) + + +def main() -> int: + base_url = os.environ.get("MISP_URL", "https://misp") + key_file = Path(os.environ.get("MISP_ADMIN_KEY_FILE", "/keys/admin-authkey")) + try: + auth_key = key_file.read_text(encoding="utf-8").strip() + if not auth_key: + raise ExerciseWorldVerificationError(f"empty admin auth key: {key_file}") + galaxy_id = find_exercise_world_galaxy(misp_get(base_url, auth_key, "/galaxies/index.json")) + verify_cluster_payload(misp_get(base_url, auth_key, f"/galaxies/view/{galaxy_id}.json")) + except (OSError, json.JSONDecodeError, ExerciseWorldVerificationError) as exc: + print(f"[verify-exercise-world] ERROR: {exc}", file=sys.stderr) + return 1 + + print( + f"[verify-exercise-world] verified galaxy {EXPECTED_GALAXY_UUID} " + f"with {EXPECTED_ENTITY_COUNT} entities", + file=sys.stderr, + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/05_world_layer/.gitignore b/05_world_layer/.gitignore new file mode 100644 index 0000000..43ae0e2 --- /dev/null +++ b/05_world_layer/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.py[cod] diff --git a/05_world_layer/NOTICE b/05_world_layer/NOTICE new file mode 100644 index 0000000..0505f14 --- /dev/null +++ b/05_world_layer/NOTICE @@ -0,0 +1,13 @@ +Synthetic Exercise World — Nacre +Copyright: MISP Project +Project: https://github.com/MISP/Synthetic-Exercise-World-Format +Canonical data: https://github.com/MISP/misp-galaxy +License: Creative Commons Attribution 4.0 International (CC-BY-4.0) +License URL: https://creativecommons.org/licenses/by/4.0/ + +Range42 redistributes byte-identical galaxy and cluster JSON snapshots with provenance in +`sewf/nacre/VERSION`. Generated indexes are identified separately under `derived/`. + +Suggested attribution from upstream: + + Synthetic Exercise World — licensed under CC BY 4.0. diff --git a/05_world_layer/README.md b/05_world_layer/README.md new file mode 100644 index 0000000..8c6195e --- /dev/null +++ b/05_world_layer/README.md @@ -0,0 +1,47 @@ +# Layer 05 — Synthetic Exercise Worlds + +This layer contains versioned, politically neutral narrative reference data for Range42 +exercises. It is content, not infrastructure: nothing in this directory provisions a VM, +network, container, or service. + +## Available worlds + +| World | Format | Entities | License | Source | +|---|---|---:|---|---| +| Nacre | MISP Galaxy `exercise-world` v1 | 60 | CC-BY-4.0 | MISP Synthetic Exercise World Format | + +Nacre contains 10 countries, 30 companies, and 20 threat actors. It does not contain +personas, infrastructure, injects, IOCs, or scoring rules. + +## Layout + +```text +05_world_layer/ + manifest.json + NOTICE + sewf/nacre/ + VERSION + clusters/exercise-world.json + galaxies/exercise-world.json + derived/ +``` + +The files under `clusters/` and `galaxies/` are byte-identical upstream snapshots. Never edit +them in place. Range42-generated lookup indexes live under `derived/`. + +## References + +Non-MISP consumers must store stable entity UUIDs, not display names. MISP event fixtures use +the canonical galaxy tag form `misp-galaxy:exercise-world=""`. + +## Updating Nacre + +1. Review upstream changes in both `MISP/Synthetic-Exercise-World-Format` and + `MISP/misp-galaxy`. +2. Replace the galaxy/cluster snapshots without modifying them. +3. Update `sewf/nacre/VERSION` with commits, retrieval date, and SHA-256 values. +4. Regenerate `derived/` with `python3 05_world_layer/tools/generate_indexes.py`. +5. Run `python3 -m unittest 05_world_layer/tests/test_nacre_world.py -v`. +6. Review the data and generated diff, including neutrality and name-collision checks. + +See `NOTICE` for attribution and license details. diff --git a/05_world_layer/manifest.json b/05_world_layer/manifest.json new file mode 100644 index 0000000..9e56d54 --- /dev/null +++ b/05_world_layer/manifest.json @@ -0,0 +1,24 @@ +{ + "schema_version": "1.0", + "worlds": [ + { + "id": "nacre", + "name": "Synthetic Exercise World — Nacre", + "planet": "Nacre", + "format": "misp-galaxy", + "license": "CC-BY-4.0", + "entity_count": 60, + "galaxy": { + "path": "sewf/nacre/galaxies/exercise-world.json", + "type": "exercise-world", + "uuid": "3c3de5f0-5982-4c7f-88cf-8abf43b8d6c1", + "version": 1 + }, + "cluster": { + "path": "sewf/nacre/clusters/exercise-world.json", + "uuid": "7d6d7f2f-b3d4-4bc5-9f27-43e12f7f4658", + "version": 1 + } + } + ] +} diff --git a/05_world_layer/sewf/nacre/VERSION b/05_world_layer/sewf/nacre/VERSION new file mode 100644 index 0000000..c10acf3 --- /dev/null +++ b/05_world_layer/sewf/nacre/VERSION @@ -0,0 +1,13 @@ +world=Nacre +format=misp-galaxy +version=1 +retrieved_at=2026-08-21 +documentation_repository=https://github.com/MISP/Synthetic-Exercise-World-Format +documentation_commit=2e32d4a5a9b241fb0f90e704e277c0cabf97729b +data_repository=https://github.com/MISP/misp-galaxy +cluster_commit=cc7792ad2406700bcdd0462927c9fd0f5ddee84a +cluster_sha256=55afe65a817c167a46dbd26850515aefb2bf72b9318f651d6adb172e498a44b4 +galaxy_commit=0694f7600eb5e302f690cf909acb3c5f4086010d +galaxy_sha256=f1fe9a26eae4148542e0d89126cdf4231c803b2c3fd255137b42e2c5f969807a +misp_version=v2.5.44 +misp_galaxy_commit=041c6d0f3da384626c07b9220c1f6cef640ddf1a diff --git a/05_world_layer/sewf/nacre/clusters/exercise-world.json b/05_world_layer/sewf/nacre/clusters/exercise-world.json new file mode 100644 index 0000000..696c82c --- /dev/null +++ b/05_world_layer/sewf/nacre/clusters/exercise-world.json @@ -0,0 +1,1825 @@ +{ + "authors": [ + "MISP Project", + "GPT-5.3-Codex" + ], + "category": "tool", + "description": "Self-contained fictional world dataset for cyber exercises and standards documents.", + "name": "Synthetic Exercise World", + "source": "https://www.misp-project.org/galaxy.html", + "type": "exercise-world", + "uuid": "7d6d7f2f-b3d4-4bc5-9f27-43e12f7f4658", + "values": [ + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Asterin Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Northern supercontinent" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "cb97ba71-e477-4acb-9470-10f3e6c9e1a9", + "value": "Asterin Union" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Velkar Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Inland industrial basin" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "e4cd09cc-7be7-46ef-8989-5b9a812b49fe", + "value": "Velkar Republic" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Orinthia Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Archipelago of research hubs" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "74d2286a-1b87-4984-8dd1-c5bd466ecca5", + "value": "Orinthia" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Caelum Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "High-altitude plateau state" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "4a600b9f-b843-446f-a234-415aded47e1b", + "value": "Caelum Protectorate" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Neruva Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Delta megacities and ports" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "cfe1b22e-38b5-4077-bb90-b2bc5fedb965", + "value": "Neruva Federation" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Thyros Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Resource-rich steppe" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "970fd807-b09e-4379-9a44-bebc5d0b9869", + "value": "Thyros Commonwealth" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Ilyndor Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Neutral trade corridor" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "1e875520-fb3e-4d26-a982-44a5fb7f9375", + "value": "Ilyndor" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Brinax Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Energy-grid cooperative state" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "91f273f8-66c0-446f-bdb2-4233fd0c55ef", + "value": "Brinax Collective" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Soreth Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Polar logistics nation" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "c4be7f53-6d08-4472-8480-49ccb7946e78", + "value": "Soreth Dominion" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Quenari Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Equatorial agri-tech alliance" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "54670ad5-49fe-4d0c-8a81-84b06a8b5050", + "value": "Quenari League" + }, + { + "description": "Fictional energy enterprise operating in Asterin Union for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Asterin Union" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Energy" + ] + }, + "uuid": "e3d6ab68-ad7b-4deb-9c0d-c0250013d1bb", + "value": "NovaCore Systems" + }, + { + "description": "Fictional finance enterprise operating in Velkar Republic for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Velkar Republic" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Finance" + ] + }, + "uuid": "df601e63-1a5f-4cec-a071-152f1c62f310", + "value": "HelixCore Group" + }, + { + "description": "Fictional healthcare enterprise operating in Orinthia for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Orinthia" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Healthcare" + ] + }, + "uuid": "7477aeca-f4ba-4d9c-a261-7e5609033ad6", + "value": "IronCore Dynamics" + }, + { + "description": "Fictional telecommunications enterprise operating in Caelum Protectorate for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Caelum Protectorate" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Telecommunications" + ] + }, + "uuid": "2531f94d-d514-4530-b4eb-35fce204aa36", + "value": "BlueBridge Networks" + }, + { + "description": "Fictional aerospace enterprise operating in Neruva Federation for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Neruva Federation" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Aerospace" + ] + }, + "uuid": "d688f826-d566-41c9-99af-16574aa05921", + "value": "SkyBridge Labs" + }, + { + "description": "Fictional logistics enterprise operating in Thyros Commonwealth for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Thyros Commonwealth" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Logistics" + ] + }, + "uuid": "8d018f2a-03c2-4467-8b4e-14ee2ea33df8", + "value": "VertexBridge Systems" + }, + { + "description": "Fictional manufacturing enterprise operating in Ilyndor for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Ilyndor" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Manufacturing" + ] + }, + "uuid": "5196ad35-99b3-41fd-bb4a-286bf08adc4c", + "value": "CinderHarbor Group" + }, + { + "description": "Fictional maritime enterprise operating in Brinax Collective for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Brinax Collective" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Maritime" + ] + }, + "uuid": "d3631b81-e8b1-473c-bd9e-d2daf003a467", + "value": "AuroraHarbor Dynamics" + }, + { + "description": "Fictional food enterprise operating in Soreth Dominion for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Soreth Dominion" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Food" + ] + }, + "uuid": "f68c4a8e-beff-4666-8c85-78deb549088e", + "value": "DeltaHarbor Networks" + }, + { + "description": "Fictional media enterprise operating in Quenari League for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Quenari League" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Media" + ] + }, + "uuid": "f0ca111f-53b1-491f-9c3e-f8ef6a83e974", + "value": "QuantumMatrix Labs" + }, + { + "description": "Fictional energy enterprise operating in Asterin Union for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Asterin Union" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Energy" + ] + }, + "uuid": "ba6c4261-b74f-4e36-ba47-9af4ad63bfd4", + "value": "NovaMatrix Systems" + }, + { + "description": "Fictional finance enterprise operating in Velkar Republic for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Velkar Republic" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Finance" + ] + }, + "uuid": "8cccd3e0-3ade-48c8-83b9-b09523ddec00", + "value": "HelixMatrix Group" + }, + { + "description": "Fictional healthcare enterprise operating in Orinthia for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Orinthia" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Healthcare" + ] + }, + "uuid": "2da913d9-d380-4461-9acd-44f67178589a", + "value": "IronPulse Dynamics" + }, + { + "description": "Fictional telecommunications enterprise operating in Caelum Protectorate for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Caelum Protectorate" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Telecommunications" + ] + }, + "uuid": "0bbd45b1-a029-4497-8d93-9df82ca4b8c3", + "value": "BluePulse Networks" + }, + { + "description": "Fictional aerospace enterprise operating in Neruva Federation for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Neruva Federation" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Aerospace" + ] + }, + "uuid": "de2e6bc9-64df-4b7b-8c10-698aed474d2c", + "value": "SkyPulse Labs" + }, + { + "description": "Fictional logistics enterprise operating in Thyros Commonwealth for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Thyros Commonwealth" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Logistics" + ] + }, + "uuid": "bbac3990-2ae8-4872-a24a-2d9bf3a44086", + "value": "VertexFoundry Systems" + }, + { + "description": "Fictional manufacturing enterprise operating in Ilyndor for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Ilyndor" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Manufacturing" + ] + }, + "uuid": "6c295716-28f9-485e-af6f-0619677d9e37", + "value": "CinderFoundry Group" + }, + { + "description": "Fictional maritime enterprise operating in Brinax Collective for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Brinax Collective" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Maritime" + ] + }, + "uuid": "10ed09dc-bd53-466a-bfc5-c47c65c75141", + "value": "AuroraFoundry Dynamics" + }, + { + "description": "Fictional food enterprise operating in Soreth Dominion for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Soreth Dominion" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Food" + ] + }, + "uuid": "47a8428c-1427-4eb2-b7a6-6f4f40b69ed1", + "value": "DeltaNimbus Networks" + }, + { + "description": "Fictional media enterprise operating in Quenari League for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Quenari League" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Media" + ] + }, + "uuid": "412eadf8-d9ff-414f-8001-9635322d4bd9", + "value": "QuantumNimbus Labs" + }, + { + "description": "Fictional energy enterprise operating in Asterin Union for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Asterin Union" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Energy" + ] + }, + "uuid": "93130c22-9361-405b-a91e-de5bd1c2e718", + "value": "NovaNimbus Systems" + }, + { + "description": "Fictional finance enterprise operating in Velkar Republic for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Velkar Republic" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Finance" + ] + }, + "uuid": "28daddab-1f7e-4116-a8ce-285dd3bb2a8d", + "value": "HelixForge Group" + }, + { + "description": "Fictional healthcare enterprise operating in Orinthia for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Orinthia" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Healthcare" + ] + }, + "uuid": "40e99f1c-44aa-4ae1-9b57-f3ee963d6a91", + "value": "IronForge Dynamics" + }, + { + "description": "Fictional telecommunications enterprise operating in Caelum Protectorate for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Caelum Protectorate" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Telecommunications" + ] + }, + "uuid": "fdc855e6-4827-4f80-84f6-eafd7687aed5", + "value": "BlueForge Networks" + }, + { + "description": "Fictional aerospace enterprise operating in Neruva Federation for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Neruva Federation" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Aerospace" + ] + }, + "uuid": "a72d657f-b242-4b6b-ab31-1aa15bff4c4f", + "value": "SkyLattice Labs" + }, + { + "description": "Fictional logistics enterprise operating in Thyros Commonwealth for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Thyros Commonwealth" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Logistics" + ] + }, + "uuid": "5b8a3c47-d6d4-470d-bca3-de2ef41391c9", + "value": "VertexLattice Systems" + }, + { + "description": "Fictional manufacturing enterprise operating in Ilyndor for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Ilyndor" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Manufacturing" + ] + }, + "uuid": "d7748db1-8949-456f-a3b3-1072c6baacc3", + "value": "CinderLattice Group" + }, + { + "description": "Fictional maritime enterprise operating in Brinax Collective for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Brinax Collective" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Maritime" + ] + }, + "uuid": "5621dc5a-ba38-45b7-93c6-40c19c9b0b4c", + "value": "AuroraBeacon Dynamics" + }, + { + "description": "Fictional food enterprise operating in Soreth Dominion for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Soreth Dominion" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Food" + ] + }, + "uuid": "a8685ecb-33cc-4f6a-850d-7b3e7ff21be6", + "value": "DeltaBeacon Networks" + }, + { + "description": "Fictional media enterprise operating in Quenari League for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Quenari League" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Media" + ] + }, + "uuid": "f869e852-7648-4066-a0dc-ed743e11aa05", + "value": "QuantumBeacon Labs" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Asterin Union" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Espionage" + ], + "sophistication": [ + "minimal" + ] + }, + "related": [ + { + "dest-uuid": "e3d6ab68-ad7b-4deb-9c0d-c0250013d1bb", + "type": "targets" + }, + { + "dest-uuid": "ba6c4261-b74f-4e36-ba47-9af4ad63bfd4", + "type": "targets" + }, + { + "dest-uuid": "93130c22-9361-405b-a91e-de5bd1c2e718", + "type": "targets" + }, + { + "dest-uuid": "cb97ba71-e477-4acb-9470-10f3e6c9e1a9", + "type": "operates-from" + } + ], + "uuid": "6c922d71-43e3-40c4-a1ea-85929f0c2f1a", + "value": "TA-700 Obsidian Jackal" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Velkar Republic" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Financial disruption" + ], + "sophistication": [ + "intermediate" + ] + }, + "related": [ + { + "dest-uuid": "df601e63-1a5f-4cec-a071-152f1c62f310", + "type": "targets" + }, + { + "dest-uuid": "8cccd3e0-3ade-48c8-83b9-b09523ddec00", + "type": "targets" + }, + { + "dest-uuid": "28daddab-1f7e-4116-a8ce-285dd3bb2a8d", + "type": "targets" + }, + { + "dest-uuid": "e4cd09cc-7be7-46ef-8989-5b9a812b49fe", + "type": "operates-from" + } + ], + "uuid": "e8b1ce9a-128c-4546-907d-02178fc72e49", + "value": "TA-701 Silver Mantis" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Orinthia" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Strategic signaling" + ], + "sophistication": [ + "advanced" + ] + }, + "related": [ + { + "dest-uuid": "7477aeca-f4ba-4d9c-a261-7e5609033ad6", + "type": "targets" + }, + { + "dest-uuid": "2da913d9-d380-4461-9acd-44f67178589a", + "type": "targets" + }, + { + "dest-uuid": "40e99f1c-44aa-4ae1-9b57-f3ee963d6a91", + "type": "targets" + }, + { + "dest-uuid": "74d2286a-1b87-4984-8dd1-c5bd466ecca5", + "type": "operates-from" + } + ], + "uuid": "8ea5ed6e-8753-4150-946f-157b3bf49bc0", + "value": "TA-702 Crimson Rook" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Caelum Protectorate" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Technology theft" + ], + "sophistication": [ + "expert" + ] + }, + "related": [ + { + "dest-uuid": "2531f94d-d514-4530-b4eb-35fce204aa36", + "type": "targets" + }, + { + "dest-uuid": "0bbd45b1-a029-4497-8d93-9df82ca4b8c3", + "type": "targets" + }, + { + "dest-uuid": "fdc855e6-4827-4f80-84f6-eafd7687aed5", + "type": "targets" + }, + { + "dest-uuid": "4a600b9f-b843-446f-a234-415aded47e1b", + "type": "operates-from" + } + ], + "uuid": "56eb0bfc-4fe4-4fbc-bd0d-9e26a87e1217", + "value": "TA-703 Violet Hydra" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Neruva Federation" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Influence operations" + ], + "sophistication": [ + "minimal" + ] + }, + "related": [ + { + "dest-uuid": "d688f826-d566-41c9-99af-16574aa05921", + "type": "targets" + }, + { + "dest-uuid": "de2e6bc9-64df-4b7b-8c10-698aed474d2c", + "type": "targets" + }, + { + "dest-uuid": "a72d657f-b242-4b6b-ab31-1aa15bff4c4f", + "type": "targets" + }, + { + "dest-uuid": "cfe1b22e-38b5-4077-bb90-b2bc5fedb965", + "type": "operates-from" + } + ], + "uuid": "716458aa-8ba1-4a82-9783-926381bfeb43", + "value": "TA-704 Amber Drift" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Thyros Commonwealth" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Espionage" + ], + "sophistication": [ + "intermediate" + ] + }, + "related": [ + { + "dest-uuid": "8d018f2a-03c2-4467-8b4e-14ee2ea33df8", + "type": "targets" + }, + { + "dest-uuid": "bbac3990-2ae8-4872-a24a-2d9bf3a44086", + "type": "targets" + }, + { + "dest-uuid": "5b8a3c47-d6d4-470d-bca3-de2ef41391c9", + "type": "targets" + }, + { + "dest-uuid": "970fd807-b09e-4379-9a44-bebc5d0b9869", + "type": "operates-from" + } + ], + "uuid": "cfecc787-5ee0-4786-a285-dc3c7919e7a0", + "value": "TA-705 Cobalt Jackal" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Ilyndor" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Financial disruption" + ], + "sophistication": [ + "advanced" + ] + }, + "related": [ + { + "dest-uuid": "5196ad35-99b3-41fd-bb4a-286bf08adc4c", + "type": "targets" + }, + { + "dest-uuid": "6c295716-28f9-485e-af6f-0619677d9e37", + "type": "targets" + }, + { + "dest-uuid": "d7748db1-8949-456f-a3b3-1072c6baacc3", + "type": "targets" + }, + { + "dest-uuid": "1e875520-fb3e-4d26-a982-44a5fb7f9375", + "type": "operates-from" + } + ], + "uuid": "10170ce4-b93c-48e0-84a5-a32f7e6818be", + "value": "TA-706 Onyx Mantis" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Brinax Collective" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Strategic signaling" + ], + "sophistication": [ + "expert" + ] + }, + "related": [ + { + "dest-uuid": "d3631b81-e8b1-473c-bd9e-d2daf003a467", + "type": "targets" + }, + { + "dest-uuid": "10ed09dc-bd53-466a-bfc5-c47c65c75141", + "type": "targets" + }, + { + "dest-uuid": "5621dc5a-ba38-45b7-93c6-40c19c9b0b4c", + "type": "targets" + }, + { + "dest-uuid": "91f273f8-66c0-446f-bdb2-4233fd0c55ef", + "type": "operates-from" + } + ], + "uuid": "7a6197e0-ee8f-4e21-ba48-ce0a42f67856", + "value": "TA-707 Ivory Rook" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Soreth Dominion" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Technology theft" + ], + "sophistication": [ + "minimal" + ] + }, + "related": [ + { + "dest-uuid": "f68c4a8e-beff-4666-8c85-78deb549088e", + "type": "targets" + }, + { + "dest-uuid": "47a8428c-1427-4eb2-b7a6-6f4f40b69ed1", + "type": "targets" + }, + { + "dest-uuid": "a8685ecb-33cc-4f6a-850d-7b3e7ff21be6", + "type": "targets" + }, + { + "dest-uuid": "c4be7f53-6d08-4472-8480-49ccb7946e78", + "type": "operates-from" + } + ], + "uuid": "fd0dcf97-33f4-47d7-84c7-9a1559929f3e", + "value": "TA-708 Sable Hydra" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Quenari League" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Influence operations" + ], + "sophistication": [ + "intermediate" + ] + }, + "related": [ + { + "dest-uuid": "f0ca111f-53b1-491f-9c3e-f8ef6a83e974", + "type": "targets" + }, + { + "dest-uuid": "412eadf8-d9ff-414f-8001-9635322d4bd9", + "type": "targets" + }, + { + "dest-uuid": "f869e852-7648-4066-a0dc-ed743e11aa05", + "type": "targets" + }, + { + "dest-uuid": "54670ad5-49fe-4d0c-8a81-84b06a8b5050", + "type": "operates-from" + } + ], + "uuid": "f3d700cb-3106-46d6-8d3d-a7b6da24d107", + "value": "TA-709 Copper Drift" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Asterin Union" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Espionage" + ], + "sophistication": [ + "advanced" + ] + }, + "related": [ + { + "dest-uuid": "e3d6ab68-ad7b-4deb-9c0d-c0250013d1bb", + "type": "targets" + }, + { + "dest-uuid": "ba6c4261-b74f-4e36-ba47-9af4ad63bfd4", + "type": "targets" + }, + { + "dest-uuid": "93130c22-9361-405b-a91e-de5bd1c2e718", + "type": "targets" + }, + { + "dest-uuid": "cb97ba71-e477-4acb-9470-10f3e6c9e1a9", + "type": "operates-from" + } + ], + "uuid": "e69c8045-5c58-4c57-adca-050f8bfe6d9b", + "value": "TA-710 Obsidian Jackal" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Velkar Republic" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Financial disruption" + ], + "sophistication": [ + "expert" + ] + }, + "related": [ + { + "dest-uuid": "df601e63-1a5f-4cec-a071-152f1c62f310", + "type": "targets" + }, + { + "dest-uuid": "8cccd3e0-3ade-48c8-83b9-b09523ddec00", + "type": "targets" + }, + { + "dest-uuid": "28daddab-1f7e-4116-a8ce-285dd3bb2a8d", + "type": "targets" + }, + { + "dest-uuid": "e4cd09cc-7be7-46ef-8989-5b9a812b49fe", + "type": "operates-from" + } + ], + "uuid": "aeb9675f-e0e6-4353-9773-d59aa3bfbc73", + "value": "TA-711 Silver Mantis" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Orinthia" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Strategic signaling" + ], + "sophistication": [ + "minimal" + ] + }, + "related": [ + { + "dest-uuid": "7477aeca-f4ba-4d9c-a261-7e5609033ad6", + "type": "targets" + }, + { + "dest-uuid": "2da913d9-d380-4461-9acd-44f67178589a", + "type": "targets" + }, + { + "dest-uuid": "40e99f1c-44aa-4ae1-9b57-f3ee963d6a91", + "type": "targets" + }, + { + "dest-uuid": "74d2286a-1b87-4984-8dd1-c5bd466ecca5", + "type": "operates-from" + } + ], + "uuid": "a99082c4-860b-4dd2-8582-da152d27332c", + "value": "TA-712 Crimson Rook" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Caelum Protectorate" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Technology theft" + ], + "sophistication": [ + "intermediate" + ] + }, + "related": [ + { + "dest-uuid": "2531f94d-d514-4530-b4eb-35fce204aa36", + "type": "targets" + }, + { + "dest-uuid": "0bbd45b1-a029-4497-8d93-9df82ca4b8c3", + "type": "targets" + }, + { + "dest-uuid": "fdc855e6-4827-4f80-84f6-eafd7687aed5", + "type": "targets" + }, + { + "dest-uuid": "4a600b9f-b843-446f-a234-415aded47e1b", + "type": "operates-from" + } + ], + "uuid": "81444ffd-67c9-43e7-9a5c-5dc3a9119778", + "value": "TA-713 Violet Hydra" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Neruva Federation" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Influence operations" + ], + "sophistication": [ + "advanced" + ] + }, + "related": [ + { + "dest-uuid": "d688f826-d566-41c9-99af-16574aa05921", + "type": "targets" + }, + { + "dest-uuid": "de2e6bc9-64df-4b7b-8c10-698aed474d2c", + "type": "targets" + }, + { + "dest-uuid": "a72d657f-b242-4b6b-ab31-1aa15bff4c4f", + "type": "targets" + }, + { + "dest-uuid": "cfe1b22e-38b5-4077-bb90-b2bc5fedb965", + "type": "operates-from" + } + ], + "uuid": "5c0cc8ef-72b8-4794-bc5c-a9cb7c549f75", + "value": "TA-714 Amber Drift" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Thyros Commonwealth" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Espionage" + ], + "sophistication": [ + "expert" + ] + }, + "related": [ + { + "dest-uuid": "8d018f2a-03c2-4467-8b4e-14ee2ea33df8", + "type": "targets" + }, + { + "dest-uuid": "bbac3990-2ae8-4872-a24a-2d9bf3a44086", + "type": "targets" + }, + { + "dest-uuid": "5b8a3c47-d6d4-470d-bca3-de2ef41391c9", + "type": "targets" + }, + { + "dest-uuid": "970fd807-b09e-4379-9a44-bebc5d0b9869", + "type": "operates-from" + } + ], + "uuid": "5487d618-0462-4a0b-8b03-b16f1253ed20", + "value": "TA-715 Cobalt Jackal" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Ilyndor" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Financial disruption" + ], + "sophistication": [ + "minimal" + ] + }, + "related": [ + { + "dest-uuid": "5196ad35-99b3-41fd-bb4a-286bf08adc4c", + "type": "targets" + }, + { + "dest-uuid": "6c295716-28f9-485e-af6f-0619677d9e37", + "type": "targets" + }, + { + "dest-uuid": "d7748db1-8949-456f-a3b3-1072c6baacc3", + "type": "targets" + }, + { + "dest-uuid": "1e875520-fb3e-4d26-a982-44a5fb7f9375", + "type": "operates-from" + } + ], + "uuid": "9b878df9-4c6e-416f-8d48-2ef872055622", + "value": "TA-716 Onyx Mantis" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Brinax Collective" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Strategic signaling" + ], + "sophistication": [ + "intermediate" + ] + }, + "related": [ + { + "dest-uuid": "d3631b81-e8b1-473c-bd9e-d2daf003a467", + "type": "targets" + }, + { + "dest-uuid": "10ed09dc-bd53-466a-bfc5-c47c65c75141", + "type": "targets" + }, + { + "dest-uuid": "5621dc5a-ba38-45b7-93c6-40c19c9b0b4c", + "type": "targets" + }, + { + "dest-uuid": "91f273f8-66c0-446f-bdb2-4233fd0c55ef", + "type": "operates-from" + } + ], + "uuid": "84d00f48-6a15-45fd-bc4a-0aa9c8dac8cf", + "value": "TA-717 Ivory Rook" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Soreth Dominion" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Technology theft" + ], + "sophistication": [ + "advanced" + ] + }, + "related": [ + { + "dest-uuid": "f68c4a8e-beff-4666-8c85-78deb549088e", + "type": "targets" + }, + { + "dest-uuid": "47a8428c-1427-4eb2-b7a6-6f4f40b69ed1", + "type": "targets" + }, + { + "dest-uuid": "a8685ecb-33cc-4f6a-850d-7b3e7ff21be6", + "type": "targets" + }, + { + "dest-uuid": "c4be7f53-6d08-4472-8480-49ccb7946e78", + "type": "operates-from" + } + ], + "uuid": "3a98840d-72f2-4f65-9781-bc02aee78193", + "value": "TA-718 Sable Hydra" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Quenari League" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Influence operations" + ], + "sophistication": [ + "expert" + ] + }, + "related": [ + { + "dest-uuid": "f0ca111f-53b1-491f-9c3e-f8ef6a83e974", + "type": "targets" + }, + { + "dest-uuid": "412eadf8-d9ff-414f-8001-9635322d4bd9", + "type": "targets" + }, + { + "dest-uuid": "f869e852-7648-4066-a0dc-ed743e11aa05", + "type": "targets" + }, + { + "dest-uuid": "54670ad5-49fe-4d0c-8a81-84b06a8b5050", + "type": "operates-from" + } + ], + "uuid": "82b93df3-2d87-4018-a5d4-cb93cad38cdc", + "value": "TA-719 Copper Drift" + } + ], + "version": 1 +} diff --git a/05_world_layer/sewf/nacre/derived/by-sector.json b/05_world_layer/sewf/nacre/derived/by-sector.json new file mode 100644 index 0000000..1d619e2 --- /dev/null +++ b/05_world_layer/sewf/nacre/derived/by-sector.json @@ -0,0 +1,206 @@ +{ + "schema_version": "1.0", + "sectors": { + "Aerospace": [ + { + "headquarters": "Neruva Federation", + "headquarters_uuid": "cfe1b22e-38b5-4077-bb90-b2bc5fedb965", + "uuid": "d688f826-d566-41c9-99af-16574aa05921", + "value": "SkyBridge Labs" + }, + { + "headquarters": "Neruva Federation", + "headquarters_uuid": "cfe1b22e-38b5-4077-bb90-b2bc5fedb965", + "uuid": "a72d657f-b242-4b6b-ab31-1aa15bff4c4f", + "value": "SkyLattice Labs" + }, + { + "headquarters": "Neruva Federation", + "headquarters_uuid": "cfe1b22e-38b5-4077-bb90-b2bc5fedb965", + "uuid": "de2e6bc9-64df-4b7b-8c10-698aed474d2c", + "value": "SkyPulse Labs" + } + ], + "Energy": [ + { + "headquarters": "Asterin Union", + "headquarters_uuid": "cb97ba71-e477-4acb-9470-10f3e6c9e1a9", + "uuid": "e3d6ab68-ad7b-4deb-9c0d-c0250013d1bb", + "value": "NovaCore Systems" + }, + { + "headquarters": "Asterin Union", + "headquarters_uuid": "cb97ba71-e477-4acb-9470-10f3e6c9e1a9", + "uuid": "ba6c4261-b74f-4e36-ba47-9af4ad63bfd4", + "value": "NovaMatrix Systems" + }, + { + "headquarters": "Asterin Union", + "headquarters_uuid": "cb97ba71-e477-4acb-9470-10f3e6c9e1a9", + "uuid": "93130c22-9361-405b-a91e-de5bd1c2e718", + "value": "NovaNimbus Systems" + } + ], + "Finance": [ + { + "headquarters": "Velkar Republic", + "headquarters_uuid": "e4cd09cc-7be7-46ef-8989-5b9a812b49fe", + "uuid": "df601e63-1a5f-4cec-a071-152f1c62f310", + "value": "HelixCore Group" + }, + { + "headquarters": "Velkar Republic", + "headquarters_uuid": "e4cd09cc-7be7-46ef-8989-5b9a812b49fe", + "uuid": "28daddab-1f7e-4116-a8ce-285dd3bb2a8d", + "value": "HelixForge Group" + }, + { + "headquarters": "Velkar Republic", + "headquarters_uuid": "e4cd09cc-7be7-46ef-8989-5b9a812b49fe", + "uuid": "8cccd3e0-3ade-48c8-83b9-b09523ddec00", + "value": "HelixMatrix Group" + } + ], + "Food": [ + { + "headquarters": "Soreth Dominion", + "headquarters_uuid": "c4be7f53-6d08-4472-8480-49ccb7946e78", + "uuid": "a8685ecb-33cc-4f6a-850d-7b3e7ff21be6", + "value": "DeltaBeacon Networks" + }, + { + "headquarters": "Soreth Dominion", + "headquarters_uuid": "c4be7f53-6d08-4472-8480-49ccb7946e78", + "uuid": "f68c4a8e-beff-4666-8c85-78deb549088e", + "value": "DeltaHarbor Networks" + }, + { + "headquarters": "Soreth Dominion", + "headquarters_uuid": "c4be7f53-6d08-4472-8480-49ccb7946e78", + "uuid": "47a8428c-1427-4eb2-b7a6-6f4f40b69ed1", + "value": "DeltaNimbus Networks" + } + ], + "Healthcare": [ + { + "headquarters": "Orinthia", + "headquarters_uuid": "74d2286a-1b87-4984-8dd1-c5bd466ecca5", + "uuid": "7477aeca-f4ba-4d9c-a261-7e5609033ad6", + "value": "IronCore Dynamics" + }, + { + "headquarters": "Orinthia", + "headquarters_uuid": "74d2286a-1b87-4984-8dd1-c5bd466ecca5", + "uuid": "40e99f1c-44aa-4ae1-9b57-f3ee963d6a91", + "value": "IronForge Dynamics" + }, + { + "headquarters": "Orinthia", + "headquarters_uuid": "74d2286a-1b87-4984-8dd1-c5bd466ecca5", + "uuid": "2da913d9-d380-4461-9acd-44f67178589a", + "value": "IronPulse Dynamics" + } + ], + "Logistics": [ + { + "headquarters": "Thyros Commonwealth", + "headquarters_uuid": "970fd807-b09e-4379-9a44-bebc5d0b9869", + "uuid": "8d018f2a-03c2-4467-8b4e-14ee2ea33df8", + "value": "VertexBridge Systems" + }, + { + "headquarters": "Thyros Commonwealth", + "headquarters_uuid": "970fd807-b09e-4379-9a44-bebc5d0b9869", + "uuid": "bbac3990-2ae8-4872-a24a-2d9bf3a44086", + "value": "VertexFoundry Systems" + }, + { + "headquarters": "Thyros Commonwealth", + "headquarters_uuid": "970fd807-b09e-4379-9a44-bebc5d0b9869", + "uuid": "5b8a3c47-d6d4-470d-bca3-de2ef41391c9", + "value": "VertexLattice Systems" + } + ], + "Manufacturing": [ + { + "headquarters": "Ilyndor", + "headquarters_uuid": "1e875520-fb3e-4d26-a982-44a5fb7f9375", + "uuid": "6c295716-28f9-485e-af6f-0619677d9e37", + "value": "CinderFoundry Group" + }, + { + "headquarters": "Ilyndor", + "headquarters_uuid": "1e875520-fb3e-4d26-a982-44a5fb7f9375", + "uuid": "5196ad35-99b3-41fd-bb4a-286bf08adc4c", + "value": "CinderHarbor Group" + }, + { + "headquarters": "Ilyndor", + "headquarters_uuid": "1e875520-fb3e-4d26-a982-44a5fb7f9375", + "uuid": "d7748db1-8949-456f-a3b3-1072c6baacc3", + "value": "CinderLattice Group" + } + ], + "Maritime": [ + { + "headquarters": "Brinax Collective", + "headquarters_uuid": "91f273f8-66c0-446f-bdb2-4233fd0c55ef", + "uuid": "5621dc5a-ba38-45b7-93c6-40c19c9b0b4c", + "value": "AuroraBeacon Dynamics" + }, + { + "headquarters": "Brinax Collective", + "headquarters_uuid": "91f273f8-66c0-446f-bdb2-4233fd0c55ef", + "uuid": "10ed09dc-bd53-466a-bfc5-c47c65c75141", + "value": "AuroraFoundry Dynamics" + }, + { + "headquarters": "Brinax Collective", + "headquarters_uuid": "91f273f8-66c0-446f-bdb2-4233fd0c55ef", + "uuid": "d3631b81-e8b1-473c-bd9e-d2daf003a467", + "value": "AuroraHarbor Dynamics" + } + ], + "Media": [ + { + "headquarters": "Quenari League", + "headquarters_uuid": "54670ad5-49fe-4d0c-8a81-84b06a8b5050", + "uuid": "f869e852-7648-4066-a0dc-ed743e11aa05", + "value": "QuantumBeacon Labs" + }, + { + "headquarters": "Quenari League", + "headquarters_uuid": "54670ad5-49fe-4d0c-8a81-84b06a8b5050", + "uuid": "f0ca111f-53b1-491f-9c3e-f8ef6a83e974", + "value": "QuantumMatrix Labs" + }, + { + "headquarters": "Quenari League", + "headquarters_uuid": "54670ad5-49fe-4d0c-8a81-84b06a8b5050", + "uuid": "412eadf8-d9ff-414f-8001-9635322d4bd9", + "value": "QuantumNimbus Labs" + } + ], + "Telecommunications": [ + { + "headquarters": "Caelum Protectorate", + "headquarters_uuid": "4a600b9f-b843-446f-a234-415aded47e1b", + "uuid": "2531f94d-d514-4530-b4eb-35fce204aa36", + "value": "BlueBridge Networks" + }, + { + "headquarters": "Caelum Protectorate", + "headquarters_uuid": "4a600b9f-b843-446f-a234-415aded47e1b", + "uuid": "fdc855e6-4827-4f80-84f6-eafd7687aed5", + "value": "BlueForge Networks" + }, + { + "headquarters": "Caelum Protectorate", + "headquarters_uuid": "4a600b9f-b843-446f-a234-415aded47e1b", + "uuid": "0bbd45b1-a029-4497-8d93-9df82ca4b8c3", + "value": "BluePulse Networks" + } + ] + }, + "world_uuid": "7d6d7f2f-b3d4-4bc5-9f27-43e12f7f4658" +} diff --git a/05_world_layer/sewf/nacre/derived/entities.index.json b/05_world_layer/sewf/nacre/derived/entities.index.json new file mode 100644 index 0000000..e2be39c --- /dev/null +++ b/05_world_layer/sewf/nacre/derived/entities.index.json @@ -0,0 +1,1826 @@ +{ + "companies": [ + { + "description": "Fictional maritime enterprise operating in Brinax Collective for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Brinax Collective" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Maritime" + ] + }, + "uuid": "5621dc5a-ba38-45b7-93c6-40c19c9b0b4c", + "value": "AuroraBeacon Dynamics" + }, + { + "description": "Fictional maritime enterprise operating in Brinax Collective for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Brinax Collective" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Maritime" + ] + }, + "uuid": "10ed09dc-bd53-466a-bfc5-c47c65c75141", + "value": "AuroraFoundry Dynamics" + }, + { + "description": "Fictional maritime enterprise operating in Brinax Collective for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Brinax Collective" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Maritime" + ] + }, + "uuid": "d3631b81-e8b1-473c-bd9e-d2daf003a467", + "value": "AuroraHarbor Dynamics" + }, + { + "description": "Fictional telecommunications enterprise operating in Caelum Protectorate for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Caelum Protectorate" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Telecommunications" + ] + }, + "uuid": "2531f94d-d514-4530-b4eb-35fce204aa36", + "value": "BlueBridge Networks" + }, + { + "description": "Fictional telecommunications enterprise operating in Caelum Protectorate for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Caelum Protectorate" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Telecommunications" + ] + }, + "uuid": "fdc855e6-4827-4f80-84f6-eafd7687aed5", + "value": "BlueForge Networks" + }, + { + "description": "Fictional telecommunications enterprise operating in Caelum Protectorate for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Caelum Protectorate" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Telecommunications" + ] + }, + "uuid": "0bbd45b1-a029-4497-8d93-9df82ca4b8c3", + "value": "BluePulse Networks" + }, + { + "description": "Fictional manufacturing enterprise operating in Ilyndor for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Ilyndor" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Manufacturing" + ] + }, + "uuid": "6c295716-28f9-485e-af6f-0619677d9e37", + "value": "CinderFoundry Group" + }, + { + "description": "Fictional manufacturing enterprise operating in Ilyndor for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Ilyndor" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Manufacturing" + ] + }, + "uuid": "5196ad35-99b3-41fd-bb4a-286bf08adc4c", + "value": "CinderHarbor Group" + }, + { + "description": "Fictional manufacturing enterprise operating in Ilyndor for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Ilyndor" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Manufacturing" + ] + }, + "uuid": "d7748db1-8949-456f-a3b3-1072c6baacc3", + "value": "CinderLattice Group" + }, + { + "description": "Fictional food enterprise operating in Soreth Dominion for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Soreth Dominion" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Food" + ] + }, + "uuid": "a8685ecb-33cc-4f6a-850d-7b3e7ff21be6", + "value": "DeltaBeacon Networks" + }, + { + "description": "Fictional food enterprise operating in Soreth Dominion for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Soreth Dominion" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Food" + ] + }, + "uuid": "f68c4a8e-beff-4666-8c85-78deb549088e", + "value": "DeltaHarbor Networks" + }, + { + "description": "Fictional food enterprise operating in Soreth Dominion for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Soreth Dominion" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Food" + ] + }, + "uuid": "47a8428c-1427-4eb2-b7a6-6f4f40b69ed1", + "value": "DeltaNimbus Networks" + }, + { + "description": "Fictional finance enterprise operating in Velkar Republic for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Velkar Republic" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Finance" + ] + }, + "uuid": "df601e63-1a5f-4cec-a071-152f1c62f310", + "value": "HelixCore Group" + }, + { + "description": "Fictional finance enterprise operating in Velkar Republic for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Velkar Republic" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Finance" + ] + }, + "uuid": "28daddab-1f7e-4116-a8ce-285dd3bb2a8d", + "value": "HelixForge Group" + }, + { + "description": "Fictional finance enterprise operating in Velkar Republic for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Velkar Republic" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Finance" + ] + }, + "uuid": "8cccd3e0-3ade-48c8-83b9-b09523ddec00", + "value": "HelixMatrix Group" + }, + { + "description": "Fictional healthcare enterprise operating in Orinthia for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Orinthia" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Healthcare" + ] + }, + "uuid": "7477aeca-f4ba-4d9c-a261-7e5609033ad6", + "value": "IronCore Dynamics" + }, + { + "description": "Fictional healthcare enterprise operating in Orinthia for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Orinthia" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Healthcare" + ] + }, + "uuid": "40e99f1c-44aa-4ae1-9b57-f3ee963d6a91", + "value": "IronForge Dynamics" + }, + { + "description": "Fictional healthcare enterprise operating in Orinthia for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Orinthia" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Healthcare" + ] + }, + "uuid": "2da913d9-d380-4461-9acd-44f67178589a", + "value": "IronPulse Dynamics" + }, + { + "description": "Fictional energy enterprise operating in Asterin Union for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Asterin Union" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Energy" + ] + }, + "uuid": "e3d6ab68-ad7b-4deb-9c0d-c0250013d1bb", + "value": "NovaCore Systems" + }, + { + "description": "Fictional energy enterprise operating in Asterin Union for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Asterin Union" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Energy" + ] + }, + "uuid": "ba6c4261-b74f-4e36-ba47-9af4ad63bfd4", + "value": "NovaMatrix Systems" + }, + { + "description": "Fictional energy enterprise operating in Asterin Union for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Asterin Union" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Energy" + ] + }, + "uuid": "93130c22-9361-405b-a91e-de5bd1c2e718", + "value": "NovaNimbus Systems" + }, + { + "description": "Fictional media enterprise operating in Quenari League for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Quenari League" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Media" + ] + }, + "uuid": "f869e852-7648-4066-a0dc-ed743e11aa05", + "value": "QuantumBeacon Labs" + }, + { + "description": "Fictional media enterprise operating in Quenari League for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Quenari League" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Media" + ] + }, + "uuid": "f0ca111f-53b1-491f-9c3e-f8ef6a83e974", + "value": "QuantumMatrix Labs" + }, + { + "description": "Fictional media enterprise operating in Quenari League for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Quenari League" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Media" + ] + }, + "uuid": "412eadf8-d9ff-414f-8001-9635322d4bd9", + "value": "QuantumNimbus Labs" + }, + { + "description": "Fictional aerospace enterprise operating in Neruva Federation for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Neruva Federation" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Aerospace" + ] + }, + "uuid": "d688f826-d566-41c9-99af-16574aa05921", + "value": "SkyBridge Labs" + }, + { + "description": "Fictional aerospace enterprise operating in Neruva Federation for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Neruva Federation" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Aerospace" + ] + }, + "uuid": "a72d657f-b242-4b6b-ab31-1aa15bff4c4f", + "value": "SkyLattice Labs" + }, + { + "description": "Fictional aerospace enterprise operating in Neruva Federation for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Neruva Federation" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Aerospace" + ] + }, + "uuid": "de2e6bc9-64df-4b7b-8c10-698aed474d2c", + "value": "SkyPulse Labs" + }, + { + "description": "Fictional logistics enterprise operating in Thyros Commonwealth for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Thyros Commonwealth" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Logistics" + ] + }, + "uuid": "8d018f2a-03c2-4467-8b4e-14ee2ea33df8", + "value": "VertexBridge Systems" + }, + { + "description": "Fictional logistics enterprise operating in Thyros Commonwealth for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Thyros Commonwealth" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Logistics" + ] + }, + "uuid": "bbac3990-2ae8-4872-a24a-2d9bf3a44086", + "value": "VertexFoundry Systems" + }, + { + "description": "Fictional logistics enterprise operating in Thyros Commonwealth for simulation scenarios.", + "meta": { + "entity-type": [ + "company" + ], + "exercise-use": [ + "standard-drafting", + "red-blue-exercise" + ], + "headquarters": [ + "Thyros Commonwealth" + ], + "planet": [ + "Nacre" + ], + "sector": [ + "Logistics" + ] + }, + "uuid": "5b8a3c47-d6d4-470d-bca3-de2ef41391c9", + "value": "VertexLattice Systems" + } + ], + "countries": [ + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Asterin Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Northern supercontinent" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "cb97ba71-e477-4acb-9470-10f3e6c9e1a9", + "value": "Asterin Union" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Brinax Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Energy-grid cooperative state" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "91f273f8-66c0-446f-bdb2-4233fd0c55ef", + "value": "Brinax Collective" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Caelum Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "High-altitude plateau state" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "4a600b9f-b843-446f-a234-415aded47e1b", + "value": "Caelum Protectorate" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Ilyndor Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Neutral trade corridor" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "1e875520-fb3e-4d26-a982-44a5fb7f9375", + "value": "Ilyndor" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Neruva Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Delta megacities and ports" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "cfe1b22e-38b5-4077-bb90-b2bc5fedb965", + "value": "Neruva Federation" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Orinthia Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Archipelago of research hubs" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "74d2286a-1b87-4984-8dd1-c5bd466ecca5", + "value": "Orinthia" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Quenari Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Equatorial agri-tech alliance" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "54670ad5-49fe-4d0c-8a81-84b06a8b5050", + "value": "Quenari League" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Soreth Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Polar logistics nation" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "c4be7f53-6d08-4472-8480-49ccb7946e78", + "value": "Soreth Dominion" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Thyros Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Resource-rich steppe" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "970fd807-b09e-4379-9a44-bebc5d0b9869", + "value": "Thyros Commonwealth" + }, + { + "description": "Synthetic country on planet Nacre used for neutral cyber exercise narratives.", + "meta": { + "capital": [ + "Velkar Prime" + ], + "entity-type": [ + "country" + ], + "exercise-use": [ + "standard-drafting", + "tabletop", + "training" + ], + "geography": [ + "Inland industrial basin" + ], + "planet": [ + "Nacre" + ] + }, + "uuid": "e4cd09cc-7be7-46ef-8989-5b9a812b49fe", + "value": "Velkar Republic" + } + ], + "schema_version": "1.0", + "threat_actors": [ + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Asterin Union" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Espionage" + ], + "sophistication": [ + "minimal" + ] + }, + "related": [ + { + "dest-uuid": "e3d6ab68-ad7b-4deb-9c0d-c0250013d1bb", + "type": "targets" + }, + { + "dest-uuid": "ba6c4261-b74f-4e36-ba47-9af4ad63bfd4", + "type": "targets" + }, + { + "dest-uuid": "93130c22-9361-405b-a91e-de5bd1c2e718", + "type": "targets" + }, + { + "dest-uuid": "cb97ba71-e477-4acb-9470-10f3e6c9e1a9", + "type": "operates-from" + } + ], + "uuid": "6c922d71-43e3-40c4-a1ea-85929f0c2f1a", + "value": "TA-700 Obsidian Jackal" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Velkar Republic" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Financial disruption" + ], + "sophistication": [ + "intermediate" + ] + }, + "related": [ + { + "dest-uuid": "df601e63-1a5f-4cec-a071-152f1c62f310", + "type": "targets" + }, + { + "dest-uuid": "8cccd3e0-3ade-48c8-83b9-b09523ddec00", + "type": "targets" + }, + { + "dest-uuid": "28daddab-1f7e-4116-a8ce-285dd3bb2a8d", + "type": "targets" + }, + { + "dest-uuid": "e4cd09cc-7be7-46ef-8989-5b9a812b49fe", + "type": "operates-from" + } + ], + "uuid": "e8b1ce9a-128c-4546-907d-02178fc72e49", + "value": "TA-701 Silver Mantis" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Orinthia" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Strategic signaling" + ], + "sophistication": [ + "advanced" + ] + }, + "related": [ + { + "dest-uuid": "7477aeca-f4ba-4d9c-a261-7e5609033ad6", + "type": "targets" + }, + { + "dest-uuid": "2da913d9-d380-4461-9acd-44f67178589a", + "type": "targets" + }, + { + "dest-uuid": "40e99f1c-44aa-4ae1-9b57-f3ee963d6a91", + "type": "targets" + }, + { + "dest-uuid": "74d2286a-1b87-4984-8dd1-c5bd466ecca5", + "type": "operates-from" + } + ], + "uuid": "8ea5ed6e-8753-4150-946f-157b3bf49bc0", + "value": "TA-702 Crimson Rook" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Caelum Protectorate" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Technology theft" + ], + "sophistication": [ + "expert" + ] + }, + "related": [ + { + "dest-uuid": "2531f94d-d514-4530-b4eb-35fce204aa36", + "type": "targets" + }, + { + "dest-uuid": "0bbd45b1-a029-4497-8d93-9df82ca4b8c3", + "type": "targets" + }, + { + "dest-uuid": "fdc855e6-4827-4f80-84f6-eafd7687aed5", + "type": "targets" + }, + { + "dest-uuid": "4a600b9f-b843-446f-a234-415aded47e1b", + "type": "operates-from" + } + ], + "uuid": "56eb0bfc-4fe4-4fbc-bd0d-9e26a87e1217", + "value": "TA-703 Violet Hydra" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Neruva Federation" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Influence operations" + ], + "sophistication": [ + "minimal" + ] + }, + "related": [ + { + "dest-uuid": "d688f826-d566-41c9-99af-16574aa05921", + "type": "targets" + }, + { + "dest-uuid": "de2e6bc9-64df-4b7b-8c10-698aed474d2c", + "type": "targets" + }, + { + "dest-uuid": "a72d657f-b242-4b6b-ab31-1aa15bff4c4f", + "type": "targets" + }, + { + "dest-uuid": "cfe1b22e-38b5-4077-bb90-b2bc5fedb965", + "type": "operates-from" + } + ], + "uuid": "716458aa-8ba1-4a82-9783-926381bfeb43", + "value": "TA-704 Amber Drift" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Thyros Commonwealth" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Espionage" + ], + "sophistication": [ + "intermediate" + ] + }, + "related": [ + { + "dest-uuid": "8d018f2a-03c2-4467-8b4e-14ee2ea33df8", + "type": "targets" + }, + { + "dest-uuid": "bbac3990-2ae8-4872-a24a-2d9bf3a44086", + "type": "targets" + }, + { + "dest-uuid": "5b8a3c47-d6d4-470d-bca3-de2ef41391c9", + "type": "targets" + }, + { + "dest-uuid": "970fd807-b09e-4379-9a44-bebc5d0b9869", + "type": "operates-from" + } + ], + "uuid": "cfecc787-5ee0-4786-a285-dc3c7919e7a0", + "value": "TA-705 Cobalt Jackal" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Ilyndor" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Financial disruption" + ], + "sophistication": [ + "advanced" + ] + }, + "related": [ + { + "dest-uuid": "5196ad35-99b3-41fd-bb4a-286bf08adc4c", + "type": "targets" + }, + { + "dest-uuid": "6c295716-28f9-485e-af6f-0619677d9e37", + "type": "targets" + }, + { + "dest-uuid": "d7748db1-8949-456f-a3b3-1072c6baacc3", + "type": "targets" + }, + { + "dest-uuid": "1e875520-fb3e-4d26-a982-44a5fb7f9375", + "type": "operates-from" + } + ], + "uuid": "10170ce4-b93c-48e0-84a5-a32f7e6818be", + "value": "TA-706 Onyx Mantis" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Brinax Collective" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Strategic signaling" + ], + "sophistication": [ + "expert" + ] + }, + "related": [ + { + "dest-uuid": "d3631b81-e8b1-473c-bd9e-d2daf003a467", + "type": "targets" + }, + { + "dest-uuid": "10ed09dc-bd53-466a-bfc5-c47c65c75141", + "type": "targets" + }, + { + "dest-uuid": "5621dc5a-ba38-45b7-93c6-40c19c9b0b4c", + "type": "targets" + }, + { + "dest-uuid": "91f273f8-66c0-446f-bdb2-4233fd0c55ef", + "type": "operates-from" + } + ], + "uuid": "7a6197e0-ee8f-4e21-ba48-ce0a42f67856", + "value": "TA-707 Ivory Rook" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Soreth Dominion" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Technology theft" + ], + "sophistication": [ + "minimal" + ] + }, + "related": [ + { + "dest-uuid": "f68c4a8e-beff-4666-8c85-78deb549088e", + "type": "targets" + }, + { + "dest-uuid": "47a8428c-1427-4eb2-b7a6-6f4f40b69ed1", + "type": "targets" + }, + { + "dest-uuid": "a8685ecb-33cc-4f6a-850d-7b3e7ff21be6", + "type": "targets" + }, + { + "dest-uuid": "c4be7f53-6d08-4472-8480-49ccb7946e78", + "type": "operates-from" + } + ], + "uuid": "fd0dcf97-33f4-47d7-84c7-9a1559929f3e", + "value": "TA-708 Sable Hydra" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Quenari League" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Influence operations" + ], + "sophistication": [ + "intermediate" + ] + }, + "related": [ + { + "dest-uuid": "f0ca111f-53b1-491f-9c3e-f8ef6a83e974", + "type": "targets" + }, + { + "dest-uuid": "412eadf8-d9ff-414f-8001-9635322d4bd9", + "type": "targets" + }, + { + "dest-uuid": "f869e852-7648-4066-a0dc-ed743e11aa05", + "type": "targets" + }, + { + "dest-uuid": "54670ad5-49fe-4d0c-8a81-84b06a8b5050", + "type": "operates-from" + } + ], + "uuid": "f3d700cb-3106-46d6-8d3d-a7b6da24d107", + "value": "TA-709 Copper Drift" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Asterin Union" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Espionage" + ], + "sophistication": [ + "advanced" + ] + }, + "related": [ + { + "dest-uuid": "e3d6ab68-ad7b-4deb-9c0d-c0250013d1bb", + "type": "targets" + }, + { + "dest-uuid": "ba6c4261-b74f-4e36-ba47-9af4ad63bfd4", + "type": "targets" + }, + { + "dest-uuid": "93130c22-9361-405b-a91e-de5bd1c2e718", + "type": "targets" + }, + { + "dest-uuid": "cb97ba71-e477-4acb-9470-10f3e6c9e1a9", + "type": "operates-from" + } + ], + "uuid": "e69c8045-5c58-4c57-adca-050f8bfe6d9b", + "value": "TA-710 Obsidian Jackal" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Velkar Republic" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Financial disruption" + ], + "sophistication": [ + "expert" + ] + }, + "related": [ + { + "dest-uuid": "df601e63-1a5f-4cec-a071-152f1c62f310", + "type": "targets" + }, + { + "dest-uuid": "8cccd3e0-3ade-48c8-83b9-b09523ddec00", + "type": "targets" + }, + { + "dest-uuid": "28daddab-1f7e-4116-a8ce-285dd3bb2a8d", + "type": "targets" + }, + { + "dest-uuid": "e4cd09cc-7be7-46ef-8989-5b9a812b49fe", + "type": "operates-from" + } + ], + "uuid": "aeb9675f-e0e6-4353-9773-d59aa3bfbc73", + "value": "TA-711 Silver Mantis" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Orinthia" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Strategic signaling" + ], + "sophistication": [ + "minimal" + ] + }, + "related": [ + { + "dest-uuid": "7477aeca-f4ba-4d9c-a261-7e5609033ad6", + "type": "targets" + }, + { + "dest-uuid": "2da913d9-d380-4461-9acd-44f67178589a", + "type": "targets" + }, + { + "dest-uuid": "40e99f1c-44aa-4ae1-9b57-f3ee963d6a91", + "type": "targets" + }, + { + "dest-uuid": "74d2286a-1b87-4984-8dd1-c5bd466ecca5", + "type": "operates-from" + } + ], + "uuid": "a99082c4-860b-4dd2-8582-da152d27332c", + "value": "TA-712 Crimson Rook" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Caelum Protectorate" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Technology theft" + ], + "sophistication": [ + "intermediate" + ] + }, + "related": [ + { + "dest-uuid": "2531f94d-d514-4530-b4eb-35fce204aa36", + "type": "targets" + }, + { + "dest-uuid": "0bbd45b1-a029-4497-8d93-9df82ca4b8c3", + "type": "targets" + }, + { + "dest-uuid": "fdc855e6-4827-4f80-84f6-eafd7687aed5", + "type": "targets" + }, + { + "dest-uuid": "4a600b9f-b843-446f-a234-415aded47e1b", + "type": "operates-from" + } + ], + "uuid": "81444ffd-67c9-43e7-9a5c-5dc3a9119778", + "value": "TA-713 Violet Hydra" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Neruva Federation" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Influence operations" + ], + "sophistication": [ + "advanced" + ] + }, + "related": [ + { + "dest-uuid": "d688f826-d566-41c9-99af-16574aa05921", + "type": "targets" + }, + { + "dest-uuid": "de2e6bc9-64df-4b7b-8c10-698aed474d2c", + "type": "targets" + }, + { + "dest-uuid": "a72d657f-b242-4b6b-ab31-1aa15bff4c4f", + "type": "targets" + }, + { + "dest-uuid": "cfe1b22e-38b5-4077-bb90-b2bc5fedb965", + "type": "operates-from" + } + ], + "uuid": "5c0cc8ef-72b8-4794-bc5c-a9cb7c549f75", + "value": "TA-714 Amber Drift" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Thyros Commonwealth" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Espionage" + ], + "sophistication": [ + "expert" + ] + }, + "related": [ + { + "dest-uuid": "8d018f2a-03c2-4467-8b4e-14ee2ea33df8", + "type": "targets" + }, + { + "dest-uuid": "bbac3990-2ae8-4872-a24a-2d9bf3a44086", + "type": "targets" + }, + { + "dest-uuid": "5b8a3c47-d6d4-470d-bca3-de2ef41391c9", + "type": "targets" + }, + { + "dest-uuid": "970fd807-b09e-4379-9a44-bebc5d0b9869", + "type": "operates-from" + } + ], + "uuid": "5487d618-0462-4a0b-8b03-b16f1253ed20", + "value": "TA-715 Cobalt Jackal" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Ilyndor" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Financial disruption" + ], + "sophistication": [ + "minimal" + ] + }, + "related": [ + { + "dest-uuid": "5196ad35-99b3-41fd-bb4a-286bf08adc4c", + "type": "targets" + }, + { + "dest-uuid": "6c295716-28f9-485e-af6f-0619677d9e37", + "type": "targets" + }, + { + "dest-uuid": "d7748db1-8949-456f-a3b3-1072c6baacc3", + "type": "targets" + }, + { + "dest-uuid": "1e875520-fb3e-4d26-a982-44a5fb7f9375", + "type": "operates-from" + } + ], + "uuid": "9b878df9-4c6e-416f-8d48-2ef872055622", + "value": "TA-716 Onyx Mantis" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Brinax Collective" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Strategic signaling" + ], + "sophistication": [ + "intermediate" + ] + }, + "related": [ + { + "dest-uuid": "d3631b81-e8b1-473c-bd9e-d2daf003a467", + "type": "targets" + }, + { + "dest-uuid": "10ed09dc-bd53-466a-bfc5-c47c65c75141", + "type": "targets" + }, + { + "dest-uuid": "5621dc5a-ba38-45b7-93c6-40c19c9b0b4c", + "type": "targets" + }, + { + "dest-uuid": "91f273f8-66c0-446f-bdb2-4233fd0c55ef", + "type": "operates-from" + } + ], + "uuid": "84d00f48-6a15-45fd-bc4a-0aa9c8dac8cf", + "value": "TA-717 Ivory Rook" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Soreth Dominion" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Technology theft" + ], + "sophistication": [ + "advanced" + ] + }, + "related": [ + { + "dest-uuid": "f68c4a8e-beff-4666-8c85-78deb549088e", + "type": "targets" + }, + { + "dest-uuid": "47a8428c-1427-4eb2-b7a6-6f4f40b69ed1", + "type": "targets" + }, + { + "dest-uuid": "a8685ecb-33cc-4f6a-850d-7b3e7ff21be6", + "type": "targets" + }, + { + "dest-uuid": "c4be7f53-6d08-4472-8480-49ccb7946e78", + "type": "operates-from" + } + ], + "uuid": "3a98840d-72f2-4f65-9781-bc02aee78193", + "value": "TA-718 Sable Hydra" + }, + { + "description": "Non-real threat actor profile designed for politically neutral cyber exercises.", + "meta": { + "entity-type": [ + "threat-actor" + ], + "exercise-use": [ + "standard-drafting", + "cti-training" + ], + "origin": [ + "Quenari League" + ], + "planet": [ + "Nacre" + ], + "primary-motivation": [ + "Influence operations" + ], + "sophistication": [ + "expert" + ] + }, + "related": [ + { + "dest-uuid": "f0ca111f-53b1-491f-9c3e-f8ef6a83e974", + "type": "targets" + }, + { + "dest-uuid": "412eadf8-d9ff-414f-8001-9635322d4bd9", + "type": "targets" + }, + { + "dest-uuid": "f869e852-7648-4066-a0dc-ed743e11aa05", + "type": "targets" + }, + { + "dest-uuid": "54670ad5-49fe-4d0c-8a81-84b06a8b5050", + "type": "operates-from" + } + ], + "uuid": "82b93df3-2d87-4018-a5d4-cb93cad38cdc", + "value": "TA-719 Copper Drift" + } + ], + "world": { + "name": "Synthetic Exercise World", + "planet": "Nacre", + "type": "exercise-world", + "uuid": "7d6d7f2f-b3d4-4bc5-9f27-43e12f7f4658", + "version": 1 + } +} diff --git a/05_world_layer/sewf/nacre/galaxies/exercise-world.json b/05_world_layer/sewf/nacre/galaxies/exercise-world.json new file mode 100644 index 0000000..bc2c341 --- /dev/null +++ b/05_world_layer/sewf/nacre/galaxies/exercise-world.json @@ -0,0 +1,9 @@ +{ + "description": "Exercise-only synthetic world entities for cyber scenarios and standards drafting.", + "icon": "globe", + "name": "Synthetic Exercise World", + "namespace": "misp", + "type": "exercise-world", + "uuid": "3c3de5f0-5982-4c7f-88cf-8abf43b8d6c1", + "version": 1 +} diff --git a/05_world_layer/tests/test_nacre_world.py b/05_world_layer/tests/test_nacre_world.py new file mode 100644 index 0000000..ec27bbb --- /dev/null +++ b/05_world_layer/tests/test_nacre_world.py @@ -0,0 +1,167 @@ +import importlib.util +import json +import subprocess +import sys +import unittest +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] +WORLD_LAYER = ROOT / "05_world_layer" +NACRE = WORLD_LAYER / "sewf" / "nacre" +MISP_STACK = ROOT / "03_container_layer" / "docker" / "admin" / "misp-standalone" + + +class NacrePackageTests(unittest.TestCase): + def test_required_upstream_package_files_exist(self) -> None: + required = [ + WORLD_LAYER / "README.md", + WORLD_LAYER / "NOTICE", + WORLD_LAYER / "manifest.json", + NACRE / "VERSION", + NACRE / "clusters" / "exercise-world.json", + NACRE / "galaxies" / "exercise-world.json", + ] + + missing = [str(path.relative_to(ROOT)) for path in required if not path.is_file()] + self.assertEqual([], missing, f"missing world package files: {missing}") + + def test_generated_indexes_are_current_and_relationally_valid(self) -> None: + generator = WORLD_LAYER / "tools" / "generate_indexes.py" + result = subprocess.run( + [sys.executable, str(generator), "--check"], + cwd=ROOT, + capture_output=True, + text=True, + check=False, + ) + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + + with (NACRE / "derived" / "entities.index.json").open() as handle: + index = json.load(handle) + with (NACRE / "derived" / "by-sector.json").open() as handle: + sectors = json.load(handle) + + self.assertEqual(10, len(index["countries"])) + self.assertEqual(30, len(index["companies"])) + self.assertEqual(20, len(index["threat_actors"])) + self.assertEqual(30, sum(len(companies) for companies in sectors["sectors"].values())) + + def test_catalog_manifest_registers_the_world_layer(self) -> None: + with (ROOT / "manifest.json").open() as handle: + catalog = json.load(handle) + + self.assertEqual( + { + "path": "05_world_layer", + "description": "Neutral, versioned narrative worlds for cyber exercises", + "manifest": "manifest.json", + }, + catalog["layers"].get("world"), + ) + + def test_misp_stack_pins_a_release_with_nacre(self) -> None: + expected = "v2.5.44" + env_example = (MISP_STACK / ".env.example").read_text() + dockerfile = (MISP_STACK / "Dockerfile").read_text() + compose = (MISP_STACK / "docker-compose.yml").read_text() + + self.assertIn(f"MISP_VERSION={expected}", env_example) + self.assertIn(f"ARG MISP_VERSION={expected}", dockerfile) + self.assertNotIn("v2.5.37", compose) + self.assertEqual(3, compose.count(expected)) + + def test_misp_build_ties_bundled_world_to_vendored_hashes(self) -> None: + dockerfile = (MISP_STACK / "Dockerfile").read_text() + version = (NACRE / "VERSION").read_text() + + expected = { + "55afe65a817c167a46dbd26850515aefb2bf72b9318f651d6adb172e498a44b4": + "clusters/exercise-world.json", + "f1fe9a26eae4148542e0d89126cdf4231c803b2c3fd255137b42e2c5f969807a": + "galaxies/exercise-world.json", + } + for digest, relative_path in expected.items(): + self.assertIn(digest, dockerfile) + self.assertIn(relative_path, dockerfile) + self.assertIn("sha256sum -c", dockerfile) + self.assertIn("misp_version=v2.5.44", version) + self.assertIn( + "misp_galaxy_commit=041c6d0f3da384626c07b9220c1f6cef640ddf1a", + version, + ) + + def test_sample_events_use_canonical_nacre_galaxy_tags(self) -> None: + expected_by_file = { + "event-01-spearphishing.json": { + 'misp-galaxy:exercise-world="Asterin Union"', + 'misp-galaxy:exercise-world="NovaCore Systems"', + 'misp-galaxy:exercise-world="TA-700 Obsidian Jackal"', + }, + "event-02-ransomware-c2.json": { + 'misp-galaxy:exercise-world="Velkar Republic"', + 'misp-galaxy:exercise-world="HelixCore Group"', + 'misp-galaxy:exercise-world="TA-701 Silver Mantis"', + }, + } + + events = MISP_STACK / "provisioning" / "sample-events" + for filename, expected in expected_by_file.items(): + with (events / filename).open() as handle: + event = json.load(handle)["Event"] + actual = {tag["name"] for tag in event["Tag"]} + self.assertTrue(expected <= actual, f"{filename} missing {sorted(expected - actual)}") + + def test_provisioner_verifies_nacre_before_importing_events(self) -> None: + provisioning = MISP_STACK / "provisioning" + verifier = provisioning / "verify-exercise-world.py" + self.assertTrue(verifier.is_file(), "missing exercise-world runtime verifier") + + spec = importlib.util.spec_from_file_location("verify_exercise_world", verifier) + self.assertIsNotNone(spec) + self.assertIsNotNone(spec.loader) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + + galaxy_id = module.find_exercise_world_galaxy( + { + "response": [ + { + "Galaxy": { + "id": "42", + "type": "exercise-world", + "uuid": "3c3de5f0-5982-4c7f-88cf-8abf43b8d6c1", + } + } + ] + } + ) + self.assertEqual("42", galaxy_id) + + clusters = [ + { + "uuid": f"00000000-0000-4000-8000-{index:012d}", + "collection_uuid": "7d6d7f2f-b3d4-4bc5-9f27-43e12f7f4658", + } + for index in range(60) + ] + try: + module.verify_cluster_payload({"Galaxy": {"id": "42"}, "GalaxyCluster": clusters}) + except Exception as exc: # noqa: BLE001 - convert unexpected parser errors into an assertion + self.fail(f"valid MISP galaxy payload was rejected: {exc}") + + provision_sh = (provisioning / "provision.sh").read_text() + self.assertLess( + provision_sh.index("provision-content.sh"), + provision_sh.index("verify-exercise-world.py"), + ) + self.assertLess( + provision_sh.index("verify-exercise-world.py"), + provision_sh.index("provision-sample-events.sh"), + ) + compose = (MISP_STACK / "docker-compose.yml").read_text() + self.assertIn("./provisioning/verify-exercise-world.py:/provisioning/verify-exercise-world.py:ro", compose) + + +if __name__ == "__main__": + unittest.main() diff --git a/05_world_layer/tools/generate_indexes.py b/05_world_layer/tools/generate_indexes.py new file mode 100644 index 0000000..263f7b0 --- /dev/null +++ b/05_world_layer/tools/generate_indexes.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +"""Validate the pinned Nacre world and generate deterministic lookup indexes.""" + +from __future__ import annotations + +import argparse +import json +from collections import defaultdict +from pathlib import Path +from typing import Any + + +WORLD_LAYER = Path(__file__).resolve().parents[1] +NACRE = WORLD_LAYER / "sewf" / "nacre" +CLUSTER_PATH = NACRE / "clusters" / "exercise-world.json" +GALAXY_PATH = NACRE / "galaxies" / "exercise-world.json" +DERIVED = NACRE / "derived" + +EXPECTED_GALAXY_UUID = "3c3de5f0-5982-4c7f-88cf-8abf43b8d6c1" +EXPECTED_COLLECTION_UUID = "7d6d7f2f-b3d4-4bc5-9f27-43e12f7f4658" +EXPECTED_COUNTS = {"country": 10, "company": 30, "threat-actor": 20} + + +class WorldValidationError(ValueError): + pass + + +def load_json(path: Path) -> dict[str, Any]: + with path.open(encoding="utf-8") as handle: + return json.load(handle) + + +def one(meta: dict[str, Any], key: str, entity: str) -> str: + values = meta.get(key) + if not isinstance(values, list) or len(values) != 1 or not isinstance(values[0], str) or not values[0]: + raise WorldValidationError(f"{entity}: meta.{key} must contain exactly one non-empty string") + return values[0] + + +def validate_and_group( + cluster: dict[str, Any], galaxy: dict[str, Any] +) -> tuple[dict[str, list[dict[str, Any]]], str]: + if galaxy.get("uuid") != EXPECTED_GALAXY_UUID: + raise WorldValidationError("unexpected Nacre galaxy UUID") + if cluster.get("uuid") != EXPECTED_COLLECTION_UUID: + raise WorldValidationError("unexpected Nacre collection UUID") + if galaxy.get("type") != cluster.get("type") or cluster.get("type") != "exercise-world": + raise WorldValidationError("galaxy and cluster types must both be exercise-world") + if galaxy.get("version") != cluster.get("version") or cluster.get("version") != 1: + raise WorldValidationError("galaxy and cluster versions must both be 1") + + values = cluster.get("values") + if not isinstance(values, list): + raise WorldValidationError("cluster.values must be an array") + + grouped: dict[str, list[dict[str, Any]]] = defaultdict(list) + uuids: set[str] = set() + names: set[str] = set() + planets: set[str] = set() + + for item in values: + name = item.get("value") + entity_uuid = item.get("uuid") + meta = item.get("meta") + if not isinstance(name, str) or not name: + raise WorldValidationError("every entity must have a non-empty value") + if not isinstance(entity_uuid, str) or not entity_uuid: + raise WorldValidationError(f"{name}: missing uuid") + if entity_uuid in uuids: + raise WorldValidationError(f"duplicate entity uuid: {entity_uuid}") + if name in names: + raise WorldValidationError(f"duplicate entity value: {name}") + if not isinstance(meta, dict): + raise WorldValidationError(f"{name}: missing meta object") + for key, meta_values in meta.items(): + if not isinstance(meta_values, list) or not all(isinstance(value, str) for value in meta_values): + raise WorldValidationError(f"{name}: meta.{key} must be an array of strings") + + entity_type = one(meta, "entity-type", name) + planet = one(meta, "planet", name) + if entity_type not in EXPECTED_COUNTS: + raise WorldValidationError(f"{name}: unsupported entity type {entity_type}") + + uuids.add(entity_uuid) + names.add(name) + planets.add(planet) + grouped[entity_type].append(item) + + if planets != {"Nacre"}: + raise WorldValidationError(f"all entities must belong to Nacre, got {sorted(planets)}") + actual_counts = {entity_type: len(grouped[entity_type]) for entity_type in EXPECTED_COUNTS} + if actual_counts != EXPECTED_COUNTS: + raise WorldValidationError(f"unexpected entity counts: {actual_counts}") + + countries = {item["value"] for item in grouped["country"]} + for company in grouped["company"]: + headquarters = one(company["meta"], "headquarters", company["value"]) + if headquarters not in countries: + raise WorldValidationError(f"{company['value']}: unknown headquarters {headquarters}") + for actor in grouped["threat-actor"]: + origin = one(actor["meta"], "origin", actor["value"]) + if origin not in countries: + raise WorldValidationError(f"{actor['value']}: unknown origin {origin}") + + for items in grouped.values(): + items.sort(key=lambda item: (item["value"].casefold(), item["uuid"])) + return dict(grouped), "Nacre" + + +def render_documents(cluster: dict[str, Any], grouped: dict[str, list[dict[str, Any]]], planet: str) -> dict[Path, str]: + country_uuids = {item["value"]: item["uuid"] for item in grouped["country"]} + index = { + "schema_version": "1.0", + "world": { + "name": cluster["name"], + "planet": planet, + "type": cluster["type"], + "uuid": cluster["uuid"], + "version": cluster["version"], + }, + "countries": grouped["country"], + "companies": grouped["company"], + "threat_actors": grouped["threat-actor"], + } + + by_sector: dict[str, list[dict[str, str]]] = defaultdict(list) + for company in grouped["company"]: + headquarters = one(company["meta"], "headquarters", company["value"]) + sector = one(company["meta"], "sector", company["value"]) + by_sector[sector].append( + { + "uuid": company["uuid"], + "value": company["value"], + "headquarters": headquarters, + "headquarters_uuid": country_uuids[headquarters], + } + ) + sectors = { + "schema_version": "1.0", + "world_uuid": cluster["uuid"], + "sectors": {key: by_sector[key] for key in sorted(by_sector, key=str.casefold)}, + } + + return { + DERIVED / "entities.index.json": json.dumps(index, indent=2, sort_keys=True, ensure_ascii=False) + "\n", + DERIVED / "by-sector.json": json.dumps(sectors, indent=2, sort_keys=True, ensure_ascii=False) + "\n", + } + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--check", action="store_true", help="fail if generated indexes are missing or stale") + args = parser.parse_args() + + try: + cluster = load_json(CLUSTER_PATH) + galaxy = load_json(GALAXY_PATH) + grouped, planet = validate_and_group(cluster, galaxy) + documents = render_documents(cluster, grouped, planet) + except (OSError, json.JSONDecodeError, WorldValidationError) as exc: + parser.error(str(exc)) + + if args.check: + stale = [path for path, expected in documents.items() if not path.is_file() or path.read_text() != expected] + if stale: + for path in stale: + print(f"stale generated file: {path.relative_to(WORLD_LAYER)}") + return 1 + return 0 + + DERIVED.mkdir(parents=True, exist_ok=True) + for path, content in documents.items(): + path.write_text(content, encoding="utf-8") + print(f"wrote {path.relative_to(WORLD_LAYER)}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/README.md b/README.md index f4cc6a3..ad308ea 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,10 @@ # Repository Content -This repository is the **range42 catalog** — a collection of reusable infrastructure bundles that can be orchestrated by the backend API or executed directly via the [range42-deployer-ui](https://github.com/range42/range42-deployer-ui) or CLI through the playbooks repository. +This repository is the **range42 catalog** — a collection of reusable infrastructure bundles +and exercise-content assets. Infrastructure can be orchestrated by the backend API or +executed directly via the [range42-deployer-ui](https://github.com/range42/range42-deployer-ui) +or CLI through the playbooks repository. Bundles include Ansible roles, Dockerfiles, and Docker Compose definitions designed to configure misconfigured or vulnerable environments for cyber training scenarios. @@ -51,6 +54,15 @@ Interface templates and challenge frameworks that gamify the deployed scenarios. - **`network/notes/`** — notes and resources for network challenges. - **`files/notes/`** — notes and resources for file-based challenges. +## Layer 05 — Synthetic Exercise Worlds + +Path: `05_world_layer/` + +Versioned, politically neutral narrative reference data for exercises. The initial Nacre +package uses MISP's Synthetic Exercise World Format and provides countries, companies, +sectors, and threat actors for MISP events and scenario/application references. Vendored +upstream data carries its own CC-BY-4.0 attribution and provenance in this layer. + --- **Note:** The deep tree structure is still evolving and may change as the project grows. @@ -63,3 +75,5 @@ We use centralized community health files in Range42 community health. ## License - GPL-3.0 license +- Vendored assets under `05_world_layer/` retain the licenses and attribution documented + alongside each package; Nacre is CC-BY-4.0. diff --git a/manifest.json b/manifest.json index 5b24df4..2f39790 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "name": "range42-catalog", "version": "1.0.0", - "description": "A collection of reusable infrastructure bundles for cyber range deployments including Ansible roles, Docker/Docker Compose stacks, and gamification templates.", + "description": "Reusable infrastructure bundles and exercise-content assets including Ansible roles, Docker/Docker Compose stacks, gamification templates, and neutral narrative worlds.", "license": "GPL-3.0", "repository": { "type": "git", @@ -90,6 +90,11 @@ "description": "Network-themed challenges" } } + }, + "world": { + "path": "05_world_layer", + "description": "Neutral, versioned narrative worlds for cyber exercises", + "manifest": "manifest.json" } }, "conventions": { From d7e4a6231ee55adc148b9ca5092f9cfd0c9f5f3d Mon Sep 17 00:00:00 2001 From: Philippe Parage <69145356+pparage@users.noreply.github.com> Date: Fri, 21 Aug 2026 16:15:32 +0200 Subject: [PATCH 2/2] fix(misp): reconcile persisted exercise-world data --- .gitignore | 2 + .../docker/admin/misp-standalone/Dockerfile | 8 ++ .../docker/admin/misp-standalone/README.md | 9 +- .../provisioning/entrypoint.sh | 5 + .../provisioning/provision-sample-events.sh | 21 ++-- .../provisioning/refresh-galaxy-files.sh | 26 +++++ 05_world_layer/tests/test_nacre_world.py | 103 ++++++++++++++++++ 7 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 03_container_layer/docker/admin/misp-standalone/provisioning/refresh-galaxy-files.sh diff --git a/.gitignore b/.gitignore index c490a59..558e4fb 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ CLAUDE.md **/CLAUDE.md **/.env !**/.env.example +__pycache__/ +*.py[cod] # operator-provided TLS certs (GITEA_TLS_MODE=provided) — never commit 03_container_layer/docker/admin/gitea-registry/certs/* !03_container_layer/docker/admin/gitea-registry/certs/.gitkeep diff --git a/03_container_layer/docker/admin/misp-standalone/Dockerfile b/03_container_layer/docker/admin/misp-standalone/Dockerfile index 5f4ab09..77c7042 100644 --- a/03_container_layer/docker/admin/misp-standalone/Dockerfile +++ b/03_container_layer/docker/admin/misp-standalone/Dockerfile @@ -92,6 +92,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY --from=builder --chown=www-data:www-data /build/misp /var/www/MISP COPY --from=builder /opt/misp-venv /opt/misp-venv +# Keep an immutable copy outside app/files. The named misp-files volume masks +# app/files at runtime and may contain data copied from an older image, so the +# entrypoint refreshes bundled galaxy definitions from this image-owned source. +COPY --from=builder --chown=www-data:www-data \ + /build/misp/app/files/misp-galaxy /opt/misp-galaxy + # Permissions on the MISP tree are set immediately after the COPY so this # slow layer stays cached even when config or provisioning files change below. # chmod -R on the full submodule tree is unavoidable; no second chown pass. @@ -130,11 +136,13 @@ COPY config/supervisord.conf /etc/supervisor/conf.d/misp.conf COPY provisioning/entrypoint.sh /entrypoint.sh COPY provisioning/configure-misp.sh /provisioning/configure-misp.sh +COPY provisioning/refresh-galaxy-files.sh /provisioning/refresh-galaxy-files.sh COPY provisioning/wait-for-tcp.sh /provisioning/wait-for-tcp.sh RUN chmod +x \ /entrypoint.sh \ /provisioning/configure-misp.sh \ + /provisioning/refresh-galaxy-files.sh \ /provisioning/wait-for-tcp.sh EXPOSE 80 443 diff --git a/03_container_layer/docker/admin/misp-standalone/README.md b/03_container_layer/docker/admin/misp-standalone/README.md index 13144dc..ca93364 100644 --- a/03_container_layer/docker/admin/misp-standalone/README.md +++ b/03_container_layer/docker/admin/misp-standalone/README.md @@ -111,7 +111,7 @@ docker push registry.example.com/range42/misp-standalone:latest | Volume | Contents | |--------|----------| | `db-data` | MariaDB data files | -| `misp-files` | MISP uploaded files | +| `misp-files` | MISP file storage and bundled content definitions | | `misp-attachments` | Event attachments | | `misp-logs` | MISP application logs | | `keys` | Bootstrap auth-key and final `api-keys.txt` | @@ -131,6 +131,13 @@ The bootstrap sentinel `/var/www/MISP/.bootstrapped` prevents re-provisioning on If the container is **recreated** (e.g. after `docker compose up --build`), the sentinel is gone but the DB volume persists — the bootstrap detects the existing schema, skips the seed, and proceeds safely. +On every MISP container start, the image's bundled `misp-galaxy` snapshot is +copied into `misp-files` before bootstrap or normal startup. This refreshes +definitions when an existing named volume survives an image upgrade. The +provisioner also reconciles the two managed sample-event UUIDs through the MISP +edit API, so fixture changes such as new exercise-world tags reach existing lab +databases. + --- ## Troubleshooting diff --git a/03_container_layer/docker/admin/misp-standalone/provisioning/entrypoint.sh b/03_container_layer/docker/admin/misp-standalone/provisioning/entrypoint.sh index e981745..229a59e 100644 --- a/03_container_layer/docker/admin/misp-standalone/provisioning/entrypoint.sh +++ b/03_container_layer/docker/admin/misp-standalone/provisioning/entrypoint.sh @@ -8,6 +8,11 @@ SENTINEL="/keys/.bootstrapped" log() { echo "[entrypoint] $*"; } +# Refresh the image-bundled galaxy definitions before MISP imports them. This +# also upgrades an existing misp-files volume that was initialized by an older +# image and would otherwise mask the newly bundled files. +/provisioning/refresh-galaxy-files.sh + # ── Wait for MariaDB and Redis ──────────────────────────────────────────────── log "Waiting for database (${DB_HOST:-db}:${DB_PORT:-3306}) …" diff --git a/03_container_layer/docker/admin/misp-standalone/provisioning/provision-sample-events.sh b/03_container_layer/docker/admin/misp-standalone/provisioning/provision-sample-events.sh index 68d5988..9071c62 100755 --- a/03_container_layer/docker/admin/misp-standalone/provisioning/provision-sample-events.sh +++ b/03_container_layer/docker/admin/misp-standalone/provisioning/provision-sample-events.sh @@ -1,14 +1,14 @@ #!/usr/bin/env bash # provision-sample-events.sh — imports sample MISP training events. -# Idempotent: checks event UUID before creating; skips if already present. +# Idempotent: creates missing fixtures and reconciles existing fixture UUIDs. # # Add more fixtures by dropping .json files into provisioning/sample-events/. # Each file must contain a top-level "Event" object with a "uuid" field. set -euo pipefail -MISP_URL="https://misp" -ADMIN_KEY_FILE="/keys/admin-authkey" -EVENTS_DIR="/provisioning/sample-events" +MISP_URL="${MISP_URL:-https://misp}" +ADMIN_KEY_FILE="${MISP_ADMIN_KEY_FILE:-/keys/admin-authkey}" +EVENTS_DIR="${MISP_SAMPLE_EVENTS_DIR:-/provisioning/sample-events}" log() { echo "[provision-sample-events] $*" >&2; } @@ -63,19 +63,22 @@ print(ev.get('info', sys.argv[1])) fi if misp_get "/events/view/${event_uuid}" >/dev/null 2>&1; then - log " Already exists (${event_uuid}): ${event_info}" - continue + endpoint="/events/edit/${event_uuid}" + action="Updated" + else + endpoint="/events/add" + action="Created" fi - resp=$(misp_post_file "${fixture}" "/events/add") + resp=$(misp_post_file "${fixture}" "${endpoint}") created_uuid=$(echo "${resp}" | python3 -c " import json, sys d = json.load(sys.stdin) print(d.get('Event', {}).get('uuid', '')) " 2>/dev/null || true) - if [ -n "${created_uuid}" ]; then - log " Created (${created_uuid}): ${event_info}" + if [ "${created_uuid}" = "${event_uuid}" ]; then + log " ${action} (${created_uuid}): ${event_info}" else log " WARNING: unexpected response for ${fixture}: ${resp:0:300}" fi diff --git a/03_container_layer/docker/admin/misp-standalone/provisioning/refresh-galaxy-files.sh b/03_container_layer/docker/admin/misp-standalone/provisioning/refresh-galaxy-files.sh new file mode 100644 index 0000000..4d69241 --- /dev/null +++ b/03_container_layer/docker/admin/misp-standalone/provisioning/refresh-galaxy-files.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Refresh image-bundled MISP galaxy definitions in the persistent app/files +# volume. Docker initializes a new named volume from the image once, but does +# not update an existing volume when a newer image is deployed. +set -euo pipefail + +SEED_DIR="${MISP_GALAXY_SEED_DIR:-/opt/misp-galaxy}" +TARGET_DIR="${MISP_GALAXY_TARGET_DIR:-/var/www/MISP/app/files/misp-galaxy}" +OWNER="${MISP_GALAXY_OWNER-www-data:www-data}" + +log() { echo "[refresh-galaxy-files] $*"; } + +if [ ! -d "${SEED_DIR}/clusters" ] || [ ! -d "${SEED_DIR}/galaxies" ]; then + log "ERROR: bundled galaxy seed is incomplete at ${SEED_DIR}" + exit 1 +fi + +log "Refreshing bundled galaxy definitions in ${TARGET_DIR} …" +mkdir -p "${TARGET_DIR}" +cp -a "${SEED_DIR}/." "${TARGET_DIR}/" + +if [ -n "${OWNER}" ]; then + chown -R "${OWNER}" "${TARGET_DIR}" +fi + +log "Bundled galaxy definitions are current." diff --git a/05_world_layer/tests/test_nacre_world.py b/05_world_layer/tests/test_nacre_world.py index ec27bbb..6f25519 100644 --- a/05_world_layer/tests/test_nacre_world.py +++ b/05_world_layer/tests/test_nacre_world.py @@ -1,7 +1,9 @@ import importlib.util import json +import os import subprocess import sys +import tempfile import unittest from pathlib import Path @@ -91,6 +93,51 @@ def test_misp_build_ties_bundled_world_to_vendored_hashes(self) -> None: version, ) + def test_misp_startup_refreshes_bundled_galaxies_in_persisted_volume(self) -> None: + dockerfile = (MISP_STACK / "Dockerfile").read_text() + entrypoint = (MISP_STACK / "provisioning" / "entrypoint.sh").read_text() + refresher = MISP_STACK / "provisioning" / "refresh-galaxy-files.sh" + + self.assertTrue(refresher.is_file(), "missing persisted-volume galaxy refresher") + self.assertIn("/opt/misp-galaxy", dockerfile) + self.assertIn("/provisioning/refresh-galaxy-files.sh", entrypoint) + self.assertLess( + entrypoint.index("/provisioning/refresh-galaxy-files.sh"), + entrypoint.index("First-boot bootstrap"), + ) + + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + seed = root / "seed" + target = root / "target" + (seed / "clusters").mkdir(parents=True) + (seed / "galaxies").mkdir(parents=True) + (target / "clusters").mkdir(parents=True) + (seed / "clusters" / "exercise-world.json").write_text("new bundled data\n") + (target / "clusters" / "exercise-world.json").write_text("old persisted data\n") + + env = os.environ.copy() + env.update( + { + "MISP_GALAXY_SEED_DIR": str(seed), + "MISP_GALAXY_TARGET_DIR": str(target), + "MISP_GALAXY_OWNER": "", + } + ) + result = subprocess.run( + ["bash", str(refresher)], + cwd=ROOT, + env=env, + capture_output=True, + text=True, + check=False, + ) + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertEqual( + "new bundled data\n", + (target / "clusters" / "exercise-world.json").read_text(), + ) + def test_sample_events_use_canonical_nacre_galaxy_tags(self) -> None: expected_by_file = { "event-01-spearphishing.json": { @@ -112,6 +159,62 @@ def test_sample_events_use_canonical_nacre_galaxy_tags(self) -> None: actual = {tag["name"] for tag in event["Tag"]} self.assertTrue(expected <= actual, f"{filename} missing {sorted(expected - actual)}") + def test_existing_sample_event_is_updated_from_fixture(self) -> None: + provisioner = MISP_STACK / "provisioning" / "provision-sample-events.sh" + + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + bin_dir = root / "bin" + events_dir = root / "events" + bin_dir.mkdir() + events_dir.mkdir() + key_file = root / "admin-authkey" + key_file.write_text("test-key\n") + event_uuid = "c0ffee01-cafe-4bab-b000-000000000001" + (events_dir / "fixture.json").write_text( + json.dumps({"Event": {"uuid": event_uuid, "info": "managed fixture"}}) + ) + curl_log = root / "curl.log" + fake_curl = bin_dir / "curl" + fake_curl.write_text( + "#!/usr/bin/env bash\n" + "printf '%s\\n' \"$*\" >> \"${CURL_LOG}\"\n" + "url=\"${!#}\"\n" + "case \"${url}\" in\n" + " */events/view/*) printf '%s\\n' '{\"Event\":{\"uuid\":\"" + + event_uuid + + "\"}}' ;;\n" + " */events/edit/*) printf '%s\\n' '{\"Event\":{\"uuid\":\"" + + event_uuid + + "\"}}' ;;\n" + " *) printf '%s\\n' '{}' ;;\n" + "esac\n" + ) + fake_curl.chmod(0o755) + + env = os.environ.copy() + env.update( + { + "PATH": f"{bin_dir}:{env['PATH']}", + "CURL_LOG": str(curl_log), + "MISP_ADMIN_KEY_FILE": str(key_file), + "MISP_SAMPLE_EVENTS_DIR": str(events_dir), + } + ) + result = subprocess.run( + ["bash", str(provisioner)], + cwd=ROOT, + env=env, + capture_output=True, + text=True, + check=False, + ) + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + requests = curl_log.read_text() + self.assertIn(f"/events/edit/{event_uuid}", requests) + self.assertNotIn("/events/add", requests) + self.assertIn("Updated", result.stderr) + def test_provisioner_verifies_nacre_before_importing_events(self) -> None: provisioning = MISP_STACK / "provisioning" verifier = provisioning / "verify-exercise-world.py"