#!/usr/bin/env bash
set -euo pipefail

# Docker Read-Only Root Filesystem Validation Script
#
# Purpose:
#   Validate that a running container uses a read-only root filesystem and
#   that only the intended writable paths are available.
#
# Usage:
#   ./docker-rofs-validate.sh <container_name_or_id> [writable_test_path]
#
# Examples:
#   ./docker-rofs-validate.sh my-app
#   ./docker-rofs-validate.sh my-app /var/lib/app
#
# Notes:
#   - This script does not change container settings.
#   - It performs non-destructive tests only.
#   - The default writable test path is /tmp.

usage() {
  cat <<'EOF'
Usage:
  docker-rofs-validate.sh <container_name_or_id> [writable_test_path]

Arguments:
  container_name_or_id   Target running container
  writable_test_path     Path expected to be writable inside the container
                         Default: /tmp

Environment:
  DRY_RUN=1              Print commands without executing them
EOF
}

log() {
  printf '[%s] %s\n' "$(date +'%Y-%m-%dT%H:%M:%S%z')" "$*"
}

run_in_container() {
  local container="$1"
  shift
  if [[ "${DRY_RUN:-0}" == "1" ]]; then
    printf 'DRY_RUN docker exec %q sh -c %q\n' "$container" "$*"
    return 0
  fi
  docker exec "$container" sh -c "$*"
}

if [[ $# -lt 1 ]]; then
  usage
  exit 1
fi

CONTAINER="$1"
WRITABLE_PATH="${2:-/tmp}"

if ! command -v docker >/dev/null 2>&1; then
  log "Docker CLI not found in PATH."
  exit 1
fi

if ! docker inspect "$CONTAINER" >/dev/null 2>&1; then
  log "Container not found: $CONTAINER"
  exit 1
fi

STATUS="$(docker inspect --format '{{.State.Status}}' "$CONTAINER")"
if [[ "$STATUS" != "running" ]]; then
  log "Container is not running: $CONTAINER (status: $STATUS)"
  exit 1
fi

READONLY="$(docker inspect --format '{{.HostConfig.ReadonlyRootfs}}' "$CONTAINER")"
log "ReadonlyRootfs: $READONLY"

if [[ "$READONLY" != "true" ]]; then
  log "Expected ReadonlyRootfs=true, but found: $READONLY"
  exit 1
fi

log "Checking that root-owned paths are not writable..."
set +e
ROOT_WRITE_TEST_OUTPUT="$(run_in_container "$CONTAINER" 'touch /etc/rofs-test 2>/dev/null; echo $?')"
ROOT_WRITE_RC=$?
set -e

if [[ $ROOT_WRITE_RC -ne 0 ]]; then
  log "Unable to execute root write test command."
  exit 1
fi

if [[ "$ROOT_WRITE_TEST_OUTPUT" == "0" ]]; then
  log "Unexpectedly able to write to /etc. Root filesystem may not be read-only."
  exit 1
fi

log "Root filesystem write test failed as expected."

log "Checking writable path: $WRITABLE_PATH"
set +e
WRITABLE_TEST_OUTPUT="$(run_in_container "$CONTAINER" "mkdir -p '$WRITABLE_PATH' >/dev/null 2>&1; touch '$WRITABLE_PATH/rofs-test' 2>/dev/null; echo $?")"
WRITABLE_TEST_RC=$?
set -e

if [[ $WRITABLE_TEST_RC -ne 0 ]]; then
  log "Unable to execute writable path test command."
  exit 1
fi

if [[ "$WRITABLE_TEST_OUTPUT" != "0" ]]; then
  log "Writable path test failed for: $WRITABLE_PATH"
  log "Confirm the path is mounted as tmpfs, volume, or bind mount as intended."
  exit 1
fi

log "Writable path test succeeded."

log "Optional inspection of mounts (for review):"
if [[ "${DRY_RUN:-0}" != "1" ]]; then
  docker inspect --format '{{range .Mounts}}{{println .Destination "->" .Type}}{{end}}' "$CONTAINER" || true
fi

log "Validation completed successfully."
log "Recommended follow-up: exercise normal application startup, request handling, and shutdown paths while watching logs for write-related errors."