Skip to content

No test covers the 0.6.0 portal generation: no published image carries it yet #262

Description

@guimard

The gap

Every portal-side test in this tree runs against the old plugin generation.
Nothing exercises the 0.6.0 half, because no published image carries it yet.

Verified on 2026-09-07, on both candidate tags:

yadd/lemonldap-ng-portal:latest (2026-09-01) …:2.23.3-3 (2026-08-30)
LLNG core 2.23.3 2.23.3
PamAccess.pm 2.22.0 2.22.0
/pam/whoami route absent absent
/pam/bastion-token route present present
_checkCaller (signature check) absent absent
pamAccessRequireFingerprint absent absent
pamAccessBastionVoucherUnboundTtl absent absent
docker run --rm --entrypoint sh yadd/lemonldap-ng-portal:latest -c \
  'grep -c "whoami\|_checkCaller" /usr/share/perl5/Lemonldap/NG/Portal/Plugins/PamAccess.pm'

So :latest is not ahead of 2.23.3-3 in any respect that matters here.
(The tag is 2.23.3-3; v2.23.3-3 does not exist on the registry.)

What that leaves untested

Each of these is implemented on our side, documented in UPGRADE-NOTES.md, and
exercised by nothing:

  1. POST /pam/whoami — the primary path of ob-bastion-id (ob-bastion-id breaks when /pam/bastion-token is removed, and deploy-shell.sh silently writes a wrong bastion id when it does #246). Only
    its legacy fallback is covered today, and only by accident of the portal
    being old. tests/test_ob_bastion_id.sh covers the shapes against a mock,
    not against a real portal.
  2. Request-signature verification (The PAM client signs 2 of 6 /pam/* endpoints, so pamAccessRequestSigningMode=required cannot be turned on #247). Every caller signs, but no portal
    in CI checks a signature, so pamAccessRequestSigningMode = optional and
    = required have never been exercised end to end — including the failure
    mode UPGRADE-NOTES.md step B3 is written to prevent.
  3. pamAccessRequireFingerprint and the 15-minute
    pamAccessBastionVoucherUnboundTtl (SSH fingerprint binding is dropped with only a DEBUG log when the spool is missing #192, Fingerprint spool: move the trust root off nobody to a socket-activated root daemon #249). The host-side half is
    tested; the portal-side refusal and the short-TTL hop failure are not.
  4. sshCaAdminRule fail-closed (Ship and document locationRules for /device and /ssh/* in the production setups #195). tests/test_ob_llng_location_rules.sh
    compiles the rules; nothing checks that the routes actually answer 403 when
    the rule is unset.
  5. Exact PAM scope matching (UPGRADE-NOTES.md step B4) — that an RP
    granted pam-prod loses /pam/*.
  6. That the fallback is not taken when /pam/whoami exists. Today it is
    always taken, so a regression that made it unconditional would pass.

Why this is a ticket and not a TODO

docker-demo-cert/sso/Dockerfile is now deliberately pinned to
2.23.3-3-non-root, with the reason in a comment. That pin is correct and
should stay: it is the only thing keeping the legacy /pam/bastion-token
fallback covered once a newer image exists.

But the pin also means that when the 0.6.0 image is published, nothing will
start failing and nothing will start passing
— coverage of the new generation
simply will not appear. There is no signal. Hence this.

What to do when an image lands

  1. Point one demo at it — a new docker-demo-next/sso, or move
    docker-demo-maxsec — and leave docker-demo-cert pinned where it is.
  2. Add the portal-side assertions the new generation makes possible, at least
    items 1, 2 and 3 above.
  3. Extend tests/test_ob_upgrade.sh, which today upgrades a host from
    v0.6.2, with the portal-upgrade direction: old portal → new portal with
    0.7.0 hosts on both sides, which is the sequence UPGRADE-NOTES.md step B1
    tells operators to follow.

Acceptance

  • One demo runs a portal whose PamAccess.pm has a /pam/whoami route and a
    _checkCaller, asserted rather than assumed.
  • docker-demo-cert still runs a portal without them, and
    tests/test_ob_upgrade.sh's pin assertion still passes.
  • ob-bastion-id is shown taking the /pam/whoami path against the new portal
    and the fallback against the old one — the same binary, both branches.
  • pamAccessRequestSigningMode = required is exercised end to end.

Detecting that it has landed

Worth a scheduled CI job rather than someone remembering: fail (or open a
notice) when :latest gains a whoami route while every demo is still pinned
below it. The one-liner above is the whole check.

Found while adding ob-post-upgrade and the upgrade suite (#261), where the
pin was introduced.

https://claude.ai/code/session_011q88Fs4nFuUs7JMvmgbBTN

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions