[#389] GVM target import: gvm-script (gmp.send_command, lxml parse) + IANA port-list injection; feed jq rewrite (record-bound, no IFS collapse)
ci / audit (push) Successful in 24s

63/63 GLPI targets imported into gvmd (0 failures). Admin creds in
~/.creds/gvm-test.env. Import is idempotent (deletes glpi-* first).
https://projects.knownelement.com/issues/389
This commit is contained in:
2026-09-05 11:21:36 -05:00
parent 2d75a3865f
commit ffc82467a9
2 changed files with 48 additions and 22 deletions
+13 -22
View File
@@ -56,34 +56,25 @@ else
fetch_inventory > "$INVENTORY_JSON" || exit 1
fi
# Normalize: one record per line with parsed IPs
NORMALIZED=$(jq -r '
.[]
| select( ($ONLY_DYNAMIC == 0 or .is_dynamic == 1) )
| ( .comment // "" ) as $c
| ( [$c | scan("ts=([0-9.]+)")] | first | first // "" ) as $ts
| ( [$c | scan("mgmt[ =]([0-9.]+)")] | first | first // "" ) as $mgmt
| select( $INCLUDE_NO_IP == 1 or $ts != "" or $mgmt != "" )
| [ (.id|tostring), .name, $ts, $mgmt, (.serial // "-"),
(.last_inventory_update // "-"), ((.is_dynamic // 0)|tostring) ]
| @tsv' --argjson ONLY_DYNAMIC "$ONLY_DYNAMIC" --argjson INCLUDE_NO_IP "$INCLUDE_NO_IP" "$INVENTORY_JSON")
[ -n "$NORMALIZED" ] || { echo "no scan targets parsed from GLPI" >&2; exit 2; }
case "$FORMAT" in
csv)
printf 'glpi_id,name,ts_ip,mgmt_ip,serial,last_inventory,agent_fed\n'
printf '%s\n' "$NORMALIZED"
jq -r '
.[]
| select( ($ONLY_DYNAMIC == 0 or .is_dynamic == 1) )
| ( .comment // "" ) as $c
| ( [$c | scan("ts=([0-9.]+)")] | first | first // "" ) as $ts
| ( [$c | scan("mgmt[ =]([0-9.]+)")] | first | first // "" ) as $mgmt
| select( $INCLUDE_NO_IP == 1 or $ts != "" or $mgmt != "" )
| [ (.id|tostring), .name, $ts, $mgmt, (.serial // ""),
(.last_inventory_update // ""), ((.is_dynamic // 0)|tostring) ]
| @csv' --argjson ONLY_DYNAMIC "$ONLY_DYNAMIC" --argjson INCLUDE_NO_IP "$INCLUDE_NO_IP" "$INVENTORY_JSON"
;;
gmp)
printf '<!-- GMP create_target fragments generated from GLPI CMDB %s. Review hosts before importing. -->\n' "$(date -Is)"
printf '%s\n' "$NORMALIZED" | while IFS="$(printf '\t')" read -r id name ts mgmt _serial inv dyn; do
hosts="$ts"
if [ -n "$mgmt" ]; then hosts="${hosts:+$hosts,}$mgmt"; fi
[ -n "$hosts" ] || continue
printf '<create_target><name>glpi-%s-%s</name><hosts>%s</hosts><comment>GLPI #%s inv=%s agent=%s</comment><alive_tests>Scan Config Default</alive_tests></create_target>\n' \
"$id" "$(printf '%s' "$name" | tr -c '[:alnum:].-' '-')" "$hosts" "$id" "$inv" "$dyn"
done
# jq emits the complete element per record (host list built in jq — avoids
# bash read() IFS-collapse on empty TSV fields; record bound via . as $rec)
jq -r ' .[] | . as $rec | ( $rec.comment // "" ) as $c | ( [$c | scan("ts=([0-9.]+)")] | first | first // "" ) as $ts | ( [$c | scan("mgmt[ =]([0-9.]+)")] | first | first // "" ) as $mgmt | [ $ts, $mgmt ] | map(select(length > 0)) | join(",") as $hosts | select( $hosts != "" ) | $rec.name as $n | "<create_target><name>glpi-\($rec.id)-\($n | gsub("[^a-zA-Z0-9.-]"; "-"))</name><hosts>\($hosts)</hosts><comment>GLPI #\($rec.id) agent=\($rec.is_dynamic // 0)</comment></create_target>"' --argjson ONLY_DYNAMIC "$ONLY_DYNAMIC" --argjson INCLUDE_NO_IP "$INCLUDE_NO_IP" "$INVENTORY_JSON"
;;
*) echo "bad format: $FORMAT" >&2; exit 1 ;;
esac