Major accomplishments: - ✅ SELinux policy installed and working - ✅ Core Traefik v2.10 deployment running - ✅ Production configuration ready (v3.1) - ✅ Monitoring stack configured - ✅ Comprehensive documentation created - ✅ Security hardening implemented Current status: - 🟡 Partially deployed (60% complete) - ⚠️ Docker socket access needs resolution - ❌ Monitoring stack not deployed yet - ⚠️ Production migration pending Next steps: 1. Fix Docker socket permissions 2. Deploy monitoring stack 3. Migrate to production config 4. Validate full functionality Files added: - Complete Traefik deployment documentation - Production and test configurations - Monitoring stack configurations - SELinux policy module - Security checklists and guides - Current status documentation
108 lines
2.9 KiB
Bash
108 lines
2.9 KiB
Bash
#!/bin/bash
|
|
# Generate Image Digest Lock File
|
|
# Collects currently running images and resolves immutable digests per host
|
|
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
cat << EOF
|
|
Generate Image Digest Lock File
|
|
|
|
Usage:
|
|
$0 --hosts "omv800 surface fedora" --output /opt/migration/configs/image-digest-lock.yaml
|
|
|
|
Options:
|
|
--hosts Space-separated hostnames to query over SSH (required)
|
|
--output Output lock file path (default: ./image-digest-lock.yaml)
|
|
--help Show this help
|
|
|
|
Notes:
|
|
- Requires passwordless SSH or ssh-agent for each host
|
|
- Each host must have Docker CLI and network access to resolve digests
|
|
- Falls back to remote `docker image inspect` to fetch RepoDigests
|
|
EOF
|
|
}
|
|
|
|
HOSTS=""
|
|
OUTPUT="./image-digest-lock.yaml"
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--hosts)
|
|
HOSTS="$2"; shift 2 ;;
|
|
--output)
|
|
OUTPUT="$2"; shift 2 ;;
|
|
--help|-h)
|
|
usage; exit 0 ;;
|
|
*)
|
|
echo "Unknown argument: $1" >&2; usage; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$HOSTS" ]]; then
|
|
echo "--hosts is required" >&2
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
TMP_DIR=$(mktemp -d)
|
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
|
|
echo "# Image Digest Lock" > "$OUTPUT"
|
|
echo "# Generated: $(date -Iseconds)" >> "$OUTPUT"
|
|
echo "hosts:" >> "$OUTPUT"
|
|
|
|
for HOST in $HOSTS; do
|
|
echo " $HOST:" >> "$OUTPUT"
|
|
|
|
# Get running images (name:tag or id)
|
|
IMAGES=$(ssh -o ConnectTimeout=10 "$HOST" "docker ps --format '{{.Image}}'" 2>/dev/null || true)
|
|
if [[ -z "$IMAGES" ]]; then
|
|
echo " images: []" >> "$OUTPUT"
|
|
continue
|
|
fi
|
|
|
|
echo " images:" >> "$OUTPUT"
|
|
|
|
while IFS= read -r IMG; do
|
|
[[ -z "$IMG" ]] && continue
|
|
|
|
# Inspect to get RepoDigests (immutable digests)
|
|
INSPECT_JSON=$(ssh "$HOST" "docker image inspect '$IMG'" 2>/dev/null || true)
|
|
if [[ -z "$INSPECT_JSON" ]]; then
|
|
# Try to pull metadata silently to populate digest cache (without actual layer download)
|
|
ssh "$HOST" "docker pull --quiet '$IMG' > /dev/null 2>&1 || true"
|
|
INSPECT_JSON=$(ssh "$HOST" "docker image inspect '$IMG'" 2>/dev/null || true)
|
|
fi
|
|
|
|
DIGEST_LINE=""
|
|
if command -v jq >/dev/null 2>&1; then
|
|
DIGEST_LINE=$(echo "$INSPECT_JSON" | jq -r '.[0].RepoDigests[0] // ""' 2>/dev/null || echo "")
|
|
else
|
|
# Grep/sed fallback: find first RepoDigests entry
|
|
DIGEST_LINE=$(echo "$INSPECT_JSON" | grep -m1 'RepoDigests' -A2 | grep -m1 sha256 | sed 's/[", ]//g' || true)
|
|
fi
|
|
|
|
# If no digest, record unresolved entry
|
|
if [[ -z "$DIGEST_LINE" || "$DIGEST_LINE" == "null" ]]; then
|
|
echo " - image: \"$IMG\"" >> "$OUTPUT"
|
|
echo " resolved: false" >> "$OUTPUT"
|
|
continue
|
|
fi
|
|
|
|
# Split repo@sha digest
|
|
IMAGE_AT_DIGEST="$DIGEST_LINE"
|
|
|
|
# Try to capture the original tag (if present)
|
|
ORIG_TAG="$IMG"
|
|
|
|
echo " - image: \"$ORIG_TAG\"" >> "$OUTPUT"
|
|
echo " digest: \"$IMAGE_AT_DIGEST\"" >> "$OUTPUT"
|
|
echo " resolved: true" >> "$OUTPUT"
|
|
done <<< "$IMAGES"
|
|
done
|
|
|
|
echo "\nWrote lock file: $OUTPUT"
|
|
|
|
|