mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
fix(peertube): let OIDC discovery reach a plaintext onion issuer
openid-client v6 refuses a non-HTTPS issuer, and an onion-exclusive Keycloak has none: the onion publishes only HiddenServicePort 80, and https there is blocked on four separate things (see TODO.md). PeerTube's plugin therefore threw OAUTH_HTTP_REQUEST_FORBIDDEN during discovery, never built a client, and answered 2326 logins with "OpenID provider unavailable" — while `test -d` on the plugin directory reported the deploy as ok. Two changes, one honest and one not: The gate at the end of enable.yml now fails when the container log carries "Initial OpenID discovery failed", so a plugin that registered without building a client stops the deploy instead of surfacing hours later in the browser suite. The sed over the installed dist is a hack and is marked as one in TODO.md. It widens the trigger of the escape hatch upstream already implements — the plugin gates `openid.allowInsecureRequests` on NODE_ENV alone, and setting NODE_ENV=dev in production would swap PeerTube's whole runtime profile. The `grep -q` after the substitution is what keeps it tolerable: an upstream release that moves the line fails the deploy loudly rather than silently doing nothing. Both are driven by one variable, PEERTUBE_OIDC_INSECURE_ISSUER, which requires SSO enabled AND tor enabled for peertube AND an .onion issuer, so no deploy without Tor can execute the patch or ever fail on it. Verified with Ansible's own templar across seven cases, including https://onionsoup.example.com/ to catch a too-greedy match. The sed itself was run against the real 2.0.1 tarball: exactly one hit, `node --check` clean, and the patched expression exercised in four environment combinations. Exit path in TODO.md: the plugin is an official Framasoft one (AGPL-3.0 in the repo root, the npm package merely ships no license field), and the proper fix is a `registerSetting({ name: 'allow-insecure-issuer' })` OR-ed into the same condition. Issue text and patch are written; upstream filing is waiting on a framagit account. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
ec58997771
commit
e64ed1cd93
4 files changed
+69
No files matched your search
@@ -20,6 +20,53 @@ failure class from that run is committed (hlth-csp onion-sibling skip,
|
||||
onion-aware Playwright request timeouts + lint guard, joomla server-side OIDC
|
||||
reachability). The items below are the ones that are NOT fixed yet.
|
||||
|
||||
- **https on the onion IdP — investigated and REJECTED, do not re-derive.** OIDC
|
||||
Discovery / RFC 8414 want an https issuer, and an onion-exclusive Keycloak has
|
||||
none, so strict client libraries refuse it. Serving TLS on the onion is blocked
|
||||
on four independent things, in this order: (1) `roles/svc-net-tor/templates/torrc.j2`
|
||||
publishes only `HiddenServicePort 80`, and no role declares 443 in
|
||||
`ports.public`/`ports.local`, so `lookup('tor_ports')` can never emit it —
|
||||
flipping TLS on first makes Keycloak unreachable over Tor entirely, because
|
||||
`nginx_ssl_header.j2` is one if/else and port 80 disappears; (2)
|
||||
`roles/sys-front-tls-selfsigned/tasks/00_core.yml` writes an unguarded CN, which
|
||||
overflows X.509's 64-byte cap on a 62-char v3 onion — `group_vars/all/02_tls.yml`
|
||||
already guards exactly this for the root CA and nowhere else; (3)
|
||||
`nginx_ssl_header.j2` emits HSTS in the same branch, and browsers offer no
|
||||
click-through on an HSTS host with an untrusted chain, so a self-signed interim
|
||||
locks real users out while staying invisible to Playwright's
|
||||
`ignoreHTTPSErrors`; (4) it fixes zero libcurl consumers, because RFC 7686
|
||||
refusal happens at name resolution and is scheme-independent. Unblocking needs a
|
||||
CA that issues for v3 `.onion` (HARICA, CA/B Forum ballot 144) — procurement,
|
||||
not code. Until then the per-consumer fixes stand: SOCKS proxy for libcurl
|
||||
clients, and the `PEERTUBE_OIDC_ALLOW_INSECURE_ISSUER` dist patch for
|
||||
openid-client v6.
|
||||
|
||||
- **peertube OIDC dist patch — a hack, kept deliberately, remove when upstream
|
||||
lands.** `roles/web-app-peertube/tasks/oidc/enable.yml` runs a `sed` over the
|
||||
npm-installed `dist/main.js` of `peertube-plugin-auth-openid-connect` so the
|
||||
plugin honours `PEERTUBE_OIDC_ALLOW_INSECURE_ISSUER` (set in `templates/env.j2`
|
||||
only when the issuer is an onion). It exists because openid-client v6 refuses a
|
||||
non-HTTPS issuer and the plugin gates its own escape hatch on `NODE_ENV` alone,
|
||||
which would swap PeerTube's whole runtime profile. Patching a third party's
|
||||
compiled output is fragile by construction; the `grep -q` after the `sed` is
|
||||
what keeps it honest — an upstream release that moves the line fails the deploy
|
||||
loudly instead of silently doing nothing.
|
||||
Exit path, in order: (1) file the issue and MR upstream — the plugin is an
|
||||
official Framasoft one by Chocobozzz, AGPL-3.0 per the repo root `LICENSE`
|
||||
(the npm package just ships no license field), and the fix is a
|
||||
`registerSetting({ name: 'allow-insecure-issuer', type: 'input-checkbox',
|
||||
default: false })` OR-ed into the existing condition; issue text and patch are
|
||||
written and waiting. Currently blocked: the framagit account is not approved
|
||||
yet. (2) Until it merges, run a fork — `git subtree split --prefix=
|
||||
peertube-plugin-auth-openid-connect` gives a standalone repo (the 16 official
|
||||
plugins sit flat in the root with no shared build, so nothing is missing except
|
||||
the root `LICENSE`, which must be copied), built with `npm ci && npm run build`
|
||||
because `library: ./dist/main.js` and `.npmignore` excludes `src`, and installed
|
||||
with `--plugin-path`: `--npm-name` cannot take a git URL because
|
||||
`getTypeFromNpmName` requires a `peertube-plugin-*` name, while `--plugin-path`
|
||||
only needs the *directory* to carry that name. (3) Delete the sed task, the env
|
||||
var and this entry once the setting is released.
|
||||
|
||||
- **dual-family providers** — the one real remaining design gap. On a CI onion
|
||||
node, tor-enabled providers (e.g. mastodon) are onion-exclusive: their domain
|
||||
list contains only the `.onion` canonical, no clearnet sibling. The
|
||||
|
||||
@@ -56,6 +56,15 @@
|
||||
changed_when: true
|
||||
delegate_to: "{{ PEERTUBE_HOST_NODE }}"
|
||||
|
||||
- name: "🩹 Let the OIDC plugin accept the plaintext onion issuer"
|
||||
ansible.builtin.shell: |
|
||||
# nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
|
||||
container exec {{ PEERTUBE_LOCAL_CID | quote }} sh -c 'f=/data/plugins/node_modules/{{ PEERTUBE_OIDC_PLUGIN }}/dist/main.js; sed -i "s#const discoverInsecureConfig = process.env.NODE_ENV#const discoverInsecureConfig = process.env.PEERTUBE_OIDC_ALLOW_INSECURE_ISSUER || process.env.NODE_ENV#" "$f"; grep -q PEERTUBE_OIDC_ALLOW_INSECURE_ISSUER "$f"'
|
||||
when: PEERTUBE_OIDC_INSECURE_ISSUER | bool
|
||||
changed_when: true
|
||||
delegate_to: "{{ PEERTUBE_HOST_NODE }}"
|
||||
notify: container recreate
|
||||
|
||||
- name: "🔄 Update the settings column of the auth-openid-connect plugin"
|
||||
database_query:
|
||||
mask_values: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
|
||||
@@ -101,3 +110,12 @@
|
||||
until: _peertube_oidc_verified.rc == 0
|
||||
changed_when: false
|
||||
delegate_to: "{{ PEERTUBE_HOST_NODE }}"
|
||||
|
||||
- name: "🛑 Fail if the OIDC plugin registered but never built a client"
|
||||
shell: |
|
||||
# nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
|
||||
container logs {{ PEERTUBE_LOCAL_CID | quote }} 2>&1 | grep -q 'Initial OpenID discovery failed'
|
||||
register: _peertube_oidc_discovery_failed
|
||||
failed_when: _peertube_oidc_discovery_failed.rc == 0
|
||||
changed_when: false
|
||||
delegate_to: "{{ PEERTUBE_HOST_NODE }}"
|
||||
@@ -54,3 +54,6 @@ PEERTUBE_SMTP_DISABLE_STARTTLS={{ 'false' if email.start_tls else 'true' }}
|
||||
{% endif %}
|
||||
|
||||
PEERTUBE_ADMIN_EMAIL={{ email['from'] }}
|
||||
{% if PEERTUBE_OIDC_INSECURE_ISSUER | bool %}
|
||||
PEERTUBE_OIDC_ALLOW_INSECURE_ISSUER=1
|
||||
{% endif %}
|
||||
@@ -7,6 +7,7 @@ PEERTUBE_CONTAINER_ADDRESS: "{{ lookup('container_address', application_id, enti
|
||||
|
||||
PEERTUBE_OIDC_PLUGIN: "peertube-plugin-auth-openid-connect"
|
||||
PEERTUBE_OIDC_ENABLED: "{{ lookup('config', application_id, 'services.sso.enabled') }}"
|
||||
PEERTUBE_OIDC_INSECURE_ISSUER: "{{ PEERTUBE_OIDC_ENABLED | bool and (lookup('config', application_id, 'services.tor.enabled') | bool) and (OIDC.CLIENT.ISSUER_URL is search('\\.onion(/|:|$)')) }}"
|
||||
|
||||
PEERTUBE_LIVE_ENABLED: "{{ lookup('config', application_id, 'services.peertube.live.enabled') | bool }}"
|
||||
PEERTUBE_RTMP_PORT: "{{ lookup('config', application_id, 'services.peertube.ports.internal.rtmp') }}"
|
||||
|
||||
Reference in new issue
Block a user