Skip to content

Latest commit

 

History

History
865 lines (623 loc) · 35.6 KB

File metadata and controls

865 lines (623 loc) · 35.6 KB

Wardex Foundry — Project Specification

Version: 0.1.0-draft
Status: Pre-implementation
Maintainer: @had-nu
Related project: Wardex


Table of Contents

  1. Vision & Positioning
  2. Architecture
  3. Threat Model
  4. Scenario Catalogue
  5. Wardex Integration Spec
  6. Observability & Audit Evidence
  7. Gitflow & Branching Strategy
  8. Documentation Strategy
  9. Contributing Guidelines
  10. License Analysis
  11. Roadmap & Milestones

1. Vision & Positioning

1.1 What Is This

Wardex Foundry is a deliberately configurable lab environment designed for IT Risk analysts, GRC practitioners, and security consultants to practise risk identification, control validation, and release-gate decision-making in a reproducible, self-hosted environment.

It is the operational counterpart to Wardex: while Wardex provides the risk-driven release-gate engine, this lab provides the environment that Wardex governs.

1.2 The Problem It Solves

Platforms like HackTheBox and TryHackMe serve offensive security practitioners — they provide vulnerable environments to practise attack techniques. No equivalent exists for defensive risk practitioners:

  • There is no hands-on environment to practise identifying misconfigured broker authentication
  • There is no reproducible lab to practise collecting audit evidence of access violations
  • There is no scenario-based environment to validate that a release gate correctly blocks a deployment when specific controls are absent

Wardex Foundry fills this gap.

1.3 Target Audience

Persona Use Case
IT Risk Analyst (junior–mid) Practise identifying control gaps in messaging and secrets infrastructure
GRC Consultant Generate reproducible audit evidence for self-assessment exercises
Security Engineer Validate that release-gate policies correctly gate on real misconfiguration
Hiring Manager / Evaluator Assess a candidate's security posture reasoning, not just their tooling knowledge

1.4 What Differentiates This From a Tutorial

Most infrastructure repositories are installation guides. This lab is different in three ways:

  1. Every component has two states: a deliberately weakened v1 (with documented risks) and a hardened v2 (with documented mitigations). The transition between them is the learning exercise.
  2. Risk is documented before code is written: each scenario begins with a threat model entry, not a docker-compose block.
  3. The Wardex gate is a first-class actor: the CI pipeline fails or passes based on Wardex's assessment of the environment, making the risk decision traceable and reproducible.

1.5 Learning Objectives

After completing the lab, a practitioner can demonstrate:

  • Identification of authentication and encryption gaps in a Kafka broker
  • Identification of hardcoded credential patterns and their remediation via Vault
  • Collection of audit-grade evidence (log excerpts, metric screenshots, gate decisions) proving control effectiveness
  • Articulation of residual risk in a hardened environment
  • Operation of a risk-driven release gate policy in a CI context

2. Architecture

2.1 Component Overview

The lab comprises four components, selected for relevance to financial infrastructure and demonstrable risk surface:

Component Role Risk Domain
Kafka (Bitnami) Message broker Authentication, encryption-in-transit
HashiCorp Vault Secrets management Credential exposure, secrets lifecycle
Prometheus + Grafana Observability Audit trail, access violation detection
Vexil (CI/Subprocess) Secrets & Policy scanner Hardcoded credentials, configuration drift
Trivy (CI - Optional) Container vulnerability scanner Supply chain, CVE gate

2.2 C4 Context Diagram

C4Context
    title Wardex Foundry — System Context

    Person(analyst, "Risk Analyst", "Practises control validation and risk identification via Web Dashboard")
    Person(evaluator, "Portfolio Evaluator", "Reviews lab design and evidence artefacts")

    System(lab, "Wardex Foundry Platform", "Locally-hosted web platform to orchestrate vulnerable/hardened environments and audit tools")
    System_Ext(wardex, "Wardex Engine", "Risk-driven release gate engine")
    System_Ext(vexil, "Vexil (Subprocess)", "Secrets and configuration scanner")

    Rel(analyst, lab, "Starts scenarios, views real-time logs, collects evidence", "HTTP")
    Rel(evaluator, lab, "Reviews architecture, threat model, audit logs")
    Rel(lab, vexil, "Executes secrets scans on scenario configs")
    Rel(lab, wardex, "Submits scan results, receives gate decision")
