Fix qBittorrent auth: stamp known password hash via initContainer
LocalhostAuthEnabled=false isn't honored in this qBT version. Instead, initContainer stamps the PBKDF2 hash for admin:adminadmin before startup so all three pods have consistent credentials. portforward-helper and coordinator restored to cookie-based SID auth.
This commit is contained in:
@@ -26,10 +26,30 @@ data:
|
|||||||
PRIMARY = BACKENDS[0] if BACKENDS else ""
|
PRIMARY = BACKENDS[0] if BACKENDS else ""
|
||||||
sids = {}
|
sids = {}
|
||||||
|
|
||||||
|
def fetch_sid(backend):
|
||||||
|
data = urllib.parse.urlencode({"username": USER, "password": PASS}).encode()
|
||||||
|
req = urllib.request.Request(f"{backend}/api/v2/auth/login", data=data)
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(req, timeout=5) as r:
|
||||||
|
for k, v in r.getheaders():
|
||||||
|
if k.lower() == "set-cookie" and "SID=" in v:
|
||||||
|
return v.split("SID=")[1].split(";")[0]
|
||||||
|
except Exception as e:
|
||||||
|
print(f"auth failed for {backend}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def sid(backend):
|
||||||
|
if not sids.get(backend):
|
||||||
|
sids[backend] = fetch_sid(backend)
|
||||||
|
return sids.get(backend, "")
|
||||||
|
|
||||||
def active_count(backend):
|
def active_count(backend):
|
||||||
"""Return number of downloading torrents on this backend, or large int on error."""
|
"""Return number of downloading torrents on this backend, or large int on error."""
|
||||||
try:
|
try:
|
||||||
req = urllib.request.Request(f"{backend}/api/v2/torrents/info?filter=downloading")
|
req = urllib.request.Request(
|
||||||
|
f"{backend}/api/v2/torrents/info?filter=downloading",
|
||||||
|
headers={"Cookie": f"SID={sid(backend)}"},
|
||||||
|
)
|
||||||
with urllib.request.urlopen(req, timeout=3) as r:
|
with urllib.request.urlopen(req, timeout=3) as r:
|
||||||
return len(json.loads(r.read()))
|
return len(json.loads(r.read()))
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -42,7 +62,7 @@ data:
|
|||||||
return chosen
|
return chosen
|
||||||
|
|
||||||
def forward(backend, method, path, body, content_type):
|
def forward(backend, method, path, body, content_type):
|
||||||
headers = {}
|
headers = {"Cookie": f"SID={sid(backend)}"}
|
||||||
if content_type:
|
if content_type:
|
||||||
headers["Content-Type"] = content_type
|
headers["Content-Type"] = content_type
|
||||||
req = urllib.request.Request(
|
req = urllib.request.Request(
|
||||||
@@ -53,6 +73,18 @@ data:
|
|||||||
with urllib.request.urlopen(req, timeout=30) as r:
|
with urllib.request.urlopen(req, timeout=30) as r:
|
||||||
return r.status, r.read(), list(r.getheaders())
|
return r.status, r.read(), list(r.getheaders())
|
||||||
except urllib.error.HTTPError as e:
|
except urllib.error.HTTPError as e:
|
||||||
|
if e.code == 403:
|
||||||
|
sids[backend] = fetch_sid(backend)
|
||||||
|
headers["Cookie"] = f"SID={sids[backend]}"
|
||||||
|
req2 = urllib.request.Request(
|
||||||
|
f"{backend}{path}", data=body if method == "POST" else None,
|
||||||
|
headers=headers, method=method,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(req2, timeout=30) as r:
|
||||||
|
return r.status, r.read(), list(r.getheaders())
|
||||||
|
except Exception as e2:
|
||||||
|
return 500, str(e2).encode(), []
|
||||||
return e.code, e.read(), []
|
return e.code, e.read(), []
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return 500, str(e).encode(), []
|
return 500, str(e).encode(), []
|
||||||
@@ -107,6 +139,10 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: BACKENDS
|
- name: BACKENDS
|
||||||
value: "http://qbittorrent.media.svc:8080,http://fornax-worker-tx253.media.svc:8080,http://fornax-worker-tx34.media.svc:8080"
|
value: "http://qbittorrent.media.svc:8080,http://fornax-worker-tx253.media.svc:8080,http://fornax-worker-tx34.media.svc:8080"
|
||||||
|
- name: QBT_USER
|
||||||
|
value: "admin"
|
||||||
|
- name: QBT_PASS
|
||||||
|
value: "adminadmin"
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8080
|
- containerPort: 8080
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
|
|||||||
@@ -41,16 +41,16 @@ spec:
|
|||||||
- -c
|
- -c
|
||||||
- |
|
- |
|
||||||
CONF=/config/qBittorrent/qBittorrent.conf
|
CONF=/config/qBittorrent/qBittorrent.conf
|
||||||
|
HASH='@ByteArray(HqYj1eGsdXlQ4CSy597Y9A==:J9hsJIlU5FYfHb5rY5qQoIpVpTijryS/H+CE07oMtplL/ytneBVFd2tfVJtqGjhdht8tEi4wmqSSlqTgEu444w==)'
|
||||||
mkdir -p /config/qBittorrent
|
mkdir -p /config/qBittorrent
|
||||||
if [ -f "$CONF" ]; then
|
if [ -f "$CONF" ]; then
|
||||||
if grep -q "LocalhostAuthEnabled" "$CONF"; then
|
if grep -q "Password_PBKDF2" "$CONF"; then
|
||||||
sed -i 's/LocalhostAuthEnabled=.*/LocalhostAuthEnabled=false/' "$CONF"
|
sed -i "s|WebUI\\\\Password_PBKDF2=.*|WebUI\\\\Password_PBKDF2=\"$HASH\"|" "$CONF"
|
||||||
else
|
else
|
||||||
sed -i '/^\[Preferences\]/a WebUI\\LocalhostAuthEnabled=false' "$CONF" || \
|
sed -i "/^\[Preferences\]/a WebUI\\\\Password_PBKDF2=\"$HASH\"" "$CONF"
|
||||||
printf '\n[Preferences]\nWebUI\\LocalhostAuthEnabled=false\n' >> "$CONF"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
echo "Config patched: $(grep LocalhostAuth $CONF 2>/dev/null || echo 'will be set on first run')"
|
echo "Password hash set."
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: config
|
- name: config
|
||||||
mountPath: /config
|
mountPath: /config
|
||||||
@@ -103,7 +103,9 @@ spec:
|
|||||||
PORT=$(cat /tmp/gluetun/forwarded_port)
|
PORT=$(cat /tmp/gluetun/forwarded_port)
|
||||||
if [ -n "$PORT" ] && [ "$PORT" != "0" ]; then
|
if [ -n "$PORT" ] && [ "$PORT" != "0" ]; then
|
||||||
echo "$(date): Forwarded port: $PORT — updating qBittorrent"
|
echo "$(date): Forwarded port: $PORT — updating qBittorrent"
|
||||||
curl -s -X POST http://localhost:8080/api/v2/app/setPreferences \
|
curl -s -c /tmp/qbt.txt -X POST http://localhost:8080/api/v2/auth/login \
|
||||||
|
-d "username=admin&password=adminadmin" >/dev/null 2>&1
|
||||||
|
curl -s -b /tmp/qbt.txt -X POST http://localhost:8080/api/v2/app/setPreferences \
|
||||||
-d "json={\"listen_port\":$PORT,\"random_port\":false}" >/dev/null 2>&1
|
-d "json={\"listen_port\":$PORT,\"random_port\":false}" >/dev/null 2>&1
|
||||||
echo "$(date): qBittorrent listen port set to $PORT"
|
echo "$(date): qBittorrent listen port set to $PORT"
|
||||||
else
|
else
|
||||||
@@ -215,16 +217,16 @@ spec:
|
|||||||
- -c
|
- -c
|
||||||
- |
|
- |
|
||||||
CONF=/config/qBittorrent/qBittorrent.conf
|
CONF=/config/qBittorrent/qBittorrent.conf
|
||||||
|
HASH='@ByteArray(HqYj1eGsdXlQ4CSy597Y9A==:J9hsJIlU5FYfHb5rY5qQoIpVpTijryS/H+CE07oMtplL/ytneBVFd2tfVJtqGjhdht8tEi4wmqSSlqTgEu444w==)'
|
||||||
mkdir -p /config/qBittorrent
|
mkdir -p /config/qBittorrent
|
||||||
if [ -f "$CONF" ]; then
|
if [ -f "$CONF" ]; then
|
||||||
if grep -q "LocalhostAuthEnabled" "$CONF"; then
|
if grep -q "Password_PBKDF2" "$CONF"; then
|
||||||
sed -i 's/LocalhostAuthEnabled=.*/LocalhostAuthEnabled=false/' "$CONF"
|
sed -i "s|WebUI\\\\Password_PBKDF2=.*|WebUI\\\\Password_PBKDF2=\"$HASH\"|" "$CONF"
|
||||||
else
|
else
|
||||||
sed -i '/^\[Preferences\]/a WebUI\\LocalhostAuthEnabled=false' "$CONF" || \
|
sed -i "/^\[Preferences\]/a WebUI\\\\Password_PBKDF2=\"$HASH\"" "$CONF"
|
||||||
printf '\n[Preferences]\nWebUI\\LocalhostAuthEnabled=false\n' >> "$CONF"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
echo "Config patched: $(grep LocalhostAuth $CONF 2>/dev/null || echo 'will be set on first run')"
|
echo "Password hash set."
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: config
|
- name: config
|
||||||
mountPath: /config
|
mountPath: /config
|
||||||
@@ -276,7 +278,9 @@ spec:
|
|||||||
PORT=$(cat /tmp/gluetun/forwarded_port)
|
PORT=$(cat /tmp/gluetun/forwarded_port)
|
||||||
if [ -n "$PORT" ] && [ "$PORT" != "0" ]; then
|
if [ -n "$PORT" ] && [ "$PORT" != "0" ]; then
|
||||||
echo "$(date): Forwarded port: $PORT — updating qBittorrent"
|
echo "$(date): Forwarded port: $PORT — updating qBittorrent"
|
||||||
curl -s -X POST http://localhost:8080/api/v2/app/setPreferences \
|
curl -s -c /tmp/qbt.txt -X POST http://localhost:8080/api/v2/auth/login \
|
||||||
|
-d "username=admin&password=adminadmin" >/dev/null 2>&1
|
||||||
|
curl -s -b /tmp/qbt.txt -X POST http://localhost:8080/api/v2/app/setPreferences \
|
||||||
-d "json={\"listen_port\":$PORT,\"random_port\":false}" >/dev/null 2>&1
|
-d "json={\"listen_port\":$PORT,\"random_port\":false}" >/dev/null 2>&1
|
||||||
echo "$(date): qBittorrent listen port set to $PORT"
|
echo "$(date): qBittorrent listen port set to $PORT"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -35,16 +35,17 @@ spec:
|
|||||||
- -c
|
- -c
|
||||||
- |
|
- |
|
||||||
CONF=/config/qBittorrent/qBittorrent.conf
|
CONF=/config/qBittorrent/qBittorrent.conf
|
||||||
|
HASH='@ByteArray(HqYj1eGsdXlQ4CSy597Y9A==:J9hsJIlU5FYfHb5rY5qQoIpVpTijryS/H+CE07oMtplL/ytneBVFd2tfVJtqGjhdht8tEi4wmqSSlqTgEu444w==)'
|
||||||
mkdir -p /config/qBittorrent
|
mkdir -p /config/qBittorrent
|
||||||
if [ -f "$CONF" ]; then
|
if [ -f "$CONF" ]; then
|
||||||
if grep -q "LocalhostAuthEnabled" "$CONF"; then
|
# Set known adminadmin password hash
|
||||||
sed -i 's/LocalhostAuthEnabled=.*/LocalhostAuthEnabled=false/' "$CONF"
|
if grep -q "Password_PBKDF2" "$CONF"; then
|
||||||
|
sed -i "s|WebUI\\\\Password_PBKDF2=.*|WebUI\\\\Password_PBKDF2=\"$HASH\"|" "$CONF"
|
||||||
else
|
else
|
||||||
sed -i '/^\[Preferences\]/a WebUI\\LocalhostAuthEnabled=false' "$CONF" || \
|
sed -i "/^\[Preferences\]/a WebUI\\\\Password_PBKDF2=\"$HASH\"" "$CONF"
|
||||||
printf '\n[Preferences]\nWebUI\\LocalhostAuthEnabled=false\n' >> "$CONF"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
echo "Config patched: $(grep LocalhostAuth $CONF 2>/dev/null || echo 'will be set on first run')"
|
echo "Password hash set."
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: config
|
- name: config
|
||||||
mountPath: /config
|
mountPath: /config
|
||||||
@@ -96,7 +97,9 @@ spec:
|
|||||||
PORT=$(cat /tmp/gluetun/forwarded_port)
|
PORT=$(cat /tmp/gluetun/forwarded_port)
|
||||||
if [ -n "$PORT" ] && [ "$PORT" != "0" ]; then
|
if [ -n "$PORT" ] && [ "$PORT" != "0" ]; then
|
||||||
echo "$(date): Forwarded port: $PORT — updating qBittorrent"
|
echo "$(date): Forwarded port: $PORT — updating qBittorrent"
|
||||||
curl -s -X POST http://localhost:8080/api/v2/app/setPreferences \
|
curl -s -c /tmp/qbt.txt -X POST http://localhost:8080/api/v2/auth/login \
|
||||||
|
-d "username=admin&password=adminadmin" >/dev/null 2>&1
|
||||||
|
curl -s -b /tmp/qbt.txt -X POST http://localhost:8080/api/v2/app/setPreferences \
|
||||||
-d "json={\"listen_port\":$PORT,\"random_port\":false}" >/dev/null 2>&1
|
-d "json={\"listen_port\":$PORT,\"random_port\":false}" >/dev/null 2>&1
|
||||||
echo "$(date): qBittorrent listen port set to $PORT"
|
echo "$(date): qBittorrent listen port set to $PORT"
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user