This commit was merged in pull request #232.
This commit is contained in:
Executable
+179
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env bash
|
||||
# Seed the curated demo targets (#187) into a running compliance-agent.
|
||||
#
|
||||
# Reads fixtures/demo-targets/targets.json and, for every target:
|
||||
# 1. POST /api/v1/targets (name = name_prefix + name)
|
||||
# 2. POST /api/v1/targets/{id}/artifacts/upload for each `upload` artifact
|
||||
# 3. POST /api/v1/targets/{id}/detect (surface detected facts)
|
||||
# 4. POST /api/v1/targets/{id}/scan (only with --scan)
|
||||
#
|
||||
# Artifact env overrides (see the manifest): DEMO_WEB_URL, DEMO_PLC_MODBUS_URL,
|
||||
# DEMO_PLC_FIRMWARE_IMAGE. Optional artifacts whose env var is unset are
|
||||
# skipped, so the set seeds on a bare laptop; set them on comp-dev / Orca.
|
||||
#
|
||||
# Usage:
|
||||
# scripts/seed-demo-targets.sh # seed all
|
||||
# scripts/seed-demo-targets.sh --scan # seed + trigger first scan
|
||||
# scripts/seed-demo-targets.sh --only web-juice-shop,git-cra-vuln-demo
|
||||
# scripts/seed-demo-targets.sh --reset # delete every "Demo · " target
|
||||
# scripts/seed-demo-targets.sh --reset --scan # reset, reseed, scan
|
||||
#
|
||||
# Env:
|
||||
# AGENT_URL base URL of the agent (default http://localhost:3011)
|
||||
# AGENT_TOKEN bearer token; omit for dev mode (no Keycloak → dev tenant)
|
||||
# MANIFEST alternative manifest path
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
AGENT_URL="${AGENT_URL:-http://localhost:3011}"
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
MANIFEST="${MANIFEST:-$ROOT/fixtures/demo-targets/targets.json}"
|
||||
|
||||
DO_SCAN=0
|
||||
DO_RESET=0
|
||||
ONLY=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--scan) DO_SCAN=1 ;;
|
||||
--reset) DO_RESET=1 ;;
|
||||
--only) ONLY="$2"; shift ;;
|
||||
-h|--help) sed -n '2,25p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
||||
*) echo "unknown arg: $1" >&2; exit 2 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
for bin in jq curl; do
|
||||
command -v "$bin" >/dev/null || { echo "need $bin" >&2; exit 1; }
|
||||
done
|
||||
[[ -f "$MANIFEST" ]] || { echo "manifest not found: $MANIFEST" >&2; exit 1; }
|
||||
|
||||
AUTH=()
|
||||
[[ -n "${AGENT_TOKEN:-}" ]] && AUTH=(-H "Authorization: Bearer ${AGENT_TOKEN}")
|
||||
|
||||
green() { printf '\033[32m%s\033[0m' "$*"; }
|
||||
yellow() { printf '\033[33m%s\033[0m' "$*"; }
|
||||
red() { printf '\033[31m%s\033[0m' "$*"; }
|
||||
|
||||
# api METHOD PATH [curl args...] → body on stdout; non-2xx → exit 1 with body.
|
||||
api() {
|
||||
local method="$1" path="$2"; shift 2
|
||||
local out code
|
||||
out=$(curl -sS -X "$method" "${AGENT_URL}${path}" "${AUTH[@]}" -w '\n%{http_code}' "$@")
|
||||
code="${out##*$'\n'}"
|
||||
out="${out%$'\n'*}"
|
||||
if [[ "$code" != 2* ]]; then
|
||||
echo "$(red "HTTP $code") $method $path" >&2
|
||||
echo "$out" >&2
|
||||
return 1
|
||||
fi
|
||||
printf '%s' "$out"
|
||||
}
|
||||
|
||||
PREFIX="$(jq -r '.name_prefix' "$MANIFEST")"
|
||||
|
||||
reset_targets() {
|
||||
echo "== reset: deleting targets named '${PREFIX}*'"
|
||||
local list ids
|
||||
list=$(api GET "/api/v1/targets?limit=500")
|
||||
ids=$(jq -r --arg p "$PREFIX" '.data[] | select(.name | startswith($p)) | ._id."$oid"' <<<"$list")
|
||||
local n=0
|
||||
for id in $ids; do
|
||||
api DELETE "/api/v1/targets/${id}" >/dev/null && n=$((n + 1))
|
||||
done
|
||||
echo " deleted $n"
|
||||
}
|
||||
|
||||
# Build the JSON artifact list for reference-style (non-upload) artifacts.
|
||||
# Prints one JSON object per artifact that should be created inline.
|
||||
inline_artifacts() {
|
||||
local target_json="$1"
|
||||
jq -c '.artifacts[] | select(.upload == null and .upload_env == null)' <<<"$target_json" |
|
||||
while IFS= read -r a; do
|
||||
local kind env ref optional branch
|
||||
kind=$(jq -r '.kind' <<<"$a")
|
||||
env=$(jq -r '.source_ref_env // empty' <<<"$a")
|
||||
ref=$(jq -r '.source_ref // empty' <<<"$a")
|
||||
optional=$(jq -r '.optional // false' <<<"$a")
|
||||
branch=$(jq -r '.branch // empty' <<<"$a")
|
||||
if [[ -n "$env" && -n "${!env:-}" ]]; then
|
||||
ref="${!env}"
|
||||
elif [[ -n "$env" && "$optional" == "true" ]]; then
|
||||
echo " $(yellow skip) $kind (set \$$env to include)" >&2
|
||||
continue
|
||||
fi
|
||||
[[ -n "$ref" ]] || continue
|
||||
jq -cn --arg k "$kind" --arg r "$ref" --arg b "$branch" \
|
||||
'{kind:$k, source_ref:$r} + (if $b != "" then {branch:$b} else {} end)'
|
||||
done
|
||||
}
|
||||
|
||||
# Upload every `upload` / `upload_env` artifact of the target.
|
||||
upload_artifacts() {
|
||||
local id="$1" target_json="$2"
|
||||
jq -c '.artifacts[] | select(.upload != null or .upload_env != null)' <<<"$target_json" |
|
||||
while IFS= read -r a; do
|
||||
local kind path env fmt optional
|
||||
kind=$(jq -r '.kind' <<<"$a")
|
||||
env=$(jq -r '.upload_env // empty' <<<"$a")
|
||||
path=$(jq -r '.upload // empty' <<<"$a")
|
||||
fmt=$(jq -r '.plc_format // empty' <<<"$a")
|
||||
optional=$(jq -r '.optional // false' <<<"$a")
|
||||
if [[ -n "$env" && -n "${!env:-}" ]]; then
|
||||
path="${!env}"
|
||||
elif [[ -n "$path" ]]; then
|
||||
path="$ROOT/$path"
|
||||
elif [[ "$optional" == "true" ]]; then
|
||||
echo " $(yellow skip) $kind (set \$$env to include)" >&2
|
||||
continue
|
||||
fi
|
||||
[[ -f "$path" ]] || { echo " $(red missing) $path" >&2; return 1; }
|
||||
local form=(-F "file=@${path}" -F "kind=${kind}")
|
||||
[[ -n "$fmt" ]] && form+=(-F "plc_format=${fmt}")
|
||||
api POST "/api/v1/targets/${id}/artifacts/upload" "${form[@]}" >/dev/null
|
||||
echo " $(green upload) $kind $(basename "$path")"
|
||||
done
|
||||
}
|
||||
|
||||
seed_target() {
|
||||
local t="$1"
|
||||
local key name type desc
|
||||
key=$(jq -r '.key' <<<"$t")
|
||||
name="${PREFIX}$(jq -r '.name' <<<"$t")"
|
||||
type=$(jq -r '.target_type' <<<"$t")
|
||||
desc=$(jq -r '.description // ""' <<<"$t")
|
||||
echo "== $key ($type)"
|
||||
|
||||
local arts body resp id
|
||||
arts=$(inline_artifacts "$t" | jq -cs '.')
|
||||
body=$(jq -cn --arg n "$name" --arg tt "$type" --arg d "$desc" --argjson a "$arts" \
|
||||
'{name:$n, target_type:$tt, description:$d, artifacts:$a}')
|
||||
resp=$(api POST "/api/v1/targets" -H 'Content-Type: application/json' -d "$body")
|
||||
id=$(jq -r '.data._id."$oid"' <<<"$resp")
|
||||
echo " $(green created) $id $(jq -r '.data.artifacts|length' <<<"$resp") inline artifact(s)"
|
||||
|
||||
upload_artifacts "$id" "$t"
|
||||
|
||||
local det
|
||||
det=$(api POST "/api/v1/targets/${id}/detect" -H 'Content-Type: application/json' -d '{}' || true)
|
||||
if [[ -n "$det" ]]; then
|
||||
echo " detect → $(jq -r '.data.classification.suggested // "n/a"' <<<"$det")"
|
||||
fi
|
||||
|
||||
if [[ "$DO_SCAN" == 1 ]]; then
|
||||
api POST "/api/v1/targets/${id}/scan" -H 'Content-Type: application/json' -d '{}' >/dev/null
|
||||
echo " $(green scan) triggered"
|
||||
fi
|
||||
}
|
||||
|
||||
[[ "$DO_RESET" == 1 ]] && reset_targets
|
||||
|
||||
echo "== seeding from $MANIFEST → $AGENT_URL"
|
||||
jq -c '.targets[]' "$MANIFEST" | while IFS= read -r t; do
|
||||
key=$(jq -r '.key' <<<"$t")
|
||||
if [[ -n "$ONLY" && ",$ONLY," != *",$key,"* ]]; then
|
||||
continue
|
||||
fi
|
||||
seed_target "$t"
|
||||
done
|
||||
echo "== done"
|
||||
Reference in New Issue
Block a user