Loading

2.3 C4 Container Diagram

C4Container
    title Wardex Foundry — Container View

    Container(ui, "Web Dashboard", "HTMX / Tailwind", "Analyst interface for scenario management and evidence review")
    Container(backend, "Go Backend", "Go 1.26.1", "Orchestrates Docker SDK, streams SSE logs, triggers scans")
    
    Container(kafka, "Kafka Broker", "Bitnami Kafka", "Message streaming. Configurable: SASL off/on, TLS off/on")
    Container(vault, "HashiCorp Vault", "Vault OSS", "Secrets storage. Configurable: dev mode / production mode with TLS")
    Container(prometheus, "Prometheus", "prom/prometheus", "Metrics collection from Kafka and Vault")
    Container(grafana, "Grafana", "grafana/grafana", "Audit dashboards, access violation alerts")
    
    Rel(ui, backend, "Commands and log streams", "API / SSE")
    Rel(backend, kafka, "Orchestrates lifecycle", "Docker Socket")
    Rel(backend, vault, "Orchestrates lifecycle", "Docker Socket")

    Rel(prometheus, kafka, "Scrapes JMX metrics", "HTTP /metrics")
    Rel(prometheus, vault, "Scrapes Vault telemetry", "HTTP /v1/sys/metrics")
    Rel(grafana, prometheus, "Queries metrics", "PromQL")
Loading

2.4 C4 Component Diagram — Kafka

C4Component
    title Kafka — Internal Components (Security Focus)

    Component(listener, "Listener", "PLAINTEXT or SSL", "Controls transport encryption. v1: PLAINTEXT. v2: SSL/TLS")
    Component(sasl, "SASL Mechanism", "NONE or SCRAM-SHA-512", "Controls broker authentication. v1: disabled. v2: SCRAM-SHA-512")
    Component(acl, "ACL Authoriser", "AclAuthorizer", "Controls topic-level access. v1: absent. v2: enforced")
    Component(jmx, "JMX Exporter", "prometheus/jmx_exporter", "Exposes metrics including failed authentication attempts")

    Rel(listener, sasl, "Authenticates after handshake")
    Rel(sasl, acl, "Passes identity for authorisation")
    Rel(jmx, listener, "Monitors connection events")
Loading

2.5 Network Topology

graph TD
    subgraph lab-network [Docker Bridge: lab-net]
        kafka[Kafka :9092 / :9093]
        vault[Vault :8200]
        prometheus[Prometheus :9090]
        grafana[Grafana :3000]
    end

    subgraph platform [Wardex Foundry]
        ui[Web UI]
        backend[Go Backend]
        vexil[Vexil Subprocess]
        wardex[Wardex Engine]
    end

    analyst[Analyst Browser] -->|HTTP :8080| ui
    ui <-->|HTMX / SSE| backend
    backend -->|Docker SDK| lab-network
    backend -->|Executes Scan| vexil
    vexil -->|Results| wardex
    wardex -->|ReleaseDecision| backend
    
    prometheus --> kafka
    prometheus --> vault
    grafana --> prometheus
Loading

3. Threat Model

3.1 Methodology

STRIDE is applied to each component in its v1 (vulnerable) state. The threat model documents what is deliberately exposed and why. This is the analytical artefact that separates this lab from a tutorial.

Reference controls are mapped to ISO/IEC 27001:2022 Annex A where applicable — relevant for practitioners operating in regulated financial environments (e.g., Euronext, EBA, DORA).

3.2 STRIDE Matrix — Kafka (v1)

Threat Category Description ISO 27001 Control Mitigated in v2?
Unauthenticated producer Spoofing Any client can publish to any topic without credentials A.8.3 — Information access restriction ✅ SASL/SCRAM-SHA-512
Plaintext message interception Information Disclosure PLAINTEXT listener allows passive network capture of all messages A.8.24 — Use of cryptography ✅ TLS listener on :9093
Unrestricted topic consumption Elevation of Privilege Any consumer can subscribe to any topic without ACL A.8.3 — Information access restriction ✅ AclAuthorizer enforced
No authentication audit trail Non-Repudiation Failed auth attempts not logged or exported A.8.15 — Logging ✅ JMX exporter + Prometheus
Image with known CVEs Tampering Unscanned base image may contain exploitable packages A.8.8 — Management of technical vulnerabilities ✅ Trivy in CI

