Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
3c37982
Update develop branch (#23)
tobmes42 Jul 13, 2026
f468645
feat(asset-type): enhance asset icon management with existing icon se…
tobmes42 Jul 8, 2026
2a8ae7b
feat(asset-type): initialize asset icon selection in form submission
tobmes42 Jul 8, 2026
8c1f9ef
feat(asset-type): implement icon selection for asset types in modal
tobmes42 Jul 8, 2026
d88e9be
feat(asset-type): sort graph icons by name in asset management
tobmes42 Jul 8, 2026
7badcd3
feat(asset-type): add option to use the same icon for compromised assets
tobmes42 Jul 8, 2026
4a7c680
feat(asset-type): update checkbox layout for using the same icon for …
tobmes42 Jul 9, 2026
f1fedc3
fix(asset-type): handle invalid file storage in asset icon upload
tobmes42 Jul 9, 2026
51273a1
feat(asset-type): enhance icon listing to support custom uploaded icons
tobmes42 Jul 9, 2026
5ae89ea
feat(icon-storage): preserve original filename for uploaded icons and…
tobmes42 Jul 9, 2026
86f6fe2
feat(icon-validation): add validation for icon file content based on …
tobmes42 Jul 9, 2026
b47dcbb
feat(asset-icon): handle missing icons by providing default placeholders
tobmes42 Jul 10, 2026
3b40561
feat(asset-type): add validation for compromised icon selection in as…
tobmes42 Jul 10, 2026
9230a5a
feat(asset-type): improve validation for asset icon selection in form…
tobmes42 Jul 10, 2026
27a5877
feat(asset-icon): enhance validation for asset icon selection in form…
tobmes42 Jul 10, 2026
a8bafdc
refactor(asset-icon): remove redundant icon resolution for asset crea…
tobmes42 Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .env.model
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
# -- COMMON
LOG_LEVEL=info

# -- HOSTNAME (single source of truth)
# When set, IRIS_HOSTNAME provides fallback defaults for SERVER_NAME
# (nginx), PUBLIC_EXTERNAL_API_URL / ORIGIN (SvelteKit), and
# VITE_ALLOWED_HOSTS (Vite dev). Explicit values still take precedence
# for split-hostname deployments (e.g. API on a different host than UI).
# Existing .env files that set the four vars individually keep working.
#IRIS_HOSTNAME=iris.app.dev

# -- NGINX
NGINX_IMAGE_NAME=ghcr.io/dfir-iris/iriswebapp_nginx

SERVER_NAME=iris.app.dev
# When both KEY_FILENAME and CERT_FILENAME are unset AND certbot's
# standard fullchain.pem + privkey.pem pair exist under
# ./certificates/web_certificates/, the nginx entrypoint autodetects
# them — useful for Let's Encrypt setups. See
# scripts/certbot-deploy-hook.sh for zero-copy renewals.
KEY_FILENAME=iris_dev_key.pem
CERT_FILENAME=iris_dev_cert.pem

# Nginx polls the cert file's mtime every N seconds and reloads on
# change so certbot renewals apply without a container restart. Set
# to 0 to disable if your deployment reloads nginx externally.
#IRIS_CERT_RELOAD_INTERVAL=60

# -- DATABASE
DB_IMAGE_NAME=ghcr.io/dfir-iris/iriswebapp_db

Expand Down Expand Up @@ -88,6 +106,23 @@ IRIS_AUTHENTICATION_TYPE=local
# optional mapping for usergroup-names
# OIDC_MAPPING_USERGROUP= "iris-roles" #Group field in OIDC Token
# OIDC_MAPPING_ROLES= '{"iris-admin": "1", "iris-analyst": "2"}'
# -- CUSTOM CA CERTIFICATES (Keycloak, LDAPS, webhooks, ...)
# The recommended way to trust internal CAs is to drop one or more
# *.crt / *.pem files into ./certificates/ca-bundle/ on the host —
# they are mounted at /etc/iris-ca/ inside the app and worker
# containers, and the entrypoint installs them into the OS trust
# store (update-ca-certificates) on every boot. This is ADDITIVE:
# system roots stay trusted, so no manual concatenation is needed.
#
# The legacy single-file bundle at
# ./certificates/ca-bundle/extra-ca.crt is still honoured for
# backward compatibility, as are the REQUESTS_CA_BUNDLE /
# SSL_CERT_FILE / TLS_ROOT_CA env vars (which REPLACE the default
# trust store rather than augmenting it — prefer the drop-in dir
# unless you have a reason to pin the exact bundle).
#REQUESTS_CA_BUNDLE=/etc/iris-ca/extra-ca.crt
#SSL_CERT_FILE=/etc/iris-ca/extra-ca.crt

# -- LISTENING PORT
INTERFACE_HTTPS_PORT=443

37 changes: 0 additions & 37 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,43 +110,6 @@ jobs:
name: iriswebapp_app
path: ${{ runner.temp }}/iriswebapp_app.tar

build-graphql-documentation:
name: Generate graphQL documentation
runs-on: ubuntu-22.04
needs:
- build-docker-db
- build-docker-nginx
- build-docker-app
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
pattern: iriswebapp_*
path: ${{ runner.temp }}
merge-multiple: true
- name: Load docker images
run: |
docker load --input ${{ runner.temp }}/iriswebapp_db.tar
docker load --input ${{ runner.temp }}/iriswebapp_nginx.tar
docker load --input ${{ runner.temp }}/iriswebapp_app.tar
- name: Check out iris
uses: actions/checkout@v4
- name: Start development server
run: |
cp .env.tests.model .env
docker compose --file docker-compose.dev.yml up --detach --wait
- name: Generate GraphQL documentation
run: |
npx spectaql@^3.0.2 source/spectaql/config.yml
- name: Stop development server
run: |
docker compose down
- uses: actions/upload-artifact@v4
with:
name: GraphQL DFIR-IRIS documentation
path: public
if-no-files-found: error

test-api:
name: Test API
runs-on: ubuntu-22.04
Expand Down
54 changes: 53 additions & 1 deletion docker-compose.base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ services:
- POSTGRES_ADMIN_USER
- POSTGRES_ADMIN_PASSWORD
- POSTGRES_DB
# PG18's Docker image refuses to use a directory mounted directly
# as PGDATA (it expects the version-prefixed layout from
# pg_ctlcluster). Pointing PGDATA at a sub-path inside the
# mounted volume sidesteps that check and keeps the on-disk
# layout the same across the project's bind mounts / named
# volumes regardless of host.
- PGDATA=/var/lib/postgresql/data/pgdata
networks:
- iris_backend
volumes:
Expand All @@ -41,6 +48,25 @@ services:
volumes:
- ./certificates/:/home/iris/certificates/:ro
- ./certificates/ldap/:/iriswebapp/certificates/ldap/:ro
# Operator-supplied CA bundle for outbound TLS from the Python
# processes (Keycloak discovery, OIDC token endpoint, LDAPS,
# webhook integrations, ...).
#
# IMPORTANT: REQUESTS_CA_BUNDLE / SSL_CERT_FILE replace the
# default trust store rather than augmenting it, so the file
# mounted at /etc/iris-ca/extra-ca.crt MUST be a full bundle:
# your internal CA chain CONCATENATED with the system root
# bundle (e.g. /etc/ssl/certs/ca-certificates.crt on the host).
#
# On the host:
# mkdir -p iris-web/certificates/ca-bundle
# cat /etc/ssl/certs/ca-certificates.crt \
# /path/to/internal-ca-chain.pem \
# > iris-web/certificates/ca-bundle/extra-ca.crt
#
# Leave it absent / empty to keep the container's default trust
# store (Python will then refuse certs signed by private CAs).
- ./certificates/ca-bundle/:/etc/iris-ca/:ro
- iris-downloads:/home/iris/downloads
- user_templates:/home/iris/user_templates
- server_data:/home/iris/server_data
Expand All @@ -59,6 +85,18 @@ services:
- POSTGRES_PORT
- IRIS_SECRET_KEY
- IRIS_SECURITY_PASSWORD_SALT
# Point Python's `requests` library AND the stdlib `ssl` module
# at an operator-supplied bundle so it trusts chains for
# internal services (Keycloak, LDAPS, etc.). The bundle must
# include the system roots too — these env vars REPLACE the
# default trust store, not add to it.
#
# Unset by default — only opt in by exporting REQUESTS_CA_BUNDLE
# in iris-web/.env, e.g.:
# REQUESTS_CA_BUNDLE=/etc/iris-ca/extra-ca.crt
# SSL_CERT_FILE=/etc/iris-ca/extra-ca.crt
- REQUESTS_CA_BUNDLE
- SSL_CERT_FILE
networks:
- iris_backend
- iris_frontend
Expand All @@ -75,6 +113,7 @@ services:
volumes:
- ./certificates/:/home/iris/certificates/:ro
- ./certificates/ldap/:/iriswebapp/certificates/ldap/:ro
- ./certificates/ca-bundle/:/etc/iris-ca/:ro
- iris-downloads:/home/iris/downloads
- user_templates:/home/iris/user_templates
- server_data:/home/iris/server_data
Expand All @@ -95,6 +134,10 @@ services:
- IRIS_SECURITY_PASSWORD_SALT
- IRIS_WORKER
- LOG_LEVEL
# See the `app` service: REPLACES the default trust store. Set
# in iris-web/.env to opt in.
- REQUESTS_CA_BUNDLE
- SSL_CERT_FILE
networks:
- iris_backend

Expand All @@ -106,10 +149,19 @@ services:
- IRIS_FRONTEND_SERVER
- IRIS_FRONTEND_PORT
- INTERFACE_HTTPS_PORT
- SERVER_NAME
# SERVER_NAME still takes precedence when set. If unset, the
# entrypoint falls back to IRIS_HOSTNAME so operators only
# declare the hostname once.
- SERVER_NAME=${SERVER_NAME:-${IRIS_HOSTNAME:-}}
# CERT_FILENAME / KEY_FILENAME still take precedence when set.
# When unset, the entrypoint autodetects certbot's standard
# fullchain.pem / privkey.pem pair under /www/certs/.
- CERT_FILENAME
- KEY_FILENAME
- IRIS_AUTHENTICATION_TYPE
# Poll interval (seconds) for the cert-reload watcher. Set to 0
# to disable auto-reload on cert change.
- IRIS_CERT_RELOAD_INTERVAL=${IRIS_CERT_RELOAD_INTERVAL:-60}
networks:
- iris_frontend
ports:
Expand Down
13 changes: 11 additions & 2 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,22 @@ services:
working_dir: /app
environment:
- IRIS_SVELTEKIT_FRONTEND_DIR=${IRIS_SVELTEKIT_FRONTEND_DIR:-../iris-frontend}
- PUBLIC_EXTERNAL_API_URL=${PUBLIC_EXTERNAL_API_URL:-https://127.0.0.1}
# PUBLIC_EXTERNAL_API_URL, ORIGIN, and VITE_ALLOWED_HOSTS all
# fall back to IRIS_HOSTNAME so operators only declare the
# external hostname once (in iris-web/.env). Explicit values
# still take precedence for split-hostname deployments.
- PUBLIC_EXTERNAL_API_URL=${PUBLIC_EXTERNAL_API_URL:-https://${IRIS_HOSTNAME:-127.0.0.1}}
- PUBLIC_INTERNAL_API_URL=http://${IRIS_UPSTREAM_SERVER}:${IRIS_UPSTREAM_PORT}
- PUBLIC_USE_MOCK_API_DATA=false
- ORIGIN=https://127.0.0.1
- ORIGIN=${ORIGIN:-https://${IRIS_HOSTNAME:-127.0.0.1}}
- PROTOCOL_HEADER=x-forwarded-proto
- HOST_HEADER=x-forwarded-host
- NODE_ENV=development
# Whitelist hostnames Vite will serve the dev SPA to. Without
# this, hitting the container behind nginx via a real hostname
# gets blocked by Vite's host-header check. Falls back to
# IRIS_HOSTNAME when unset; use `all` to disable the check.
- VITE_ALLOWED_HOSTS=${VITE_ALLOWED_HOSTS:-${IRIS_HOSTNAME:-}}
volumes:
- ${IRIS_SVELTEKIT_FRONTEND_DIR:-../iris-frontend}:/app # Map the frontend directory dynamically
- /app/node_modules # Ensure `node_modules` is preserved inside the container
Expand Down
155 changes: 155 additions & 0 deletions docker-compose.new-ui.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# IRIS Source Code
# contact@dfir-iris.org
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# Production-style stack for the new SvelteKit UI.
#
# Mirrors docker-compose.dev.yml, but the frontend is a compiled
# SvelteKit Node bundle (no Vite, no HMR, no bind mount). Use this
# when you want the new UI behind nginx without running the Vite dev
# server.
#
# Usage:
# docker compose -f docker-compose.new-ui.yml --profile new-ui up -d --build
#
# Required env (iris-web/.env):
# ORIGIN=https://your.deployment.host # SvelteKit CSRF gate
# IRIS_SVELTEKIT_FRONTEND_DIR=../iris-frontend
# NGINX_CONF_FILE=nginx-newui.conf

services:
rabbitmq:
extends:
file: docker-compose.base.yml
service: rabbitmq
user: rabbitmq
healthcheck:
test: rabbitmq-diagnostics check_port_connectivity || exit 1
start_period: 60s
start_interval: 1s

db:
extends:
file: docker-compose.base.yml
service: db
build:
context: docker/db
image: iriswebapp_db:newui
ports:
- "127.0.0.1:5432:5432"
healthcheck:
test: pg_isready -U postgres -d iris_db || exit 1
start_period: 60s
start_interval: 1s

app:
extends:
file: docker-compose.base.yml
service: app
build:
context: .
dockerfile: docker/webApp/Dockerfile
image: iriswebapp_app:newui
ports:
- "8000:8000"
depends_on:
db:
condition: service_healthy
rabbitmq:
condition: service_healthy
healthcheck:
test: curl --head --fail http://localhost:8000 || exit 1
start_period: 60s
start_interval: 1s

worker:
extends:
file: docker-compose.base.yml
service: worker
build:
context: .
dockerfile: docker/webApp/Dockerfile
image: iriswebapp_app:newui
depends_on:
app:
condition: service_healthy
db:
condition: service_healthy
rabbitmq:
condition: service_healthy
healthcheck:
test: celery -A app.celery inspect ping || exit 1
start_period: 60s
start_interval: 1s

nginx:
extends:
file: docker-compose.base.yml
service: nginx
build:
context: ./docker/nginx
args:
NGINX_CONF_GID: 1234
NGINX_CONF_FILE: ${NGINX_CONF_FILE:-nginx-newui.conf}
image: iriswebapp_nginx:newui
depends_on:
app:
condition: service_healthy
worker:
condition: service_healthy

frontend:
# Compiled SvelteKit Node bundle. No source bind-mount, no `npm
# install` on boot — the image carries everything it needs.
build:
context: ${IRIS_SVELTEKIT_FRONTEND_DIR:-../iris-frontend}
dockerfile: ${IRIS_FRONTEND_DOCKERFILE:-../iris-web/docker/frontend/Dockerfile}
image: iris_frontend:newui
profiles: ["new-ui"]
container_name: iris_sveltekit_frontend
environment:
# Both fall back to IRIS_HOSTNAME so operators only declare the
# external hostname once (in iris-web/.env). Explicit
# PUBLIC_EXTERNAL_API_URL / ORIGIN still take precedence — useful
# when the API is served from a different host than the UI.
- PUBLIC_EXTERNAL_API_URL=${PUBLIC_EXTERNAL_API_URL:-https://${IRIS_HOSTNAME:-127.0.0.1}}
- PUBLIC_INTERNAL_API_URL=http://${IRIS_UPSTREAM_SERVER}:${IRIS_UPSTREAM_PORT}
- PUBLIC_USE_MOCK_API_DATA=false
# ORIGIN gates SvelteKit's CSRF check in production (see
# svelte.config.js → kit.csrf.checkOrigin). Must match the
# external URL the user hits.
- ORIGIN=${ORIGIN:-https://${IRIS_HOSTNAME:-127.0.0.1}}
- PROTOCOL_HEADER=x-forwarded-proto
- HOST_HEADER=x-forwarded-host
- NODE_ENV=production
# Disable adapter-node's 512K default so avatar (multi-MB) and
# datastore (multi-GB) uploads aren't truncated mid-stream — the
# per-endpoint caps live in nginx (client_max_body_size).
- BODY_SIZE_LIMIT=Infinity
ports:
- "5173:5173"
networks:
- iris_backend
- iris_frontend
restart: always

volumes:
iris-downloads:
user_templates:
server_data:
db_data:

networks:
iris_backend:
name: iris_backend
iris_frontend:
name: iris_frontend
2 changes: 1 addition & 1 deletion docker/db/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.


FROM postgres:12-alpine
FROM postgres:18-alpine

COPY create_user.sh /docker-entrypoint-initdb.d/10-create_user.sh
Loading