029 - Checkmk Role with oauth2-proxy SSO + LDAP¶
User Story¶
As a platform administrator of Infinito.Nexus, I want Checkmk integrated as a web-app-checkmk role with Keycloak SSO (via the oauth2-proxy gate) and native LDAP user management so that operators can run the open-source Checkmk monitoring server behind the platform’s central Single Sign-On, validated end-to-end with Playwright personas.
Background¶
Checkmk is an open-source IT/infrastructure & application monitoring system. The Raw / Community edition (100% open source) ships an official all-in-one container that bundles the monitoring core, RRD storage, and the Apache-served web GUI — it needs no external database.
Upstream facts established by research¶
Topic |
Finding |
Source |
|---|---|---|
Image |
|
|
Bootstrap env |
|
|
Ports |
|
|
Database |
None external — Checkmk Raw bundles Nagios core + RRDtool; all state on one persistent volume ( |
|
LDAP |
Native in all editions (incl. Raw): LDAP “connections” sync users, contact groups, roles. |
|
SAML |
Commercial editions only; Raw needs |
|
OIDC |
Not native in any edition; Raw only via Apache |
|
Header SSO |
Global setting “Authenticate users by incoming HTTP requests” / |
In-repo analogues¶
SSO flavor is
oauth2(oauth2-proxy sidecar → Keycloak), NOT native OIDC — because Checkmk Raw has no OIDC. The oauth2-proxy authenticates against Keycloak and passesX-Remote-User; Checkmk’s site Apache trusts it viaauth_by_http_header. This mirrorsweb-app-openproject’s header-SSO bridge (OPENPROJECT_AUTH__SOURCE__SSO_HEADER+ LDAP-gated header trust).LDAP native (the user record + roles/contact groups), gated on
svc-db-openldap, so theX-Remote-User(Keycloakpreferred_username) resolves to a real Checkmk user.No external DB consumer (unlike the Semaphore role, which is tracked on a separate branch/PR).
Confirmed Decisions¶
These decisions were confirmed by the operator before implementation starts and are NOT subject to re-litigation during implementation.
# |
Decision |
Rationale |
|---|---|---|
1 |
Canonical hostname |
Standard single-host convention; Checkmk serves its GUI under the OMD site path. |
2 |
Edition is Raw / Community ( |
Operator decision: 100% open source, matches the platform; OIDC handled via the oauth2-proxy gate. |
3 |
SSO is the oauth2-proxy gate + Checkmk header-auth ( |
Operator decision: Keycloak SSO at the proxy, Checkmk trusts the proxy-supplied user, LDAP supplies the user record/roles/contact groups. |
4 |
The agent receiver (port 8000) IS exposed (mapped + proxied) for TLS agent registration. |
Operator decision: enable remote-host agent registration in v1. |
5 |
Image pinned to a concrete stable Checkmk 2.x patch tag (no |
Standard upstream-pin policy. |
6 |
OMD site id |
Checkmk Raw bundles its own core/RRD; nothing external needed. |
Target Schema¶
Role layout¶
roles/web-app-checkmk/
├── README.md
├── files/playwright/{_shared,playwright.spec,test-guest,test-login-oidc-biber,test-login-oidc-administrator,test-login-ldap-biber}.js
├── meta/{main,info,server,services,schema,users,rbac,variants,volumes}.yml
├── tasks/{main,00_core}.yml
├── templates/{compose.yml.j2,env.j2,playwright.env.j2}
└── vars/main.yml
meta/services.yml excerpt (oauth2-proxy flavor, no external DB)¶
sso:
enabled: "{{ 'web-app-keycloak' in group_names }}"
shared: "{{ 'web-app-keycloak' in group_names }}"
flavor: oauth2
oauth2:
origin: { host: application, port: "5000" }
ldap:
enabled: "{{ 'svc-db-openldap' in group_names }}"
shared: "{{ 'svc-db-openldap' in group_names }}"
checkmk:
image: checkmk/check-mk-raw
version: "X.Y.Zp?"
name: checkmk
ports:
internal: { http: 5000 }
local: { http: <free port> }
run_after: [web-app-keycloak]
lifecycle: alpha
Acceptance Criteria¶
Routing & TLS¶
[ ]
monitoring.{{ DOMAIN_PRIMARY }}resolves throughsys-svc-proxy(and, when SSO is on, the oauth2-proxy gate) to the Checkmk site Apache;GET /<site>/check_mk/returns the Checkmk login/GUI.[ ] The site-path redirect (
/→/<site>/check_mk/) works behind the proxy.[ ] The role emits a
Content-Security-Policyheader on the canonical surface.[ ] The agent receiver (container port
8000) is mapped to a host port (Decision #4) and reachable for TLS agent registration.
Role layout & image¶
[ ]
roles/web-app-checkmk/exists per the Target Schema; image pinned to a concrete Checkmk 2.x patch (no:latest).[ ] All
meta/*.ymlexist and pass the role-meta lint.
Bootstrap¶
[ ]
CMK_SITE_ID,CMK_PASSWORD(from a rendered credential),TZseed the site +cmkadminon first run; the stack reaches a steady running state on one persistent volume.
SSO / oauth2 + header auth (Decision #3)¶
[ ] When SSO is enabled, the oauth2-proxy gate fronts Checkmk and authenticates against Keycloak (client auto-provisioned via the
redirect_urisfilter).[ ] Checkmk’s
auth_by_http_header = "X-Remote-User"is configured so the proxy-supplied user is logged in without a second login.[ ] A Playwright OIDC flow (biber + administrator) passes the oauth2-proxy → Keycloak chain and lands authenticated in the Checkmk GUI (administrator additionally reaches a Setup/admin-only surface).
LDAP (Decision #3)¶
[ ] When
svc-db-openldapis ingroup_names, an LDAP connection is provisioned (files/configure-sso.sh) so LDAP users (matching theX-Remote-User) exist with roles/contact groups. LDAP is a backend identity source behind the oauth2 gate — there is no separate LDAP login surface, so it is exempted from a Playwright gate (# nocheck: playwright-service-flag), mirroringweb-app-openproject.
Variants¶
[ ]
meta/variants.ymldefines three variants (V1 sso+ldap, V2 all-false, V3 ldap-only); all deploy cleanly on a fresh box.
Playwright¶
[ ] Persona coverage via the shared oauth2-gate helpers (mirroring
web-app-openproject):test-baseline.js(reachability + guest/biber/administrator personas),test-oidc-login.js(oauth2 gate +X-Remote-Usersession, gated onsso),test-oidc-security.js(forged-header bypass guard).biber/administratorare gated to SSO viaPERSONA_*_BLOCKED.templates/playwright.env.j2exposes every read env var;make compose-playwright role=web-app-checkmkexits 0 with no stub tests and a clean logged-out final state.
Health & quality¶
[ ] Stack steady across all three variants;
make testgreen tree-wide.
Documentation¶
[ ]
README.mddocuments edition + bump policy, the oauth2-proxy+header-auth+LDAP model, the site-path routing, the agent-receiver decision, and the no-external-DB design.[ ] This requirement is cross-linked from the implementing PR.
Validation Apps¶
INFINITO_APPS="web-app-checkmk" make deploy-fresh-purged-apps INFINITO_FULL_CYCLE=true
Smoke: visit https://monitoring.{{ DOMAIN_PRIMARY }}/ → (SSO) Keycloak chain → Checkmk GUI; open Setup (admin); confirm an LDAP user resolves.
Prerequisites¶
Before implementation, the agent MUST read AGENTS.md, then Role Loop and the Playwright contract.
Implementation Strategy¶
Execute autonomously after the Open Questions are resolved. Scaffold using roles/web-app-openproject/ as the structural template (oauth2 flavor + header SSO + LDAP). Verify all Checkmk env names, the auth_by_http_header config mechanism, site-path routing, and the GUI selectors against the pinned upstream version before claiming done.
Commit Policy¶
No git commit until every Acceptance Criterion is checked off.
When met and
make testis green, instruct the operator to rungit-sign-pushoutside the sandbox. The agent MUST NOT push.
Context¶
Upstream repo: https://github.com/Checkmk/checkmk
Docker docs: https://docs.checkmk.com/latest/en/introduction_docker.html
Header auth: https://checkmk.com/werk/7819
Closest in-repo analogue:
roles/web-app-openproject/(oauth2 + header SSO + LDAP)