282 lines
11 KiB
Markdown
282 lines
11 KiB
Markdown
# ansipa Single Sign-On
|
|
|
|
How identity flows through the ansipa stack, which services can actually use
|
|
it, and how to wire the infrastructure appliances (Proxmox VE/BS, OPNsense)
|
|
into it.
|
|
|
|
The rule for this stack: **no service keeps its own account list.** Every
|
|
account lives in FreeIPA, and every login is decided either by Keycloak or by
|
|
FreeIPA itself. The only exceptions are two deliberate break-glass local
|
|
admins, documented at the bottom.
|
|
|
|
---
|
|
|
|
## The identity chain
|
|
|
|
```
|
|
FreeIPA ── accounts, groups, sudo/HBAC rules. The source of truth.
|
|
│
|
|
├─ LDAP (READ_ONLY federation) ──▶ Keycloak ── issues OIDC/SAML
|
|
│ │
|
|
│ ├─▶ Nextcloud (user_oidc)
|
|
│ ├─▶ Proxmox VE (OpenID realm)
|
|
│ ├─▶ Proxmox Backup (OpenID realm)
|
|
│ └─▶ OPNsense (see caveat)
|
|
│
|
|
└─ LDAP (direct bind) ───────────▶ CheckMK
|
|
└ no SAML/OIDC in the Community
|
|
edition, so it binds IPA itself
|
|
```
|
|
|
|
Keycloak mirrors FreeIPA read-only. Creating a user in Keycloak's own database
|
|
is always a mistake here — it produces an account IPA does not know about, and
|
|
it will not survive a re-sync.
|
|
|
|
---
|
|
|
|
## Support matrix
|
|
|
|
| Service | Method | Edition/version caveat |
|
|
|---|---|---|
|
|
| Nextcloud | OIDC via Keycloak, accounts from IPA LDAP | `user_oidc` app must be installed |
|
|
| Proxmox VE | OpenID Connect realm | PVE 7.0+ |
|
|
| Proxmox Backup Server | OpenID Connect realm | PBS 2.2+ |
|
|
| CheckMK | **Direct LDAP to FreeIPA** | SAML is commercial-only; OIDC unsupported in every edition |
|
|
| OPNsense | LDAP to FreeIPA (recommended) | No built-in OIDC relying-party support |
|
|
|
|
### The two that cannot use Keycloak
|
|
|
|
**CheckMK.** The Community (Raw) edition has no SAML — the docs state plainly
|
|
that "SAML is supported in the commercial editions" — and no edition of CheckMK
|
|
supports OIDC at all. The old `mod_auth_mellon` workaround was dropped in 2.3.
|
|
So CheckMK binds FreeIPA over LDAP directly. Identity still comes from one
|
|
place, it just takes a shorter path. Run `./checkmk-ldap-configure.sh`.
|
|
|
|
**OPNsense.** It can consume LDAP and RADIUS, but it is not an OIDC relying
|
|
party, so Keycloak cannot front the web UI. Point it at FreeIPA's LDAP
|
|
directly (System → Access → Servers), which keeps accounts centralised even
|
|
though the login is not federated. The `opnsense` Keycloak client that
|
|
`keycloak-configure.sh` can provision is only useful if you put an
|
|
OIDC-aware proxy in front of the UI, or for OPNsense plugins that speak OIDC.
|
|
|
|
---
|
|
|
|
## Setup order
|
|
|
|
Everything below assumes the stack is up (`./run.sh all`).
|
|
|
|
```bash
|
|
cd setup/modules/FreeipaAnsible/image
|
|
|
|
./keycloak-configure.sh # IPA LDAP federation + OIDC clients + groups claim
|
|
./nextcloud-configure.sh # Nextcloud → IPA LDAP + Keycloak OIDC
|
|
./checkmk-ldap-configure.sh # CheckMK → IPA LDAP directly
|
|
```
|
|
|
|
`keycloak-configure.sh` writes each client's secret to `image/.oidc-secrets`
|
|
(mode 0600, gitignored). Clients are only created for relying parties whose
|
|
base URL is set in `.env` — `NC_PUBLIC_URL`, `PVE_URL`, `PBS_URL`,
|
|
`OPNSENSE_URL`. Set one later and re-run; existing clients keep their secrets.
|
|
|
|
The discovery URL every relying party needs is:
|
|
|
|
```
|
|
https://<your-gateway>/auth/realms/<KC_REALM>/.well-known/openid-configuration
|
|
```
|
|
|
|
---
|
|
|
|
## Nextcloud
|
|
|
|
Two backends do two different jobs, and both are required:
|
|
|
|
- **`user_ldap`** binds FreeIPA and owns the account list. Users, display
|
|
names, mail and group membership come from IPA and are read-only.
|
|
- **`user_oidc`** performs the login against Keycloak, so password policy, MFA
|
|
and session control stay in one place.
|
|
|
|
The join between them is the username, and it is the part that breaks if you
|
|
change it carelessly. Nextcloud's internal username is pinned to the IPA `uid`
|
|
(`ldapExpertUsernameAttr`), and the OIDC provider maps `preferred_username`
|
|
onto it with **unique-uid disabled**. Leave unique-uid on and `user_oidc`
|
|
hashes the claim into an ID of its own, so every SSO login creates a second,
|
|
empty account beside the LDAP one.
|
|
|
|
Verify after setup:
|
|
|
|
```bash
|
|
docker compose exec -u www-data nextcloud php occ user:list
|
|
```
|
|
|
|
That should list your FreeIPA users. Log in once through the Keycloak button,
|
|
then run it again — if a second account appeared for the same person, the uid
|
|
mapping is wrong.
|
|
|
|
Restrict who gets an account with `NC_LDAP_GROUP=usr_nextcloud` in `.env`; the
|
|
LDAP filter also excludes IPA-disabled users (`nsAccountLock=TRUE`), so
|
|
disabling someone in IPA locks them out of Nextcloud too.
|
|
|
|
---
|
|
|
|
## Proxmox VE
|
|
|
|
Set `PVE_URL=https://pve.example.com:8006` in `.env`, re-run
|
|
`./keycloak-configure.sh`, then on the PVE node:
|
|
|
|
```bash
|
|
pveum realm add keycloak \
|
|
--type openid \
|
|
--issuer-url https://<gateway>/auth/realms/<KC_REALM> \
|
|
--client-id proxmox-ve \
|
|
--client-key <secret from .oidc-secrets> \
|
|
--username-claim username \
|
|
--autocreate 1
|
|
```
|
|
|
|
`--username-claim` accepts only `subject`, `username` or `email` — not
|
|
`preferred_username`, despite that being the underlying claim name. `username`
|
|
is the one you want; it is what makes the PVE user match the IPA uid.
|
|
|
|
`--autocreate 1` creates the PVE user entry on first login. It does **not**
|
|
grant permissions: assign those to groups under Datacenter → Permissions.
|
|
|
|
Two things that reliably break this:
|
|
|
|
- Keycloak must be reachable from the PVE node over **HTTPS with a
|
|
certificate the node trusts**. A self-signed gateway cert produces an
|
|
opaque HTTP 500 at login; install the CA on the node.
|
|
- Proxmox expects RS256-signed tokens, which is Keycloak's default. Do not
|
|
switch the realm or client to ES256/HS256.
|
|
|
|
## Proxmox Backup Server
|
|
|
|
Same model, `PBS_URL` and the `proxmox-bs` client:
|
|
|
|
```bash
|
|
proxmox-backup-manager openid create keycloak \
|
|
--issuer-url https://<gateway>/auth/realms/<KC_REALM> \
|
|
--client-id proxmox-bs \
|
|
--client-key <secret from .oidc-secrets> \
|
|
--username-claim username \
|
|
--autocreate true
|
|
```
|
|
|
|
PBS needs its own client — reusing the PVE one fails on the redirect URI.
|
|
|
|
---
|
|
|
|
## Monitoring the same appliances
|
|
|
|
Separate from SSO, and worth not conflating: these appliances are also
|
|
monitored, and monitoring uses CheckMK's automation credentials, never a user
|
|
identity.
|
|
|
|
### Proxmox VE / PBS — already wired
|
|
|
|
`ansipa-infra-checkmk-install.sh` installs the agent, drops the
|
|
`ansipa_pve` / `ansipa_pbs` local check and registers the host under
|
|
`/ansipa/infra`. Run it on each node:
|
|
|
|
```bash
|
|
./ansipa-infra-checkmk-install.sh https://mon.example.com:8090 cmk <automation-secret>
|
|
```
|
|
|
|
That covers cluster quorum, storage utilisation, guest counts and backup
|
|
freshness (PVE); datastore usage, last-backup outcome and task failures (PBS).
|
|
|
|
**Also worth enabling:** CheckMK ships a built-in *Proxmox VE special agent*
|
|
(Setup → Agents → VM, cloud, container → Proxmox VE) that talks to the PVE API
|
|
on port 8006 and generates piggyback data for the guests. It complements the
|
|
local checks rather than replacing them — the special agent sees the cluster
|
|
from outside and gives you per-VM data, the local check sees the node from
|
|
inside. Create a dedicated `checkmk@pve` user in the *Proxmox VE
|
|
authentication server* realm for it, not an OIDC user: the special agent needs
|
|
a password it can present non-interactively.
|
|
|
|
### OPNsense — new
|
|
|
|
```bash
|
|
scp ansipa-opnsense-*.sh root@fw:/root/
|
|
ssh root@fw /root/ansipa-opnsense-checkmk-install.sh \
|
|
https://mon.example.com:8090 cmk <automation-secret>
|
|
```
|
|
|
|
Adds `Ansipa_OPN_Gateways`, `Ansipa_OPN_States` (pf state table against its
|
|
hard limit — the check that actually catches a firewall falling over),
|
|
`Ansipa_OPN_Firmware`, and `Ansipa_OPN_CARP` on HA pairs.
|
|
|
|
The transport is deliberately **agent-over-SSH**, not the usual TCP 6556 via
|
|
inetd. OPNsense generates `/etc/inetd.conf`, `/etc/services` and
|
|
`/etc/hosts.allow` from `config.xml`, so it reverts those edits on the next
|
|
reboot or config apply and monitoring dies quietly weeks later. With the SSH
|
|
datasource nothing listens on the firewall and nothing gets overwritten. The
|
|
installer prints the exact key-restriction and CheckMK rule to add.
|
|
|
|
If you would rather not give CheckMK SSH access at all, enable SNMP on the
|
|
firewall and set the host to SNMP in CheckMK — you get interfaces, CPU, memory
|
|
and uptime, but none of the `Ansipa_OPN_*` checks, which need local execution.
|
|
|
|
### Keycloak itself
|
|
|
|
Keycloak exposes Prometheus-format metrics on the management port 9000
|
|
(`/metrics`, with `KC_HEALTH_ENABLED=true` already set in the compose file).
|
|
CheckMK Raw can scrape those, and health endpoints `/health/ready` and
|
|
`/health/live` are the cheap liveness signal. Note these live on port **9000**
|
|
and are *not* under `KC_HTTP_RELATIVE_PATH` — probing
|
|
`https://gateway/auth/health/ready` returns 404 and will look like an outage
|
|
that is not there.
|
|
|
|
---
|
|
|
|
## Packet captures to the SmartestHome LLM
|
|
|
|
Short answer: **not through CheckMK.** Passing a CheckMK API key to the LLM is
|
|
a good idea, but it buys you monitoring state, not packet data.
|
|
|
|
**Why not.** CheckMK is a state-and-metrics system. Its REST API exposes hosts,
|
|
services, service states, metrics, events, downtimes and comments — there is no
|
|
packet-capture object and no blob transport. You could technically smuggle
|
|
base64 pcap through a custom agent section, but the agent payload is re-parsed
|
|
in full on every check cycle (60s by default): captures are megabytes per
|
|
second, agent output is expected to be kilobytes, and you would blow up the
|
|
monitoring core to build a bad file transfer.
|
|
|
|
**What does work, with the same "one API key" ergonomics:**
|
|
|
|
1. **Give the LLM the CheckMK REST API for state.** One automation secret gets
|
|
it every host, every service, current and historical metrics, and the event
|
|
console. That answers "what is broken, since when, and what changed" —
|
|
which is most of what you actually want an LLM triaging.
|
|
|
|
2. **Put the packet analysis where the packets are.** Run Suricata or Zeek on
|
|
the OPNsense box (both are OPNsense plugins). They turn traffic into
|
|
structured events — `eve.json`, Zeek logs — which is far better LLM input
|
|
than raw pcap anyway, and orders of magnitude smaller.
|
|
|
|
3. **Bridge the two.** A local check on the firewall summarises IDS alert
|
|
counts/severities into CheckMK, so alerts show up beside everything else and
|
|
the LLM can see them through the same API key. When it needs detail, it
|
|
fetches the full event from the Suricata/Zeek store — a second, narrow
|
|
credential — using the timestamp and flow ID CheckMK gave it.
|
|
|
|
That keeps the "one key for situational awareness" property you wanted, without
|
|
making the monitoring system carry traffic it was never designed to move. If
|
|
you do want genuine on-demand pcap, the honest design is a small capture
|
|
service on the firewall exposing an authenticated endpoint, referenced *from* a
|
|
CheckMK service — not tunnelled through it.
|
|
|
|
---
|
|
|
|
## Break-glass accounts
|
|
|
|
Two local accounts deliberately do not live in FreeIPA, because they are how
|
|
you get in when the directory or Keycloak is the thing that is broken:
|
|
|
|
| Account | Where | Reach it at |
|
|
|---|---|---|
|
|
| `cmkadmin` | CheckMK | `/cmk/` normal login form |
|
|
| `ncadmin` (`NC_ADMIN_USER`) | Nextcloud | `/nextcloud/login?direct=1` |
|
|
|
|
Keep both in a password manager. Everything else — including your own
|
|
day-to-day admin account — should be an IPA identity.
|