3.3 STRIDE Matrix — Vault (v1)

Threat Category Description ISO 27001 Control Mitigated in v2?
Dev mode with root token Spoofing Vault dev mode exposes a static root token, defeating auth entirely A.8.5 — Secure authentication ✅ Production mode + AppRole
Secrets in environment variables Information Disclosure docker-compose exposes credentials in env vars readable by any process in container A.8.13 — Information backup / A.8.12 — Data leakage prevention ✅ Vault dynamic secrets
Unsealed Vault with no TLS Information Disclosure API traffic to Vault unencrypted; token interception possible A.8.24 — Use of cryptography ✅ TLS on :8200
No audit device enabled Non-Repudiation Vault operations not logged; no trail of secret access A.8.15 — Logging ✅ File audit device enabled

3.4 Residual Risks (v2 — Hardened)

Even in the hardened configuration, the following residual risks are documented and accepted for lab scope:

Risk Reason Accepted Compensating Control
Self-signed TLS certificates Lab scope; no PKI infrastructure Certificate pinning in client configuration
Single-node Kafka No HA; availability risk Out of scope for risk lab (focus is confidentiality/integrity)
Vault unsealing via environment Auto-unseal not configured Documented as gap; Vault Shamir unseal is manual in lab
Grafana with default admin password Lab convenience Network isolation; not exposed externally

4. Scenario Catalogue

Each scenario is a standalone directory under /scenarios/ containing its own README.md, docker-compose.yml (v1), and reference to the hardened equivalent in /hardened/.

4.1 Scenario 01 — Plaintext Credentials

Directory: /scenarios/01-plaintext-credentials/
Risk Category: Information Disclosure / Spoofing
CVSS (contextual): High — credentials transmitted in plaintext over network

Description: Kafka broker accepts PLAINTEXT connections with no authentication. Vault runs in dev mode with a static root token exposed as an environment variable in docker-compose.yml.

How to reproduce:

# Start v1 environment
docker compose -f scenarios/01-plaintext-credentials/docker-compose.yml up -d

# Capture broker traffic (demonstrates plaintext)
tcpdump -i any -A port 9092 | grep -i "password\|token"

# Inspect environment variables leaking credentials
docker inspect kafka | jq '.[0].Config.Env'

Expected evidence: Network capture shows credentials in clear text. docker inspect reveals KAFKA_PASSWORD=changeme in environment.

Wardex gate behaviour (v1): BLOCK. Policy no-plaintext-brokers evaluates TLS_ENABLED=falseReleaseDecision: blocked.

Mitigation (v2): TLS listener on :9093, credentials sourced from Vault via AppRole, no secrets in environment variables.


4.2 Scenario 02 — Unauthenticated Broker

Directory: /scenarios/02-unauthenticated-broker/
Risk Category: Spoofing / Elevation of Privilege
CVSS (contextual): High — any client can produce/consume any topic

Description: Kafka broker has no SASL mechanism configured and no ACL authoriser. Any client on the network can publish to or consume from any topic without presenting credentials.

How to reproduce:

# Start v1 environment
docker compose -f scenarios/02-unauthenticated-broker/docker-compose.yml up -d

# Produce to sensitive topic without credentials
kafka-console-producer --broker-list localhost:9092 --topic financial-transactions

# Consume without credentials
kafka-console-consumer --bootstrap-server localhost:9092 --topic financial-transactions --from-beginning

Expected evidence: Both operations succeed without any authentication prompt. Prometheus metric kafka_server_socket_server_metrics_failed_authentication_total remains at zero (no auth attempted, so no failure recorded — absence of the metric is itself the finding).

Wardex gate behaviour (v1): BLOCK. Policy require-sasl-auth evaluates SASL_ENABLED=falseReleaseDecision: blocked.

Mitigation (v2): SASL/SCRAM-SHA-512 enabled; AclAuthorizer enforced; credentials stored in Vault.


