fix(cmdb): GLPI import fixes — input wrapper + Read-Only agent profile [#705]

Import executed live: 87 CIs seeded, scoped cmdb user (Read-Only)
verified read-ok / write-denied. Fixes: POST body needs {input:[...]}
(ERROR_BAD_ARRAY on bare array), profile swapped Technician ->
Read-Only per least-priv ruling, shape-tolerant user-exists check.

Detail: https://projects.knownelement.com/issues/705
This commit is contained in:
2026-09-03 12:26:39 -05:00
parent 379f7d376b
commit 07a0a3472b
+8 -7
View File
@@ -11,7 +11,7 @@
# #
# What it does: # What it does:
# 1. initSession as the admin user token. # 1. initSession as the admin user token.
# 2. Creates local user 'cmdb' (Technician profile, random password + # 2. Creates local user 'cmdb' (Read-Only profile, random password +
# random api_token) — the scoped agent identity per Charles's ruling. # random api_token) — the scoped agent identity per Charles's ruling.
# Writes ~/.creds/glpi-agent.env (0600). Skipped if the user exists. # Writes ~/.creds/glpi-agent.env (0600). Skipped if the user exists.
# 3. Imports systems.csv rows as GLPI Computers (batch; skips names that # 3. Imports systems.csv rows as GLPI Computers (batch; skips names that
@@ -35,12 +35,12 @@ hdr() { printf 'Content-Type: application/json\nApp-Token: %s\nSession-Token: %s
echo "— initSession" echo "— initSession"
SESSION=$(curl -sS --max-time 20 -H "Content-Type: application/json" \ SESSION=$(curl -sS --max-time 20 -H "Content-Type: application/json" \
-H "App-Token: $GLPI_APP_TOKEN" \ -H "App-Token: $GLPI_APP_TOKEN" \
-H "Authorization: user_token $(printf %s "$GLPI_USER_TOKEN" | base64 -w0)" \ -H "Authorization: user_token $GLPI_USER_TOKEN" \
"$API/initSession" | jq -re '.session_token') "$API/initSession" | jq -re '.session_token')
echo " session ok (${#SESSION} chars)" echo " session ok (${#SESSION} chars)"
# --- 2. scoped agent user ------------------------------------------------- # --- 2. scoped agent user -------------------------------------------------
if curl -sS -H "$(hdr)" "$API/User?searchText%5Bname%5D=cmdb" | jq -e '.totalcount > 0' >/dev/null; then 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)" echo "— user 'cmdb' already exists (skipping create)"
else else
AGENT_PASS=$(head -c 24 /dev/urandom | base64 | tr -d '/+=') AGENT_PASS=$(head -c 24 /dev/urandom | base64 | tr -d '/+=')
@@ -51,10 +51,10 @@ 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") 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') NEWUID=$(echo "$UID_JSON" | jq -r '.id // .users_id // empty')
echo " created users_id=$NEWUID" echo " created users_id=$NEWUID"
PROF_ID=$(curl -sS -H "$(hdr)" "$API/Profile?range=0-50" | jq -r '.[] | select(.name=="Technician") | .id' | head -1) 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)" \ [ -n "$PROF_ID" ] && curl -sS -X POST -H "$(hdr)" \
-d '{"input":{"users_id":"'"$NEWUID"'","profiles_id":"'"$PROF_ID"'","entities_id":0,"is_recursive":1}}' \ -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" "$API/Profile_User" > /dev/null && echo " profile Read-Only ($PROF_ID) @ root entity"
umask 077 umask 077
printf 'GLPI_URL=%s\nGLPI_APP_TOKEN=%s\nGLPI_USER_TOKEN=%s\n' \ 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" "$GLPI_URL" "$GLPI_APP_TOKEN" "$AGENT_TOKEN" > "${HOME}/.creds/glpi-agent.env"
@@ -96,8 +96,9 @@ if [ "$DRY" = "1" ]; then echo "— DRY: no changes made"; exit 0; fi
SPLIT=25; i=0 SPLIT=25; i=0
while [ "$i" -lt "$TOTAL" ]; do while [ "$i" -lt "$TOTAL" ]; do
jq ".[$i:$((i+SPLIT))]" /tmp/glpi-batch.json > /tmp/glpi-chunk.json 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" \ curl -sS -X POST -H "$(hdr)" \
| jq -r 'if type=="array" then " +\(.length) created" else " ERR: \(.)" end' -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)) i=$((i+SPLIT))
done done
echo "done — verify count via GET /Computer?range=0-200" echo "done — verify count via GET /Computer?range=0-200"