Add SBOM, symbols, traces, and VEX files for CVE-2022-21661 SQLi case
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Created CycloneDX and SPDX SBOM files for both reachable and unreachable images. - Added symbols.json detailing function entry and sink points in the WordPress code. - Included runtime traces for function calls in both reachable and unreachable scenarios. - Developed OpenVEX files indicating vulnerability status and justification for both cases. - Updated README for evaluator harness to guide integration with scanner output.
This commit is contained in:
169
ops/devops/sealed-mode-ci/run-sealed-ci.sh
Normal file
169
ops/devops/sealed-mode-ci/run-sealed-ci.sh
Normal file
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
COMPOSE_FILE=${COMPOSE_FILE:-"$SCRIPT_DIR/sealed-mode-compose.yml"}
|
||||
PROJECT_NAME=${COMPOSE_PROJECT_NAME:-sealedmode}
|
||||
NETWORK_NAME="${PROJECT_NAME}_sealed-ci"
|
||||
ARTIFACT_ROOT=${ARTIFACT_ROOT:-"$SCRIPT_DIR/artifacts/sealed-mode-ci"}
|
||||
STAMP=$(date -u +"%Y%m%dT%H%M%SZ")
|
||||
OUT_DIR="$ARTIFACT_ROOT/$STAMP"
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
log() {
|
||||
printf '[%s] %s\n' "$(date -u +%H:%M:%S)" "$*"
|
||||
}
|
||||
|
||||
EXIT_CODE=0
|
||||
IPTABLES_SNAPSHOT=""
|
||||
|
||||
cleanup() {
|
||||
local exit_code=$?
|
||||
log "Collecting docker compose logs"
|
||||
docker compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" logs >"$OUT_DIR/compose.log" 2>&1 || true
|
||||
docker compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" ps -a >"$OUT_DIR/compose.ps" 2>&1 || true
|
||||
log "Tearing down sealed-mode stack"
|
||||
docker compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" down -v >"$OUT_DIR/docker-down.log" 2>&1 || true
|
||||
if [[ -n "$IPTABLES_SNAPSHOT" && -f "$IPTABLES_SNAPSHOT" ]]; then
|
||||
log "Restoring iptables snapshot"
|
||||
sudo iptables-restore <"$IPTABLES_SNAPSHOT" || true
|
||||
rm -f "$IPTABLES_SNAPSHOT"
|
||||
fi
|
||||
log "Artifacts stored at $OUT_DIR"
|
||||
exit $exit_code
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
log "Pulling compose images (best effort)"
|
||||
docker compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" pull --ignore-pull-failures || true
|
||||
|
||||
log "Starting sealed-mode stack"
|
||||
docker compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" up -d --remove-orphans
|
||||
|
||||
wait_for_port() {
|
||||
local port=$1
|
||||
local label=$2
|
||||
for attempt in $(seq 1 30); do
|
||||
if curl -fsS --max-time 5 "http://127.0.0.1:${port}/healthz" >/dev/null 2>&1; then
|
||||
log "$label responded on port $port"
|
||||
return 0
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
log "$label failed to respond on port $port"
|
||||
return 1
|
||||
}
|
||||
|
||||
wait_for_port 5088 "Authority" || EXIT_CODE=1
|
||||
wait_for_port 6088 "Signer" || EXIT_CODE=1
|
||||
wait_for_port 7088 "Attestor" || EXIT_CODE=1
|
||||
|
||||
log "Fetching probe helper image"
|
||||
docker pull curlimages/curl:8.6.0 >/dev/null 2>&1 || true
|
||||
|
||||
log "Snapshotting iptables state"
|
||||
IPTABLES_SNAPSHOT=$(mktemp)
|
||||
sudo iptables-save >"$IPTABLES_SNAPSHOT"
|
||||
|
||||
log "Applying sealed-mode egress policy"
|
||||
CHAIN="STELLAOPS_SEALED"
|
||||
sudo iptables -N "$CHAIN" 2>/dev/null || sudo iptables -F "$CHAIN"
|
||||
for cidr in 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16; do
|
||||
sudo iptables -A "$CHAIN" -d "$cidr" -j RETURN
|
||||
done
|
||||
sudo iptables -A "$CHAIN" -j LOG --log-prefix "stellaops-sealed-deny " --log-level 4
|
||||
sudo iptables -A "$CHAIN" -j DROP
|
||||
sudo iptables -I DOCKER-USER 1 -j "$CHAIN"
|
||||
sudo iptables -I OUTPUT 1 -j "$CHAIN"
|
||||
|
||||
check_health() {
|
||||
local name=$1
|
||||
local port=$2
|
||||
local url="http://127.0.0.1:${port}/healthz"
|
||||
local log_file="$OUT_DIR/${name}.health.log"
|
||||
local status="fail"
|
||||
for attempt in $(seq 1 20); do
|
||||
if curl -fsS --max-time 5 "$url" >"$log_file" 2>&1; then
|
||||
status="pass"
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
if [[ "$status" == "pass" ]]; then
|
||||
log "$name health check succeeded"
|
||||
else
|
||||
log "$name health check failed"
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
local upper
|
||||
upper=$(echo "$name" | tr '[:lower:]' '[:upper:]')
|
||||
eval "${upper}_HEALTH_STATUS=$status"
|
||||
eval "${upper}_HEALTH_URL=$url"
|
||||
}
|
||||
|
||||
check_health authority 5088
|
||||
check_health signer 6088
|
||||
check_health attestor 7088
|
||||
|
||||
log "Running egress probe via docker network $NETWORK_NAME"
|
||||
EGRESS_JSON="$OUT_DIR/egress-probe.json"
|
||||
if python3 "$SCRIPT_DIR/egress_probe.py" --network "$NETWORK_NAME" --image curlimages/curl:8.6.0 --timeout 8 --output "$EGRESS_JSON"; then
|
||||
EGRESS_STATUS="pass"
|
||||
else
|
||||
EGRESS_STATUS="fail"
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
|
||||
log "Dumping iptables counters"
|
||||
sudo iptables -v -x -L DOCKER-USER >"$OUT_DIR/iptables-docker-user.txt"
|
||||
sudo iptables -v -x -L OUTPUT >"$OUT_DIR/iptables-output.txt"
|
||||
|
||||
log "Recording summary JSON"
|
||||
export PROJECT_NAME NETWORK_NAME EGRESS_STATUS EGRESS_JSON
|
||||
export AUTHORITY_HEALTH_STATUS SIGNER_HEALTH_STATUS ATTESTOR_HEALTH_STATUS
|
||||
export AUTHORITY_HEALTH_URL SIGNER_HEALTH_URL ATTESTOR_HEALTH_URL
|
||||
python3 - <<'PY' >"$OUT_DIR/authority-sealed-ci.json"
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
summary = {
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"project": os.environ.get("PROJECT_NAME"),
|
||||
"network": os.environ.get("NETWORK_NAME"),
|
||||
"health": {
|
||||
"authority": {
|
||||
"status": os.environ.get("AUTHORITY_HEALTH_STATUS", "unknown"),
|
||||
"url": os.environ.get("AUTHORITY_HEALTH_URL"),
|
||||
"log": "authority.health.log",
|
||||
},
|
||||
"signer": {
|
||||
"status": os.environ.get("SIGNER_HEALTH_STATUS", "unknown"),
|
||||
"url": os.environ.get("SIGNER_HEALTH_URL"),
|
||||
"log": "signer.health.log",
|
||||
},
|
||||
"attestor": {
|
||||
"status": os.environ.get("ATTESTOR_HEALTH_STATUS", "unknown"),
|
||||
"url": os.environ.get("ATTESTOR_HEALTH_URL"),
|
||||
"log": "attestor.health.log",
|
||||
},
|
||||
},
|
||||
"egressProbe": {
|
||||
"status": os.environ.get("EGRESS_STATUS", "unknown"),
|
||||
"report": os.path.basename(os.environ.get("EGRESS_JSON", "egress-probe.json")),
|
||||
},
|
||||
}
|
||||
json.dump(summary, sys.stdout, indent=2)
|
||||
print()
|
||||
PY
|
||||
|
||||
if [[ $EXIT_CODE -eq 0 ]]; then
|
||||
log "Sealed-mode CI run completed successfully"
|
||||
else
|
||||
log "Sealed-mode CI run completed with failures"
|
||||
fi
|
||||
|
||||
exit $EXIT_CODE
|
||||
Reference in New Issue
Block a user