4.3 Scenario 03 — No Audit Trail

Directory: /scenarios/03-no-audit-trail/
Risk Category: Non-Repudiation
CVSS (contextual): Medium — operations cannot be attributed or detected

Description: Neither Kafka nor Vault have audit logging configured. Failed authentication attempts on Kafka are not exported to Prometheus. Vault's audit device is disabled. An attacker can attempt credential stuffing or unauthorised secret access with no detectable trace.

How to reproduce:

# Start v1 environment
docker compose -f scenarios/03-no-audit-trail/docker-compose.yml up -d

# Attempt failed authentication on Kafka (wrong password)
kafka-console-producer --broker-list localhost:9092 \
  --producer-property security.protocol=SASL_PLAINTEXT \
  --producer-property sasl.mechanism=PLAIN \
  --producer-property 'sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username="attacker" password="wrongpassword";'

# Verify: no evidence in Prometheus
curl -s http://localhost:9090/api/v1/query?query=kafka_server_socket_server_metrics_failed_authentication_total
# Expected: empty result set

Expected evidence: No metrics, no logs, no alert. The failed attempt is invisible.

Wardex gate behaviour (v1): BLOCK. Policy require-audit-trail checks Prometheus scrape targets and Vault audit device status → ReleaseDecision: blocked.

Mitigation (v2): JMX exporter enabled on Kafka; Vault file audit device configured; Grafana dashboard with alert rule on failed_authentication_total > 0.


4.4 Scenario 04 — Exposed Secrets in Compose

Directory: /scenarios/04-exposed-secrets/
Risk Category: Information Disclosure
CVSS (contextual): Critical — infrastructure credentials committed to source/orchestration templates

Description: The docker-compose.yml file contains hardcoded passwords, API keys, or root tokens as environment variables. This represents a mature supply-chain risk where infrastructure-as-code exposes secrets.

How to reproduce:

# Scan the v1 compose file with Vexil
vexil scan -t compile scenarios/04-exposed-secrets/docker-compose.yml

Expected evidence: Vexil reports high-confidence matches for VAULT_DEV_ROOT_TOKEN_ID and KAFKA_PASSWORD in the plaintext YML hierarchy.

Wardex gate behaviour (v1): BLOCK. Policy no-exposed-secrets evaluates the JSON output of Vexil. max_confidence: HIGH threshold is breached → ReleaseDecision: blocked.

Mitigation (v2): Secrets removed from environment blocks. Vault agent injector or manual volume mounts used to deliver secrets at runtime. Vexil scan returns 0 findings.


5. Wardex Integration Spec

5.1 Vexil Integration

Wardex Foundry natively integrates with Vexil to detect hardcoded secrets and configuration drift before evaluating release gates.

  1. Subprocess execution: The Go backend invokes the vexil binary against the active scenario's docker-compose.yml and environment files.
  2. Contract: Vexil produces a vexil-results.json artifact containing identified secrets and their confidence levels.
  3. Gate Policy: Wardex consumes this JSON and evaluates the no-exposed-secrets rule against it, blocking the release if high-confidence secrets are found.

5.2 Contract

Wardex consumes a release-policy.yaml file that defines the conditions under which a release is blocked or permitted. This file lives in /wardex-integration/ and is the bridge between the lab environment and the gate engine.

5.3 Policy File Schema

# wardex-integration/release-policy.yaml
apiVersion: wardex/v1
kind: ReleasePolicy
metadata:
  name: lab-baseline-policy
  description: Baseline security controls required before any lab component is considered release-ready
  version: "1.0.0"

gates:
  - id: no-plaintext-brokers
    description: Kafka must not expose a PLAINTEXT listener
    check:
      type: env_var
      target: kafka
      key: KAFKA_CFG_LISTENERS
      must_not_contain: "PLAINTEXT://"
    on_fail: block
    risk_level: high

  - id: require-sasl-auth
    description: Kafka must have SASL mechanism configured
    check:
      type: env_var
      target: kafka
      key: KAFKA_CFG_SASL_ENABLED_MECHANISMS
      must_not_be_empty: true
    on_fail: block
    risk_level: high

  - id: no-vault-dev-mode
    description: Vault must not run in dev mode
    check:
      type: env_var
      target: vault
      key: VAULT_DEV_ROOT_TOKEN_ID
      must_be_absent: true
    on_fail: block
    risk_level: critical

  - id: require-audit-trail
    description: Vault audit device must be enabled
    check:
      type: vault_api
      endpoint: /v1/sys/audit
      must_have_keys: ["file/"]
    on_fail: block
    risk_level: high

  - id: no-exposed-secrets
    description: No hardcoded credentials in environment configurations (Vexil)
    check:
      type: vexil_report
      path: vexil-results.json
      max_confidence: HIGH # Block on high confidence secrets only
    on_fail: block
    risk_level: critical

