From cecde3e1977d8e595b21798914643ce6bc3c738d Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 24 Dec 2025 15:26:02 -0300 Subject: [PATCH] jellyfin: drop OIDC plugin and strip injected script --- services/jellyfin/deployment.yaml | 204 ++++++++---------------------- 1 file changed, 50 insertions(+), 154 deletions(-) diff --git a/services/jellyfin/deployment.yaml b/services/jellyfin/deployment.yaml index fdd244a..14e9686 100644 --- a/services/jellyfin/deployment.yaml +++ b/services/jellyfin/deployment.yaml @@ -21,6 +21,31 @@ spec: labels: app: jellyfin spec: + # Clean up any lingering OIDC artifacts and strip the injected script tag + initContainers: + - name: strip-oidc + image: docker.io/jellyfin/jellyfin:10.11.5 + securityContext: + runAsUser: 0 + runAsGroup: 0 + command: + - /bin/sh + - -c + - | + set -euxo pipefail + cp -a /jellyfin/jellyfin-web/. /web-root + # remove injected OIDC script tags everywhere just in case + for f in $(find /web-root -type f -name 'index.html'); do + sed -i '/oidc\/inject/d' "$f" + printf '%s\n' "$f" + done + # clean any lingering OIDC plugin artifacts on the config volume + rm -rf "/config/plugins/OIDC Authentication_"* /config/plugins/configurations/JellyfinOIDCPlugin.v2.xml || true + volumeMounts: + - name: web-root + mountPath: /web-root + - name: config + mountPath: /config nodeSelector: jellyfin: "true" securityContext: @@ -28,142 +53,6 @@ spec: fsGroup: 65532 fsGroupChangePolicy: OnRootMismatch runAsGroup: 65532 - initContainers: - - name: fetch-oidc-plugin - image: alpine:3.20 - securityContext: - runAsUser: 0 - env: - - name: OIDC_PLUGIN_REPO - value: "registry.bstein.dev/streaming/oidc-plugin" - - name: OIDC_PLUGIN_TAG - value: "10.11.5" - - name: ORAS_USERNAME - valueFrom: - secretKeyRef: - name: harbor-robot - key: username - optional: true - - name: ORAS_PASSWORD - valueFrom: - secretKeyRef: - name: harbor-robot - key: password - optional: true - volumeMounts: - - name: oidc-plugin - mountPath: /plugin-src - command: ["/bin/sh", "-c"] - args: - - | - set -euo pipefail - apk add --no-cache curl tar - ORAS_VERSION=1.2.0 - curl -sSL "https://github.com/oras-project/oras/releases/download/v${ORAS_VERSION}/oras_${ORAS_VERSION}_linux_amd64.tar.gz" | tar -xz -C /usr/local/bin oras - ref="${OIDC_PLUGIN_REPO}:${OIDC_PLUGIN_TAG}" - cd /plugin-src - if [ -n "${ORAS_USERNAME:-}" ] && [ -n "${ORAS_PASSWORD:-}" ]; then - oras login "$(echo "${OIDC_PLUGIN_REPO}" | cut -d/ -f1)" -u "${ORAS_USERNAME}" -p "${ORAS_PASSWORD}" - fi - oras pull --allow-path-traversal "${ref}" - ls -lh /plugin-src - - name: install-oidc-plugin - image: alpine:3.20 - securityContext: - runAsUser: 0 - env: - - name: OIDC_PLUGIN_VERSION - value: "1.0.2.0" - - name: OIDC_ISSUER - value: "https://sso.bstein.dev/realms/atlas" - - name: OIDC_REDIRECT_URI - value: "https://stream.bstein.dev/api/oidc/callback" - - name: OIDC_LOGOUT_URI - value: "https://sso.bstein.dev/realms/atlas/protocol/openid-connect/logout?redirect_uri=https://stream.bstein.dev/" - - name: OIDC_SCOPES - value: "openid,profile,email" - - name: OIDC_ROLE_CLAIM - value: "groups" - - name: OIDC_CLIENT_ID - valueFrom: - secretKeyRef: - name: jellyfin-oidc - key: client-id - - name: OIDC_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: jellyfin-oidc - key: client-secret - volumeMounts: - - name: config - mountPath: /config - - name: oidc-plugin - mountPath: /plugin-src - command: ["/bin/sh", "-c"] - args: - - | - set -euo pipefail - if [ -z "${OIDC_CLIENT_ID:-}" ] || [ -z "${OIDC_CLIENT_SECRET:-}" ]; then - echo "OIDC_CLIENT_ID or OIDC_CLIENT_SECRET missing; create secret jellyfin-oidc" >&2 - exit 1 - fi - rm -rf "/config/plugins/LDAP Authentication_20.0.0.0" - apk add --no-cache unzip - plugin_dir="/config/plugins/OIDC Authentication_${OIDC_PLUGIN_VERSION}" - config_dir="/config/plugins/configurations" - plugin_zip="/plugin-src/OIDC_Authentication_${OIDC_PLUGIN_VERSION}-net9.zip" - if [ ! -s "${plugin_zip}" ]; then - echo "Plugin zip missing at ${plugin_zip}" >&2 - echo "Contents of /plugin-src:" >&2 - ls -lah /plugin-src >&2 || true - exit 1 - fi - rm -rf "${plugin_dir}" - mkdir -p "${plugin_dir}" "${config_dir}" - unzip -o "${plugin_zip}" -d "${plugin_dir}" - rm -f "${plugin_dir}"/Microsoft.Extensions.*.dll - cat >"${plugin_dir}/meta.json" <<'EOF' - { - "category": "Authentication", - "changelog": "OIDC SSO authentication plugin; auto user creation and role mapping", - "description": "OpenID Connect (OIDC) authentication provider for Jellyfin with SSO support.", - "guid": "a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6", - "name": "OIDC Authentication", - "overview": "Enable Single Sign-On (SSO) for Jellyfin using an OpenID Connect provider.", - "owner": "lolerskatez", - "targetAbi": "10.11.5.0", - "timestamp": "2025-12-17T04:00:00Z", - "version": "1.0.2.0", - "status": "Active", - "autoUpdate": false, - "imagePath": "", - "assemblies": [] - } - EOF - scope_lines="" - for s in $(echo "${OIDC_SCOPES}" | tr ',' ' '); do - trimmed="$(echo "${s}" | xargs)" - [ -z "${trimmed}" ] && continue - scope_lines="${scope_lines} ${trimmed}\n" - done - config_file="${config_dir}/JellyfinOIDCPlugin.v2.xml" - cat >"${config_file}" < - - ${OIDC_ISSUER} - ${OIDC_CLIENT_ID} - ${OIDC_CLIENT_SECRET} - - $(printf "%b" "${scope_lines}") - ${OIDC_ROLE_CLAIM} - ${OIDC_REDIRECT_URI} - ${OIDC_LOGOUT_URI} - - true - false - - EOF - chown -R 1000:65532 "${plugin_dir}" "${config_file}" runtimeClassName: nvidia containers: - name: jellyfin @@ -183,22 +72,6 @@ spec: value: "65532" - name: UMASK value: "002" - lifecycle: - postStart: - exec: - command: - - /bin/sh - - -c - - | - set -e - target="/jellyfin/jellyfin-web/index.html" - marker='api/oidc/inject' - if grep -q "${marker}" "${target}"; then - exit 0 - fi - tmp="$(mktemp)" - awk -v marker="${marker}" 'BEGIN{inserted=0} /<\/head>/ && !inserted {print " "; inserted=1} {print}' "${target}" > "${tmp}" - cp "${tmp}" "${target}" resources: limits: nvidia.com/gpu: 1 @@ -211,16 +84,35 @@ spec: volumeMounts: - name: config mountPath: /config + # Override LDAP plugin configuration from a secret to avoid embedding credentials in the PVC. + - name: ldap-config + mountPath: /config/plugins/configurations/LDAP-Auth.xml + subPath: ldap-config.xml - name: cache mountPath: /cache - name: media mountPath: /media + - name: web-root + mountPath: /jellyfin/jellyfin-web + lifecycle: + postStart: + exec: + command: + - /bin/sh + - -c + - | + set -eux + for f in $(find /jellyfin/jellyfin-web -type f -name 'index.html'); do + sed -i '/oidc\/inject/d' "$f" || true + done securityContext: runAsUser: 0 runAsGroup: 0 allowPrivilegeEscalation: false readOnlyRootFilesystem: false volumes: + - name: web-root + emptyDir: {} - name: config persistentVolumeClaim: claimName: jellyfin-config-astreae @@ -230,5 +122,9 @@ spec: - name: media persistentVolumeClaim: claimName: jellyfin-media-asteria-new - - name: oidc-plugin - emptyDir: {} + - name: ldap-config + secret: + secretName: jellyfin-ldap-config + items: + - key: ldap-config.xml + path: ldap-config.xml