Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .dev/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# -------------------------------------------------------------------------
# SCCM plugin for GLPI - local development image (OPTIONAL / NOT wired in)
# -------------------------------------------------------------------------
# GLPI development image + Microsoft SQL Server client stack:
# - msodbcsql18 (Microsoft ODBC Driver 18 for SQL Server)
# - sqlsrv / pdo_sqlsrv PHP extensions
#
# This mirrors GLPI core's .docker/app/Dockerfile and adds the pieces the
# SCCM plugin needs to talk to a real MSSQL instance.
#
# NOTE: the default workflow no longer builds a custom `app` image - that
# recreated the `app` container and broke VS Code Dev Containers. Instead,
# `make sccm-env-up` installs the same stack into the *running* container
# via plugins/sccm/.dev/install-sqlsrv.sh. This Dockerfile is kept only for
# building a standalone image outside a dev container (e.g. CI):
# docker build -t glpi-sccm-app --build-arg PHP_VERSION=8.4 plugins/sccm/.dev
# -------------------------------------------------------------------------

ARG PHP_VERSION=8.4

FROM ghcr.io/glpi-project/glpi-development-env:${PHP_VERSION}

USER root

# --- verbatim from GLPI core .docker/app/Dockerfile -----------------------
ENV PHP_INI_SCAN_DIR="/usr/local/etc/php/conf.d/:/usr/local/etc/php/custom_conf.d/"
RUN mkdir -p /usr/local/etc/php/custom_conf.d/

ARG HOST_GROUP_ID=1000
ARG HOST_USER_ID=1000
RUN groupmod --gid ${HOST_GROUP_ID} www-data \
&& usermod --uid ${HOST_USER_ID} www-data \
&& usermod --shell /bin/bash www-data \
&& echo "www-data ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \
&& mkdir --parents /home/www-data \
&& chown www-data:www-data /home/www-data \
&& usermod --home /home/www-data www-data

