Skip to content

Commit 853c273

Browse files
committed
hardening: Devcontainer + Push-Block-Hook fuer java-properties
Stack: java-maven (Library). Template aus ~/.claude/skills/hardening/templates/java-maven/.devcontainer/. Anpassung: - name -> java-properties - 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
1 parent 98cd2a5 commit 853c273

3 files changed

Lines changed: 161 additions & 0 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
// Devcontainer-Sicherheitsmodell: Push aus Container ist hart geblockt (DEVCONTAINER=true + pre-push-Hook).
3+
// Keine Credentials im Image, kein SSH-Agent-Forwarding, keine Cred-Mounts.
4+
// Quelle: ~/.claude/vault/concepts/devcontainer-architektur.md
5+
"name": "java-properties",
6+
7+
// 2026-05-13: JDK 25 LTS zum Zeitpunkt dieser Vorlage. Verfuegbarkeit pruefen mit:
8+
// docker manifest inspect mcr.microsoft.com/devcontainers/java:25-bookworm
9+
// Fallback falls 25er-Tag noch nicht verfuegbar: java:21-bookworm.
10+
// Microsoft-Java-Bookworm bringt JDK mit, **kein Maven** — wird im post-create per apt installiert.
11+
"image": "mcr.microsoft.com/devcontainers/java:25-bookworm",
12+
13+
// Features:
14+
// - docker-outside-of-docker: docker-CLI im Container + Sock-Permissions/Group fuer nonroot-User.
15+
// Voraussetzung fuer Testcontainers, jib, ko, Buildpacks (alles was Sibling-Container startet).
16+
// Maven wird absichtlich NICHT ueber `features/java:1` installiert: das SDKMAN-Feature scheitert
17+
// in manchen buildx-Sandbox-Netzen am Internet-Healthcheck. apt im post-create ist robust und
18+
// liefert Maven 3.8.7 (Debian Bookworm). Wer ein anderes Maven braucht: Apache-Tarball im
19+
// post-create unpacken oder eigenen Layer im Dockerfile.
20+
"features": {
21+
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
22+
},
23+
24+
// Sicherheitsmarker: Hook .githooks/pre-push prueft diesen Wert und blockt bei "true".
25+
// JDWP-Opts: agent listet auf 5005 fuer Remote-Debugging. suspend=n -> Build startet sofort.
26+
// TESTCONTAINERS_HOST_OVERRIDE: Sibling-Container (Ryuk, Test-DB) sind ueber Host-Gateway
27+
// erreichbar, nicht ueber default-bridge `172.17.0.1`. runArgs unten haengt `host.docker.internal`
28+
// an /etc/hosts (Linux-Equivalent zum Mac/Win-Default). Wenn das Repo keinen Testcontainers-Pfad
29+
// hat (kein jOOQ-Generate o.ae.), kann der Override entfernt werden — schadet aber nicht.
30+
// JAVA_HOME: Eclipse Temurin (Adoptium) statt Microsoft OpenJDK. post-create.sh installiert
31+
// Temurin parallel zum Microsoft-JDK aus dem Image. Begruendung: Distributions-Konsistenz mit
32+
// CI (setup-java distribution=temurin) und Toolchains, die das Temurin-JDK-Layout erwarten
33+
// (z.B. JAVA_HOME/Packages). Microsoft-OpenJDK liegt ungenutzt parallel — IDE-Indexing nimmt JAVA_HOME.
34+
"containerEnv": {
35+
"DEVCONTAINER": "true",
36+
"MAVEN_OPTS": "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005",
37+
"TESTCONTAINERS_HOST_OVERRIDE": "host.docker.internal",
38+
"JAVA_HOME": "/usr/lib/jvm/temurin-25-jdk-amd64"
39+
},
40+
41+
// - --add-host: Linux-Equivalent zu Mac/Win `host.docker.internal`. Fuer Testcontainers.
42+
// - --name: fester Container-Name (`devcontainer-<basename>`) — verbessert `docker ps`-Lesbarkeit.
43+
// Konflikte handhabt devcontainer-CLI via --remove-existing-container.
44+
// Unterstuetzt `./dev down` (siehe dev-skripte.md).
45+
"runArgs": [
46+
"--add-host=host.docker.internal:host-gateway",
47+
"--name", "devcontainer-${localWorkspaceFolderBasename}"
48+
],
49+
50+
// 5005 = JDWP (Remote JVM Debug, IntelliJ/VS Code). App-Port hier ergaenzen, z.B. 8080.
51+
"forwardPorts": [5005],
52+
53+
// Mounts:
54+
// - docker.sock: Daemon-Zugriff fuer Testcontainers + Build-Tools mit Container-Targets.
55+
// Trade-off + Anti-Pattern (NIE im Production-Image): vault/concepts/devcontainer-architektur.md "Docker-Zugriff im Container".
56+
// - m2 Named Volume: persistenter Maven-Cache. Permissions im post-create gechownt
57+
// (Docker-Named-Volumes sind root:root by default; vscode-User braucht Schreibzugriff).
58+
// - target/ NICHT als Root-Volume bei Multi-Module-Repos (jedes Sub-Modul hat eigenes target/).
59+
"mounts": [
60+
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind",
61+
"source=devcontainer-${localWorkspaceFolderBasename}-m2,target=/home/vscode/.m2,type=volume"
62+
],
63+
64+
// Maven via apt + Volume-chown + Push-Block-Hook. Script erlaubt sauberes Fehler-Handling.
65+
"postCreateCommand": ".devcontainer/post-create.sh",
66+
67+
"customizations": {
68+
"vscode": {
69+
"extensions": [
70+
"vscjava.vscode-java-pack",
71+
"vscjava.vscode-maven"
72+
]
73+
}
74+
}
75+
}