5.4 CI Integration (GitHub Actions)

# .github/workflows/wardex-gate.yml
name: Wardex Risk Gate

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Scan environment configs for secrets
        uses: had-nu/vexil-action@v1
        with:
          target: './scenarios'
          format: json
          output: vexil-results.json

      - name: Run Wardex gate
        run: |
          wardex evaluate \
            --policy wardex-integration/release-policy.yaml \
            --vexil-report vexil-results.json \
            --compose hardened/docker-compose.yml

5.5 ReleaseDecision Output

The Wardex gate produces a ReleaseDecision record for each evaluation. This is the audit artefact that proves the gate operated.

{
  "id": "rd-20250308-001",
  "policy_version": "1.0.0",
  "evaluated_at": "2025-03-08T14:32:00Z",
  "decision": "blocked",
  "gates_evaluated": 5,
  "gates_passed": 3,
  "gates_failed": [
    {
      "id": "no-vault-dev-mode",
      "reason": "VAULT_DEV_ROOT_TOKEN_ID is present",
      "risk_level": "critical"
    },
    {
      "id": "require-audit-trail",
      "reason": "No audit devices found at /v1/sys/audit",
      "risk_level": "high"
    }
  ],
  "residual_risk_accepted_by": null,
  "notes": "Environment matches Scenario 03 (no-audit-trail) v1 configuration"
}

6. Observability & Audit Evidence

6.1 Prometheus Scrape Targets

# infrastructure/prometheus/prometheus.yml
scrape_configs:
  - job_name: kafka
    static_configs:
      - targets: ["kafka:9101"]  # JMX exporter
    metrics_path: /metrics

  - job_name: vault
    static_configs:
      - targets: ["vault:8200"]
    metrics_path: /v1/sys/metrics
    params:
      format: ["prometheus"]
    bearer_token_file: /etc/prometheus/vault-token

6.2 Key Metrics for Audit Dashboards

Metric Source Audit Purpose
kafka_server_socket_server_metrics_failed_authentication_total Kafka JMX Detect credential stuffing / unauthorised access attempts
kafka_network_requestmetrics_errors_total Kafka JMX Detect malformed/unauthorised requests
vault_audit_log_response_count Vault telemetry Confirm audit device is active and receiving writes
vault_token_lookup Vault telemetry Track token usage patterns
vault_secret_kv_count Vault telemetry Monitor secrets inventory changes

6.3 Grafana Dashboard Structure

The lab ships with a pre-built Grafana dashboard (infrastructure/grafana/dashboards/lab-audit.json) containing:

  • Row 1 — Authentication Events: Failed auth attempts over time (Kafka + Vault), with threshold alert at >0
  • Row 2 — Secrets Access: Vault secret reads/writes per minute, token lifecycle events
  • Row 3 — System Integrity: Container uptime, JMX exporter health, audit device write latency
  • Row 4 — Wardex Gate History: Table of recent ReleaseDecision outcomes (sourced from Wardex API)

6.4 Reproducible Audit Evidence

For each scenario, the lab provides a collect-evidence.sh script that:

  1. Exports Prometheus metrics snapshot to /evidence/metrics-$(date +%Y%m%d).json
  2. Exports Grafana dashboard screenshot (headless) to /evidence/dashboard-$(date +%Y%m%d).png
  3. Exports Wardex ReleaseDecision to /evidence/gate-decision-$(date +%Y%m%d).json
  4. Bundles all three into a timestamped .tar.gz for submission or portfolio inclusion

7. Gitflow & Branching Strategy

7.1 Branch Model

This project follows a simplified Gitflow adapted for a single-maintainer open-source lab:

