diff --git a/cmdb/seed/to-glpi.sh b/cmdb/seed/to-glpi.sh new file mode 100644 index 0000000..e967aa8 --- /dev/null +++ b/cmdb/seed/to-glpi.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# +# to-glpi.sh — seed GLPI from the CMDB CSV + create the scoped agent user [#705] +# +# Prereqs: ~/.creds/glpi.env with GLPI_URL, GLPI_APP_TOKEN, and a VALID +# GLPI_USER_TOKEN (glpi admin). Run cmdb/seed/from-inventory.sh first +# to produce systems.csv. +# +# Usage: +# to-glpi.sh [--dry-run] [systems.csv] +# +# What it does: +# 1. initSession as the admin user token. +# 2. Creates local user 'cmdb' (Technician profile, random password + +# random api_token) — the scoped agent identity per Charles's ruling. +# Writes ~/.creds/glpi-agent.env (0600). Skipped if the user exists. +# 3. Imports systems.csv rows as GLPI Computers (batch; skips names that +# already exist). comment carries category/specs/ts_ip provenance. +# +set -euo pipefail + +DRY=0 +[ "${1:-}" = "--dry-run" ] && { DRY=1; shift; } +CSV="${1:-$(dirname "$0")/systems.csv}" +[ -r "$CSV" ] || { echo "no CSV at $CSV" >&2; exit 2; } + +CREDS="${HOME}/.creds/glpi.env" +# shellcheck disable=SC1090 +. "$CREDS" +: "${GLPI_URL:?}" "${GLPI_APP_TOKEN:?}" "${GLPI_USER_TOKEN:?}" +API="$GLPI_URL/apirest.php" + +hdr() { printf 'Content-Type: application/json\nApp-Token: %s\nSession-Token: %s\n' "$GLPI_APP_TOKEN" "$SESSION"; } + +echo "— initSession" +SESSION=$(curl -sS --max-time 20 -H "Content-Type: application/json" \ + -H "App-Token: $GLPI_APP_TOKEN" \ + -H "Authorization: user_token $(printf %s "$GLPI_USER_TOKEN" | base64 -w0)" \ + "$API/initSession" | jq -re '.session_token') +echo " session ok (${#SESSION} chars)" + +# --- 2. scoped agent user ------------------------------------------------- +if curl -sS -H "$(hdr)" "$API/User?searchText%5Bname%5D=cmdb" | jq -e '.totalcount > 0' >/dev/null; then + echo "— user 'cmdb' already exists (skipping create)" +else + AGENT_PASS=$(head -c 24 /dev/urandom | base64 | tr -d '/+=') + AGENT_TOKEN=$(head -c 24 /dev/urandom | od -An -tx1 | tr -d ' \n') + if [ "$DRY" = "1" ]; then + echo "— DRY: would create user cmdb" + else + UID_JSON=$(curl -sS -X POST -H "$(hdr)" -d '{"input":{"name":"cmdb","realname":"CMDB agent (core-IT)","password":"'"$AGENT_PASS"'","api_token":"'"$AGENT_TOKEN"'"}}' "$API/User") + NEWUID=$(echo "$UID_JSON" | jq -r '.id // .users_id // empty') + echo " created users_id=$NEWUID" + PROF_ID=$(curl -sS -H "$(hdr)" "$API/Profile?range=0-50" | jq -r '.[] | select(.name=="Technician") | .id' | head -1) + [ -n "$PROF_ID" ] && curl -sS -X POST -H "$(hdr)" \ + -d '{"input":{"users_id":"'"$NEWUID"'","profiles_id":"'"$PROF_ID"'","entities_id":0,"is_recursive":1}}' \ + "$API/Profile_User" > /dev/null && echo " profile Technician ($PROF_ID) @ root entity" + umask 077 + printf 'GLPI_URL=%s\nGLPI_APP_TOKEN=%s\nGLPI_USER_TOKEN=%s\n' \ + "$GLPI_URL" "$GLPI_APP_TOKEN" "$AGENT_TOKEN" > "${HOME}/.creds/glpi-agent.env" + echo " agent creds written to ~/.creds/glpi-agent.env (0600)" + fi +fi + +# --- 3. seed import ------------------------------------------------------- +echo "— existing Computers" +EXIST=$(curl -sS -H "$(hdr)" "$API/Computer?range=0-999&is_deleted=0" | jq -r '[.[].name] | join("\n")') + +# CSV -> JSON objects (pure jq; header names become keys) +jq -Rn ' + def strip: gsub("^\"";"") | gsub("\"$";""); + (input | split(",") | map(strip)) as $keys | + [ inputs | split(",") | map(strip) as $v | + reduce range(0; ($keys | length)) as $i + ({}; . + {($keys[$i]): ($v[$i] // "")}) ] +' "$CSV" > /tmp/glpi-rows.json + +# GLPI Computer input objects; skip names already present +jq -c --arg existing "$EXIST" ' + [ .[] | select(.ci_name != "") | select(.ci_name as $n | ($existing | split("\n")) | index($n) | not)] +' /tmp/glpi-rows.json > /tmp/glpi-batch.json + +# Map to GLPI Computer fields +jq -c '[ .[] | {name: .ci_name, + comment: ((.category // "") + " | " + (.specs // "") + " | ts=" + (.ts_ip // "") + + " | " + (.extra // "") + " | src=" + (.source_section // "") + + " | status=" + (.status // ""))} ]' /tmp/glpi-batch.json > /tmp/glpi-input.json +mv /tmp/glpi-input.json /tmp/glpi-batch.json + +TOTAL=$(jq 'length' /tmp/glpi-batch.json) +skipped=$(( $(wc -l < "$CSV") - 1 - TOTAL )) +echo "— import: $TOTAL to create, $skipped already present" +if [ "$DRY" = "1" ]; then echo "— DRY: no changes made"; exit 0; fi + +# Batch-create in chunks of 25 (API limits) +SPLIT=25; i=0 +while [ "$i" -lt "$TOTAL" ]; do + jq ".[$i:$((i+SPLIT))]" /tmp/glpi-batch.json > /tmp/glpi-chunk.json + curl -sS -X POST -H "$(hdr)" -d @/tmp/glpi-chunk.json "$API/Computer" \ + | jq -r 'if type=="array" then " +\(.length) created" else " ERR: \(.)" end' + i=$((i+SPLIT)) +done +echo "done — verify count via GET /Computer?range=0-200"