# --- Microsoft ODBC driver 18 + sqlsrv/pdo_sqlsrv PHP extensions ---------
# NOTE: the base image is Debian 12 (bookworm). If it ever switches distro
# or release, adjust the packages.microsoft.com path below.
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates curl gnupg apt-transport-https unixodbc-dev; \
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc \
| gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg; \
echo "deb [signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" \
> /etc/apt/sources.list.d/mssql-release.list; \
apt-get update; \
ACCEPT_EULA=Y apt-get install -y --no-install-recommends msodbcsql18; \
pecl install sqlsrv pdo_sqlsrv; \
docker-php-ext-enable sqlsrv pdo_sqlsrv; \
apt-get clean; \
rm -rf /var/lib/apt/lists/*

VOLUME /home/www-data

USER www-data
127 changes: 127 additions & 0 deletions .dev/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# SCCM plugin — local test environment

The plugin talks to a **Microsoft SQL Server** database (the SCCM / MECM
source) through the `sqlsrv` PHP extension, then pushes FusionInventory-style
XML to GLPI's **native** inventory endpoint (`/front/inventory.php`).

A full SCCM/MECM install is not reproducible in a dev environment, so this
folder ships a **fixture MSSQL database** containing only the tables/views the
plugin actually queries, plus two sample machines.

## What's here

| File | Purpose |
|------|---------|
| `docker-compose.sccm.yaml` | Purely additive: declares only the `mssql` service (never touches `app`) |
| `install-sqlsrv.sh` | Installs `msodbcsql18` + `sqlsrv` / `pdo_sqlsrv` into the **running** `app` container |
| `Dockerfile` | Optional standalone image (CI); **not** used by the default `make` workflow |
| `sccm-schema.sql` | Idempotent fixture schema + data (database `CM_TST`) |

> **Why no image rebuild?** When `app` is a VS Code Dev Container, running
> `docker compose … up --build` recreates it *without* the Dev Container
> overrides (`/vscode` mount, keep-alive command) and the running container
> breaks. So the MSSQL client stack is installed into the live container
> instead. It lives in the container's writable layer — **re-run
> `make sccm-env-up` (or `make install-ext`) after every container rebuild.**

## Requirements

- The GLPI core docker stack (`docker-compose.yaml` at the GLPI root).
- `x86_64` host. On Apple Silicon / ARM, swap the image in
`docker-compose.sccm.yaml` for `mcr.microsoft.com/azure-sql-edge`.
- The base image is assumed to be Debian 12. If GLPI core changes it, adjust
the `packages.microsoft.com` line in `Dockerfile`.

## Usage

All commands are `make` targets defined in `plugins/sccm/Makefile`; run them
from the **plugin** directory (`plugins/sccm`).

The `app` (dev) container must already be running.

```bash
# 1. start the MSSQL service + install sqlsrv/ODBC 18 into the running app container
make sccm-env-up

# 2. wait ~20-30s for MSSQL to become healthy, then load the fixtures
make sccm-db-seed

# 3. sanity check: the extension is loaded
make sccm-verify-ext
```

Then install / enable the plugin as usual:

```bash
make install
make enable
```

### 1. Enable GLPI's native inventory

*Setup → Inventory → General setup* → check **"Enable inventory"**. Disabled by
default on a fresh instance → the SCCM push would otherwise get a `403
Forbidden` from `/front/inventory.php` regardless of any plugin setting.

Note the **"Authorization header"** selector on that same page: as soon as
inventory is enabled it defaults to **Basic Authentication**, which the push
will need to satisfy (step 2 below) — otherwise you get a `401 Authorization
header required to send an inventory`. Set a login/password there, e.g.
`sccm-agent` / `Glpi_Sccm_2026!`.

### 2. Plugin configuration to enter in GLPI

*Setup → SCCM → add a configuration*

| Field | Value |
|-------|-------|
| Enable synchronization | ✅ |
| Server hostname (MSSQL) | `mssql` |
| Database name | `CM_TST` |
| Username | `sa` |
| Password | `Glpi_Sccm_2026!` |
| Collection name | *(empty = all machines)* — or `Workstations`, or `Site Bordeaux - O'Brien` to exercise the quote-escaping path (only matches `PC-DEV-01`) |
| **Verify SSL certificate** | ❌ **must be unchecked** — MSSQL uses a self-signed cert; ODBC Driver 18 forces encryption and would otherwise reject the connection |
| Inventory server base URL | `http://localhost` — **not** the value of `url_base` if it points at the host-side published port (e.g. `http://localhost:12080`): that port mapping isn't reachable *from inside* the `app` container, only from the host. `http://localhost` (no port = 80) reaches GLPI's own Apache, in-container. |
| Utiliser des informations d'authentification spécifique | ✅ — required as soon as GLPI's inventory "Authorization header" is set to Basic Auth (the default, see step 1) |
| Value for specific authentication | `sccm-agent:Glpi_Sccm_2026!` — **`login:password`**, matching step 1 exactly. This is the raw string passed to cURL's `CURLOPT_USERPWD`, not two separate fields. |

Use the **Test connection** button to confirm MSSQL connectivity (this only
tests the `sqlsrv` side, not the inventory push).

### 3. Running the sync

*Setup → Automatic actions → `SCCMCollect` → Execute*, then `SCCMPush`.
Generated XML lands in `files/_plugins/sccm/xml/<config_id>/`.
Expected result: computer `PC-DEV-01` (and `PC-DEV-02` if the collection scope
is left empty) imported as an asset. Check `files/_log/sccm.log` for
`Push OK` / `Push KO` lines — a `KO` line includes GLPI's own inventory error
response, which is usually the fastest way to diagnose a failure.

### Inspecting / resetting the fixture DB

```bash
make sccm-db-shell # interactive sqlcmd on CM_TST
make sccm-db-seed # re-run to reset fixture data (idempotent)
```

### Teardown

```bash
make sccm-env-down # remove the mssql container, keep its volume
make sccm-env-destroy # remove the mssql container AND its data volume
```

`app` never depends on `mssql`, so teardown only affects the MSSQL container.
The `sqlsrv` extension stays in the `app` container until its next rebuild.

## Notes

- `docker-compose.sccm.yaml` is **layered** on core via `-f` (see the Makefile),
so it never edits a GLPI core file and needs no `docker-compose.override.yaml`.
It is purely additive (only the `mssql` service), so it never recreates `app`.
- The MSSQL port is published on `localhost:12433` for external GUI tools.
- `make install-ext` runs `install-sqlsrv.sh` on its own — use it to reinstall
the client stack after a container rebuild without restarting MSSQL.
- The extension is picked up immediately by any new `php` CLI process (the test
runner); the web (Apache) side is reloaded by the script.
51 changes: 51 additions & 0 deletions .dev/docker-compose.sccm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# -------------------------------------------------------------------------
# SCCM plugin for GLPI - local test environment
# -------------------------------------------------------------------------
# Adds a Microsoft SQL Server instance (the "SCCM source database") to the
# running GLPI development stack.
#
# This file is *purely additive*: it declares only the `mssql` service and
# its volume. It deliberately does NOT redefine the `app` service, so
# layering it on top of core's docker-compose.yaml can never recreate the
# `app` container - which matters when `app` is a VS Code Dev Container
# (recreating it there drops the /vscode mount + keep-alive command and
# breaks the running dev container).
#
# The `sqlsrv` / `pdo_sqlsrv` PHP extensions + Microsoft ODBC Driver 18 are
# installed into the *running* `app` container by `make sccm-env-up`
# (see plugins/sccm/.dev/install-sqlsrv.sh), not baked into an image.
#
# Layer it on core:
# cd /var/www/glpi
# docker compose -f docker-compose.yaml \
# -f plugins/sccm/.dev/docker-compose.sccm.yaml up -d mssql
#
# All relative paths below are resolved from the GLPI root (the directory of
# the first -f file), NOT from this file's directory.
# -------------------------------------------------------------------------

services:
mssql:
container_name: "glpi-sccm-mssql-v12"
image: "mcr.microsoft.com/mssql/server:2022-latest"
restart: "unless-stopped"
environment:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "Glpi_Sccm_2026!"
MSSQL_PID: "Developer"
ports:
- "12433:1433"
volumes:
- "sccm_mssql:/var/opt/mssql"
- "./plugins/sccm/.dev/sccm-schema.sql:/sql/sccm-schema.sql:ro"
healthcheck:
test:
- "CMD-SHELL"
- "/opt/mssql-tools18/bin/sqlcmd -C -S localhost -U sa -P \"$${MSSQL_SA_PASSWORD}\" -Q 'SELECT 1' || exit 1"
interval: "10s"
timeout: "5s"
retries: 12
start_period: "30s"

volumes:
sccm_mssql:
61 changes: 61 additions & 0 deletions .dev/install-sqlsrv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
# -------------------------------------------------------------------------
# SCCM plugin for GLPI - MSSQL client stack installer
# -------------------------------------------------------------------------
# Installs, into a *running* GLPI dev container (no image rebuild):
# - Microsoft ODBC Driver 18 for SQL Server (msodbcsql18)
# - sqlsrv / pdo_sqlsrv PHP extensions
#
# Run as root inside the `app` container. Idempotent - safe to re-run.
# Must be re-run after every container rebuild: the changes live in the
# container's writable layer, not in an image.
#
# Driven by `make sccm-env-up` / `make install-ext` (plugins/sccm/Makefile).
#
# NOTE: the base image is Debian 12 (bookworm). If GLPI core switches distro
# or release, adjust the packages.microsoft.com path below.
# -------------------------------------------------------------------------
set -euo pipefail

if php -m | grep -qx 'sqlsrv' && php -m | grep -qx 'pdo_sqlsrv'; then
echo "sqlsrv + pdo_sqlsrv already loaded - nothing to do."
exit 0
fi

export DEBIAN_FRONTEND=noninteractive

apt-get update
apt-get install -y --no-install-recommends \
ca-certificates curl gnupg apt-transport-https unixodbc-dev

if [ ! -f /usr/share/keyrings/microsoft-prod.gpg ]; then
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc \
| gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
fi
echo "deb [signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" \
> /etc/apt/sources.list.d/mssql-release.list

apt-get update
ACCEPT_EULA=Y apt-get install -y --no-install-recommends msodbcsql18

pecl list 2>/dev/null | grep -qi '^sqlsrv' || pecl install sqlsrv
pecl list 2>/dev/null | grep -qi '^pdo_sqlsrv' || pecl install pdo_sqlsrv
docker-php-ext-enable sqlsrv pdo_sqlsrv

apt-get clean
rm -rf /var/lib/apt/lists/*

# Best-effort reload so a running Apache picks up the extension.
# (A fresh `php` CLI - i.e. the test runner - sees it with no reload.)
if command -v apache2ctl >/dev/null 2>&1; then
apache2ctl -k restart 2>/dev/null && echo "Apache reloaded." || true
fi

echo
if php -m | grep -qE '^(pdo_)?sqlsrv$'; then
echo "sqlsrv stack installed OK:"
php -m | grep -E '^(pdo_)?sqlsrv$'
else
echo "ERROR: sqlsrv extension still not loaded." >&2
exit 1
fi
Loading