main          ← stable, tagged releases only
develop       ← integration branch, always deployable
feature/*     ← new scenarios, components, or integrations
fix/*         ← bug fixes on existing scenarios or infrastructure
docs/*        ← documentation-only changes (no infra impact)
chore/*       ← dependency updates, CI changes, tooling

7.2 Conventional Commits

All commits must follow Conventional Commits v1.0.0:

<type>(<scope>): <description>

[optional body]

[optional footer: BREAKING CHANGE, Closes #issue]

Types:

Type Use
feat New scenario, new component, new Wardex gate rule
fix Corrected scenario configuration, broken compose, incorrect threat model
docs README, SPEC, scenario write-ups, contributing guide
chore Dependency bumps, CI config, .gitignore
test Evidence collection scripts, scenario validation scripts
security Hardening changes, CVE mitigations (non-breaking)
refactor Infrastructure reorganisation without behaviour change

Examples:

feat(scenario): add unauthenticated-broker scenario with v1 compose and STRIDE entry
fix(kafka): correct JMX exporter port mapping in hardened compose
docs(spec): add residual risk table to threat model section
security(vault): enable TLS on Vault listener in hardened configuration
chore(ci): update Trivy action to v0.18.0

7.3 Versioning

Semantic versioning (MAJOR.MINOR.PATCH) applied to tagged releases on main:

  • MAJOR: Breaking change to Wardex policy contract or scenario directory structure
  • MINOR: New scenario added or new component integrated
  • PATCH: Fix to existing scenario, documentation correction, dependency update

7.4 Pull Request Rules

All PRs targeting develop or main must:

  1. Pass GitHub Actions CI (Vexil scan + Wardex gate on hardened compose)
  2. Include an update to the relevant scenario README.md if infrastructure changes
  3. Include a CHANGELOG.md entry following Keep a Changelog format
  4. Be reviewed by at least one maintainer (self-review acceptable for docs PRs)

7.5 Git Hooks

# Install hooks
./scripts/hooks/install-hooks.sh
Hook Purpose
commit-msg Validates Conventional Commits format
pre-commit Runs docker compose config --quiet on changed compose files
pre-push Runs Vexil scan on targeted environments before push to CI

8. Documentation Strategy

8.1 Documentation Taxonomy

Document Location Audience Update Trigger
SPEC.md (this file) / Maintainers, evaluators Architecture changes, new components
README.md / All — first contact Every release
Scenario README.md /scenarios/<name>/ Practitioners Scenario content changes
CHANGELOG.md / All Every PR merged to develop
CONTRIBUTING.md / Contributors Process changes
SECURITY.md / Security reporters Policy changes
Grafana dashboards /infrastructure/grafana/ Operators Metric changes

8.2 Documentation Update Policy

Documentation is treated as a first-class deliverable, not an afterthought. The following rules apply:

A PR that changes infrastructure without updating documentation will not be merged.

Specifically:

  • Adding or modifying a scenario requires updating that scenario's README.md and the threat model table in SPEC.md
  • Adding a new component requires updating the C4 diagrams in SPEC.md and the architecture section of README.md
  • Changing the Wardex policy contract requires updating Section 5 of SPEC.md and the integration example in README.md
  • Changing the branching model or commit format requires updating Section 7 of SPEC.md and CONTRIBUTING.md

8.3 Diagram Maintenance

All diagrams are written in Mermaid and live in SPEC.md and README.md. They are version-controlled alongside the code they describe.

Rule: If a compose file changes network topology, the corresponding Mermaid diagram must be updated in the same commit.

Mermaid renders natively in GitHub. No external diagram tool dependencies.

8.4 Scenario Documentation Template

Each scenario's README.md follows this structure:

# Scenario NN — <Name>

## Risk Summary
| Field | Value |
|---|---|
| Category | STRIDE category |
| Severity | Critical / High / Medium |
| ISO 27001 Control | A.X.Y — Control name |
| Mitigated in v2 | Yes / Partially / No |

## What You Will Learn
- ...

## Prerequisites
- ...

## Step-by-Step
### 1. Deploy v1 (Vulnerable)
### 2. Reproduce the Finding
### 3. Collect Evidence
### 4. Deploy v2 (Hardened)
### 5. Verify Mitigation

## Wardex Gate Behaviour
| Configuration | Gate Decision | Reason |
|---|---|---|
| v1 | BLOCK | ... |
| v2 | PASS | ... |

## Residual Risk
...

8.5 CHANGELOG Format

## [1.1.0] - 2025-04-01

### Added
- Scenario 02: Unauthenticated Broker with SASL/SCRAM mitigation
- Grafana alert rule for failed_authentication_total

### Changed
- Kafka base image updated to Bitnami 3.7.x

### Fixed
- JMX exporter port conflict with Prometheus on default bridge network

### Security
- Trivy baseline updated; 3 HIGH CVEs resolved by image update

9. Contributing Guidelines

The full CONTRIBUTING.md is generated from this section and lives at the repository root.

9.1 Philosophy

Wardex Foundry welcomes contributions that deepen the risk analysis dimension of the lab. Contributions that add tooling complexity without adding a corresponding risk narrative are out of scope.

A good contribution answers at least one of these questions:

  • What new risk can a practitioner identify with this change?
  • What new evidence can a practitioner collect?
  • What new control can the Wardex gate validate?

9.2 Types of Accepted Contributions

Type Welcome? Notes
New scenario (v1 + v2 + threat model entry) ✅ Yes Must follow scenario template
New Wardex gate rule ✅ Yes Must include test case
Improved audit evidence scripts ✅ Yes Must be POSIX-compatible
Documentation corrections ✅ Yes Docs PR; no CI gate required
New component (e.g., Elasticsearch, Redis) ⚠️ Discuss first Open an issue before implementing
Tutorial-style how-to guides ❌ No Out of scope; refer to scenario template
Replacing existing components with alternatives ❌ No Stability of the lab environment is a priority

9.3 Contribution Workflow

1. Fork the repository
2. Create a branch: git checkout -b feat/scenario-04-no-tls-vault
3. Make changes following the scenario template
4. Run pre-commit hooks: ./scripts/hooks/install-hooks.sh
5. Commit with Conventional Commits format
6. Open a PR targeting `develop`
7. Fill in the PR template (scenario description, threat model entry, evidence screenshot)
8. Wait for CI and maintainer review

9.4 Reporting Security Issues

Do not open a public GitHub issue for security vulnerabilities.

This is a security lab — it intentionally contains vulnerable configurations. If you discover an unintentional vulnerability in the lab's own infrastructure (e.g., the CI pipeline, the evidence collection scripts), report it via email to the maintainer with subject line [SECURITY] Wardex Foundry.

See SECURITY.md for the full responsible disclosure policy.

9.5 Code of Conduct

This project follows the Contributor Covenant v2.1. All contributors are expected to uphold its standards.


10. License Analysis

10.1 EU Regulatory Context

This project operates in a European Union context and is intended as a portfolio piece for engagements in regulated financial infrastructure (Euronext, EBA-supervised entities, DORA-regulated firms). License selection must account for:

Regulation Relevance
DORA (Digital Operational Resilience Act) Applies to financial entities and their ICT third-party providers. Open-source tools used in financial infrastructure may fall under ICT risk management obligations.
NIS2 Directive Requires adequate cybersecurity measures for operators of essential services. Open-source components used in critical infrastructure must be maintainable and auditable.
Cyber Resilience Act (CRA) Applies to products with digital elements placed on the EU market. Open-source software distributed "in the course of commercial activity" may fall under CRA obligations.
GDPR Relevant if the lab processes any personal data (it does not, by design).

10.2 License Options Evaluated

License Type Patent Grant CRA Impact EU Compatibility Verdict
MIT Permissive ❌ None Low — hobbyist/non-commercial framing available ✅ Full Simple, but no patent protection
Apache 2.0 Permissive ✅ Explicit Low — same CRA framing available ✅ Full Recommended for tools with commercial derivative potential
EUPL v1.2 Weak copyleft ✅ Implicit Low — developed by EU institutions ✅ Full EU-native; copyleft means derivatives must share source
GPL v3 Strong copyleft ✅ Implicit Low ✅ Full Viral; may deter enterprise adoption
AGPL v3 Network copyleft ✅ Implicit Low ✅ Full Strongest copyleft; SaaS derivatives must publish source
BSL 1.1 Source-available ❌ None Not applicable ⚠️ Not OSI-approved Inappropriate for this project

10.3 Recommendation

Apache License 2.0 is recommended for Wardex Foundry for the following reasons:

  1. Patent protection: The explicit patent grant protects contributors and downstream users from patent claims, relevant in a commercial financial context.
  2. CRA compatibility: Apache 2.0 software distributed non-commercially (as a portfolio/educational project) falls within CRA's open-source steward exemption as currently interpreted.
  3. DORA compatibility: Permissive license allows financial entities to use, audit, and modify the lab without copyleft obligations — reducing adoption friction.
  4. Consistency with ecosystem: Kafka (Apache), Vault (BSL with Apache history), Prometheus (Apache), and Grafana (AGPL) — Apache 2.0 is the natural licence for a project in this ecosystem.
  5. Portfolio signal: Apache 2.0 signals awareness of IP considerations and commercial-readiness without the complexity of copyleft management.

10.4 Dependency License Audit

Dependency License Copyleft Risk Notes
Bitnami Kafka Apache 2.0 None Bitnami packaging is Apache 2.0
HashiCorp Vault OSS BSL 1.1 ⚠️ Post-2023 BSL restricts competing SaaS use; lab use is compliant
Prometheus Apache 2.0 None
Grafana OSS AGPL v3 ⚠️ Network copyleft Grafana usage does not require publishing lab source under AGPL; only modifications to Grafana itself do
Trivy Apache 2.0 None

Vault BSL 1.1 note: HashiCorp changed Vault's license from MPL 2.0 to BSL 1.1 in August 2023. The BSL restricts use "in a competitive offering". A portfolio lab is not a competitive offering. If this is a concern, OpenBao (MPL 2.0 fork) is a drop-in alternative.

10.5 License File

The repository includes a LICENSE file at the root containing the full Apache 2.0 license text, and a NOTICE file listing all third-party dependencies and their respective licenses per Apache 2.0 requirements.


11. Roadmap & Milestones

Phase 0 — Specification (Current)

Goal: Define the full scope before writing infrastructure code.

Deliverables:

  • SPEC.md (this document)
  • README.md skeleton with positioning statement
  • CONTRIBUTING.md generated from Section 9
  • LICENSE and NOTICE files
  • Repository structure created on GitHub

Completion criteria: Repository is publicly visible with spec, licence, and contributing guide in place.


Phase 1 — Skeleton

Goal: All four components running, no security configuration applied (pure v1 state).

Deliverables:

  • /infrastructure/docker-compose.yml with all components
  • Prometheus scraping Kafka JMX and Vault telemetry
  • Grafana accessible with blank dashboard
  • GitHub Actions workflow running Trivy (expected: failures)
  • Wardex gate running (expected: all gates BLOCK)

Completion criteria: docker compose up brings all services healthy. Wardex evaluates and produces a ReleaseDecision: blocked with all gates failing.


Phase 2 — Scenarios

Goal: Three v1 scenarios documented and reproducible, each with evidence collection.

Deliverables:

  • Scenario 01: Plaintext Credentials — compose, README.md, evidence script
  • Scenario 02: Unauthenticated Broker — compose, README.md, evidence script
  • Scenario 03: No Audit Trail — compose, README.md, evidence script
  • Threat model complete in SPEC.md
  • Evidence collection producing timestamped bundles

Completion criteria: A practitioner can follow any scenario README from zero to collected evidence without external documentation.


Phase 3 — Hardened

Goal: All controls applied in hardened compose; Wardex gate passes; dashboards show audit trail.

Deliverables:

  • /hardened/docker-compose.yml — TLS, SASL, Vault production mode, audit device
  • Wardex gate: all five policies passing → ReleaseDecision: approved
  • Grafana dashboard: Lab Audit v1.0 with alert rules
  • CI badge on README showing gate status
  • CHANGELOG v1.0.0 entry

Completion criteria: wardex evaluate on hardened compose produces decision: approved. CI is green. Grafana shows live metrics from all components.


Specification maintained by @had-nu. Open an issue before proposing changes to Sections 2, 3, or 5.