From 52a9d2b9ada03ec4f8db2e4b38440431cf52d965 Mon Sep 17 00:00:00 2001 From: Aleksandar Damjanovic Date: Wed, 13 May 2026 17:09:50 +0200 Subject: [PATCH] hardening: Devcontainer + Push-Block-Hook fuer java-identifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stack: java-maven (Library). Template aus ~/.claude/skills/hardening/templates/java-maven/.devcontainer/. Anpassung: - name -> java-identifiers - forwardPorts -> [5005] (nur JDWP — Library hat keinen App-Port) Pre-push-Hook blockt Push aus dem Container (DEVCONTAINER=true). Plan-Ref: vault/plans/2026-05-14-devcontainer-hardening.md (Welle 1, personal-Workspace) Konzept: ~/.claude/vault/concepts/devcontainer-architektur.md --- .devcontainer/devcontainer.json | 75 +++++++++++++++++++++++++++++++++ .devcontainer/post-create.sh | 68 ++++++++++++++++++++++++++++++ .githooks/pre-push | 18 ++++++++ 3 files changed, 161 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100755 .devcontainer/post-create.sh create mode 100755 .githooks/pre-push diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..2786686 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,75 @@ +{ + // Devcontainer-Sicherheitsmodell: Push aus Container ist hart geblockt (DEVCONTAINER=true + pre-push-Hook). + // Keine Credentials im Image, kein SSH-Agent-Forwarding, keine Cred-Mounts. + // Quelle: ~/.claude/vault/concepts/devcontainer-architektur.md + "name": "java-identifiers", + + // 2026-05-13: JDK 25 LTS zum Zeitpunkt dieser Vorlage. Verfuegbarkeit pruefen mit: + // docker manifest inspect mcr.microsoft.com/devcontainers/java:25-bookworm + // Fallback falls 25er-Tag noch nicht verfuegbar: java:21-bookworm. + // Microsoft-Java-Bookworm bringt JDK mit, **kein Maven** — wird im post-create per apt installiert. + "image": "mcr.microsoft.com/devcontainers/java:25-bookworm", + + // Features: + // - docker-outside-of-docker: docker-CLI im Container + Sock-Permissions/Group fuer nonroot-User. + // Voraussetzung fuer Testcontainers, jib, ko, Buildpacks (alles was Sibling-Container startet). + // Maven wird absichtlich NICHT ueber `features/java:1` installiert: das SDKMAN-Feature scheitert + // in manchen buildx-Sandbox-Netzen am Internet-Healthcheck. apt im post-create ist robust und + // liefert Maven 3.8.7 (Debian Bookworm). Wer ein anderes Maven braucht: Apache-Tarball im + // post-create unpacken oder eigenen Layer im Dockerfile. + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {} + }, + + // Sicherheitsmarker: Hook .githooks/pre-push prueft diesen Wert und blockt bei "true". + // JDWP-Opts: agent listet auf 5005 fuer Remote-Debugging. suspend=n -> Build startet sofort. + // TESTCONTAINERS_HOST_OVERRIDE: Sibling-Container (Ryuk, Test-DB) sind ueber Host-Gateway + // erreichbar, nicht ueber default-bridge `172.17.0.1`. runArgs unten haengt `host.docker.internal` + // an /etc/hosts (Linux-Equivalent zum Mac/Win-Default). Wenn das Repo keinen Testcontainers-Pfad + // hat (kein jOOQ-Generate o.ae.), kann der Override entfernt werden — schadet aber nicht. + // JAVA_HOME: Eclipse Temurin (Adoptium) statt Microsoft OpenJDK. post-create.sh installiert + // Temurin parallel zum Microsoft-JDK aus dem Image. Begruendung: Distributions-Konsistenz mit + // CI (setup-java distribution=temurin) und Toolchains, die das Temurin-JDK-Layout erwarten + // (z.B. JAVA_HOME/Packages). Microsoft-OpenJDK liegt ungenutzt parallel — IDE-Indexing nimmt JAVA_HOME. + "containerEnv": { + "DEVCONTAINER": "true", + "MAVEN_OPTS": "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005", + "TESTCONTAINERS_HOST_OVERRIDE": "host.docker.internal", + "JAVA_HOME": "/usr/lib/jvm/temurin-25-jdk-amd64" + }, + + // - --add-host: Linux-Equivalent zu Mac/Win `host.docker.internal`. Fuer Testcontainers. + // - --name: fester Container-Name (`devcontainer-`) — verbessert `docker ps`-Lesbarkeit. + // Konflikte handhabt devcontainer-CLI via --remove-existing-container. + // Unterstuetzt `./dev down` (siehe dev-skripte.md). + "runArgs": [ + "--add-host=host.docker.internal:host-gateway", + "--name", "devcontainer-${localWorkspaceFolderBasename}" + ], + + // 5005 = JDWP (Remote JVM Debug, IntelliJ/VS Code). App-Port hier ergaenzen, z.B. 8080. + "forwardPorts": [5005], + + // Mounts: + // - docker.sock: Daemon-Zugriff fuer Testcontainers + Build-Tools mit Container-Targets. + // Trade-off + Anti-Pattern (NIE im Production-Image): vault/concepts/devcontainer-architektur.md "Docker-Zugriff im Container". + // - m2 Named Volume: persistenter Maven-Cache. Permissions im post-create gechownt + // (Docker-Named-Volumes sind root:root by default; vscode-User braucht Schreibzugriff). + // - target/ NICHT als Root-Volume bei Multi-Module-Repos (jedes Sub-Modul hat eigenes target/). + "mounts": [ + "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind", + "source=devcontainer-${localWorkspaceFolderBasename}-m2,target=/home/vscode/.m2,type=volume" + ], + + // Maven via apt + Volume-chown + Push-Block-Hook. Script erlaubt sauberes Fehler-Handling. + "postCreateCommand": ".devcontainer/post-create.sh", + + "customizations": { + "vscode": { + "extensions": [ + "vscjava.vscode-java-pack", + "vscjava.vscode-maven" + ] + } + } +} diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh new file mode 100755 index 0000000..605ff2c --- /dev/null +++ b/.devcontainer/post-create.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Devcontainer Post-Create-Hook (java-maven Template). +# Idempotent — wird bei jeder Container-Erstellung ausgefuehrt. + +echo "[post-create] Fixing named-volume permissions (m2-cache)..." +# Docker-Named-Volumes werden mit root:root erstellt; der vscode-User braucht Schreibzugriff. +sudo chown -R vscode:vscode /home/vscode/.m2 + +# Eclipse Temurin via Adoptium apt-Repo. Hintergrund: +# Microsoft-Java-Image bringt Microsoft OpenJDK mit — manche Gradle/Plugin-Toolchains erwarten +# das Standard-JDK-Layout (JAVA_HOME/Packages, Temurin-Style). Auch generelle Distributions- +# Konsistenz mit CI (setup-java mit distribution=temurin) ist erwuenscht. +# Adoptium installiert nach /usr/lib/jvm/temurin-{ver}-jdk-amd64. devcontainer.json setzt +# JAVA_HOME entsprechend. Microsoft-OpenJDK bleibt ungenutzt parallel im Image. +TEMURIN_VERSION=25 +TEMURIN_HOME="/usr/lib/jvm/temurin-${TEMURIN_VERSION}-jdk-amd64" + +if [ ! -d "$TEMURIN_HOME" ]; then + echo "[post-create] Installing Eclipse Temurin ${TEMURIN_VERSION} (Adoptium)..." + sudo apt-get update -qq + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + wget apt-transport-https gpg >/dev/null + wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public \ + | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/adoptium.gpg + echo "deb https://packages.adoptium.net/artifactory/deb bookworm main" \ + | sudo tee /etc/apt/sources.list.d/adoptium.list > /dev/null + sudo apt-get update -qq + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + "temurin-${TEMURIN_VERSION}-jdk" >/dev/null + echo "[post-create] Temurin ${TEMURIN_VERSION} installed at $TEMURIN_HOME." +else + echo "[post-create] Temurin ${TEMURIN_VERSION} already present." +fi + +echo "[post-create] Installing Maven via apt..." +# Microsoft-Java-Bookworm hat JDK, aber kein Maven vorinstalliert. +# `features/java:1` mit installMaven schlaegt in manchen buildx-Sandbox-Netzen am +# SDKMAN-Internet-Healthcheck fehl — apt ist robust und liefert Maven 3.8.7 (Bookworm). +sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends maven >/dev/null +echo "[post-create] Maven installed: $(mvn -version 2>&1 | grep -E '^Apache Maven' | head -1)" + +echo "[post-create] Java versions:" +echo " JAVA_HOME: ${JAVA_HOME:-not set}" +echo " active java: $(java -version 2>&1 | head -1)" + +# IntelliJ Native Devcontainer Mode-Fix: das JetBrains-Backend laeuft im Container als root +# (Container-Default-User), waehrend mvn/gradle im Terminal als vscode-User laufen (devcontainer +# remoteUser). Der Indexer sucht in /root/.m2/repository/ — leer, weil Maven nach +# /home/vscode/.m2/repository/ schreibt. Folge: alle Dependencies im IntelliJ-Editor rot. +# Symlink /root/.m2 -> /home/vscode/.m2 macht beide User auf denselben m2-Cache zeigen. +# Idempotent: -f ueberschreibt eventuell vorhandenen Pfad (Dir oder Symlink). +echo "[post-create] Symlinking /root/.m2 -> /home/vscode/.m2 (IntelliJ-Backend-Fix)..." +sudo ln -sfn /home/vscode/.m2 /root/.m2 + +echo "[post-create] Activating pre-push hook (core.hooksPath=.githooks)..." +if git rev-parse --git-dir >/dev/null 2>&1; then + git config core.hooksPath .githooks + echo "[post-create] core.hooksPath=.githooks set" +else + # Tritt typischerweise auf, wenn ein Sandbox-Worktree verwendet wird, dessen .git + # auf einen nicht gemounteten Eltern-Pfad zeigt. Produktive Klone (normale Checkouts) + # sind nicht betroffen. + echo "[post-create] WARN: git dir not reachable inside container." + echo "[post-create] WARN: Push-Block-Hook NICHT aktiv. Auf dem Host setzen:" + echo "[post-create] WARN: git config core.hooksPath .githooks" +fi diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100755 index 0000000..c5cd3be --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Devcontainer Push-Block-Hook. +# Verhindert git push aus dem Devcontainer. +# Host (WSL/Mac) pusht unblockiert -- DEVCONTAINER-Env nur im Container gesetzt. +# Quelle: ~/.claude/vault/concepts/devcontainer-architektur.md + +if [ "${DEVCONTAINER:-}" = "true" ]; then + echo "" >&2 + echo "[pre-push] BLOCKED: git push is not allowed from inside a devcontainer." >&2 + echo "[pre-push]" >&2 + echo "[pre-push] Devcontainer hat keine Credentials und darf keine haben." >&2 + echo "[pre-push] Push vom Host (WSL-Distro / Mac), dort liegen die Token." >&2 + echo "[pre-push]" >&2 + echo "[pre-push] Konzept: ~/.claude/vault/concepts/devcontainer-architektur.md" >&2 + echo "" >&2 + exit 1 +fi +exit 0