.devcontainer/post-create.sh

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Devcontainer Post-Create-Hook (java-maven Template).
5+
# Idempotent — wird bei jeder Container-Erstellung ausgefuehrt.
6+
7+
echo "[post-create] Fixing named-volume permissions (m2-cache)..."
8+
# Docker-Named-Volumes werden mit root:root erstellt; der vscode-User braucht Schreibzugriff.
9+
sudo chown -R vscode:vscode /home/vscode/.m2
10+
11+
# Eclipse Temurin via Adoptium apt-Repo. Hintergrund:
12+
# Microsoft-Java-Image bringt Microsoft OpenJDK mit — manche Gradle/Plugin-Toolchains erwarten
13+
# das Standard-JDK-Layout (JAVA_HOME/Packages, Temurin-Style). Auch generelle Distributions-
14+
# Konsistenz mit CI (setup-java mit distribution=temurin) ist erwuenscht.
15+
# Adoptium installiert nach /usr/lib/jvm/temurin-{ver}-jdk-amd64. devcontainer.json setzt
16+
# JAVA_HOME entsprechend. Microsoft-OpenJDK bleibt ungenutzt parallel im Image.
17+
TEMURIN_VERSION=25
18+
TEMURIN_HOME="/usr/lib/jvm/temurin-${TEMURIN_VERSION}-jdk-amd64"
19+
20+
if [ ! -d "$TEMURIN_HOME" ]; then
21+
echo "[post-create] Installing Eclipse Temurin ${TEMURIN_VERSION} (Adoptium)..."
22+
sudo apt-get update -qq
23+
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
24+
wget apt-transport-https gpg >/dev/null
25+
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public \
26+
| sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/adoptium.gpg
27+
echo "deb https://packages.adoptium.net/artifactory/deb bookworm main" \
28+
| sudo tee /etc/apt/sources.list.d/adoptium.list > /dev/null
29+
sudo apt-get update -qq
30+
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
31+
"temurin-${TEMURIN_VERSION}-jdk" >/dev/null
32+
echo "[post-create] Temurin ${TEMURIN_VERSION} installed at $TEMURIN_HOME."
33+
else
34+
echo "[post-create] Temurin ${TEMURIN_VERSION} already present."
35+
fi
36+
37+
echo "[post-create] Installing Maven via apt..."
38+
# Microsoft-Java-Bookworm hat JDK, aber kein Maven vorinstalliert.
39+
# `features/java:1` mit installMaven schlaegt in manchen buildx-Sandbox-Netzen am
40+
# SDKMAN-Internet-Healthcheck fehl — apt ist robust und liefert Maven 3.8.7 (Bookworm).
41+
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends maven >/dev/null
42+
echo "[post-create] Maven installed: $(mvn -version 2>&1 | grep -E '^Apache Maven' | head -1)"
43+
44+
echo "[post-create] Java versions:"
45+
echo " JAVA_HOME: ${JAVA_HOME:-not set}"
46+
echo " active java: $(java -version 2>&1 | head -1)"
47+
48+
# IntelliJ Native Devcontainer Mode-Fix: das JetBrains-Backend laeuft im Container als root
49+
# (Container-Default-User), waehrend mvn/gradle im Terminal als vscode-User laufen (devcontainer
50+
# remoteUser). Der Indexer sucht in /root/.m2/repository/ — leer, weil Maven nach
51+
# /home/vscode/.m2/repository/ schreibt. Folge: alle Dependencies im IntelliJ-Editor rot.
52+
# Symlink /root/.m2 -> /home/vscode/.m2 macht beide User auf denselben m2-Cache zeigen.
53+
# Idempotent: -f ueberschreibt eventuell vorhandenen Pfad (Dir oder Symlink).
54+
echo "[post-create] Symlinking /root/.m2 -> /home/vscode/.m2 (IntelliJ-Backend-Fix)..."
55+
sudo ln -sfn /home/vscode/.m2 /root/.m2
56+
57+
echo "[post-create] Activating pre-push hook (core.hooksPath=.githooks)..."
58+
if git rev-parse --git-dir >/dev/null 2>&1; then
59+
git config core.hooksPath .githooks
60+
echo "[post-create] core.hooksPath=.githooks set"
61+
else
62+
# Tritt typischerweise auf, wenn ein Sandbox-Worktree verwendet wird, dessen .git
63+
# auf einen nicht gemounteten Eltern-Pfad zeigt. Produktive Klone (normale Checkouts)
64+
# sind nicht betroffen.
65+
echo "[post-create] WARN: git dir not reachable inside container."
66+
echo "[post-create] WARN: Push-Block-Hook NICHT aktiv. Auf dem Host setzen:"
67+
echo "[post-create] WARN: git config core.hooksPath .githooks"
68+
fi

.githooks/pre-push

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
# Devcontainer Push-Block-Hook.
3+
# Verhindert git push aus dem Devcontainer.
4+
# Host (WSL/Mac) pusht unblockiert -- DEVCONTAINER-Env nur im Container gesetzt.
5+
# Quelle: ~/.claude/vault/concepts/devcontainer-architektur.md
6+
7+
if [ "${DEVCONTAINER:-}" = "true" ]; then
8+
echo "" >&2
9+
echo "[pre-push] BLOCKED: git push is not allowed from inside a devcontainer." >&2
10+
echo "[pre-push]" >&2
11+
echo "[pre-push] Devcontainer hat keine Credentials und darf keine haben." >&2
12+
echo "[pre-push] Push vom Host (WSL-Distro / Mac), dort liegen die Token." >&2
13+
echo "[pre-push]" >&2
14+
echo "[pre-push] Konzept: ~/.claude/vault/concepts/devcontainer-architektur.md" >&2
15+
echo "" >&2
16+
exit 1
17+
fi
18+
exit 0

0 commit comments

Comments
 (0)