From 6bff6a1ad711b01685d4be5c8589fa5035f8b498 Mon Sep 17 00:00:00 2001 From: continuist Date: Thu, 4 Sep 2025 22:38:49 -0400 Subject: [PATCH] Security improvements #2 --- .forgejo/workflows/ci.yml | 41 +++++++++++++++++++++++---------------- secure_pip_setup.sh | 28 +++++++++++++++++--------- 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 1e8badc..60ffc61 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -57,20 +57,22 @@ jobs: - name: Run backend unit tests run: | - podman exec ci-pip-$RUN_ID podman run --rm \ - -v $(pwd):/workspace \ + podman exec ci-pip-$RUN_ID sh -c \ + 'cd /workspace && podman run --rm \ + -v /workspace:/workspace \ -w /workspace \ rust:latest \ - sh -c "cargo test --lib -- --test-threads=1" + sh -c "cargo test --lib -- --test-threads=1"' - name: Run backend integration tests run: | - podman exec ci-pip-$RUN_ID podman run --rm \ - -v $(pwd):/workspace \ + podman exec ci-pip-$RUN_ID sh -c \ + 'cd /workspace && podman run --rm \ + -v /workspace:/workspace \ -w /workspace \ -e DATABASE_URL=postgres://testuser:testpassword@test-postgres:5432/testdb \ rust:latest \ - sh -c "cargo test --test '*' -- --test-threads=1" + sh -c "cargo test --test '*' -- --test-threads=1"' - name: Cleanup test resources if: always() @@ -98,11 +100,12 @@ jobs: - name: Run frontend tests in PiP run: | - podman exec ci-pip-$RUN_ID podman run --rm \ - -v $(pwd):/workspace \ + podman exec ci-pip-$RUN_ID sh -c \ + 'cd /workspace && podman run --rm \ + -v /workspace:/workspace \ -w /workspace \ node:20 \ - sh -c "npm ci && npm run test" + sh -c "npm ci && npm run test"' build-backend: runs-on: [self-hosted, ci] @@ -129,9 +132,9 @@ jobs: - name: Build backend image run: | - podman exec ci-pip-$RUN_ID podman build \ - -t ${{ secrets.REGISTRY_HOST }}/${{ secrets.APP_NAME }}/backend:${{ github.sha }} \ - -f Dockerfile.backend . + podman exec ci-pip-$RUN_ID sh -c \ + 'cd /workspace/backend && podman build \ + -t "$REGISTRY/$APP_NAME/backend:$IMAGE_TAG" .' - name: Push backend image run: | @@ -163,9 +166,9 @@ jobs: - name: Build frontend image run: | - podman exec ci-pip-$RUN_ID podman build \ - -t ${{ secrets.REGISTRY_HOST }}/${{ secrets.APP_NAME }}/frontend:${{ github.sha }} \ - -f Dockerfile.frontend . + podman exec ci-pip-$RUN_ID sh -c \ + 'cd /workspace/frontend && podman build \ + -t "$REGISTRY/$APP_NAME/frontend:$IMAGE_TAG" .' - name: Push frontend image run: | @@ -177,7 +180,11 @@ jobs: needs: [build-backend, build-frontend] if: always() steps: - - name: Cleanup PiP container and socket + - name: Cleanup PiP container and per-run socket run: | podman rm -f ci-pip-$RUN_ID 2>/dev/null || true - rm -f ${XDG_RUNTIME_DIR}/podman-host/podman.sock 2>/dev/null || true \ No newline at end of file + SOCKET_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/podman-host-${RUN_ID}" + if pgrep -u "$(id -u)" -fa 'podman system service' | grep -F "unix://${SOCKET_DIR}/podman.sock" >/dev/null; then + pgrep -u "$(id -u)" -fa 'podman system service' | grep -F "unix://${SOCKET_DIR}/podman.sock" | awk '{print $1}' | xargs -r kill || true + fi + rm -rf "${SOCKET_DIR}" 2>/dev/null || true \ No newline at end of file diff --git a/secure_pip_setup.sh b/secure_pip_setup.sh index 29fbf0f..1ecaf36 100644 --- a/secure_pip_setup.sh +++ b/secure_pip_setup.sh @@ -7,18 +7,26 @@ set -euo pipefail # Configuration RUN_ID="${GITHUB_RUN_ID:-local}" PIP_CONTAINER_NAME="ci-pip-${RUN_ID}" -SOCKET_DIR="${XDG_RUNTIME_DIR}/podman-host" +SOCKET_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/podman-host-${RUN_ID}" SOCKET_PATH="${SOCKET_DIR}/podman.sock" PODMAN_IMAGE="quay.io/podman/stable:latest" +WORKSPACE="${GITHUB_WORKSPACE:-$PWD}" -# Clean up any existing container and socket -echo "๐Ÿงน Cleaning up any existing PiP container and socket..." +# Clean up any existing container and socket for this run +echo "๐Ÿงน Cleaning up any existing PiP container and socket for run ${RUN_ID}..." podman rm -f "${PIP_CONTAINER_NAME}" 2>/dev/null || true -rm -f "${SOCKET_PATH}" -rm -rf "${SOCKET_DIR}" -# Create secure socket directory -echo "๐Ÿ“ Creating secure socket directory..." +# Kill any host service bound to this specific socket path +if pgrep -u "$(id -u)" -fa 'podman system service' | grep -F "unix://${SOCKET_PATH}" >/dev/null; then + echo "๐Ÿ›‘ Stopping existing host service for this socket..." + pgrep -u "$(id -u)" -fa 'podman system service' | grep -F "unix://${SOCKET_PATH}" | awk '{print $1}' | xargs -r kill || true +fi + +# Remove existing socket directory +rm -rf "${SOCKET_DIR}" 2>/dev/null || true + +# Create secure per-run socket directory +echo "๐Ÿ“ Creating per-run socket directory..." mkdir -p "${SOCKET_DIR}" chmod 700 "${SOCKET_DIR}" @@ -40,7 +48,7 @@ echo "๐Ÿ”’ Setting secure socket permissions..." chmod 660 "${SOCKET_PATH}" # Create ephemeral PiP container as client only (no inner daemon) -echo "๐Ÿณ Creating secure PiP client container..." +echo "๐Ÿณ Creating secure PiP client container with workspace mount..." podman run -d \ --name "${PIP_CONTAINER_NAME}" \ --security-opt=no-new-privileges \ @@ -49,7 +57,8 @@ podman run -d \ --network=none \ --tmpfs /run:rw,size=64M \ --tmpfs /tmp:rw,size=256M \ - -v "${SOCKET_PATH}:/var/run/podman.sock" \ + -v "${SOCKET_PATH}:/var/run/podman.sock:z" \ + -v "${WORKSPACE}:/workspace:rw,z" \ -e CONTAINER_HOST="unix:///var/run/podman.sock" \ "${PODMAN_IMAGE}" \ sleep infinity @@ -69,4 +78,5 @@ fi echo "๐ŸŽ‰ Secure PiP client container setup complete!" echo " Container: ${PIP_CONTAINER_NAME}" echo " Socket: ${SOCKET_PATH}" +echo " Workspace: ${WORKSPACE} โ†’ /workspace" echo " Security: No network, no capabilities, read-only rootfs, client-only" \ No newline at end of file