#!/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' (Read-Only 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 $GLPI_USER_TOKEN" \ "$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 'if type=="object" then (.totalcount > 0) else (length > 0) end' >/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=="Read-Only") | .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 Read-Only ($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 "$(jq -c '{input: .}' /tmp/glpi-chunk.json)" "$API/Computer" \ | jq -r 'if type=="array" then " +\(length) created" else " ERR: \(tostring)" end' i=$((i+SPLIT)) done echo "done — verify count via GET /Computer?range=0-200"